Program for PIC16F628 micro
The following sets up the ports and the equates for the notes for the tunes:
;****************************************************************
;* MEMORY GAME - Simon *
;****************************************************************
;Port A definitions
PORTA_CONFIG1 equ 0xFD ;1111 1110
0 ;not used
BUZZER equ 1 ;buzzer output
2 ;not used
3 ;not used
4 ;not used
;Port B definitions
PORTB_CONFIG1 equ 0x0F ;bit7: out,out,out,out,in,in,in,in :bit0
KEY_RED equ 0 ;red key input - bit0
KEY_GREEN equ 1 ;green key input - bit1
KEY_YELLOW equ 2 ;yellow key input - bit2
KEY_ORANGE equ 3 ;orange key input - bit3
LED_RED equ 4 ;red led output - bit4
LED_GREEN equ 5 ;green led output - bit5
LED_YELLOW equ 6 ;yellow led output- bit6
LED_ORANGE equ 7 ;orange led output- bit7
RAM_START equ 0x20 ;start of global variable ram
LINE_OFFSET equ 0x3A ;start of step memory in ram area
RECORD_STEPS equ 0x00 ;eeprom address for step record
;Data for song notes
;Value = 10's of microseconds
;octave 1
NOTE_G0 equ D'255' ;196 Hz
NOTE_A0 equ D'227' ;220 Hz
NOTE_B0 equ D'202' ;247 Hz
;octave 2
NOTE_C1 equ D'191' ;262 Hz
NOTE_D1 equ D'170' ;294 Hz
NOTE_E1 equ D'152' ;330 Hz
NOTE_F1 equ D'143' ;349 Hz
NOTE_G1 equ D'128' ;392 Hz
NOTE_A1 equ D'114' ;440 Hz
NOTE_B1 equ D'101' ;494 Hz
;octave 3
NOTE_C2 equ D'95' ;524 Hz
NOTE_D2 equ D'85' ;588 Hz
NOTE_E2 equ D'76' ;660 Hz
NOTE_F2 equ D'72' ;698 Hz
NOTE_G2 equ D'64' ;784 Hz
NOTE_A2 equ D'57' ;880 Hz
NOTE_B2 equ D'51' ;988 Hz
;octave 4
NOTE_C3 equ D'48' ;1048 Hz
NOTE_D3 equ D'43' ;1176 Hz
NOTE_E3 equ D'38' ;1320 Hz
NOTE_F3 equ D'36' ;1396 Hz
NOTE_G3 equ D'32' ;1568 Hz
NOTE_A3 equ D'28' ;1760 Hz
NOTE_B3 equ D'25' ;1976 Hz
;length of notes
;"tempo"(nomalized) length is set in SoundPlay function by timerb
LENGTH_SEMIBREVE equ 0x20 ;tempo
LENGTH_MINIM equ 0x10 ;tempo/2
LENGTH_CROTCHET equ 0x08 ;tempo/4
LENGTH_QUAVER equ 0x04 ;tempo/8
LENGTH_SEMIQUAVER equ 0x02 ;tempo/16
LENGTH_DEMISEMIQUAVER equ 0x01 ;tempo/32
SONG_HEY_JUDE_LEN equ D'68' ;total No of notes + lengths
SONG_OSUSANA_LEN equ D'108'
SONG_DEATHMARCH_LEN equ D'22'
KEY_RED_SOUND equ NOTE_C2
KEY_GREEN_SOUND equ NOTE_E2
KEY_YELLOW_SOUND equ NOTE_G2
KEY_ORANGE_SOUND equ NOTE_B2
The following contains all the comments for the Simon program:
Note: __Config 3F18h covers the following:
_CP_off & _LVP_off & _PWRTE_off & Boden_off & _WDT_off & _IntRC_osc_I/O
where:
CP = code protection
LVP = low-voltage programming
PWRTE = power-up timer
Boden = Brown-out detector
WDT = watchdog timer
IntRC_osc_I/O = internal RC for 4MHz - all pins for in-out
You can simply write: __Config 3F18h
or:
__Config _CP_off & _LVP_off & _PWRTE_off & Boden_off & _WDT_off & _IntRC_osc_I/O
or select the boxes in IC Prog at the time of burning the chip.
In all cases the chip will get burnt with the correct configuration value and when it is copied, the copy will automatically have the correct configuration value.
;****************************************************************
;* Memory Game - SIMON *
;****************************************************************
list p=16f628, ;microcontroller
include "p16F628.inc" ;registers for F628
include "simon628.inc" ;Simon definitions for F628
__Config 3F18h
;****************************************************************
;global variables
;Files for PIC16F628 start at 0x20
;****************************************************************
timera equ 0x2c ;general purpose timer
timerb equ 0x2d ;general purpose timer
timerc equ 0x2e ;general purpose timer
timerd equ 0x2f ;general purpose timer
note_select equ 0x30 ;selection of note
note_tone equ 0x31 ;frequency of note
note_length equ 0x32 ;length of note
note_tempo equ 0x33 ;tempo of song
random equ 0x34 ;random number
key equ 0x35 ;key last pressed
column_w equ 0x36 ;write pointer in sequence table X
line_w equ 0x37 ;write pointer in sequence table Y
column_r equ 0x38 ;read pointer in sequence table X
line_r equ 0x39 ;read pointer in sequence table Y
steps0104 equ 0x3a ;step memory
steps0508 equ 0x3b ;step memory
steps0912 equ 0x3c ;step memory
steps1316 equ 0x3d ;step memory
steps1720 equ 0x3e ;step memory
steps2124 equ 0x3f ;step memory
steps2528 equ 0x40 ;step memory
steps2932 equ 0x41 ;step memory
steps3336 equ 0x42 ;step memory
steps3740 equ 0x43 ;step memory
steps4144 equ 0x44 ;step memory
steps4548 equ 0x45 ;step memory
steps4952 equ 0x46 ;step memory
steptemp equ 0x47 ;temporary step memory
stepsgood equ 0x48 ;number of successful steps by player
;****************************************************************
;reset vector
;****************************************************************
reset: org 0x00 ;reset vector address
goto Begin ;start program execution
Begin: org 0x06 ;start of program
goto start
;****************************************************************
; Data tables for Songs
;****************************************************************
SongHeyJude:
addwf pcl,f ;jump forward according to W value
retlw NOTE_G1 ;Hey
retlw LENGTH_CROTCHET
retlw NOTE_E1 ;jude
retlw LENGTH_MINIM
retlw NOTE_E1 ;don't
retlw LENGTH_QUAVER
retlw NOTE_G1 ;make
retlw LENGTH_QUAVER
retlw NOTE_A1 ;it
retlw LENGTH_QUAVER
retlw NOTE_D1 ;bad,
retlw LENGTH_MINIM
retlw NOTE_D1 ;take
retlw LENGTH_QUAVER
retlw NOTE_E1 ;a
retlw LENGTH_QUAVER
retlw NOTE_F1 ;sad
retlw LENGTH_CROTCHET
retlw NOTE_C2 ;song
retlw LENGTH_MINIM
retlw NOTE_C2 ;and
retlw LENGTH_QUAVER
retlw NOTE_B1 ;make
retlw LENGTH_QUAVER
retlw NOTE_G1 ;it
retlw LENGTH_QUAVER
retlw NOTE_A1 ;bet-
retlw LENGTH_QUAVER
retlw NOTE_G1 ;ter.
retlw LENGTH_MINIM
retlw NOTE_G1 ;Re-
retlw LENGTH_QUAVER
retlw NOTE_A1 ;mem-
retlw LENGTH_QUAVER
retlw NOTE_A1 ;ber
retlw LENGTH_CROTCHET
retlw NOTE_A1 ;to
retlw LENGTH_QUAVER
retlw NOTE_D2 ;let
retlw LENGTH_SEMIQUAVER
retlw NOTE_C2 ;her
retlw LENGTH_CROTCHET
retlw NOTE_B1 ;in
retlw LENGTH_QUAVER
retlw NOTE_C2 ;to
retlw LENGTH_QUAVER
retlw NOTE_A1 ;your
retlw LENGTH_CROTCHET
retlw NOTE_G1 ;heart,
retlw LENGTH_MINIM
retlw NOTE_C1 ;then
retlw LENGTH_QUAVER
retlw NOTE_D1 ;you
retlw LENGTH_QUAVER
retlw NOTE_E1 ;can
retlw LENGTH_QUAVER
retlw NOTE_A1 ;start
retlw LENGTH_MINIM
retlw NOTE_G1 ;to
retlw LENGTH_QUAVER
retlw NOTE_F1 ;make
retlw LENGTH_QUAVER
retlw NOTE_E1 ;it
retlw LENGTH_QUAVER
retlw NOTE_C1 ;bet-
retlw LENGTH_QUAVER
retlw NOTE_C1 ;ter.
retlw LENGTH_MINIM
SongOSusana:
addwf pcl,f ;jump forward according to W value
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_QUAVER
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_QUAVER
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_MINIM
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_QUAVER
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_MINIM
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_F2
retlw LENGTH_CROTCHET
retlw NOTE_F2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_MINIM
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_QUAVER
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_A2
retlw LENGTH_CROTCHET
retlw NOTE_G2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_MINIM
retlw NOTE_D2
retlw LENGTH_QUAVER
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_E2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_CROTCHET
retlw NOTE_D2
retlw LENGTH_CROTCHET
retlw NOTE_C2
retlw LENGTH_SEMIBREVE
SongDeathMarch:
addwf pcl,f ;jump forward according to W value
retlw NOTE_C1
retlw LENGTH_MINIM
retlw NOTE_C1
retlw LENGTH_QUAVER
retlw NOTE_C1
retlw LENGTH_CROTCHET
retlw NOTE_C1
retlw LENGTH_QUAVER
retlw NOTE_C1
retlw LENGTH_CROTCHET
retlw NOTE_E1
retlw LENGTH_QUAVER
retlw NOTE_D1
retlw LENGTH_CROTCHET
retlw NOTE_C1
retlw LENGTH_QUAVER
retlw NOTE_C1
retlw LENGTH_CROTCHET
retlw NOTE_B0
retlw LENGTH_CROTCHET
retlw NOTE_C1
retlw LENGTH_MINIM
;****************************************************************
;Name : Start
;Description : set-up ports A and B
;****************************************************************
Start: MOVLW 07 ;to disable the comparators
MOVWF 0x1F ;file 1F is the CMCON file
bsf status,rp0 ;select bank1 register
movlw PORTA_CONFIG1 ;porta configuration
movwf 0x05
movlw PORTB_CONFIG1 ;portb configuration
movwf 0x06
movlw 0x81 ;Fosc/4;No prescaler
movwf 0x81 ;Timer configuration in option register
bcf status,rp0 ;select bank0 registers
NewGame:
clrf porta ;turn off status leds
clrf portb ;turn off all leds
movlw RAM_START ;clear global variables
movwf fsr
S1: clrf indf
incf fsr,f
btfss fsr,6
goto S1
movf line_w,w ;initialise step memory base
addlw LINE_OFFSET ;put 3Ah into file 37h at beginning
movwf line_w
call ClearRecord ;clear record steps?
call Introduction ;introductory song & calibration
;****************************************************************
;Name : Mainloop
;Description :
;****************************************************************
Mainloop:
call MakeStep ;create a new step & add it to sequence
call ShowSequence ;show sequence on LEDs
call GetUserSequence ;player's sequence (result returned in W)
;W=1 - correct, W=0 - wrong
xorlw 1 ;is player's sequence correct?
btfss status,z ;yes - ignore next instruction
goto SequenceBad ;no - it's wrong!
incf stepsgood,f ;another successful step by player
call Delay150
call Delay150
call Delay150
movf line_w,w ;max sequence reached (52 steps)?
xorlw D'52'
btfss status,z
goto Mainloop ;no - do another step
movf column_w,w
xorlw D'3'
btfss status,z
goto Mainloop ;no - do another step
goto SequenceRecord ;yes - max sequence correct!
;****************************************************************
;Name : ClearRecord
;Description : allows the player to clear the current step
; : record. Player must press one of the keys
; : at power-on for EEPROM to be set to zero
;****************************************************************
ClearRecord:
movf portb,w ;test for a key press
andlw 0x0f ;mask keys
xorlw 0x00 ;are any keys being pressed?
btfsc status,z ;yes - skip next instruction
return ;no - return!
movlw RECORD_STEPS ;clear step record in EEPROM
movwf eeadr
clrf eedata
bsf status,rp0 ;select bank1
bsf eecon1,wren ;enable write
movlw 0x55 ;unlock codes
movwf eecon2
movlw 0xaa
movwf eecon2
bsf eecon1,wr ;write begins
bcf eecon1,wren ;disable further writes
Crec: btfsc eecon1,wr ;wait to write complete
goto Crec
bcf status,rp0 ;select bank0
movlw 0x02
movwf note_tempo
call SoundRisingRocket ;cleared record indication
return
;****************************************************************
;Name : Introduction
;Description : plays the introductory "hey jude" song until
; : one of the keys is pressed.
;Inputs : none
;****************************************************************
Introduction:
clrf note_select ;beginning of "hey jude" song
Intr1: incf steptemp,f
movf steptemp,w
andlw 0x03
movwf random
call Delay150
call ShowLed ;show it on leds
movlw 0x10
movwf note_tempo ;speed of song
movf note_select,w ;get next "hey jude" note
call SongHeyJude ;returned in W
movwf note_tone
incf note_select,f
movf note_select,w ;get length of note
call SongHeyJude
movwf note_length
call SoundPlay ;play music
clrf portb ;turn all leds off
incf note_select,f ;select next note
movf note_select,w
xorlw SONG_HEY_JUDE_LEN ;end of song?
btfsc status,z ;no - skip next instruction
clrf note_select ;yes - play it again from beginning
movf portb,w ;test for a key press
andlw 0x0f ;mask keys
xorlw 0x00 ;are any keys being pressed?
btfsc status,z ;yes - skip next instruction
goto Intr1 ;no - keep playing music!
movlw 0x02
movwf note_tempo
call SoundRisingRocket ;start new game indication
return ;start new game
;****************************************************************
;Name : SoundPlay
;Description : plays a tone on the buzzer
;Inputs : note_tone - frequency of the tone
; : note_length - length of note
; : note_tempo - speed of song
;****************************************************************
SoundPlay:
clrf timerc ;initialise timer
Sp1: movf timerc,w
xorwf note_length,w ;end of note?
btfsc status,z ;no - skip next instruction
return ;yes - exit function
movf note_tempo,w
movwf timerb
Sp2: movf note_tone,w ;frequency
bsf porta,BUZZER ;high time
call SoundDelay
bcf porta,BUZZER ;low time
call SoundDelay
decfsz timerb,f
goto Sp2
incf timerc,f
goto Sp1
;****************************************************************
;Name : SoundDelay
;Description : a delay used whenever sound
; : must be produced on the piezo diaphragm. The W register
; : contains the number of cycles to wait (in 10's
; : of microseconds.
;Inputs : W - contains the note to be played
; : ie. W=191, delay==1,91msec
;****************************************************************
SoundDelay:
movwf timera
Sd1: nop
nop
nop
nop
nop
nop
nop
decfsz timera,f
goto Sd1
return
;****************************************************************
;Name : SoundRisingRocket
;Description : rising rocket sound effect
;Inputs : note_tempo - speed of rocket
;Outputs : none
;****************************************************************
SoundRisingRocket:
clrf note_tone ;make tone=255 - start
comf note_tone,f ;with lowest frequency
Srr1: movlw LENGTH_DEMISEMIQUAVER
movwf note_length
call SoundPlay
decfsz note_tone,f ;do a "rising" sound
goto Srr1
CALL Delay150
CALL Delay150
CALL Delay150
CALL Delay150
CALL Delay150
CALL Delay150
CALL Delay150
CALL Delay150
return
;****************************************************************
;Name : MakeRandom
;Description : reads the PIC's timer register at various
; : "random" intervals caused by the player
;Inputs : pressing one of the keys.
;Outputs : random number will be 0, 1, 2, 3
;****************************************************************
MakeRandom:
movf tmr0,w
andlw 0x03 ;mask all but bit0 and bit1
movwf random ;move random number into file 34h
return
;****************************************************************
;Name : MakeStep
;Description : gets a random number and stores it into the
; : next available position in table.
;****************************************************************
MakeStep:
call MakeRandom ;ascertain random number
movf line_w,w ;get current line
movwf fsr ;pointer to next available memory
bcf status,c ;initialise carry
movf column_w,w ;get current column
xorlw 0
BTFSC STATUS,Z
GOTO GCol0 ;column=0 - don't shift
xorlw 0x01
BTFSC STATUS,Z
GOTO GCol1 ;column=1 - shift random 2 times
XORLW 0x03
BTFSC STATUS,Z
GOTO GCol2 ;column=2 - shift random 4 times
rlf random,f ;column=3 - shift random 6 times
rlf random,f
GCol2: rlf random,f
rlf random,f
GCol1: rlf random,f
rlf random,f
GCol0: movf indf,w ;get current memory byte of table
iorwf random,w ;merge new random number into table
movwf indf ;restore in sequence table
incf column_w,f ;update column
btfss column_w,2 ;end of this memory byte in table?
return ;no - return
clrf column_w ;yes - select next memory byte in table
incf line_w,f
return
;****************************************************************
;Name : ShowSequence
;Description : displays the step sequence that the player
; : has to remember and repeat.
;****************************************************************
ShowSequence:
clrf column_r ;begin at start of step sequence
movlw LINE_OFFSET
movwf line_r
Ss1: movf line_r,w
movwf fsr
movf indf,w
movwf steptemp
movf column_r,w ;get current column
xorlw 0
BTFSC STATUS,Z
GOTO SCol0 ;column=0 - don't shift
xorlw 0x01
BTFSC STATUS,Z
GOTO SCol1 ;column=1 - shift random 2 times
XORLW 0x03
BTFSC STATUS,Z
GOTO SCol2 ;column=2 - shift random 4 times
rrf steptemp,f ;column=3 - shift random 6 times
rrf steptemp,f
SCol2: rrf steptemp,f
rrf steptemp,f
SCol1: rrf steptemp,f
rrf steptemp,f
SCol0: movf steptemp,w ;get current memory byte of table
andlw 0x03 ;mask bits 2-7
movwf random
call ShowStep ;display LED according to stored value
call Delay150 ;wait a little after player
call Delay150 ;has pressed a key
call Delay150
incf column_r,f ;update column
btfsc column_r,2 ;overflow?
goto Colov1 ;yes
Ss2: movf column_r,w ;no
xorwf column_w,w ;column pointers the same?
btfss status,z
goto Ss1 ;no - at least another step to show
movf line_r,w ;yes
xorwf line_w,w ;reached the end of sequence?
btfsc status,z ;no - jump next instruction
return ;yes - sequence complete!
goto Ss1 ;at least another step to show
Colov1: clrf column_r
incf line_r,f
goto Ss2
;****************************************************************
;Name : ShowStep
;Description : turns on one of the LEDs and beeps according to
; : the random number & level of difficulty
;Inputs : random - random number
;Outputs : none
;****************************************************************
ShowStep:
call ShowLed ;show random number on led
movwf note_tone ;ShowLed returns with beep value in W
movlw LENGTH_SEMIBREVE
movwf note_length
movlw 0x10 ;easy level
btfss porta,LEVEL ;get level of difficulty
movlw 0x01 ;hard level
movwf note_tempo ;speed of beep
call SoundPlay ;play button beep
clrf portb ;turn all leds off
return
;****************************************************************
;Name : ShowLed
;Description : turns on one of the LEDs according to the random
; : number & prepares W with tone value
;Inputs : random - random number
;Outputs : W - value of tone frequency
;****************************************************************
ShowLed:
movf random,w ;get random number
xorlw 0
BTFSC STATUS,Z
goto ShowRed ;random=0
xorlw 0x01
BTFSC STATUS,Z
GOTO ShowGreen ;random=1
xorlw 0x03
BTFSC STATUS,Z
GOTO ShowYellow ;random=2
goto ShowOrange ;random=3
ShowRed:
bsf portb,LED_RED ;turn on red led
retlw KEY_RED_SOUND ;tone frequency
ShowGreen:
bsf portb,LED_GREEN ;turn on green led
retlw KEY_GREEN_SOUND ;tone frequency
ShowYellow:
bsf portb,LED_YELLOW ;turn on yellow led
retlw KEY_YELLOW_SOUND ;tone frequency
ShowOrange:
bsf portb,LED_ORANGE ;turn on orange led
retlw KEY_ORANGE_SOUND ;tone frequency
;****************************************************************
;Name : GetUserSequence
;Description : checks the player's sequence to that required
;Inputs : none
;Outputs : W=0 : player has made a mistake
; : W=1 : player has successfully repeated sequence
;****************************************************************
GetUserSequence:
clrf column_r ;begin at start of step sequence
movlw LINE_OFFSET
movwf line_r
Us1: movf line_r,w
movwf fsr
movf indf,w
movwf steptemp
movf column_r,w ;get current column
xorlw 0
BTFSC STATUS,Z
GOTO UCol0 ;column=0 - don't shift
xorlw 0x01
BTFSC STATUS,Z
GOTO UCol1 ;column=1 - shift random 2 times
xorlw 0x03
BTFSC STATUS,Z
GOTO UCol2 ;column=2 - shift random 4 times
UCol3: rrf steptemp,f ;column=3 - shift random 6 times
rrf steptemp,f
UCol2: rrf steptemp,f
rrf steptemp,f
UCol1: rrf steptemp,f
rrf steptemp,f
UCol0: movf steptemp,w ;get current memory byte of table
andlw 0x03 ;mask bits 2-7
movwf random
call Keypad ;get player's input - returned in W
;W=0 - no key pressed (timeout)
;W=1 - player has pressed a key
xorlw 0 ;did player press a key?
btfsc status,z ;yes - jump next instruction
retlw 0 ;no - exit function
movf key,w ;compare pressed key with step
xorwf random,w ;is it the same?
btfss status,z ;yes - jump next instruction
retlw 0 ;no - incorrect, exit function
incf column_r,f ;update column
btfsc column_r,2 ;overflow?
goto Colov2 ;yes
Us2: movf column_r,w ;no
xorwf column_w,w ;column pointers the same?
btfss status,z
goto Us1 ;no - at least another step to show
movf line_r,w ;yes
xorwf line_w,w ;reached the end of sequence?
btfsc status,z ;no - jump next instruction
retlw 1 ;yes - sequence complete!
goto Us1 ;at least another step to show
Colov2: clrf column_r
incf line_r,f
goto Us2
;****************************************************************
;Name : Keypad
;Description : scans the keys for a press and lights up the
; : corresponding LED and beeps.
;Inputs : none
;Outputs : W=0 : key timeout - no key has been pressed
; : W=1 : key has been pressed
; : key : 0=red,1=green,2=yellow,3=orange
;****************************************************************
Keypad:
clrf key ;initialise key
movlw 0x07 ;assume easy level - 5 sec timeout
btfss porta,LEVEL ;get level of difficulty
movlw 0x03 ;hard level - 2 sec timeout
movwf timerc
Kp2: movlw 0xff
movwf timerb
Kp1: movlw 0xff
movwf timera
Kwait: btfsc portb,KEY_RED
goto KeyRed
btfsc portb,KEY_GREEN
goto KeyGreen
btfsc portb,KEY_YELLOW
goto KeyYellow
btfsc portb,KEY_ORANGE
goto KeyOrange
decfsz timera,f
goto Kwait
decfsz timerb,f
goto Kp1
decfsz timerc,f
goto Kp2
retlw 0 ;player hasn't pressed key!
KeyRed:
bsf portb,LED_RED ;turn on red led
clrf key ;key=0
movlw KEY_RED_SOUND ;tone frequency
goto Beep1
KeyGreen:
bsf portb,LED_GREEN ;turn on green led
bsf key,0 ;key=1
movlw KEY_GREEN_SOUND ;tone frequency
goto Beep1
KeyYellow:
bsf portb,LED_YELLOW ;turn on yellow led
bsf key,1 ;key=2
movlw KEY_YELLOW_SOUND ;tone frequency
goto Beep1
KeyOrange:
bsf portb,LED_ORANGE ;turn on orange led
bsf key,0 ;key=3
bsf key,1
movlw KEY_ORANGE_SOUND ;tone frequency
Beep1: movwf note_tone ;save tone
movlw LENGTH_SEMIBREVE
movwf note_length
movlw 0x03
movwf note_tempo ;speed of beep
Beep2: call SoundPlay ;play button beep
movf portb,w ;test for a key press
andlw 0x0f ;mask keys
xorlw 0x00 ;are any keys being pressed?
btfss status,z ;no - skip next instruction
goto Beep2 ;yes - keep beeping!
clrf portb ;turn off all leds
retlw 1 ;return to calling function
;****************************************************************
;Name : SequenceBad
;Description : player has made a mistake - show player the
; : correct sequence. Test to see if a record has
; : been made.
;****************************************************************
SequenceBad:
movlw 0x01
movwf note_tempo
call SoundRisingRocket
movlw 0x01
movwf note_tempo
call SoundRisingRocket
call ShowSequence ;replay proper sequence again
movlw 0x01
movwf note_tempo
call SoundRisingRocket
movlw 0x01
movwf note_tempo
call SoundRisingRocket
call Delay150
call Delay150
call Delay150
movlw RECORD_STEPS ;get current record from EEPROM
movwf eeadr
bsf status,rp0 ;select bank1
bsf eecon1,rd ;read eeprom
bcf status,rp0 ;select bank0
movf eedata,w ;W=record number of steps
subwf stepsgood,w ;a record sequence (or same)?
btfsc status,c ;no - jump next instruction
goto SequenceRecord ;yes - tell player about it!
clrf note_select ;beginning of song
movlw 0x10 ;slow
movwf note_tempo ;speed of song
Sb1: call Delay150
movf note_select,w ;get next note
call SongDeathMarch ;returned in W
movwf note_tone
incf note_select,f
movf note_select,w ;get length of note
call SongDeathMarch
movwf note_length
call SoundPlay ;play music
incf note_select,f ;select next note
movf note_select,w
xorlw SONG_DEATHMARCH_LEN ;end of song?
btfss status,z ;yes - skip next instruction
goto Sb1 ;no - keep playing
call Delay150
call Delay150
call Delay150
goto NewGame ;start new game
;****************************************************************
;Name : SequenceRecord
;Description : player has beaten the record, save new step
; : record in EEPROM and play record tune.
;****************************************************************
SequenceRecord:
movlw RECORD_STEPS ;save new step record in EEPROM
movwf eeadr
movf stepsgood,w
movwf eedata
bsf status,rp0 ;select bank1
bsf eecon1,wren ;enable write
movlw 0x55 ;unlock codes
movwf eecon2
movlw 0xaa
movwf eecon2
bsf eecon1,wr ;write begins
bcf eecon1,wren ;disable other writes
Sre1: btfsc eecon1,wr ;wait for "write" to complete
goto Sre1
bcf status,rp0 ;select bank0
clrf note_select ;beginning of song
Sr1: incf steptemp,f
movf steptemp,w
andlw 0x03
movwf random
call Delay150
call ShowLed ;show it on leds
movlw 0x5 ;fast
movwf note_tempo ;speed of song
movf note_select,w ;get next note
call SongOSusana ;returned in W
movwf note_tone
incf note_select,f
movf note_select,w ;get length of note
call SongOSusana
movwf note_length
call SoundPlay ;play music
clrf portb ;turn all leds off
incf note_select,f ;select next note
movf note_select,w
xorlw SONG_OSUSANA_LEN ;end of song?
btfsc status,z ;no - skip next instruction
goto Sr2 ;yes - end playing
movf portb,w ;test for a key press
andlw 0x0f ;mask keys
xorlw 0x00 ;are any keys being pressed?
btfsc status,z ;yes - skip next instruction
goto Sr1 ;no - keep playing music!
goto NewGame ;start new game
Sr2 call Delay150
call Delay150
call Delay150
goto NewGame ;start new game
;****************************************************************
;Name : Delay
;Description : causes a delay of 150msec with 4MHz crystal!
;****************************************************************
Delay150:
movlw 0xc3 ;number of wait states
movwf timerb
L4: movlw 0xff ;number of wait states
movwf timera
L5: decfsz timera,f
goto L5
decfsz timerb,f
goto L4
return
END
Hex file for Simon PIC16F628:
:020000000628D0 :04000C00D02882076F :1000100080340834983410349834043480340434F0 :1000200072340434AA341034AA34043498340434B6 :100030008F3408345F3410345F340434653404344E :100040008034043472340434803410348034043402 :100050007234043472340834723404345534023443 :100060005F340834653404345F3404347234083443 :1000700080341034BF340434AA3404349834043443 :1000800072341034803404348F340434983404349B :10009000BF340434BF34103482075F341034553415 :1000A00004344C340834403408344034083439348F :1000B0000834403408344C3408345F341034553438 :1000C00004344C3408344C340834553408345F3428 :1000D0000834553410345F341034553404344C34FF :1000E0000834403408344034083439340834403457 :1000F00008344C3408345F341034553410344C34E4 :1001000008344C340834553408345F3410344834DF :10011000083448340834393408343934083439342C :10012000083440340834403408344C3408345F34E4 :100130000834553410345F341034553404344C349E :1001400008344034083440340834393408344034F6 :1001500008344C3408345F341034553404344C348F :1001600008344C34083455340834553408345F347A :1001700020348207BF341034BF340434BF34083411 :10018000BF340434BF34083498340434AA340834F7 :10019000BF340434BF340834CA340834BF34103494 :1001A00007309F008316FD3085000F3086008130B8 :1001B000810083128601203084008001840A041F9C :1001C000DD2837083A3EB700F92010215F217C2155 :1001D000C721013A031D2F2AC80A872287228722B6 :1001E0003708343A031DE6283608033A031DE6288B :1001F000572A06080F39003A0319080000309B00FF :100200009A0183161C1555309D00AA309D009C1440 :100210001C119C18092983120230B3004B210800DD :10022000B001C70A47080339B4008722B42110304F :10023000B30030080720B100B00A30080720B20030 :1002400030218601B00A3008443A0319B00106088B :100250000F39003A031911290230B3004B2108006D :10026000AE012E083206031908003308AD0031082C :100270008514402185104021AD0B3729AE0A312964 :10028000AC000000000000000000000000000000C2 :10029000AC0B41290800B101B1090130B200302195 :1002A000B10B4D2987228722872287228722872226 :1002B00087228722080001080339B40008005B2167 :1002C0003708840003103608003A03197329013AED :1002D00003197129033A03196F29B40DB40DB40D34 :1002E000B40DB40DB40D000834048000B60A361DF8 :1002F0000800B601B70A0800B8013A30B900390859 :1003000084000008C7003808003A03199329013A0D :1003100003199129033A03198F29C70CC70CC70C7D :10032000C70CC70CC70C47080339B400A9218722A2 :1003300087228722B80A3819A62938083606031DED :100340007F2939083706031908007F29B801B90A3F :100350009D29B421B1002030B2001030051E0130BB :10036000B3003021860108003408003A0319BF2980 :10037000013A0319C129033A0319C329C5290616ED :100380005F3486164C340617403486173334051113 :100390008515B8013A30B900390884000008C70053 :1003A0003808003A0319E029013A0319DE29033A13 :1003B0000319DC29C70CC70CC70CC70CC70CC70C2A :1003C00047080339B400FA21003A0319003435080C :1003D0003406031D0034B80A3819F72938083606E0 :1003E000031DCC293908370603190134CC29B8017B :1003F000B90AEE29B5010730051E0330AE00FF3003 :10040000AD00FF30AC000618122A8618162A06190D :100410001A2A86191E2AAC0B032AAD0B012AAE0B31 :10042000FF2900340616B5015F30222A86163514DE :100430004C30222A0617B5144030222A861735146C :10044000B5143330B1002030B2000330B300302196 :1004500006080F39003A031D272A860101340130AE :10046000B3004B210130B3004B217C21872287222E :10047000872200309B0083161C1483121A0848023E :100480000318572AB0011030B30087223008B92072 :10049000B100B00A3008B920B2003021B00A3008EB :1004A000163A031D452A872287228722DA28003040 :1004B0009B0048089A0083161C1555309D00AA30F1 :1004C0009D009C141C119C18632A8312B001C70A5A :1004D00047080339B4008722B4210530B30030083F :1004E0004C20B100B00A30084C20B2003021860107 :1004F000B00A30086C3A0319832A06080F39003A0B :100500000319672ADA28872287228722DA28C3304C :10051000AD00FF30AC00AC0B8B2AAD0B892A080074 :02400E00183F59 :00000001FF
Quick Links
Legal Stuff
Social Media