A simple Simon Says style game for use on a Moterolla HC11 processor.
***********************************************************************************
* Lab 9 - ECE 171 - Fall 2005 *
* Simon Says *
* *
* Programmer: Sean P. O. MacCath-Moran *
* Date: 07 Apr 2005 *
* *
* *
***********************************************************************************
******************** DATA *******************
DIPSWITCHES EQU $1003
*1 & 2 reserved for PC0 and PC1
DIPSWITCH1 EQU $01
DIPSWITCH2 EQU $02
*3 & 4 set nothing
DIPSWITCH3 EQU $04
DIPSWITCH4 EQU $08
*5, 6 & 7 set nothing
DIPSWITCH5 EQU $10
DIPSWITCH6 EQU $20
DIPSWITCH7 EQU $40
*Termination switch
DIPSWITCH8 EQU $80
********************* CODE *******************
ORG $AFFF
RANDVAL RMB 1 ;randomizing value for next light
SEQLENGTH RMB 1 ;current lengh of memorized sequence
SEQUENCE RMB 40
***************** MAIN PROGRAM ***************
START ORG $8800 ;start out in timbucktoo
LDS #$DFFF ;initialize stack pointer.
JSR KEYSCANINIT ;initialize keypad usage
JSR MIMICINIT ;initialize MIMIC usage
LDY #MIMICFLAGS ;retrieve address of mimic flags
WAITAGAIN JSR INITnWAIT ;wait for user to press key
CLR SEQLENGTH ;init sequence length to 0
GETNEXTSEQ JSR INCSEQ ;get new value onto SEQUENCE stack
JSR DISPLAY ;show the current sequence to the user
JSR MIMIC ;accept sequence of button presses
BRCLR 0,Y MIMICFLAGERR GETNEXTSEQ
;if no errorflag, then get next value
JSR ERRORDISPLAY ;display error message to user
ENDISNIGH LDAA #DIPSWITCH8 ;check for end switch
BITA DIPSWITCHES
BEQ ENDISWAYNEIGH
JMP WAITAGAIN ;keep up with loop until switch set
ENDISWAYNEIGH SWI ;ok - love ya - bye bye now
* Main END ************************************************************************
***********************************************************************************
* Initialize and Wait *
* *
* PURPOSE: Setup for next game start and wait for user interaction *
* *
* USE: Call the function *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
INITPORTB EQU $1004
INITPAUSETIME EQU 2
****************** CODE START ****************
INITnWAIT PSHB ;save the B reg state
PSHA ;save the A reg state
PSHY ;save the X reg state
CLR INITPORTB ;blank out the LEDs
LDY #KEYPADFLAGS ;load X with address of flags
INITnWAIT1 LDAA #INITPAUSETIME ;setup to pause for about 1/4 second
JSR DELAY10X ;pause for x/10th second
INC RANDVAL ;set random value to next digit
JSR KEYSCAN ;check status of keypad
BRCLR 0,Y KEYPADFLAGPRE INITnWAIT1
;wait until a key is pressed
LDAB KEYPADKEYCHK ;retrieve the key being pressed
JSR DISPLAYKEY ;display this key to user while it's being pressed
INITnWAIT2 JSR KEYSCAN ;check status of keypad
BRSET 0,Y KEYPADFLAGPRE INITnWAIT2
;wait until key is released
CLR INITPORTB ;blank out the LEDs
PULY ;restore the X reg state
PULA ;restore the A reg state
PULB ;restore the B reg state
RTS ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Increment Sequence *
* *
* PURPOSE: generate the next value in the sequence *
* *
* USE: Call the function *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
INCSEQVALMASK EQU %00000011 ;mask to retrieve bits used in random value
****************** CODE START ****************
INCSEQ PSHX ;save the X reg state
PSHB ;save the B reg state
PSHA ;save the A reg state
LDX #SEQUENCE ;retrieve memory position of SEQUENCE
LDAB SEQLENGTH ;retrieve lench of SEQUENCE
ABX ;move X to end of sequence
LDAA RANDVAL ;retrieve the current random value
ANDA #INCSEQVALMASK ;keep only those values in mask
INCA ;add 1 to value for use as index
STAA 0,X ;store new value at end of SEQUENCE
INC SEQLENGTH ;increase length of sequence by 1
PULA ;restore the A reg state
PULB ;restore the B reg state
PULX ;restore the X reg state
RTS ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Accept Sequence *
* *
* PURPOSE: Accpept button presses from user and check them against the SEQUENCE. *
* If a wrong key is pressed or if more than three seconds elapses in *
* waiting for a button, then MIMIC will abort with an error. If all *
* keys are pressed correctly, then MIMIC returns with no ERROR. *
* *
* USE: Call the function *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
MIMICFLAGERR EQU %00000001 ;flag for user error detected
MIMICFLAGB EQU %00000010 ;flag for ?
MIMICFLAGC EQU %00000100 ;flag for ?
MIMICFLAGD EQU %00001000 ;flag for ?
MIMICFLAGE EQU %00010000 ;flag for ?
MIMICFLAGF EQU %00100000 ;flag for ?
MIMICFLAGG EQU %01000000 ;flag for ?
MIMICFLAGH EQU %10000000 ;flag for ?
MIMICPAUSETIM EQU 2
MIMICBCNTRVAL EQU 15
MIMICPORTB EQU $1004
****************** CODE **********************
MIMICFLAGS RMB 1 ;status flags for MIMIC
;0 = Error,
;1 = ?, 2 = ?, 3 = ?, 4 = ?, 5 = ?, 6 = ?, 7 = ?
MIMICBCNTR RMB 1 ;BCounter value
MIMICSCNTR RMB 1 ;SEQLENGTH value
****************** CODE INITIALIZATION *******
MIMICINIT
CLR MIMICFLAGS ;clear all flags
RTS ;return to sender *weg*
****************** CODE START ****************
MIMIC PSHB ;save the B reg state
PSHA ;save the A reg state
PSHY ;save the X reg state
PSHX ;save the X reg state
LDY #MIMICFLAGS ;retrieve location of flags
BSET 0,Y MIMICFLAGERR ;set the error flag
LDY #KEYPADFLAGS ;load Y with address of flags
LDX #SEQUENCE ;retrieve memory position of SEQUENCE
LDAA SEQLENGTH ;retrieve the SEQLENGTH
STAA MIMICSCNTR ;init the total sequence length count
MIMICNEXTBUT LDAA #MIMICBCNTRVAL ;retrive BCOUNTER value
STAA MIMICBCNTR ;initialize BCOUNTER value
MIMICWAITBUT INC RANDVAL ;set random value to next digit
LDAA #MIMICPAUSETIM ;setup pause count
JSR DELAY10X ;pause for x/10th second
DEC MIMICBCNTR ;count down pause timer
BEQ MIMICEND ;if out of time, then end
JSR KEYSCAN ;check status of keypad
BRCLR 0,Y KEYPADFLAGPRE MIMICWAITBUT
;wait for button pressed status
LDAA 0,X ;retrieve value pointed to by stack
CMPA KEYPADKEYCHK ;check for match with value from KEYSCAN
BNE MIMICEND ;wrong button pressed
LDAB KEYPADKEYCHK ;retrieve the key being pressed
JSR DISPLAYKEY ;display this key to user while it's being pressed
MIMICWAITREL JSR KEYSCAN ;check status of keypad
BRSET 0,Y KEYPADFLAGPRE MIMICWAITREL
;wait for button released status
CLR MIMICPORTB ;blank out the LEDs
INX ;point at next value
DEC MIMICSCNTR ;count off another success
BNE MIMICNEXTBUT ;go wait for next button press if not done
LDY #MIMICFLAGS ;retrieve location of flags
BCLR 0,Y MIMICFLAGERR ;clear the error flag
MIMICEND
PULX ;restore the X reg state
PULY ;restore the X reg state
PULA ;restore the A reg state
PULB ;restore the B reg state
RTS ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Display Sequence *
* *
* PURPOSE: Display the required sequence to the user *
* *
* USE: Call the function *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
DISPLAYPORTB EQU $1004
DISPLAYPAUSE EQU 3
****************** CODE **********************
DISPLAYINDEX RMB 1
****************** CODE START ****************
DISPLAY PSHB ;save the B reg state
PSHA ;save the A reg state
PSHX ;save the X reg state
LDAA SEQLENGTH ;retrieve current length
STAA DISPLAYINDEX ;init index to length
LDAA #DISPLAYPAUSE ;init time to pause for each cycle
LDX #SEQUENCE ;point at the next value to display
DISPLAYNEXT CLR DISPLAYPORTB ;clear the LEDs
JSR DELAY10X ;pause for DISPLAYPAUSE/10th sec
LDAB 0,X ;retrieve the next value in SEQUENCE
JSR DISPLAYKEY ;display the next value in SEQUENCE
JSR DELAY10X ;pause for DISPLAYPAUSE/10th sec
INX ;point at the next value to display
DEC DISPLAYINDEX ;completed another loop
BNE DISPLAYNEXT ;show next value if not done
CLR DISPLAYPORTB ;clear the LEDs
PULX ;restore the X reg state
PULA ;restore the A reg state
PULB ;restore the B reg state
RTS ;return to sender *weg*
* INITnWAIT END *******************************************************************
***********************************************************************************
* Check Next Key *
* *
* PURPOSE: Retrieve the next key being pressed, returning indicators via flags *
* to determine if a key has been pressed, is being pressed, or was just *
* pressed. *
* *
* USE: Call function and examine flags to determine keypad status. *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
KEYPADLAST EQU 3333 ;Holds the last key value pressed
KEYPADPRTG EQU $6200 ;keypad memory address
KEYPADPRTGMSK EQU $6202 ;keypad mask memory address
KEYPADPRTGINI EQU %00001111 ;mask for DDRG
KEYPADCNTROWS EQU 4 ;number of rows of buttons to initialize to
KEYPADCNTCOLS EQU 4 ;number of columns of buttons to initialize to
KEYPADCNTBUTS EQU 16 ;total number of buttons to initialize too
KEYPADSCANPAT EQU %11110111 ;starting scan pattern for keypad
KEYPADFLAGDET EQU %00000001 ;flag for no current activity detected
KEYPADFLAGPRE EQU %00000010 ;flag for key is currenty being pressed by user
KEYPADFLAGPRO EQU %00000100 ;flag for key has been released and is ready to be processed
KEYPADFLAGD EQU %00001000 ;flag for ?
KEYPADFLAGE EQU %00010000 ;flag for ?
KEYPADFLAGF EQU %00100000 ;flag for ?
KEYPADFLAGG EQU %01000000 ;flag for ?
KEYPADFLAGH EQU %10000000 ;flag for ?
********************* CODE *******************
KEYPADFLAGS RMB 1 ;set of byte flags for use by Get Next Key function (0 = false, 1 = true)
;bit 0: No current activity detected
;bit 1: Key is currently being pressed
;bit 2: Key is ready to be processed
;bit 3:
;bit 4:
;bit 5:
;bit 6:
;bit 7:
KEYPADSMASK RMB 1 ;scan pattern for keypad
KEYPADCURRENT RMB 1 ;
KEYPADKEYCHK RMB 1 ;
KEYPADROWNUM RMB 1 ;
KEYPADCOLNUM RMB 1 ;
****************** CODE INITIALIZATION *******
KEYSCANINIT PSHA ;save the A reg state
LDAA #KEYPADPRTGINI ;retrieve the DDRG mask and ...
STAA KEYPADPRTGMSK ;... initialize the DDRG mask
CLR KEYPADFLAGS ;clear the flags register
PULA ;restore the A reg state
RTS ;return to sender *weg*
****************** CODE START ****************
KEYSCAN PSHX ;save the X reg state
PSHB ;save the B reg state
PSHA ;save the A reg state
LDAA #KEYPADCNTROWS ;retrieve the row count and ...
STAA KEYPADROWNUM ;... initialize the number of rows
LDAA #KEYPADCNTBUTS ;retrive the button count and ...
STAA KEYPADCURRENT ;... initialize the current button position
LDAA #KEYPADSCANPAT ;retrieve the starting scan pattern ...
STAA KEYPADSMASK ;... initialize the current mask
;why isn't this working????
;BCLR KEYPADFLAGS,KEYPADFLAGPRE ;clear the "key is being pressed" flag
LDAB #KEYPADFLAGPRE ;retrieve the "key is being pressed" flag
COMB ;reverse the flag to create a mask
ANDB KEYPADFLAGS ;clear the "key is being pressed" flag if it was set
STAB KEYPADFLAGS ;store the resulting flag set
KEYPADOUTTER LDAA KEYPADSMASK ;Retrieve the current mask and ...
STAA KEYPADPRTG ;... set the keypad mask to this value
LDAA KEYPADPRTG ;retrieve the current row from the keypad (leave in A reg)
*Start Process Row
LDAB #KEYPADCNTCOLS ;retrieve the coloumn count and ...
STAB KEYPADCOLNUM ;... initialize the number of columns
KEYPADINNER LSLA ;rotate the PortG values to find if next bit is set
BCS KEYPADSKIPKEYCAPTURE ;if carry isn't set then don't capture the key
LDAB KEYPADCURRENT ;retrieve the current key value
STAB KEYPADKEYCHK ;store the current key value
LDAB KEYPADFLAGS ;retrieve the set of flags
ORAB #KEYPADFLAGPRE ;set the "key is being pressed" flag
ORAB #KEYPADFLAGPRO ;set the "ready to process" flag
STAB KEYPADFLAGS ;store the resulting flag set
KEYPADSKIPKEYCAPTURE ;target for jumping over the key kapture
DEC KEYPADCURRENT ;decrement current key value
DEC KEYPADCOLNUM ;decrement column number
BNE KEYPADINNER ;check next column
*End Process Row
LSR KEYPADSMASK ;rotate the mask to set the next entry point
DEC KEYPADROWNUM ;decrement row number
BNE KEYPADOUTTER ;check next row
PULA ;restore the A reg state
PULB ;restore the B reg state
PULX ;restore the X reg state
RTS ;return to sender *weg*
* KEYPADLAST END ******************************************************************
***********************************************************************************
* User Error *
* *
* PURPOSE: Indicates to the user that an error has occured *
* *
* USE: Call the function *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
ERRFLASHES EQU 4 ;20000 c / (3c + 3c) -- pause 1/100th sec
ERRSHOWTIME EQU 2
ERRPORTB EQU $1004
****************** CODE START ****************
ERRORDISPLAY PSHB ;save the B reg state
PSHA ;save the A reg state
CLR ERRPORTB ;clear out the LED lights display
LDAA #ERRSHOWTIME ;load the time (in x/100ths) to pause
LDAB #ERRFLASHES ;load port B with number of flashes to execute
DISPLAYERRLP JSR DELAY10X ;pause for x/10th second
COM ERRPORTB ;turn on all port be lights
JSR DELAY10X ;pause for x/10th second
COM ERRPORTB ;turn off all port be lights
DECB ;count off a completed loop
BNE DISPLAYERRLP ;show next flash if not done
PULA ;restore the A reg state
PULB ;restore the A reg state
RTS ;return to sender *weg*
* Password Rejected END ***********************************************************
***********************************************************************************
* Display LED Value At Pos *
* *
* PURPOSE: Display a specific value in LED *
* *
* USE: Reg B = what position value to display (0-4) *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
DISPLAYKEYPB EQU $1004
********************* CODE *******************
DISPLAYKEYTABLE ;values of display mask
FCB %00000000 ;dummey value
FCB %10000000 ;1 (leftmost)
FCB %01000000 ;2 (second from left)
FCB %00100000 ;3 (second from right)
FCB %00010000 ;4 (rightmost)
****************** CODE START ****************
DISPLAYKEY PSHX ;save the X reg state
PSHB ;save the B reg state
CLR DISPLAYKEYPB ;clear the display in port B
TSTB ;make sure position is not set to 0
BEQ DISPLAYKEYEND ;jump to end if it is
LDX #DISPLAYKEYTABLE
ABX
LDAB 0, X ;retrieve the display mask of current digit
STAB DISPLAYKEYPB ;store the digit mask to display into port B
DISPLAYKEYEND PULB ;restore the B reg state
PULX ;restore the X reg state
RTS ;return to sender *weg*
* Display LED Value At Pos END ****************************************************
***********************************************************************************
* PAUSE BY X/100th SECOND *
* *
* PURPOSE: Pauses program execution for X/10th seconds. X is indicated by the *
* value in the A register *
* *
* USE: Load the A register with the number of 1/10th seconds to pause *
* *
* MODIFIES: Flags *
* *
***********************************************************************************
********************* DATA *******************
PAUSE100thVAL EQU 3333 ;20000 c / (3c + 3c) -- pause 1/100th sec
PAUSE10thVAL EQU 10 ;bring pause time incrments up to a 10th
****************** CODE START ****************
DELAY10X PSHX ;save the X reg state
PSHB ;save the B reg state
PSHA ;save the A reg state
PAUSE10th LDAB #PAUSE10thVAL ;set B reg to count of 10
PAUSE100th LDX #PAUSE100thVAL ;load X with 1/100th worth of counter
PAUSEINNER DEX ;count down one in pause loop
BNE PAUSEINNER ;continue loop if not done with 1/100th pause
DECB ;count down another 1/100 sec
BNE PAUSE100th ;continue loop if not done with 1/10th pause
DECA ;decrement user specified pause count
BNE PAUSE10th ;continue loop if not done with this pause
PULA ;restore the A reg state
PULB ;restore the B reg state
PULX ;restore the X reg state
RTS ;return to sender *weg*
* PAUSE END ***********************************************************************
ENDOFCODE