;******************************************************************************** ;* * ;* Dice Kit * ;* * ;******************************************************************************** ; Operation; ; ; 1. Reads a piezo strike to create random dice count, displayed on 7 leds ; ;******************************************************************************** ; ; Copyright SpikenzieLabs 2010, All rights reserved ; By: Mark Demers list p=12f675 ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _CPD_OFF & _BODEN_ON & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ;*************************** MACROs ******************************** LITELEDS macro LEDPATTERN movlw LEDPATTERN movwf GPIO endm MULTIPLY3 macro VALX ; result in W movlw 0x03 movwf TIMES movf VALX,w movwf SUM decf SUM,f movf SUM,w movwf TEMPDICE MULTIPLYLOOP: decfsz TIMES,f goto MULTIPLYCONT movf SUM,w goto MULTIPLYEXIT MULTIPLYCONT: movf TEMPDICE,w addwf SUM,f goto MULTIPLYLOOP MULTIPLYEXIT: endm ;*************************** DEFINE STATEMENTS ******************************** #define OFFFLAG FLAGVAR,0 #define GOODREADFLAG FLAGVAR,1 #define SLEEPFLAG FLAGVAR,3 #define HITDEBOUNCEFLAG FLAGVAR,4 #define ANAREJECTFLAG FLAGVAR,5 ;****************************************************************************** ; VARIABLE DEFINITIONS ;****************************************************************************** cblock 0x20 ; - General Variables ; (8 Bit) DICE buffer onLEDoffset TIMES SUM TEMPDICE TEMP2 ; (16 bit) sleepycounter:2 ; (Boolean) FLAGVAR ; - Temp. INTERRUPT Variables WTEMP STATUSTEMP PCLATHTEMP FSRTEMP endc ;****************************** Start of Program ****************************** org 0x000 ; processor reset vector goto Initialize org 0x004 goto INTERRUPT ;****************************************************************************** ; Initialize ;****************************************************************************** org 0x005 ; Start of Programm Memory Vector Initialize ;****************************************************************************** ; Comparator Init ;****************************************************************************** bsf CMCON,CM0 ; Comparitors off bsf CMCON,CM1 bsf CMCON,CM2 ;****************************************************************************** ; A2D Init ;****************************************************************************** bsf STATUS,RP0 ; Bank 1 movlw b'01010001' ; Channel 0 Analog input & Fosc/16 (for 4mhz) movwf ANSEL bcf STATUS,RP0 ; Bank 0 movlw b'10000001' ; ADC ON & Chanel 0 & RIGHT justified movwf ADCON0 ;****************************************************************************** ; PIN Init ;****************************************************************************** clrf GPIO bsf STATUS,RP0 ; Bank 1 movlw b'00001001' ; All outputs, except PIN 0 - Analog input movwf TRISIO bcf STATUS,RP0 ; Bank 0 ;****************************************************************************** ; General Init ;****************************************************************************** clrf TEMP2 ; clear clrf TMR0 ; clear Timer 0 clrf sleepycounter clrf sleepycounter+1 bcf SLEEPFLAG ;****************************************************************************** ; Timer ZERO Inits - TMR0 ;****************************************************************************** clrwdt bsf STATUS,RP0 ; Bank 1 bcf OPTION_REG,T0CS ; Use internal clock source bcf OPTION_REG,PSA ; Prescaler assigned to TMR0 bcf STATUS,RP0 ; Bank 0 ;****************************************************************************** ; Timer ONE Inits - TMR1 ;****************************************************************************** movlw b'00000000' ; Prescaler b'00xx0000' where 11=1:8, 10=1:4, 01=1:2, 00=1:1 movwf T1CON ;****************************************************************************** ; GPIO IOC Init ;****************************************************************************** movf GPIO,w ; Clears missmatch bcf INTCON,GPIF ; Clear flag bsf STATUS,RP0 ; Bank 1 bsf IOC,0 ; Enable IOC for GPIO pin 0 bcf STATUS,RP0 ; Bank 0 ;****************************************************************************** ; Variable Init ;****************************************************************************** movlw 0x01 movwf DICE clrf onLEDoffset bcf OFFFLAG bcf GOODREADFLAG bcf HITDEBOUNCEFLAG bcf ANAREJECTFLAG ;****************************************************************************** ; INTERRUPT Init ;****************************************************************************** ;TIMER 1 bcf PIR1,TMR1IF ; Clear Timer 1 Overflow Flag clrf TMR1L clrf TMR1H bcf INTCON,T0IF clrf TMR0 bsf INTCON,T0IE bsf STATUS,RP0 ; Bank 1 bsf PIE1,TMR1IE ; Enable timer 1 overflow bsf PIE1,ADIE ; Enable AD Conversion Inter. bcf STATUS,RP0 ; Bank 0 bsf T1CON,TMR1ON ;ALL INTERRUPTS bsf INTCON,GIE bsf INTCON,PEIE ;******************************************************************************** ; * ; MAIN PROGRAM * ; * ;******************************************************************************** MAIN: call UPDATELEDS btfsc GOODREADFLAG goto MAIN btfss ADCON0,GO bsf ADCON0,GO ; Start the analog reading btfss SLEEPFLAG goto MAIN ; ------------------------ SLEEP SET-UP - START ; --- Turn off A/D converter bcf ADCON0,ADON ; --- Turn off analog pins bsf STATUS,RP0 ; Bank 1 bcf ANSEL,ANS0 bcf STATUS,RP0 ; Bank 0 ; --- Clear GPIO clrf GPIO movf GPIO,W ; --- Clear IOC FLAG bcf INTCON,GPIF ; Clear flag ; --- Turn on IOC for Pin 0 bsf INTCON,GPIE ; ------------------------ SLEEP SET-UP - END nop nop SLEEP nop nop ; ------------------------ SLEEP WAKE - START ; --- Turn off IOC for Pin 0 bcf INTCON,GPIE ; --- Turn ON analog pins bsf STATUS,RP0 ; Bank 1 bsf ANSEL,ANS0 bcf STATUS,RP0 ; Bank 0 ; --- Turn ON A/D converter bsf ADCON0,ADON ; --- Clear IOC FLAG bcf INTCON,GPIF ; Clear flag ; ------------------------ SLEEP WAKE - END bcf GOODREADFLAG ; Start reading Analog values right away bsf ANAREJECTFLAG ; Try to re-new the DICE value goto MAIN ;******************************************************************************** ; * ; SUBROUTINES * ; * ;******************************************************************************** ;****************************************************************************** ; Flash the LEDS ;****************************************************************************** UPDATELEDS: btfsc OFFFLAG goto EXITUPDATELEDS UPDATELEDSSTATE: movlw HIGH UPDATELEDSTABLE movwf PCLATH banksel DICE MULTIPLY3 DICE addwf onLEDoffset,w addlw LOW UPDATELEDSTABLE btfsc STATUS,C incf PCLATH,f movwf PCL UPDATELEDSTABLE: ; STATE goto ONEA ; 1 goto ONEB ; 1 goto ONEC ; 1 goto TWOA ; 2 goto TWOB ; 2 goto TWOC ; 2 goto THREEA ; 3 goto THREEB ; 3 goto THREEC ; 3 goto FOURA ; 4 goto FOURB ; 4 goto FOURC ; 4 goto FIVEA ; 5 goto FIVEB ; 5 goto FIVEC ; 5 goto SIXA ; 6 goto SIXB ; 6 goto SIXC ; 6 ONEA: LITELEDS b'00100000' goto EXITUPDATELEDS ONEB: LITELEDS b'00000000' goto EXITUPDATELEDS ONEC: LITELEDS b'00000000' goto EXITUPDATELEDS TWOA: LITELEDS b'00010000' goto EXITUPDATELEDS TWOB: LITELEDS b'00000000' goto EXITUPDATELEDS TWOC: LITELEDS b'00000000' goto EXITUPDATELEDS THREEA: LITELEDS b'00010000' goto EXITUPDATELEDS THREEB: LITELEDS b'00100000' goto EXITUPDATELEDS THREEC: LITELEDS b'00000000' goto EXITUPDATELEDS FOURA: LITELEDS b'00010000' goto EXITUPDATELEDS FOURB: LITELEDS b'00000100' goto EXITUPDATELEDS FOURC: LITELEDS b'00000000' goto EXITUPDATELEDS FIVEA: LITELEDS b'00100000' goto EXITUPDATELEDS FIVEB: LITELEDS b'00010000' goto EXITUPDATELEDS FIVEC: LITELEDS b'00000100' goto EXITUPDATELEDS SIXA: LITELEDS b'00000010' goto EXITUPDATELEDS SIXB: LITELEDS b'00010000' goto EXITUPDATELEDS SIXC: LITELEDS b'00000100' goto EXITUPDATELEDS EXITUPDATELEDS: return ;****************************************************************************** ;******************************************************************************** ; * ; INTERRUPT * ; * ;******************************************************************************** INTERRUPT: ; Interrupt PREP. here --------------------------------- movwf WTEMP ;Save off current W register contents swapf STATUS,w clrf STATUS ;Force to page0 movwf STATUSTEMP movf PCLATH,w movwf PCLATHTEMP ;Save PCLATH movf FSR,w movwf FSRTEMP ;Save FSR ; -------------------------------------------------------- ; TEST Cause of INTERRUPT GP2_INT_ExternalInterruptCheck: bcf STATUS,RP0 ; Force to Bank 0 ; Timer 1 Overflow btfsc PIR1,TMR1IF goto TIMEUP ; ADC conversion Done btfsc PIR1,ADIF goto ANALOGREAD ; Timer Zero Int. btfsc INTCON,T0IF goto TIMERZERO ; GPIO IOC pin int. btfsc INTCON,GPIF goto IOCHANDEL ; Interrupt EXIT here ---------------------------------- InterruptEXIT: movf FSRTEMP,w movwf FSR ;Restore FSR movf PCLATHTEMP,w movwf PCLATH ;Restore PCLATH swapf STATUSTEMP,w movwf STATUS ;Restore STATUS swapf WTEMP,f swapf WTEMP,w ;Restore W without corrupting STATUS bits retfie ; ===================================================================================================== ** ;***************************************************************************************** ; TMR0 Overflow (Used for "hit" debounnce, and incrementor for delay before Sleep ;***************************************************************************************** TIMERZERO: btfsc HITDEBOUNCEFLAG goto HITISDEBOUNCED ; Use 2x Timer 0 for the debounce HITDEBOUNCE: bsf HITDEBOUNCEFLAG clrf TMR0 bcf INTCON,T0IF goto CHECKSLEEP HITISDEBOUNCED: bcf GOODREADFLAG bcf HITDEBOUNCEFLAG clrf TMR0 bcf INTCON,T0IF ;--- CHECKSLEEP: incf sleepycounter,f btfss STATUS,Z goto CHECKSLEEPEXIT ; incf sleepycounter+1,f ; Use for longer ON time ; btfss STATUS,Z ; goto CHECKSLEEPEXIT YESSLEEP: bsf SLEEPFLAG CHECKSLEEPEXIT: ;--- goto InterruptEXIT ;***************************************************************************************** ; TMR1 Overflow - Used to adjust ON time of LEDs ;***************************************************************************************** TIMEUP: incf onLEDoffset,f movlw 0x03 subwf onLEDoffset,w btfss STATUS,Z goto TIMEUPEXIT clrf onLEDoffset TIMEUPEXIT: clrf STATUS movlw 0x40 movwf TMR1L movlw 0xFF movwf TMR1H bcf PIR1,TMR1IF bsf T1CON,TMR1ON goto InterruptEXIT ;***************************************************************************************** ; Analog read is done ;***************************************************************************************** ANALOGREAD: movf ADRESH,w movwf TEMP2 btfsc ANAREJECTFLAG goto ANALOGREADFORCED ; -- old ; bcf TEMP2,0 ; Comment out this line to make "hit" more sensitive ; movf TEMP2,f ; btfsc STATUS,Z ; ADRESH will be zero if Analog read is less than 256 ; goto ANALOGREADEXIT ; Not Hit hard enough ! ; -- old movf TEMP2,f btfss STATUS,Z ; ADRESH goto ANALOGREADFORCED ; ADRESH is greater than 0 -> use the reading bsf STATUS,RP0 ; Bank 1 movf ADRESL,w bcf STATUS,RP0 ; Bank 0 sublw 0x20 btfsc STATUS,C ; ADRESL is at least XX goto ANALOGREADEXIT ; Not Hit hard enough ! ANALOGREADFORCED: bcf ANAREJECTFLAG clrf GPIO bsf STATUS,RP0 ; Bank 1 movf ADRESL,w bcf STATUS,RP0 ; Bank 0 movwf TEMP2 movlw b'00000111' andwf TEMP2,f incf TEMP2,f ; remove zero as posible answer movf TEMP2,w sublw 0x06 ; Test for less than or = to 6 btfss STATUS,C goto ANALOGREAD_REJECT movf TEMP2,w movwf DICE bsf GOODREADFLAG clrf TMR0 bcf INTCON,T0IF clrf sleepycounter clrf sleepycounter+1 goto ANALOGREADEXIT ANALOGREAD_REJECT: bcf GOODREADFLAG bsf ANAREJECTFLAG ANALOGREADEXIT: bcf PIR1,ADIF goto InterruptEXIT ;***************************************************************************************** ; GPIO IOC HANDLE (Used only to wake PIC from Sleep mode) ;***************************************************************************************** IOCHANDEL: bcf SLEEPFLAG movf GPIO,w ; Clears missmatch bcf INTCON,GPIF ; Clear flag goto InterruptEXIT ;****************************************************************************** PLACETOSTOP: end ; directive 'end of program'