;------------------------------------------------------------------------------- ; FILE: LEDsnake ; AUTH: Ed's Projects ; DATE: 01/09/2016 ; DESC: 5x7 LED Dot Matrix Snake Game ;------------------------------------------------------------------------------- LIST P=16F690, R=DEC ; All numbers Decimal format unless otherwise stated. include ; Define configurations, registers, etc. __config _FCMEN_OFF & _IESO_OFF & _BOREN_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _INTRC_OSC_NOCLKOUT ;------------------------------------------------------------------------------- ;----------------------------- Port Definitions ------------------------------ ;------------------------------------------------------------------------------- ; PortA - Output - RA0 - Pin 19 - Row 1 ; PortA - Output - RA1 - Pin 18 - Row 2 ; PortA - Output - RA2 - Pin 17 - Row 3 ; PortC - Output - RC0 - Pin 16 - Row 4 ; PortB - Output - RB7 - Pin 10 - Row 5 ; PortC - Output - RC7 - Pin 9 - Row 6 ; PortC - Output - RC6 - Pin 8 - Row 7 ; PortC - Output - RC1 - Pin 15 - Column 1 ; PortC - Output - RC2 - Pin 14 - Column 2 ; PortB - Output - RB4 - Pin 13 - Column 3 ; PortB - Output - RB5 - Pin 12 - Column 4 ; PortB - Output - RB6 - Pin 11 - Column 5 ; PortA - Input - RA3 - Pin 4 - Button Up ; PortC - Input - RC5 - Pin 5 - Button Down ; PortC - Input - RC4 - Pin 6 - Button Left ; PortC - Input - RC3 - Pin 7 - Button Right ; PortA - Output - RA4 - Pin 3 - Provides pull-up voltage for button resistors ;------------------------------------------------------------------------------- ;-------------------------------- Variables ---------------------------------- ;------------------------------------------------------------------------------- cblock h'20' temp temp2 temp3 temp4 temp5 C1 ; Column 1 Matrix Display C2 C3 C4 C5 ; Column 5 Matrix Display S1 ; Snake Position Column 1 S2 ; Snake Position Column 2 S3 ; Snake Position Column 3 S4 ; Snake Position Column 4 S5 ; Snake Position Column 5 Posind ; Column Indicator, bit4 - 0 Posdir ; Snake Direction 0-up, 1-down, 2-left, 3-right w_save status_save pclath_save snake ; Snake length colind ; Collision Indicator apptmr ; Apple timer T1H ; Timer1 High endc ;------------------------------------------------------------------------------- ;----------------------------- Define Symbols -------------------------------- ;------------------------------------------------------------------------------- #define ROW1 PORTA, 0 #define ROW2 PORTA, 1 #define ROW3 PORTA, 2 #define ROW4 PORTC, 0 #define ROW5 PORTB, 7 #define ROW6 PORTC, 7 #define ROW7 PORTC, 6 #define COL1 PORTC, 1 #define COL2 PORTC, 2 #define COL3 PORTB, 4 #define COL4 PORTB, 5 #define COL5 PORTB, 6 #define UP PORTA, 3 #define DOWN PORTC, 5 #define LEFT PORTC, 4 #define RIGHT PORTC, 3 ;------------------------------------------------------------------------------- ;------------------------------- Program Code -------------------------------- ;------------------------------------------------------------------------------- ORG 0 goto Init ;------------------------------------------------------------------------------- ;----------------------------- Interrupt Vector ------------------------------ ;------------------------------------------------------------------------------- ORG 04 goto Interrupt ;------------------------------------------------------------------------------- ;-------------------------- Initialisation of Ports -------------------------- ;------------------------------------------------------------------------------- Init bsf STATUS,RP0 bcf STATUS,RP1 ; Bank 1 Selected movlw b'00001000' movwf TRISA movlw b'00000000' movwf TRISB movlw b'00111000' movwf TRISC bcf STATUS,RP0 bsf STATUS,RP1 ; Bank 2 Selected clrf VRCON ; Set Vref to off clrf CM1CON0 ; Turn off comparator 1 clrf CM2CON0 ; Turn off comparator 2 clrf ANSEL ; Set analogue inputs to digital clrf ANSELH ; Set analogue inputs to digital bsf STATUS,RP0 ; Bank 3 Selected clrf SRCON ; Disable SR latch bcf STATUS,RP0 bcf STATUS,RP1 ; Bank 0 Selected clrf PORTA clrf PORTB clrf PORTC clrf Posdir clrf S1 clrf S2 clrf S3 clrf S4 clrf S5 clrf colind clrf apptmr movlw d'3' movwf snake ; Start with 3 snake segments movlw d'160' movwf FSR clrram clrf INDF incf FSR, f movf FSR, w xorlw d'220' btfss STATUS, Z goto clrram ;------------------------------------------------------------------------------- ;----------------------- Interrupt Timer Initialisation ---------------------- ;------------------------------------------------------------------------------- movlw b'00110100' ; Internal clock, prescaler 8 movwf T1CON movlw b'00001011' movwf T1H movlw b'11011011' movwf TMR1L ; Half a second bsf INTCON, PEIE ; Peripheral interrupts on bsf STATUS, RP0 ; Bank 1 Selected bsf PIE1, TMR1IE ; Enable Timer 1 Interrupt bcf STATUS, RP0 ; Bank 0 Selected bsf INTCON, GIE ; Enable Interrupt Function ;------------------------------------------------------------------------------- ;-------------------------------- Initialisaton ------------------------------ ;------------------------------------------------------------------------------- bsf PORTA, 4 ; Provides pull-up voltage for button resistors movlw d'2' call delay1 ; Wait 0.5 second movlw b'00000000' movwf C1 movlw b'00000000' movwf C2 movlw b'00001000' movwf C3 movwf S3 movlw b'00000000' movwf C4 movlw b'00000000' movwf C5 movlw b'00000100' movwf Posind here call Button movf Posdir, w addlw d'0' btfsc STATUS, Z ; Start snake moving when button pressed goto here bsf T1CON, TMR1ON ; Start timer counting goto Start ;------------------------------------------------------------------------------- ;-------------------------------- Delay Loops -------------------------------- ;------------------------------------------------------------------------------- delay1 movwf temp4 loopy2 movlw d'100' ;multiples of 2.5ms movwf temp3 loopy movlw d'250' movwf temp initloop goto $+1 ;2us goto $+1 ;2us goto $+1 ;2us nop ;1us decfsz temp, f ;1us goto initloop ;2us decfsz temp3, f goto loopy ;250ms total decfsz temp4, f goto loopy2 ;Multiples of 250ms return msdelay movlw d'100' movwf temp loop goto $+1 ;2us goto $+1 ;2us goto $+1 ;2us nop ;1us decfsz temp, f ;1us goto loop ;2us return ;------------------------------------------------------------------------------- ;-------------------------------- Main Program ------------------------------- ;------------------------------------------------------------------------------- Start call Disp btfss colind, 0 goto Start ; Game over! bcf T1CON, TMR1ON ; Stop timer counting movlw d'8' movwf temp5 gameover movlw d'100' movwf temp4 call Disp decfsz temp4, f goto $-2 movlw d'1' call delay1 ; Wait 250ms delay decfsz temp5, f goto gameover goto Init ; Start Again ;------------------------------------------------------------------------------- ;-------------------------------- Display Cycle ------------------------------ ;------------------------------------------------------------------------------- Disp movf C1, w call PRTLD bsf COL1 call msdelay bcf COL1 call Button movf C2, w call PRTLD bsf COL2 call msdelay bcf COL2 call Button movf C3, w call PRTLD bsf COL3 call msdelay bcf COL3 call Button movf C4, w call PRTLD bsf COL4 call msdelay bcf COL4 call Button movf C5, w call PRTLD bsf COL5 call msdelay bcf COL5 call Button return PRTLD movwf temp bsf ROW1 bsf ROW2 bsf ROW3 bsf ROW4 bsf ROW5 bsf ROW6 bsf ROW7 btfsc temp, 0 bcf ROW1 btfsc temp, 1 bcf ROW2 btfsc temp, 2 bcf ROW3 btfsc temp, 3 bcf ROW4 btfsc temp, 4 bcf ROW5 btfsc temp, 5 bcf ROW6 btfsc temp, 6 bcf ROW7 return ;------------------------------------------------------------------------------- ;-------------------------------- Button Input ------------------------------- ;------------------------------------------------------------------------------- Button btfss UP goto dirup btfss DOWN goto dirdw btfss LEFT goto dirlf btfss RIGHT goto dirrt return dirup btfsc Posdir, 1 ; Make sure we can't go back on ourself goto dirdw movlw b'00000001' movwf Posdir return dirdw btfsc Posdir, 0 goto dirup movlw b'00000010' movwf Posdir return dirlf btfsc Posdir, 3 goto dirrt movlw b'00000100' movwf Posdir return dirrt btfsc Posdir, 2 goto dirlf movlw b'00001000' movwf Posdir return ;------------------------------------------------------------------------------- ;----------------------------- Interrupt Program ----------------------------- ;------------------------------------------------------------------------------- Interrupt bcf PIR1, TMR1IF movwf w_save movf STATUS, w clrf STATUS movwf status_save movf PCLATH, w movwf pclath_save bcf T1CON, TMR1ON ; Stop timer counting movf T1H, w movwf TMR1H movlw b'11011011' movwf TMR1L ; Half a second bsf T1CON, TMR1ON ; Start timer counting btfsc apptmr, 7 ; Indicates apple not eaten goto skip incf apptmr, f movf apptmr, w xorlw d'10' btfsc STATUS, Z call Apple skip btfsc Posind, 4 ; Are we column 5? goto Col5 btfsc Posind, 3 ; Are we column 4? goto Col4 btfsc Posind, 2 ; Are we column 3? goto Col3 btfsc Posind, 1 ; Are we column 2? goto Col2 ; Then we must be column 1 Col1 movf S1, w call Checkdir call Placecont goto LoadDisp Col2 movf S2, w call Checkdir call Placecont goto LoadDisp Col3 movf S3, w call Checkdir call Placecont goto LoadDisp Col4 movf S4, w call Checkdir call Placecont goto LoadDisp Col5 movf S5, w call Checkdir call Placecont goto LoadDisp Placecont clrf S5 clrf S4 clrf S3 clrf S2 clrf S1 btfsc Posind, 4 ; Are we to place contents in column 5? goto Placa btfsc Posind, 3 ; Are we to place contents in column 4? goto Placb btfsc Posind, 2 ; Are we to place contents in column 3? goto Placc btfsc Posind, 1 ; Are we to place contents in column 2? goto Placd movwf S1 ; Then we must place them in column 1 movwf temp3 clrw call plcdot ; Place dot in counter return Placa movwf S5 movwf temp3 ; Save column offset movlw d'4' ; Tells next program what column we're in call plcdot ; Place dot in counter return Placb movwf S4 movwf temp3 ; Save column offset movlw d'3' ; Tells next program what column we're in call plcdot ; Place dot in counter return Placc movwf S3 movwf temp3 ; Save column offset movlw d'2' ; Tells next program what column we're in call plcdot ; Place dot in counter return Placd movwf S2 movwf temp3 ; Save column offset movlw d'1' ; Tells next program what column we're in call plcdot ; Place dot in counter return Checkdir btfsc Posdir, 0 ; Going up? goto DirectU btfsc Posdir, 1 ; Going down? goto DirectD btfsc Posdir, 2 ; Going left? goto DirectL goto DirectR ; Going right then DirectU movwf temp5 rrf temp5, f btfsc STATUS, C bsf temp5, 6 movf temp5, w return DirectD movwf temp5 rlf temp5, f btfsc temp5, 7 call DirectDa movf temp5, w return DirectDa clrf temp5 bsf temp5, 0 return DirectL movwf temp5 rrf Posind, f btfsc STATUS, C bsf Posind, 4 movf temp5, w return DirectR movwf temp5 rlf Posind, f btfsc Posind, 5 call DirectRa movf temp5, w return DirectRa clrf Posind bsf Posind, 0 return LoadDisp call Decdot movf S1, w iorwf C1, f movf S2, w iorwf C2, f movf S3, w iorwf C3, f movf S4, w iorwf C4, f movf S5, w iorwf C5, f movf pclath_save, w movwf PCLATH movf status_save, w movwf STATUS swapf w_save, f swapf w_save, w retfie ;------------------------------------------------------------------------------- ;---------------------------- Dot Counter Decrement -------------------------- ;------------------------------------------------------------------------------- Decdot movlw d'160' movwf temp2 clrf temp3 dotdecloop movf temp2, w movwf FSR movlw d'1' subwf INDF, f btfss STATUS, C clrf INDF movf INDF, w addlw d'0' btfsc STATUS, Z call delum ; Deluminate LED's if RAM empty incf temp3, f incf temp3, f incf temp2, f movf temp2, w xorlw d'195' btfss STATUS, Z goto dotdecloop movf temp4, w movwf FSR movlw d'0' addwf INDF, w btfss STATUS, Z call colapp movf snake, w movwf INDF return colapp btfsc INDF, 7 ; Bit 7 set indicates apple goto apcl bsf colind, 0 return apcl clrf apptmr incf snake, f return delum movlw LOW table ; Deluminate chosen LED addwf temp3, w movlw HIGH table btfsc STATUS, C addlw 1 movwf PCLATH movlw LOW table addwf temp3, w movwf PCL table bcf C1, 0 return bcf C2, 0 return bcf C3, 0 return bcf C4, 0 return bcf C5, 0 return bcf C1, 1 return bcf C2, 1 return bcf C3, 1 return bcf C4, 1 return bcf C5, 1 return bcf C1, 2 return bcf C2, 2 return bcf C3, 2 return bcf C4, 2 return bcf C5, 2 return bcf C1, 3 return bcf C2, 3 return bcf C3, 3 return bcf C4, 3 return bcf C5, 3 return bcf C1, 4 return bcf C2, 4 return bcf C3, 4 return bcf C4, 4 return bcf C5, 4 return bcf C1, 5 return bcf C2, 5 return bcf C3, 5 return bcf C4, 5 return bcf C5, 5 return bcf C1, 6 return bcf C2, 6 return bcf C3, 6 return bcf C4, 6 return bcf C5, 6 return ;------------------------------------------------------------------------------- ;---------------------------- Dot Counter Increment -------------------------- ;------------------------------------------------------------------------------- plcdot addlw d'160' btfsc temp3, 6 addlw d'30' btfsc temp3, 5 addlw d'25' btfsc temp3, 4 addlw d'20' btfsc temp3, 3 addlw d'15' btfsc temp3, 2 addlw d'10' btfsc temp3, 1 addlw d'5' movwf temp4 Ilum movlw d'127' movwf C1 movwf C2 movwf C3 movwf C4 movwf C5 return ;------------------------------------------------------------------------------- ;--------------------------- Random Apple Generator -------------------------- ;------------------------------------------------------------------------------- Apple movlw b'10000000' movwf apptmr ; States apple is present call Random ; Fetch a "sort of" random number addlw d'159' movwf FSR notclr incf FSR, f movf INDF, w addlw d'0' btfsc STATUS, Z goto addapple movf FSR, w addlw d'62' ; Make sure no more than 194 btfss STATUS, C goto notclr ; Location not clear, try again. movlw d'159' movwf FSR goto notclr ; Location not clear, try again. addapple movlw d'255' movwf INDF ; Seventh bit indicates apple to collision movlw d'7' ; program. addwf T1H, f ; Increase snake speed. return ;------------------------------------------------------------------------------- ;---------------------------- Random Number Routine -------------------------- ;------------------------------------------------------------------------------- Random movf snake, w movwf temp3 movlw LOW Rantbl addwf temp3, w movlw HIGH Rantbl btfsc STATUS, C addlw 1 movwf PCLATH movlw LOW Rantbl addwf temp3, w movwf PCL Rantbl retlw d'2' retlw d'7' retlw d'11' retlw d'3' retlw d'21' retlw d'6' retlw d'19' retlw d'34' retlw d'10' retlw d'8' retlw d'18' retlw d'26' retlw d'25' retlw d'33' retlw d'1' retlw d'9' retlw d'0' retlw d'32' retlw d'17' retlw d'4' retlw d'22' retlw d'5' retlw d'12' retlw d'16' retlw d'20' retlw d'30' retlw d'24' retlw d'31' retlw d'13' retlw d'27' retlw d'15' retlw d'23' retlw d'28' retlw d'14' retlw d'29' end