This code has been heavily streamlined, and SLEEP mode has been added. If the 'ROLL DICE' button is not pressed within 10 seconds of the last press, the PIC will enter sleep mode and wake up when the button is finally pressed. Hopefully this will save some battery life.
;---------------------------------------------------;
; Name: Electronic_Dice.ASM ;
; Use: Electronic Dice Simulator ;
;---------------------------------------------------;
; (C): 2012 Dysfunctional Technologies, Inc. ;
; All Rights Reserved ;
;---------------------------------------------------;
; Author: Timothy S. Carlson ;
; Dysfunctional Technologies, Inc. ;
; Date: November 12, 2012 ;
; Version: V2.02 ;
;---------------------------------------------------;
; Revision History: ;
; 2012.07.03: Initial Code ;
; 2012.10.20: Dual Die display with select ;
; 2012.10.21: Dual Die display enhancements ;
; 2012.10.27: Code reductions ;
; 2012.11.11: MORE Code reductions ;
; 2012.11.12: Trying to fix V2 ghosting. Not yet :( ;
; 2012.11.12: Added SLEEP mode to conserve power ;
;---------------------------------------------------;
;---------------------------------------------------;
; Includes ;
;---------------------------------------------------;
LIST P=12F629 ;
#INCLUDE
;
ERRORLEVEL -207 ; suppress message 207 from list file
; (Found label after column 1)
;
ERRORLEVEL -302 ; suppress message 302 from list file
; (Register in operand not in bank 0)
;
__CONFIG _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
;---------------------------------------------------;
;---------------------------------------------------;
; Defines ;
;---------------------------------------------------;
;#DEFINE _V2_HARDWARE_ ;
; V1 Hardware has two transistors (a 2n4401 and a ;
; 2n4403) that are controlled by the SELECT line. ;
; The 2n4403 is connected to the cathodes of the ;
; LEDs on die 1 and the 2n4401 is connected to the ;
; cathodes of the LEDs on die 2. This way, toggle ;
; SELECT low or high will select die 1 or die 2. ;
; ;
; V2 Hardware gets rid of these transistors (and ;
; associated resistors). SELECT is connected to the ;
; cathodes of the LEDs on die 1 and the anodes of ;
; the LEDs on die 2. HOWEVER, when writing the data ;
; for the die 2 LEDs, it must be inverted first in ;
; order to work properly. ;
;---------------------------------------------------;
;
BANK0 MACRO ;
BCF STATUS, RP0 ;
ENDM ;
;
BANK1 MACRO ;
BSF STATUS, RP0 ;
ENDM ;
;
SET_DICE MACRO VALUE, WAIT ;
MOVLW VALUE ;
MOVWF Dice ; Set Dice value
IF (WAIT!=NOWAIT) ;
MOVLW WAIT ; Wait for specified time
CALL _Wait ; (allows ISR to display values)
ENDIF ;
ENDM ;
;
#DEFINE NOWAIT 0 ;
#DEFINE MOLASSES H'FF' ;
#DEFINE SUPERSLOW 100 ;
#DEFINE SLOW 50 ;
#DEFINE MEDIUM 25 ;
#DEFINE FAST 10 ;
#DEFINE SUPERFAST 3 ;
;
#DEFINE LDIAG_BIT 0 ; GPIO 0 - Pin 7
#DEFINE LDIAG H'01' ;
#DEFINE CTR_BIT 1 ; GPIO 1 - Pin 6
#DEFINE CTR H'02' ;
#DEFINE SELECT_BIT 2 ; GPIO 2 - Pin 5
#DEFINE SELECT H'04' ;
#DEFINE BUTTON_BIT 3 ; GPIO 3 - Pin 4
#DEFINE BUTTON H'08' ;
#DEFINE RDIAG_BIT 4 ; GPIO 4 - Pin 3
#DEFINE RDIAG H'10' ;
#DEFINE SIDES_BIT 5 ; GPIO 5 - Pin 2
#DEFINE SIDES H'20' ;
;
;---------------------------------------------------;
;---------------------------------------------------;
EDICE_DATA UDATA ;
;---------------------------------------------------;
sW res 1 ; ISR req'd
sSTATUS res 1 ;
;
Temp res 1 ; temp storage
;
RAND_HI res 1 ; 16-bit 'random' number
RAND_LO res 1 ; 16-bit 'random' number
;
Dice res 1 ; holds dice values
Dice_TEMP res 1 ; temp storage for dice
;
IV_TMRCount res 1 ; TIMER 0 ISR Count
Wait_Count res 1 ; Used for delay
Sleep_Count1 res 1 ; Used for sleep delay
Sleep_Count2 res 1 ; Used for sleep delay
;---------------------------------------------------;
;---------------------------------------------------;
; Reset Vector ;
;---------------------------------------------------;
EDICE_RV CODE H'000' ;
;---------------------------------------------------;
CALL _Initialize_System ;
MOVLW MOLASSES ;
CALL _Wait ;
GOTO _Main_DIAG_LOOP ;
;---------------------------------------------------;
;---------------------------------------------------;
; Interrupt Vector ;
;---------------------------------------------------;
EDICE_IV CODE H'004' ;
;---------------------------------------------------;
MOVWF sW ; Save W
MOVFW STATUS ; Retrieve STATUS
MOVWF sSTATUS ; and save it
;
BTFSC INTCON, T0IF ; Timer0 interrupt?
GOTO IV_TMR ; Yes, process
GOTO IV_EXIT ; No, exit
;
IV_TMR: ;
BTFSC GPIO, SELECT_BIT ;
GOTO IV_TMR_DIE_2 ;
;
IV_TMR_DIE_1: ;
MOVFW Dice ;
CALL _Die_GET_VALUES ;
#IFDEF _V2_HARDWARE_ ;
XORLW CTR | LDIAG | RDIAG | SIDES ;
#ENDIF ;
IORLW BUTTON | SELECT ;
MOVWF GPIO ;
GOTO IV_TMR_EXIT ;
;
IV_TMR_DIE_2: ;
SWAPF Dice, W ;
CALL _Die_GET_VALUES ;
IORLW BUTTON ;
MOVWF GPIO ;
;
IV_TMR_EXIT: ;
INCF IV_TMRCount, F ;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
CLRF TMR0 ;
;
IV_EXIT: ;
CALL _Random ;
;
MOVFW sSTATUS ; Retrieve saved STATUS
MOVWF STATUS ; and restore
MOVFW sW ; Retrieve and restore saved W
RETFIE ;
;---------------------------------------------------;
;---------------------------------------------------;
_Die_GET_VALUES: ;
;---------------------------------------------------;
ANDLW H'0F' ;
MOVWF Dice_TEMP ;
;
MOVLW HIGH DIE_VALUES ;
MOVWF PCLATH ;
;
MOVFW Dice_TEMP ;
ADDLW LOW DIE_VALUES ;
BTFSC STATUS, C ; Check for
INCF PCLATH, F ; boundary cross
MOVWF PCL ; Do the jump!
;---------------------------------------------------;
DIE_VALUES: ;
;---------------------------------------------------;
; O O ;
; 000 ;
; 0 0 DIE 0 - 0=OFF, X=ON (0ma) ;
;-----------------------------------------------;
DT 0 ; Die1 0
;-----------------------------------------------;
; O O ;
; 0X0 ;
; 0 0 DIE 1 - 0=OFF, X=ON (20ma) ;
;-----------------------------------------------;
DT CTR ; Die1 1
;-----------------------------------------------;
; X O ;
; 000 ;
; 0 X DIE 2 - 0=OFF, X=ON (40ma) ;
;-----------------------------------------------;
DT LDIAG ; Die1 2
;-----------------------------------------------;
; O X ;
; 0X0 ;
; X 0 DIE 3 - 0=OFF, X=ON (60ma) ;
;-----------------------------------------------;
DT CTR | RDIAG ; Die1 3
;-----------------------------------------------;
; X X ;
; 000 ;
; X X DIE 4 - 0=OFF, X=ON (80ma) ;
;-----------------------------------------------;
DT LDIAG | RDIAG ; Die1 4
;-----------------------------------------------;
; X X ;
; 0X0 ;
; X X DIE 5 - 0=OFF, X=ON (100ma) ;
;-----------------------------------------------;
DT CTR | LDIAG | RDIAG ; Die1 5
;-----------------------------------------------;
; X X ;
; X0X ;
; X X DIE 6 - 0=OFF, X=ON (120ma) ;
;-----------------------------------------------;
DT LDIAG | RDIAG | SIDES ; Die1 6
;-----------------------------------------------;
; X X ;
; XXX ;
; X X DIE 7 - 0=OFF, X=ON (140ma) ;
;-----------------------------------------------;
DT CTR | LDIAG | RDIAG | SIDES ; Die1 7
;-----------------------------------------------;
; 0 0 ;
; XXX ;
; 0 0 DIE 8 - 0=OFF, X=ON (60ma) ;
;-----------------------------------------------;
DT CTR | SIDES ; Die1 8
;-----------------------------------------------;
; X 0 ;
; 0X0 ;
; 0 X DIE 9 - 0=OFF, X=ON (60ma) ;
;-----------------------------------------------;
DT CTR | LDIAG ; Die1 9
;-----------------------------------------------;
; 0 0 ;
; X0X ;
; 0 0 DIE A - 0=OFF, X=ON (40ma) ;
;-----------------------------------------------;
DT SIDES ; Die1 A
;-----------------------------------------------;
; 0 X ;
; 000 ;
; X 0 DIE B - 0=OFF, X=ON (40ma) ;
;-----------------------------------------------;
DT RDIAG ; Die1 B
;-----------------------------------------------;
; X O ;
; XXX ;
; 0 X DIE C - 0=OFF, X=ON (100ma) ;
;-----------------------------------------------;
DT CTR | LDIAG | SIDES ; Die1 C
;-----------------------------------------------;
; 0 X ;
; XXX ;
; X 0 DIE D - 0=OFF, X=ON (100ma) ;
;-----------------------------------------------;
DT CTR | RDIAG | SIDES ; Die1 D
;-----------------------------------------------;
; X 0 ;
; X0X ;
; 0 X DIE E - 0=OFF, X=ON (80ma) ;
;-----------------------------------------------;
DT LDIAG | SIDES ; Die1 E
;-----------------------------------------------;
; 0 X ;
; X0X ;
; X 0 DIE F - 0=OFF, X=ON (80ma) ;
;-----------------------------------------------;
DT RDIAG | SIDES ; Die1 F
;---------------------------------------------------;
;---------------------------------------------------;
_Main_DIAG_LOOP: ;
;---------------------------------------------------;
BTFSS GPIO, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
CALL _Diagnostics ;
BTFSC GPIO, BUTTON_BIT ; Check Button LOW
GOTO _Main_DIAG_LOOP ; is not, DIAGS again
BTFSS GPIO, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
;
;---------------------------------------------------;
_Main_ROLL_DICE: ;
;---------------------------------------------------;
CALL _Die_ROLL ; Roll dice
;---------------------------------------------------;
_Main_INIT_SLEEP: ;
;---------------------------------------------------;
CLRF IV_TMRCount ;
CLRF Sleep_Count1 ;
MOVLW 10 ;
MOVWF Sleep_Count2 ;
;---------------------------------------------------;
_Main_WAIT: ;
;---------------------------------------------------;
MOVLW H'FF' ;
XORWF IV_TMRCount, W ;
BTFSS STATUS, Z ;
GOTO _Main_CHECK_BUTTON ;
;
INCFSZ Sleep_Count1, F ;
GOTO _Main_CHECK_BUTTON ;
;
DECFSZ Sleep_Count2, F ;
GOTO _Main_CHECK_BUTTON ;
;
_Main_SLEEP: ;
BCF INTCON, GIE ;
MOVLW BUTTON ;
MOVWF GPIO ;
BANKSEL IOC ;
BSF IOC, BUTTON_BIT ;
BANKSEL INTCON ;
BCF INTCON, GPIF ;
BSF INTCON, GPIE ;
SLEEP ;
BCF INTCON, GPIE ;
BCF INTCON, GPIF ;
BANKSEL IOC ;
BCF IOC, BUTTON_BIT ;
BANKSEL INTCON ;
BSF INTCON, GIE ;
;
BTFSS GPIO, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
GOTO _Main_INIT_SLEEP ;
;
_Main_CHECK_BUTTON: ;
BTFSC GPIO, BUTTON_BIT ; Check Button LOW
GOTO _Main_WAIT ; if not, wait
BTFSS GPIO, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
GOTO _Main_ROLL_DICE ;
;---------------------------------------------------;
;---------------------------------------------------;
_Diagnostics: ;
;---------------------------------------------------;
; Flash all die dots ;
;-----------------------------------------------;
MOVLW 3 ;
MOVWF Temp ;
;
D1_Loop: ;
SET_DICE H'00', FAST ;
SET_DICE H'70', FAST ;
SET_DICE H'07', FAST ;
SET_DICE H'77', FAST ;
;
DECFSZ Temp, F ;
GOTO D1_Loop ;
;
SET_DICE H'00', NOWAIT ;
;-----------------------------------------------;
; Wobble Die Dots ;
;-----------------------------------------------;
MOVLW 6 ;
MOVWF Temp ;
;
SET_DICE H'00', NOWAIT ;
;
D2_Loop: ;
SET_DICE H'30', FAST ;
SET_DICE H'80', FAST ;
SET_DICE H'90', FAST ;
SET_DICE H'80', FAST ;
;
SET_DICE H'39', FAST ;
SET_DICE H'88', FAST ;
SET_DICE H'93', FAST ;
SET_DICE H'88', FAST ;
;
SET_DICE H'09', FAST ;
SET_DICE H'08', FAST ;
SET_DICE H'03', FAST ;
SET_DICE H'08', FAST ;
;
DECFSZ Temp, F ;
GOTO D2_Loop ;
;-----------------------------------------------;
; Cycle through all die faces ;
;-----------------------------------------------;
MOVLW H'3' ;
MOVWF Temp ;
;
SET_DICE H'00', NOWAIT ;
;
D3_Loop: ;
SET_DICE H'00', MEDIUM ;
SET_DICE H'07', MEDIUM ;
SET_DICE H'16', MEDIUM ;
SET_DICE H'25', MEDIUM ;
SET_DICE H'34', MEDIUM ;
SET_DICE H'43', MEDIUM ;
SET_DICE H'52', MEDIUM ;
SET_DICE H'61', MEDIUM ;
SET_DICE H'70', MEDIUM ;
SET_DICE H'61', MEDIUM ;
SET_DICE H'52', MEDIUM ;
SET_DICE H'43', MEDIUM ;
SET_DICE H'34', MEDIUM ;
SET_DICE H'25', MEDIUM ;
SET_DICE H'16', MEDIUM ;
SET_DICE H'07', MEDIUM ;
;
DECFSZ Temp, F ;
GOTO D3_Loop ;
;---------------------------------------------------;
_Die_ROLL: ;
;---------------------------------------------------;
MOVLW 3 ;
MOVWF Temp ;
;
D4_Loop: ;
SET_DICE H'00', FAST ;
SET_DICE H'11', FAST ;
SET_DICE H'88', FAST ;
SET_DICE H'AA', FAST ;
;
DECFSZ Temp, F ;
GOTO D4_Loop ;
;---------------------------------------------------;
_Get_Dice: ;
;---------------------------------------------------;
BCF INTCON, GIE ;
;
CALL _Random ;
;
MOVFW RAND_LO ;
ANDLW H'07' ;
XORLW H'00' ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
XORLW H'07' ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVWF Dice ;
SWAPF Dice, F ;
;
MOVFW RAND_HI ;
ANDLW H'07' ;
XORLW H'00' ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
XORLW H'07' ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
IORWF Dice, F ;
;
BSF INTCON, GIE ;
RETURN ;
;---------------------------------------------------;
;---------------------------------------------------;
_Random: ;
; 16 bit value returned in RAND_HI and RAND_LO ;
;---------------------------------------------------;
; Need a better (pseudo) RANDOM method ;
;-----------------------------------------------;
MOVF RAND_HI, W ;
IORWF RAND_LO, W ;
BTFSS STATUS, Z ;
GOTO RANDOM_GO ;
; if current random is H'0000', make it H'DEAD' ;
MOVLW H'DE' ;
MOVWF RAND_HI ;
MOVLW H'AD' ;
MOVWF RAND_LO ;
;
RANDOM_GO: ;
; hi.7 = hi.7 xor hi.6 ;
BTFSS RAND_HI, 6 ;
MOVLW H'00' ;
BTFSC RAND_HI, 6 ;
MOVLW H'80' ;
XORWF RAND_HI, F ;
;
; hi.7 = hi.7 xor hi.4 ;
BTFSS RAND_HI, 4 ;
MOVLW H'00' ;
BTFSC RAND_HI, 4 ;
MOVLW H'80' ;
XORWF RAND_HI, F ;
;
; hi.7 = hi.7 xor lo.3 ;
BTFSS RAND_LO, 3 ;
MOVLW H'00' ;
BTFSC RAND_LO, 3 ;
MOVLW H'80' ;
XORWF RAND_HI, F ;
;
; carry = hi.7 ;
RLF RAND_HI, W ;
; double left shift ;
RLF RAND_LO, F ;
RLF RAND_HI, F ;
;
RETURN ;
;---------------------------------------------------;
;---------------------------------------------------;
_Wait: ;
; Time to wait is in W ;
; Time is counted in Timer 0 interrupts ;
;---------------------------------------------------;
MOVWF Wait_Count ;
CLRF IV_TMRCount ;
Wait_Loop: ;
BTFSS GPIO, BUTTON_BIT ;
RETURN ;
;
MOVFW Wait_Count ;
XORWF IV_TMRCount, W ;
BTFSS STATUS, Z ;
GOTO Wait_Loop ;
;
RETURN ;
;---------------------------------------------------;
;---------------------------------------------------;
_Initialize_System: ;
;---------------------------------------------------;
; Hardware First ;
;-----------------------------------------------;
BANK0 ; Bank 0 registers
;
CLRF INTCON ; No interrupts enabled
;
MOVLW B'00000111' ; Comparator disabled
MOVWF CMCON ;
;
MOVLW BUTTON ; Button HIGH
MOVWF GPIO ; All DIE bits LOW
;
BANK1 ; Bank 1 registers
;
MOVLW BUTTON ; Button INPUT
MOVWF TRISIO ; All DIE bits OUTPUTS
;
; CALL H'3FF' ; SHOULD USE THIS
MOVLW H'3C' ; Change value for each device
MOVFW OSCCAL ; Set Oscillator Calibration
;
BSF OPTION_REG, NOT_GPPU ; No pullups
BCF OPTION_REG, INTEDG ; Don't care
BCF OPTION_REG, T0CS ;
BCF OPTION_REG, T0SE ;
BCF OPTION_REG, PSA ;
BSF OPTION_REG, PS2 ; 100 seems to be
BCF OPTION_REG, PS1 ; a good value for
BCF OPTION_REG, PS0 ; select delay
;
BANK0 ; Bank 0 registers
;
BTFSS GPIO, BUTTON_BIT ; wait for button high (released)
GOTO $-1 ;
;
;-----------------------------------------------;
; Memory Next ;
;-----------------------------------------------;
;
CLRF Dice ;
CLRF Dice_TEMP ;
CLRF IV_TMRCount ;
;
;-----------------------------------------------;
; Enable Timer0 Interrupt ;
;-----------------------------------------------;
;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
BSF INTCON, T0IE ; Enable timer0 interrupt
BSF INTCON, GIE ; Enable interrupts
;
RETURN ;
;---------------------------------------------------;
;---------------------------------------------------;
END ;
;---------------------------------------------------;
No comments:
Post a Comment