;****************************************************************
;* MEMORY GAME - SIMON   					*
;* BY KEITH WILSON						*
;****************************************************************

	list p=16f84,	;microcontroller 

	include	"p16F84A.inc"	;register memory mapping file
	include "simonF84.inc"	;Simon definitions

	__Config 3FF3h

;****************************************************************
;global variable memory
;****************************************************************
timera		equ	0x0c		;general purpose timer
timerb		equ	0x0d		;general purpose timer
timerc		equ	0x0e		;general purpose timer
timerd		equ	0x0f		;general purpose timer
note_select	equ	0x10		;selection of note
note_tone	equ	0x11		;frequency of note
note_length	equ	0x12		;length of note
note_tempo	equ	0x13		;tempo of song
random		equ	0x14		;random number
key		equ	0x15		;key last pressed
column_w	equ	0x16		;write pointer in sequence table X
line_w		equ	0x17		;write pointer in sequence table Y
column_r	equ	0x18		;read pointer in sequence table X
line_r		equ	0x19		;read pointer in sequnece table Y
steps0104	equ	0x1a		;step memory
steps0508	equ	0x1b		;step memory
steps0912	equ	0x1c		;step memory
steps1316	equ	0x1d		;step memory
steps1720	equ	0x1e		;step memory
steps2124	equ	0x1f		;step memory
steps2528	equ	0x20		;step memory
steps2932	equ	0x21		;step memory
steps3336	equ	0x22		;step memory
steps3740	equ	0x23		;step memory
steps4144	equ	0x24		;step memory
steps4548	equ	0x25		;step memory
steps4952	equ	0x26		;step memory
steptemp	equ	0x27		;temporary step memory
stepsgood	equ	0x28		;successful steps by player

;****************************************************************
;reset vector
;****************************************************************
reset:	org	0x00			;reset vector address	
	goto	start			;start program execution
	

start:	org 	0x06			;start of program
	goto	Initialisation

;****************************************************************
; Data tables for Songs
;****************************************************************
SongHeyJude:	
	addwf	pcl,f		;jump formward accoding 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 formward 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		: Initialisation
;Description	: system initialisation and mainloop
;Inputs		: none
;Outputs	: none
;****************************************************************
Initialisation:

;system initialisation

;port A and port B initialisation

	bcf	status,rp1		;select bank1 register
	bsf	status,rp0

	movlw	PORTA_CONFIG1		;porta configuration
	movwf	trisa			
	movlw	PORTB_CONFIG1		;portb configuration
	movwf	trisb

	movlw	0x88			;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		;add step memory offset
	movwf	line_w

	call	ClearRecord		;clear record steps?
	call	Introduction		;introductory song & calibration

;****************************************************************
;Name		: Mainloop
;Description	: 
;Inputs		: none
;Outputs	: none
;****************************************************************
Mainloop:
	call	GetStep			;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
;Inputs		: none
;Outputs	: none
;****************************************************************
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
;Outputs	: 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
;Outputs	: none
;****************************************************************
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 special delay function used whenever sound
;		: must be produced on the buzzer. 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
;Outputs	: none
;****************************************************************
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		: GetRandom
;Description	: reads the PIC's timer register at various
;		: "random" intervals caused by the player
;Inputs		: pressing one of the keys.
;Outputs	: random number 0-3
;****************************************************************
GetRandom:
	movf	tmr0,w
	andlw	0x03			;mask all but bit0,bit1
	movwf	random

	return

;****************************************************************
;Name		: GetStep
;Description	: gets a random number and stores it into the
;		: next available position in sequence table.
;Inputs		: none
;Outputs	: none
;****************************************************************
GetStep:
	call	GetRandom		;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
		
GCol3:	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 sequence 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 sequence table?
	return				;no - return
	clrf	column_w		;yes - select next memory byte in sequence table
	incf	line_w,f

	return

;****************************************************************
;Name		: ShowSequence
;Description	: displays the step sequence that the player
;		: has to remember and repeat.
;Inputs		: none
;Outputs	: none
;****************************************************************
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
		
SCol3:	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 sequence 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 sequence 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.
;Inputs		: none
;Outputs	: none
;****************************************************************
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

	;get current record from EEPROM
	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.
;Inputs		: none
;Outputs	: none
;****************************************************************
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 to write 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?
	btfss	status,z		;yes - skip next instruction
	goto	Sr1			;no - keep playing

	call	Delay150
	call	Delay150
	call	Delay150

	goto	NewGame			;start new game

;****************************************************************
;Name		: Delay
;Description	: causes a delay of 150msec with 4MHz crystal!
;Inputs		: none
;Outputs	: none
;****************************************************************
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

