Music Jingle Generator

 

Photograph of the prototype hardware:

 

 

N.B. the grey ‘dongle’ in the background is the In-System Programmer.

 

Circuit diagram:

 

 

Controlling program:

 

(*$c 4 clock=4MHz*)

(*$d 2313 *)

PROGRAM Music;

(* Play a tune stored in EEPROM variables *)

USES

  LCDdisp2, ToneGen2; (* edit ToneGen2 for output on PB0 *)

CONST

  rest = 0; A = #1; As = #2; B = #3; C = #4; Cs = #5; D = #6;

  Ds = #7; E = #8; F = #9; Fs = #10; G = #11; Gs = #12;

  semiQ = #1; quaver = #2; crochet = #4; minim = #8;

TYPE

  TmusArray  = array[0..71] of byte;

  TmsgArray  = array[0..1] of string;

VAR

(* initialized array variables in EEPROM *)

  music : TmusArray | EEPROM = (*note, octave, duration*)

          [A, #3,semiQ,   Gs,#2,semiQ,   A, #3,semiQ,

           rest,#0,semiQ, E, #2,semiQ,   rest,#0,semiQ,

           Cs,#2,semiQ,   rest,#0,semiQ, E, #2,semiQ,

           rest,#0,semiQ, A, #2,semiQ,   B, #2,semiQ,

           A, #2,semiQ,   Gs,#1,semiQ,   A, #2,semiQ,

           rest,#0,semiQ, E, #1,semiQ,   rest,#0,semiQ,

           Cs,#1,semiQ,   rest,#0,semiQ, E, #1,semiQ,

           rest,#0,semiQ, A, #1,minim,   #15,#0,#0];

          

(* initialized simple variables *)

  intro1  : string | EEPROM = "Music Player V1";

  intro2  : string | EEPROM = "Press button...";

 

(* simple vars. in SRAM *)

  note, octave, duration : byte;

  i : word;

 

(* library subroutines *)

(* LCDdisp2 *)

PROCEDURE InitLCD; LIBRARY;

PROCEDURE WriteCh(ch:BYTE); LIBRARY;

PROCEDURE WriteStr(str:STRING); LIBRARY;

PROCEDURE CursorAt(posn:BYTE); LIBRARY;

PROCEDURE ClearLCD; LIBRARY;

 

(* ToneGen2: change this module to output on PB0 first *)

PROCEDURE InitTones; LIBRARY;

PROCEDURE SoundTone(pitch,octave,duration: BYTE); LIBRARY;

 

(* global procedures *)

PROCEDURE InitSwitch;

(* set up a press-switch on port D, line 0 *)

  BEGIN

    ASM

    cbi   ddrD,0   ; declare this an input

    sbi   portD,0  ; switch on pull-up resistor

    END;

  END;

 

PROCEDURE WaitForSwitchPress;

(* wait for switch on Pin D.0 to be pressed *)

  BEGIN

    ASM (* do this in assembler *)

wait:sbic   pinD,0

     rjmp   wait

    END;

  END;

 

BEGIN

  (* set up hardware *)

  InitLCD;

  InitTones;

  InitSwitch;

  REPEAT

    (* display intro. message *)

    ClearLCD;

    CursorAt(#0); WriteStr(intro1);

    CursorAt(#16); WriteStr(intro2);

    WaitForSwitchPress;

    (* display title *)

    ClearLCD;

    CursorAt(#0); WriteStr("A bit of Bach..");

    i:=0; (* start of music in array *)

    note := music[i]; octave := music[i+1]; duration := music[i+2];

    WHILE note <> #15 DO BEGIN

      SoundTone(note, octave, duration);

      i := i + 3; (* move to next group *)

      note := music[i]; octave := music[i+1]; duration := music[i+2];

    END;

  FOREVER

END.

 

Back