;Programmable Lights ;Author: Kirill Yelizarov LIST P=PIC12C509, R=DEC INCLUDE__CONFIG _IntRC_OSC & _WDT_OFF & _CP_OFF & _MCLRE_OFF ; ------------ D A T A ------------ MPC equ 0x07 ;Macro program counter KeyFlags equ 0x08 ;Keyboard flags Keys equ 0x09 ;Keyboard keys Command equ 0x0a ;Current command Value equ 0x0b ;Local data Program equ 0x0c ;Current program number TimeDelay equ 0x0d ;Time delay changed with Inc or Dec buttons TimeCount equ 0x0e ;Current time count RepeatCount equ 0x0f ;Counter for a loop ;----- KeyBoard bits ----- ResetKey equ 1 ;Switch to program #1 TestKey equ 4 ;Switch to program #0 (called Test, all lamps are turned on) LineIn equ 3 ;Line in for all buttons DecKey equ 5 ;Decrease delay between lights flow IncKey equ 0 ;Increase delay between lights flow ProgKey equ 2 ;Switch to next program ; ---------- Lights macro language ------------- #define Light retlw 0x00+ ;Set new light #define MarkLabel retlw 0x20+ ;Mark a label #(1...31) #define ReturnToLabel retlw 0x40+ ;Return to label #(1...31) #define SetRepeatValue retlw 0x80+ ;Set repeat value (1...31) #define JumpToProgram retlw 0xa0+ ;Jump to program #(1...31) #define StartOfProgram retlw 0xc0+ ;Start of program #(1...31) #define RestartProgram retlw 0xe0+ ;Return to start of program #(1...31) Mark equ 0x20 ReturnTo equ 0x40 RepeatValue equ 0x80 JumpTo equ 0xa0 StartOf equ 0xc0 Restart equ 0xe0 Button equ 0x00 Line equ 0x01 MAX_PROGRAM equ 12 Test equ 0 ;Test program ; ------------ M A C R O ---------- ;This macro is used to search pressed button ;total button de bounce test is 2*16 ms = 32 ms with one extra test on the 16th ms TestButton macro source,line,butt,key,flag,out local reset local test ;source - type of signal (Button - synchronized by the lights, Line - not syncronized) ;line - input test GPIO pin ;butt - button output GPIO pin ;key - depression memory location ;flag - key flag memory location ;out - label to return from macro bcf GPIO,butt ;drive butt pin low nop ;wait btfsc GPIO,line ;look what happens on line pin goto reset ;if high go and reset all for this button bsf GPIO,butt ;drive butt pin high IF source==Button ;extra test for syncronized buttons nop ;wait btfss GPIO,line ;test pin for high value goto reset ;if pin is still low then it's a line in signal ENDIF IF source==Line nop ;wait btfsc GPIO,line ;test line in if signal is still low goto reset ;else a polling signal was read ENDIF btfsc key,butt ;test key depression for butt pin goto test ;yes there was a depression on last test, go to test bsf key,butt ;no then set key depression flag goto out ;and wait for the next test reset: bsf GPIO,butt ;drive butt pin high bcf key,butt ;clear depression key bcf flag,butt ;clear key flag goto out ;test next test: btfsc flag,butt ;test key flag goto out ;if set then test next (to prevent multiple run of the ; same function while the button is pressed) bsf flag,butt ;set key flag ;function code will be merged here endm ; ------------ C O D E ------------ org 0x00 goto Start ;Skip subroutine and table ;This multifunction subroutine can fetch next, or previous, or current command from the table DecPC ;Get previous command decf MPC,F movlw low Table xorwf MPC,W btfss STATUS,Z goto ReadPC movlw low (Start-1) movwf MPC goto ReadPC IncPC ;Get next command incf MPC,F movlw low Start xorwf MPC,W btfss STATUS,Z goto ReadPC movlw low (Table+1) movwf MPC ReadPC ;Read current command movf MPC,W call Table movwf Value retlw 0 ; ------------------- P R O G R A M --------------------- Table ;Start of program table movwf PCL ;*********************************************** ;* Christmas Lights * ;* 1997 * ;* Author: Kirill Yelizarov * ;*********************************************** StartOfProgram Test Light b'11111' RestartProgram Test StartOfProgram 1 Light b'11111' Light b'11111' Light b'11111' Light b'01111' Light b'01111' Light b'01111' Light b'00111' Light b'00111' Light b'00111' Light b'00011' Light b'00011' Light b'00011' Light b'00001' Light b'00001' Light b'00001' SetRepeatValue 10 MarkLabel 1 StartOfProgram 2 Light b'10000' Light b'01000' Light b'00100' Light b'00010' Light b'00001' RestartProgram 2 ReturnToLabel 1 SetRepeatValue 10 MarkLabel 2 StartOfProgram 3 Light b'10001' Light b'11000' Light b'01100' Light b'00110' Light b'00011' RestartProgram 3 ReturnToLabel 2 SetRepeatValue 10 MarkLabel 3 StartOfProgram 4 Light b'10011' Light b'11001' Light b'11100' Light b'01110' Light b'00111' RestartProgram 4 ReturnToLabel 3 SetRepeatValue 10 MarkLabel 4 StartOfProgram 5 Light b'10111' Light b'11011' Light b'11101' Light b'11110' Light b'01111' RestartProgram 5 ReturnToLabel 4 SetRepeatValue 10 MarkLabel 5 Light b'00111' Light b'10011' Light b'11001' Light b'11100' Light b'01110' ReturnToLabel 5 SetRepeatValue 10 MarkLabel 6 Light b'00110' Light b'00011' Light b'10001' Light b'11000' Light b'01100' ReturnToLabel 6 SetRepeatValue 10 MarkLabel 7 Light b'00100' Light b'00010' Light b'00001' Light b'10000' Light b'01000' ReturnToLabel 7 Light b'00100' Light b'00010' Light b'00001' StartOfProgram 6 Light b'10000' Light b'10000' Light b'10000' Light b'11000' Light b'11000' Light b'11000' Light b'11100' Light b'11100' Light b'11100' Light b'11110' Light b'11110' Light b'11110' Light b'11111' Light b'11111' Light b'11111' Light b'11110' Light b'11110' Light b'11110' Light b'11100' Light b'11100' Light b'11100' Light b'11000' Light b'11000' Light b'11000' Light b'10000' Light b'10000' Light b'10000' RestartProgram 6 SetRepeatValue 10 MarkLabel 8 StartOfProgram 7 Light b'00001' Light b'00010' Light b'00100' Light b'01000' Light b'10000' RestartProgram 7 ReturnToLabel 8 SetRepeatValue 10 MarkLabel 9 StartOfProgram 8 Light b'10001' Light b'00011' Light b'00110' Light b'01100' Light b'11000' RestartProgram 8 ReturnToLabel 9 SetRepeatValue 10 MarkLabel 10 StartOfProgram 9 Light b'11001' Light b'10011' Light b'00111' Light b'01110' Light b'11100' RestartProgram 9 ReturnToLabel 10 SetRepeatValue 10 MarkLabel 11 StartOfProgram 10 Light b'11101' Light b'11011' Light b'10111' Light b'01111' Light b'11110' RestartProgram 10 ReturnToLabel 11 SetRepeatValue 10 MarkLabel 12 Light b'11100' Light b'11001' Light b'10011' Light b'00111' Light b'01110' ReturnToLabel 12 SetRepeatValue 10 MarkLabel 13 Light b'01100' Light b'11000' Light b'10001' Light b'00011' Light b'00110' ReturnToLabel 13 SetRepeatValue 10 MarkLabel 14 Light b'00100' Light b'01000' Light b'10000' Light b'00001' Light b'00010' ReturnToLabel 14 Light b'00100' Light b'01000' Light b'10000' StartOfProgram 11 Light b'00001' Light b'00001' Light b'00001' Light b'00011' Light b'00011' Light b'00011' Light b'00111' Light b'00111' Light b'00111' Light b'01111' Light b'01111' Light b'01111' RestartProgram 1 Light b'11111' Light b'11111' Light b'11111' Light b'01111' Light b'01111' Light b'01111' Light b'00111' Light b'00111' Light b'00111' Light b'00011' Light b'00011' Light b'00011' Light b'00001' Light b'00001' Light b'00001' RestartProgram 11 StartOfProgram 12 Light b'10001' Light b'00000' Light b'01010' Light b'00000' Light b'00100' Light b'00000' Light b'01010' Light b'00000' RestartProgram 12 ; ------------ M A I N ------------- Start: IF Start>0x100 ERROR "Lights Message: Program Table too large." ENDIF clrf Keys ;Reset key depression clrf KeyFlags ;Reset keyboard flags clrf TMR0 ;clear TMR0 movlw b'10000101' ;Enable weak pull-up on GP3 and set prescaler to 1:64 ; movlw b'10000000' ;*****For MPLAB debug option clrf GPIO comf GPIO,F ;Turn OFF the lights movlw b'00001000' ;Set GP3 (LineIn) as input and the rest are outputs tris GPIO movlw low (Start-1) ;Set program counter to the end of Table movwf MPC movlw 0x10 ; movlw 0x01 ;*****For MPLAB debug movwf TimeCount ;Each time TMR0 overflows this value will decrement movwf TimeDelay ;Set time dalay between two Light commands to 16*16 ms = 256 ms ;may be changed with Inc and Dec keys movlw 0x01 movwf Program ;Set program #1 SetProgram: call IncPC ;Get next command movf Value,W andlw b'11100000' xorlw StartOf ;If it's a StartOfProgram then continue btfss STATUS,Z ;else go and get another command goto SetProgram movf Value,W andlw b'00011111' xorwf Program,W ;Be shure the right program found btfss STATUS,Z ;else go and get another command goto SetProgram MainLoop: call IncPC ;Get next command movf Value,W andlw b'11100000' ;Test Light Command btfsc STATUS,Z goto SetLights movwf Command ;Save Command xorlw ReturnTo ;Test ReturnToLabel command btfss STATUS,Z goto TestRestartProgram ;else analyze next command movf Value,W andlw b'00011111' movwf Command ;Save label in Command because it's contents are no longer needed decfsz RepeatCount,F ;decrease loop counter set by goto FindLabel goto MainLoop FindLabel: call DecPC ;Search backward for a desired label movf Value,W andlw b'1110000' xorlw Mark btfss STATUS,Z goto FindLabel movlw b'00011111' andwf Value,W xorwf Command,W btfss STATUS,Z goto FindLabel goto MainLoop TestRestartProgram: ;Look if it's a RestartProgram command movf Command,W xorlw Restart btfss STATUS,Z goto TestRepeatValue movlw b'00011111' andwf Value,W xorwf Program,W btfss STATUS,Z goto MainLoop goto SetProgram TestRepeatValue: movf Command,W xorlw RepeatValue btfss STATUS,Z goto TestJumpTo movlw b'00011111' andwf Value,W movwf RepeatCount goto MainLoop TestJumpTo: movf Command,W xorlw JumpTo btfss STATUS,Z goto MainLoop movlw b'00011111' andwf Value,W movwf Program goto SetProgram SetLights: movlw b'00110111' btfsc Value,4 bsf Value,5 bcf Value,4 btfsc Value,3 bsf Value,4 andwf Value,F ;cut everything but the lights Wait1: btfss TMR0,7 ;wait till seventh bit rise, ***** comment it when in MPLAB debug goto Wait1 ;***** Comment it when in MPLAB debug movlw b'11111111' movwf GPIO TestButton Button,LineIn,ProgKey,Keys,KeyFlags,TestInc NextProgram: incf Program,F movlw MAX_PROGRAM+1 xorwf Program,W btfss STATUS,Z goto SetProgram movlw 0x01 movwf Program goto SetProgram TestInc: TestButton Button,LineIn,IncKey,Keys,KeyFlags,TestDec movlw 0x01 movwf TimeCount ;Set TimeCount to one to make delay change fast incfsz TimeDelay,F goto TestDec movlw 0xff movwf TimeDelay TestDec: TestButton Button,LineIn,DecKey,Keys,KeyFlags,TestLine movlw 0x01 movwf TimeCount ;Set TimeCount to one to make delay change fast decfsz TimeDelay,F goto TestLine movlw 0x01 movwf TimeDelay TestLine: TestButton Line,LineIn,LineIn,Keys,KeyFlags,TestTest goto NextProgram TestTest: TestButton Button,LineIn,TestKey,Keys,KeyFlags,TestReset clrf Program goto SetProgram TestReset: TestButton Button,LineIn,ResetKey,Keys,KeyFlags,RestoreLights goto Start RestoreLights: movf Value,W movwf GPIO ;output Lights to GPIO Wait0: btfsc TMR0,7 ;wait till the seventh bit reset, *****Comment it when in MPLAB debug goto Wait0 ;*****Comment it when in MPLAB debug decfsz TimeCount,F goto Wait1 ;if zero not reached then make another key check movf TimeDelay,W ;reset TimeCount with TimeDelay value movwf TimeCount goto MainLoop org 0x3ff movlw b'01110000' ;set OSCCAL end