;****************************************************************
;* MEMORY GAME - SIMON   					*
;* BY KEITH WILSON						*				
;****************************************************************

	list p=16f628,	;microcontroller 

	include	"p16F628.inc"	;registers for F628
	include "simon628.inc"	;Simon definitions for F628

	__Config 3F18h

;****************************************************************
;global variable memory
;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 sequnece 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		;successful steps by player

;****************************************************************
;reset vector
;****************************************************************
reset:	org	0x00			;reset vector address	
	goto	Begin			;start program execution
	
Begin	org	0x06
	GOTO 	start

;****************************************************************
; 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 formward accoding 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	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	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
;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.
;****************************************************************
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		: 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 0-3
;****************************************************************
MakeRandom:
	movf	tmr0,w
	andlw	0x03			;mask all but bit0,bit1
	movwf	random
	return

;****************************************************************
;Name		: MakeStep
;Description	: gets a random number and stores it into the
;		: next available position in sequence table.
;Inputs		: none
;Outputs	: none
;****************************************************************
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
		
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
		
	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 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

	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?
	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
