;********************* ; demo software for Triklits controller. ; for PIC16F684 running with internal 8mhz oscillator ; ; two pushbuttons ; first cycles between: modes/patterns ; second cycles through variations (brightness, color, speed) ; repeats if held in ; if first held in 1+ seconds, turns 'off' until any button pushed. ;********************* ; ; Copyright (C) 2006 by Network Wizards ; For use with Triklits control box. ; LIST P=PIC16F684 include "p16f684.inc" __CONFIG _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF & _BOD_ON & _MCLRE_OFF & _WDT_OFF & _CP_ON & _CPD_OFF & _PWRTE_ON ; PORT A ; pushbuttons, normally high, low on press #define BUTTON1 PORTA,5 #define BUTTON2 PORTA,0 ;A.1 pulled low (unused) ;A.2-4 N/C ; PORT C ;C.0 set externally at 2.5v ;C.1 network RX input NETCTL equ 2 ; direction of rs485 driver (0=RX,1=TX) ;C.3 N/C ;C.5 N/C ;RC4 is output to lights LEDOUT equ 4 ; output data line to light string LEDMSK equ H'10' ; mask for LEDOUT bit CMSK equ H'04' ; port C default output bits (NETCTL=1) lights equ D'24' ; total number of lights MC equ D'255' ; max color value ;values for white WVR equ D'72' WVG equ D'152' WVB equ D'160' ;general ram is from 20 to 7f (96 bytes) in bank 0 ;other space is from a0 to bf (32 bytes) in bank 1 cblock 0x20 rgbd:lights*3 ; rgb data (3 bytes each light) (24*3=72) rgbdend:0 ;data used by txframe routine rout gout bout bits slots pbit pattern ; current pattern number var ; pattern variation index endc ;random storage cblock 0x70 ;interrupt saving (must be in area 70-7f) IntW IntSTAT SFSR ; CT1 CTL ; rval gval bval ; index windex cindex tmp1 tmp2 tmp3 tmp4 ; flags endc ;flag bits #define FAST flags,0 #define FLASH flags,1 #define OFF flags,2 #define NEWP flags,3 cblock 0x0a0 ; bank 1 (32 bytes a0-bf) ;unused storage endc ;code section org 0 ; reset vector goto Start ;interrupt handler ; this handles the buttons being pressed, debouncing and repeating org 4 ; interrupt vector DoInt movwf IntW ; save W swapf STATUS,W clrf STATUS ; bank 0 movwf IntSTAT ; save STATUS btfsc PIR1,TMR1IF ; timer1 interrupt? goto t1int btfss INTCON,RAIF ; porta pin change interrupt? goto IntDone ;pin change on port A (button changed state) ; if button 1 was pressed, wait here for up to 1sec to see if released, ; if released, increment pattern counter and jump out to new pattern ; otherwise go to power down state ; if button 2 pressed ; increment variation count every 100msec until released ; by doing: inc var, enable t1 int every 100ms ; if t1 int: if button still down, inc var, else turn off t1 btfsc OFF ; were we off? goto bon ; yes, turn on btfsc BUTTON1 goto bint1 movlw D'50' ; 50 * 20ms = 1sec movwf tmp1 b1wait call Delay20 btfsc BUTTON1 goto b1short decfsz tmp1,1 goto b1wait ;button1 held in longer than 1sec, turn off lights call setoff bcf INTCON,RAIE call txframe movf PORTA,W ;read any mismatch bcf INTCON,RAIF bsf INTCON,RAIE bcf INTCON,GIE ;wait for both buttons to be released b1wait2 btfss BUTTON1 goto b1wait2 btfss BUTTON2 goto b1wait2 call Delay100 ;debounce delay ;turn everything off bsf OFF movf PORTA,W ;read any mismatch bcf INTCON,RAIF bsf INTCON,GIE goto poweroff ;now resume as if turned on (after buttons released) bon btfss BUTTON1 goto bon btfss BUTTON2 goto bon call Delay100 ;debounce delay bcf OFF movf PORTA,W ;read any mismatch bcf INTCON,RAIF bsf INTCON,GIE goto softpowerup ;button1 released in under 2sec b1short bsf NEWP incf pattern,1 movf pattern,W xorlw maxpats skpnz clrf pattern bcf INTCON,RAIF bsf INTCON,GIE goto newpattern ; exit interrupt directly! ;maybe button2? bint1 btfsc BUTTON2 goto bintx btfsc T1CON,TMR1ON ; already set? goto bintx ; ignore ;inc var, reset counter 1 and start it bsf NEWP incf var,1 ; next variation call Delay100 ; debounce clrf TMR1L clrf TMR1H bsf T1CON,TMR1ON ; start counting bintx movf PORTA,W ; clear mismatch bcf INTCON,RAIF goto IntDone ;timer1 interrupt (every 131 milliseconds) ; if button2 still down, inc var, else turn off timer t1int bcf PIR1,TMR1IF btfss BUTTON2 goto t1intb2 ;button released bcf T1CON,TMR1ON goto IntDone ;button still pressed t1intb2 bsf NEWP incf var,1 ; next variation ;exit interrupts IntDone swapf IntSTAT,W movwf STATUS ; restore STATUS swapf IntW,1 swapf IntW,W ; restore W retfie ;---------------------------------------------------------------------- Start ;set initial output port pin states clrf PORTA clrf PORTC ;configure ports movlw H'07' ; comparators off! movwf CMCON0 ;BEGIN PAGE 1 bsf STATUS,RP0 movlw B'00100011' movwf TRISA movlw B'00000011' movwf TRISC clrf ANSEL ; set digital mode on PORTA bsf WPUA,0 bsf WPUA,5 ;setup oscillator for 8mhz movlw B'01110001' ; 8mhz movwf OSCCON movlw B'00001000' ; prescaler off (for wdt) ; TMR0 counts instruction cycles ; INT on falling edge ; pullups on PORTA available movwf OPTION_REG ; set option register clrf PIE1 ; peripheral interrupt mask bcf STATUS,RP0 ; select register page 0 ;END PAGE 1 clrf INTCON ; disable all interrupts bsf INTCON,PEIE ; enable peripheral interrupts bsf INTCON,RAIE ; enable PORTA pin change interrupt clrf TMR1L clrf TMR1H ;8mhz/4 = 0.5us *65536*4 = 131msec movlw B'00100000' ; 1:4 prescale, osc/4, timer off movwf T1CON ; timer1 options bsf STATUS,RP0 bsf PIE1,TMR1IE ; enable timer1 interrupts movlw B'00100001' movwf IOCA ; set interrupt on change PORTA 0 and 5 bcf STATUS,RP0 movf PORTA,W ; clear any mismatch bcf INTCON,RAIF bcf PIR1,TMR1IF ; clear any timer1 interrupts bsf INTCON,GIE ; global interrupt enable ;power-up delay powerup clrf flags clrf pattern clrf var bcf PORTC,LEDOUT call Delay100 bsf PORTC,NETCTL ; set rs-485 transmitter on ; will output copies of frames to RJ11 jack ;init variables call setoff call txframe ;---------------------------------------------------------------------- ;here if resuming operation from software 'off' mode softpowerup ;make sure this fits on a single page of code!! (256 byte boundary) newpattern clrf PCLATH ; this table is on page 0!! movf pattern,W addwf PCL,1 goto test ; - goto colorsweep ; - goto strobe ; speed goto fixwhite ; dim(16) goto fixcolor ; color(256) goto fixdim ; dim(16) last color maxpats equ D'6' ; number of patterns in jump table above!! ;---------------------------------------------------------------------- ;here in soft power down mode poweroff bcf NEWP poweroffl call setoff ; set all rgb values to zero call txframe ; send a frame to lights call Delay1s goto poweroffl ;---------------------------------------------------------------------- ;all lights same color (adjustable) fixcolor movf var,W ; get variation value to index color wheel call wheel ; get rgb values from color wheel call setall ; set all lights to rgb value from wheel call txframe ; send it to the lights call varwait ; wait for var to change (button press) goto fixcolor ;---------------------------------------------------------------------- ;all lights same last color, dimmable fixdim movf var,W movwf tmp2 ; save last color selected fixdim1 movf tmp2,W call wheel call setall ;use var as amount to dim the lights movf var,W andlw H'0f' movwf tmp1 skpnz goto fixnodim fixdim2 call dimall82 decfsz tmp1,1 goto fixdim2 fixnodim call txframe call varwait goto fixdim1 ;---------------------------------------------------------------------- ;all lights cool white (and dimmable) fixwhite call pickwhite call setall movf var,W andlw H'0f' movwf tmp1 skpnz goto fwnodim fixwhite2 call dimall82 decfsz tmp1,1 goto fixwhite2 fwnodim call txframe call varwait goto fixwhite ;---------------------------------------------------------------------- ;strobe lighting (speed adjustable) strobe call pickwhite ;get white value call setall ;set all lights to that value call txframe ;send a frame to set them movlw 1 call Delay call setoff ;zero all rgb values call txframe ;send frame to turn lights off swapf var,W andlw H'f0' call Delay goto strobe ;---------------------------------------------------------------------- ;colorwheel sweep colorsweep csw3 clrf index csw2 movf index,W movwf tmp1 movlw lights movwf slots movlw rgbd movwf FSR csw1 movf tmp1,W call wheel movf rval,W movwf INDF incf FSR,1 movf gval,W movwf INDF incf FSR,1 movf bval,W movwf INDF incf FSR,1 movlw D'8' subwf tmp1,1 decfsz slots,1 goto csw1 call txframe movlw D'32' call Delay movlw 1 addwf index,1 goto csw2 ;---------------------------------------------------------------------- ;color wheel table generator ;call with index in W, returns with rval/gval/bval setting ; wheel is 256 "entries", div 3, so divisions at 0,85,170 wheel movwf windex ; save wheel index call nwindex movwf rval movf windex,W addlw D'85' call nwindex movwf gval movf windex,W addlw D'170' call nwindex movwf bval return ;color wheel lookup routine nwindex movwf cindex ; save color index movlw D'85' subwf cindex,1 ; set carry if cindex >= w skpc retlw 0 movlw D'85' subwf cindex,1 skpc goto nwup ndwn ;return number from 255-0 based on cindex 0-85 (cindex = 255 - cindex*3) movf cindex,W call nwtable sublw D'255' return ;return number from 0-255 based on cindex 0-85 (cindex = cindex*3) nwup addwf cindex,1 ;restore cindex to 0-85 range movf cindex,W call nwtable return ;---------------------------------------------------------------------- ;wait for var to change (button2 pressed) varwait movf var,W movwf tmp1 varwait1 movf var,W xorwf tmp1,W ; changed? skpnz goto varwait1 ; no, wait return ;set one light (@index) to rgb/val setindex movlw rgbd movwf FSR movf index,W addwf FSR,1 addwf FSR,1 addwf FSR,1 movf rval,W movwf INDF incf FSR,1 movf gval,W movwf INDF incf FSR,1 movf bval,W movwf INDF incf FSR,1 return ;get one light (@index) to rgb/val getindex movlw rgbd movwf FSR movf index,W addwf FSR,1 addwf FSR,1 addwf FSR,1 movf INDF,W movwf rval incf FSR,1 movf INDF,W movwf gval incf FSR,1 movf INDF,W movwf bval incf FSR,1 return ;get values to use for white color pickwhite movlw WVR movwf rval movlw WVG movwf gval movlw WVB movwf bval return ;turn everything off setoff clrf rval clrf gval clrf bval ;set all lights to rval,gval,bval setall movlw lights movwf slots movlw rgbd movwf FSR sa1 movf rval,W movwf INDF incf FSR,1 movf gval,W movwf INDF incf FSR,1 movf bval,W movwf INDF incf FSR,1 decfsz slots,1 goto sa1 return ;dim all lights to 82% of their current value dimall82 movlw lights*3 movwf slots movlw rgbd movwf FSR ;start with 1/2 da81 rrf INDF,1 bcf INDF,7 ;add in 1/4 rrf INDF,W andlw H'7f' addwf INDF,1 ;add in 1/16 movwf tmp4 rrf tmp4,1 rrf tmp4,W andlw H'3f' addwf INDF,1 ;don't let it go to zero skpnz bsf INDF,0 incf FSR,1 decfsz slots,1 goto da81 return ;---------------------------------------------------------------------- ;test pattern. ; sequence lights in order, r then g then b then white. test ;red call setoff call txframe movlw MC movwf rval clrf gval clrf bval clrf index test1 call setindex call txframe call Delay100 incf index,1 movf index,W xorlw lights skpz goto test1 call Delay100 ;green call setoff call txframe call Delay100 movlw MC movwf gval clrf rval clrf bval clrf index test2 call setindex call txframe call Delay100 incf index,1 movf index,W xorlw lights skpz goto test2 call Delay100 ;blue call setoff call txframe call Delay100 movlw MC movwf bval clrf rval clrf gval clrf index test3 call setindex call txframe call Delay100 incf index,1 movf index,W xorlw lights skpz goto test3 call Delay100 ;white call setoff call txframe call Delay100 call pickwhite clrf index test4 call setindex call txframe call Delay100 incf index,1 movf index,W xorlw lights skpz goto test4 call Delay1s call setoff call txframe call Delay100 goto test ;---------------------------------------------------------------------- ;frame tx routine ; sends a full frame of rgb data ; a bit every 25us to PORTC,LEDOUT (every 50 instructions @8mhz) ; note that the instructions are very carefully counted so there ; are exactly 50 between every bit output. ; frame format: 0010 rgbP ... rgbP 0000 (P = ~b) txframe bcf INTCON,GIE ; no interrupts ; send the header bits (0010) bcf PORTC,LEDOUT call bdelay49 bcf PORTC,LEDOUT call bdelay49 bsf PORTC,LEDOUT call bdelay49 bcf PORTC,LEDOUT call bdelay30 movlw lights movwf slots ;loop counter for each light on the string movlw rgbd movwf FSR ;set FSR to point to RGB data for first light fslotloop ;get the RGB data for the next light into rout,gout,bout movf INDF,W movwf rout incf FSR,1 movf INDF,W movwf gout incf FSR,1 movf INDF,W movwf bout incf FSR,1 ;now output all 8-bits of RGB for this light movlw D'8' movwf bits ;count down bits to go fbitloop movlw CMSK rrf rout,1 skpnc iorlw LEDMSK movwf PORTC ;output R bit call bdelay45 movlw CMSK rrf gout,1 skpnc iorlw LEDMSK movwf PORTC ;output G bit call bdelay45 movlw CMSK rrf bout,1 skpnc iorlw LEDMSK movwf PORTC ;output B bit movwf pbit call bdelay45 ;send inverse of last bit sent movlw CMSK btfss pbit,4 iorlw LEDMSK movwf PORTC ;output P bit call bdelay29 decfsz bits,1 ;next bit? goto fdbitloop decfsz slots,1 ;next light? goto fslotloop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop ;send the trailer bits (0000) bcf PORTC,LEDOUT call bdelay49 bcf PORTC,LEDOUT call bdelay49 bcf PORTC,LEDOUT call bdelay49 bcf PORTC,LEDOUT call bdelay49 bsf INTCON,GIE return fdbitloop nop nop nop nop nop nop nop nop nop nop nop goto fbitloop ;bit delays in instructions total minus 4 (call/return) bdelay49 nop nop nop nop bdelay45 nop nop movlw D'9' ;9*4=36 movwf CTL bd45 nop decfsz CTL,1 goto bd45 nop nop return bdelay30 nop bdelay29 nop nop movlw D'5' ;5*4=20 movwf CTL bd29 nop decfsz CTL,1 goto bd29 nop nop return ;---------------------------------------------------------------------- ;delay 1 second Delay1s call Delay500 call Delay500 return Delay500 movlw D'250' call Delay movlw D'250' call Delay return Delay100 movlw D'100' goto Delay Delay50 movlw D'50' goto Delay Delay20 movlw D'20' ;delay W milliseconds (8mhz clock!) Delay iorlw 0 skpnz return movwf CTL ;delay 1 msec (2000 instructions) DlyL movlw D'250' movwf CT1 Dly1 nop nop nop nop nop decfsz CT1,1 goto Dly1 decfsz CTL,1 goto DlyL return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; radix DECIMAL org 0x07a2 ;color wheel lookup table (make sure is on one page!) nwtable bsf PCLATH,0 bsf PCLATH,1 bsf PCLATH,2 addwf PCL,1 retlw 0 retlw 1 retlw 2 retlw 4 retlw 6 retlw 8 retlw 10 retlw 12 retlw 14 retlw 16 retlw 19 retlw 21 retlw 24 retlw 26 retlw 29 retlw 32 retlw 34 retlw 37 retlw 40 retlw 43 retlw 46 retlw 49 retlw 52 retlw 56 retlw 59 retlw 62 retlw 66 retlw 69 retlw 73 retlw 76 retlw 80 retlw 83 retlw 87 retlw 91 retlw 94 retlw 98 retlw 102 retlw 106 retlw 110 retlw 113 retlw 117 retlw 121 retlw 125 retlw 129 retlw 133 retlw 136 retlw 140 retlw 144 retlw 148 retlw 152 retlw 156 retlw 159 retlw 163 retlw 167 retlw 170 retlw 174 retlw 178 retlw 181 retlw 185 retlw 188 retlw 192 retlw 195 retlw 198 retlw 202 retlw 205 retlw 208 retlw 211 retlw 214 retlw 217 retlw 220 retlw 223 retlw 225 retlw 228 retlw 231 retlw 233 retlw 235 retlw 238 retlw 240 retlw 242 retlw 244 retlw 246 retlw 248 retlw 250 retlw 252 retlw 254 retlw 255 retlw 0 retlw 0 retlw 0 end