Above The Post Update 12.1117:
Final changes have been made. I added two 220 ohm resistors - between the collector of each transistor and the cathodes of the corresponding LEDs. This helps to reduce the current draw and increases battery life. I also added a 9V Transistor Battery to +5V circuit, so I can connect an easy to find 9V battery to the device. Lastly, I cleaned up the schematic and it should be easier to read. That should be it for any changes, unless I need to increase the battery life even more.
-----
I found some 100 LED Christmas lights at a local discount store for CHEAP. I paid only p169.50 (around US $4) for each string. I saw that they had one with PINK LEDs, so I bought that for projects and disassembled it once I got back to my MadLab.
100 LED Christmas light string in its' original condition.
The 100 LED Christmas light string - disassembled.
Since I
had 100 Pink LEDs, I decided to build something LED intensive. So, using
a PIC12F629 as the microcontroller, I decided to build a Dual Die
Emulator. Each die would consume 7 LEDs, so I would use 14 LEDs total for the project.
Back to the future: the project as it will look when completed.
The
PIC12F629 only has 8 pins - 1 power, 1 ground, 5 I/Os and 1 input. I
can produce the desired die faces using on 4 of the I/O lines, and the
input is used as the 'roll dice' button. With one I/O left, I decided to
use that to switch between the two die.
The prototype with many of the parts installed - the PIC, 14 LEDs,
the pushbutton switch, and the ISP header for programming the PIC.
I needed a pull up resistor for the pushbutton circuit, two transistors (a 2N4401 and 2N4403) with a 1K resistor each for the switching circuit, and 4 more resistors for limiting the current to the LEDs (also to isolate the LEDs from the PIC pins so they would not affect the programming of the PIC).
The prototype with all of the components installed.
What I was really concerned with was the switching circuit, so I wired up that part of the circuit and the center LEDs of each die and ran a test.
Testing the switching circuit.
That test came out just fine, so I wired up the rest of the circuitry.
The solder side / rat's nest. Not _too_ ugly.
After some testing and programming, I have a working Dual Die Emulator. Surprisingly, I didn't have to do any rework on the wires or components.
The completed dual die emulator
Now I just have to find a suitable power source and a nice enclosure.
UPDATE 12.1021
Here's a parts list for the project as it stands.
DUAL DIE EMULATOR
- (1) 6-pin male header (optional)
- (1) MicroChip PIC12F629
- (1) 8-pin DIP socket (optional)
- (14) Pink LED
- (1) 2N4401 transistor
- (1) 2N4403 transistor
- (3) 1K ohm resistor
- (3) 560 ohm resistor
- (1) 10K ohm resistor
- (1) Pushbutton switch (NO, momentary)
- (1) Piece of perf board, 4.5cm x 3cm
- (AR) Blue wire
Please note that both the 6-pin male header AND the 8-pin DIP socket are BOTH optional if the PIC microcontroller is programmed before installing on the board.UPDATE 12.1021:The Schematic for the Dual Die Emulator
UPDATE 12.1023
V2.01 Of The Dual Die Emulator CodeI've been working on the Die Emulator code. I've changed it where a timer triggers an interrupt, and the interrupt routine is responsible for drawing the actual die faces on the LEDs. This simplifies the code elsewhere as each routine does not need to know how to switch between the die - any new routine just writes to two die variables and the interrupt service routine takes care of displaying it. Cool! Looks good, too - bright and even.
Next up (V2.02) - enter a sleep mode 10 seconds after a roll. When the button is pushed, the PIC will wake up and roll the dice again. In sleep mode, the PIC will turn off all LEDs and enter a low power mode.
V2.01 of the dual die emulator code
Hack-A-Day has posted this project! Thanks! You've had an old hacker very happy. *wipes away tear*
Update 12.1027 (later in the day)There have been requests for the code, so it is included, below. I use the standard Microchip MPLAB IDE for my development environment. It's in assembly, so - sorry to all you 'C' hacks. I'm an old BIOS guy, I like assembly. Heh.
The formatting is weird on Blogger, but if you copy and paste into MPLAB, it should be okay.
NOTE: This code is free to use for educational purposes. If you intend to use it in a product that is intended to make money, please contact me first.
NOTE: I glommed the _Random code from somewhere on the 'net and the code is not my work and does not belong to me. As soon as I figure out where I got it, I will cite the ownership.
;***************************************************;
; Name: Electronic_Dice.ASM ;
; Use: Electronic Dice Simulator ;
;***************************************************;
; (C): 2012 Dysfunctional Technologies, Inc. ;
; All Rights Reserved ;
;***************************************************;
; Author: Timothy S. Carlson ;
; Dysfunctional Technologies, Inc. ;
; Date: October 27, 2012 ;
; Version: V2.01 ;
;***************************************************;
; 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 ;
;***************************************************;
;***************************************************;
; 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 ;
;***************************************************;
BANK0 MACRO ;
BCF STATUS, RP0 ;
ENDM ;
;
BANK1 MACRO ;
BSF STATUS, RP0 ;
ENDM ;
;
SET_DICE MACRO VAL1, VAL2, WAIT ;
MOVLW VAL1 ;
MOVWF Die1 ; Set Die 1 value
MOVLW VAL2 ;
MOVWF Die2 ; Set Die 2 value
IF (WAIT!=NOWAIT) ;
MOVLW WAIT ; Wait for specified time
CALL _Wait ; (allows ISR to display values)
ENDIF ;
ENDM ;
;
#DEFINE NOWAIT 0 ;
#DEFINE SUPERSLOW 100 ;
#DEFINE SLOW 50 ;
#DEFINE MEDIUM 25 ;
#DEFINE FAST 10 ;
#DEFINE SUPERFAST 3 ;
;
#DEFINE BUTTON_DIR TRISIO ;
#DEFINE BUTTON_PORT GPIO ;
#DEFINE BUTTON_BIT 3 ; GPIO 3 - Pin 4
;
#DEFINE DIE_DIR TRISIO ;
#DEFINE DIE_PORT GPIO ;
#DEFINE DIE_LDIAG_BIT 0 ; GPIO 0 - Pin 7
#DEFINE DIE_LDIAG H'01' ;
#DEFINE DIE_CTR_BIT 1 ; GPIO 1 - Pin 6
#DEFINE DIE_CTR H'02' ;
#DEFINE DIE_SELECT_BIT 2 ; GPIO 2 - Pin 5
#DEFINE DIE_SELECT H'04' ;
#DEFINE DIE_RDIAG_BIT 4 ; GPIO 4 - Pin 3
#DEFINE DIE_RDIAG H'10' ;
#DEFINE DIE_SIDES_BIT 5 ; GPIO 5 - Pin 2
#DEFINE DIE_SIDES H'20' ;
;
;***************************************************;
;***************************************************;
; Data ;
;***************************************************;
EDICE_DATA UDATA ;
sW res 1 ; 20
sSTATUS res 1 ; 21
sINTCON res 1 ; 22
;
Temp res 1 ; 23 general use
;
RAND_HI res 1 ; 24 16-bit random number
RAND_LO res 1 ; 25
;
Die1 res 1 ; 26
Die2 res 1 ; 27
Die_CURR res 1 ; 28
Die_TEMP res 1 ; 29
;
IV_Count res 1 ; 2A
Wait_Count res 1 ; 2B
;***************************************************;
;***************************************************;
; Reset Vector ;
;***************************************************;
RV_CODE CODE H'000' ;
;***************************************************;
CALL _Initialize_System ;
NOP ;
NOP ;
GOTO _Main ;
;***************************************************;
;***************************************************;
; Interrupt Vector ;
;***************************************************;
IV_CODE CODE H'004' ;
;***************************************************;
MOVWF sW ; Save W
MOVFW STATUS ; Retrieve STATUS
MOVWF sSTATUS ; and save it
;
IV_TIMER: ;
CALL _Die_BLANK ;
;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
;
MOVLW DIE_SELECT ; Toggle to other
XORWF DIE_PORT, F ; die face
CALL _Die_DISPLAY ; Display selected die
;
INCF IV_Count, F ;
;
IV_EXIT: ;
MOVFW sSTATUS ; Retrieve saved STATUS
MOVWF STATUS ; and restore
MOVFW sW ; Retrieve and restore saved W
RETFIE ;
;***************************************************;
;***************************************************;
MAIN_CODE CODE ;
;***************************************************;
_Main: ;
;***************************************************;
_Main_DIAG_LOOP: ;
MOVLW SLOW ; Delay, just in case
CALL _Wait ; PICKIT2 is attached
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
CALL _Diagnostics ;
BTFSC BUTTON_PORT, BUTTON_BIT ; Check Button LOW
GOTO _Main_DIAG_LOOP ; is not, DIAGS again
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
;
_Main_ROLL_DICE: ;
CALL _Die_ROLL ; Roll dice
_Main_WAIT: ;
BTFSC BUTTON_PORT, BUTTON_BIT ; Check Button LOW
GOTO _Main_WAIT ; if not, wait
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
GOTO _Main_ROLL_DICE ;
;***************************************************;
;***************************************************;
_Wait: ;
; Time to wait is in W ;
; Time is counted in Timer 0 interrupts ;
;***************************************************;
MOVWF Wait_Count ;
CLRF IV_Count ;
Wait_Loop: ;
BTFSS BUTTON_PORT, BUTTON_BIT ;
RETURN ;
;
MOVFW Wait_Count ;
XORWF IV_Count, W ;
BTFSS STATUS, Z ;
GOTO Wait_Loop ;
;
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 ;
;***************************************************;
;***************************************************;
_Diagnostics: ;
;***************************************************;
; Flash all die dots ;
;***********************************************;
MOVLW 3 ;
MOVWF Temp ;
;
D1_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 7, 0, FAST ;
SET_DICE 0, 7, FAST ;
SET_DICE 7, 7, FAST ;
;
DECFSZ Temp, F ;
GOTO D1_Loop ;
;
SET_DICE 0, 0, NOWAIT ;
;
;***********************************************;
; Wobble Die Dots ;
;***********************************************;
MOVLW 3 ;
MOVWF Temp ;
;
D2a_Loop: ;
SET_DICE 3, 0, FAST ;
SET_DICE 8, 0, FAST ;
SET_DICE 9, 0, FAST ;
SET_DICE 8, 0, FAST ;
SET_DICE 3, 0, FAST ;
SET_DICE 0, 3, FAST ;
SET_DICE 0, 8, FAST ;
SET_DICE 0, 9, FAST ;
SET_DICE 0, 8, FAST ;
SET_DICE 0, 3, FAST ;
;
DECFSZ Temp, F ;
GOTO D2a_Loop ;
;
MOVLW 6 ;
MOVWF Temp ;
;
SET_DICE 0, 0, NOWAIT ;
;
D2b_Loop: ;
SET_DICE 3, 9, FAST ;
SET_DICE 8, 8, FAST ;
SET_DICE 9, 3, FAST ;
SET_DICE 8, 8, FAST ;
;
DECFSZ Temp, F ;
GOTO D2b_Loop ;
;
;***********************************************;
; Cycle through all die faces ;
;***********************************************;
MOVLW H'3' ;
MOVWF Temp ;
;
D3_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 1, 0, FAST ;
SET_DICE 2, 0, FAST ;
SET_DICE 3, 0, FAST ;
SET_DICE 4, 0, FAST ;
SET_DICE 5, 0, FAST ;
SET_DICE 6, 0, FAST ;
SET_DICE 0, 0, FAST ;
SET_DICE 0, 1, FAST ;
SET_DICE 0, 2, FAST ;
SET_DICE 0, 3, FAST ;
SET_DICE 0, 4, FAST ;
SET_DICE 0, 5, FAST ;
SET_DICE 0, 6, FAST ;
SET_DICE 0, 0, FAST ;
SET_DICE 6, 1, FAST ;
SET_DICE 5, 2, FAST ;
SET_DICE 4, 3, FAST ;
SET_DICE 3, 4, FAST ;
SET_DICE 2, 5, FAST ;
SET_DICE 1, 6, FAST ;
;
DECFSZ Temp, F ;
GOTO D3_Loop ;
;
CALL _Die_ROLL ;
;
RETURN ;
;***************************************************;
;***************************************************;
_Die_DISPLAY: ;
;***************************************************;
MOVLW HIGH DIE_TABLE ;
MOVWF PCLATH ;
MOVFW Die1 ; Die1 or Die2
BTFSC DIE_PORT, DIE_SELECT_BIT ; depending on
MOVFW Die2 ; die select bit
ANDLW H'0F' ; Limit to 16
ADDLW LOW DIE_TABLE ;
BTFSC STATUS, C ; Check for
INCF PCLATH, F ; boundary cross
MOVWF PCL ; Do the jump!
;***********************************************;
; Die Table ;
;***********************************************;
DIE_TABLE: ;
GOTO _Die_BLANK ; 0
GOTO _Die_ONE ; 1
GOTO _Die_TWO ; 2
GOTO _Die_THREE ; 3
GOTO _Die_FOUR ; 4
GOTO _Die_FIVE ; 5
GOTO _Die_SIX ; 6
GOTO _Die_SEVEN ; 7
GOTO _Die_EIGHT ; 8
GOTO _Die_NINE ; 9
GOTO _Die_TEN ; A
GOTO _Die_BLANK ; B
GOTO _Die_BLANK ; C
GOTO _Die_BLANK ; D
GOTO _Die_BLANK ; E
GOTO _Die_BLANK ; F
;***************************************************;
;***************************************************;
_Die_ROLL: ;
;***************************************************;
MOVLW 3 ;
MOVWF Temp ;
;
DR_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 1, 1, FAST ;
SET_DICE 8, 8, FAST ;
SET_DICE 10, 10, FAST ;
;
DECFSZ Temp, F ;
GOTO DR_Loop ;
;
CALL _Get_Dice ;
RETURN ;
;***************************************************;
;***************************************************;
_Get_Dice: ;
;***************************************************;
CALL _Random ;
;
MOVFW RAND_LO ;
MOVWF Die1 ;
;
MOVLW H'07' ;
ANDWF Die1, F ;
;
MOVLW 0 ;
XORWF Die1, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVLW 7 ;
XORWF Die1, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVFW RAND_HI ;
MOVWF Die2 ;
;
MOVLW H'07' ;
ANDWF Die2, F ;
;
MOVLW 0 ;
XORWF Die2, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVLW 7 ;
XORWF Die2, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
RETURN ;
;***************************************************;
;***************************************************;
_Die_BLANK: ;
;***************************************************;
; 0 0 ;
; 000 ;
; 0 0 ;
;***************************************************;
MOVLW B'00000000' ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_ONE: ;
;***************************************************;
; 0 0 ;
; 0X0 ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_TWO: ;
;***************************************************;
; X 0 ;
; 000 ;
; 0 X ;
;***************************************************;
MOVLW DIE_LDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_THREE: ;
;***************************************************;
; 0 X ;
; 0XO ;
; X 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_FOUR: ;
;***************************************************;
; X X ;
; 0OO ;
; X X ;
;***************************************************;
MOVLW DIE_LDIAG | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_FIVE: ;
;***************************************************;
; X X ;
; 0X0 ;
; X X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_SIX: ;
;***************************************************;
; X X ;
; X0X ;
; X X ;
;***************************************************;
MOVLW DIE_LDIAG | DIE_RDIAG | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_SEVEN: ;
;***************************************************;
; X X ;
; XXX ;
; X X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG | DIE_RDIAG | DIE_SIDES
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_EIGHT: ;
;***************************************************;
; 0 0 ;
; XXX ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_NINE: ;
;***************************************************;
; X 0 ;
; 0X0 ;
; 0 X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_TEN: ;
;***************************************************;
; 0 0 ;
; X0X ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_DRAW: ;
;***************************************************;
MOVWF Die_TEMP ;
MOVLW DIE_SELECT ;
ANDWF DIE_PORT, F ;
MOVFW Die_TEMP ;
IORWF DIE_PORT, F ;
RETURN ;
;***************************************************;
;***************************************************;
_Initialize_System: ;
;***************************************************;
; Hardware First ;
;***********************************************;
BANK0 ; Bank 0 registers
;
CLRF INTCON ; No interrupts enabled
;
MOVLW B'00000111' ; Comparator disabled
MOVWF CMCON ;
;
BCF DIE_PORT, DIE_CTR_BIT ; Set LOW
BCF DIE_PORT, DIE_LDIAG_BIT ; Set LOW
BCF DIE_PORT, DIE_RDIAG_BIT ; Set LOW
BCF DIE_PORT, DIE_SIDES_BIT ; Set LOW
BCF DIE_PORT, DIE_SELECT_BIT ; Set LOW
BSF BUTTON_PORT, BUTTON_BIT ; Button HIGH (act as pull-up)
;
BANK1 ; Bank 1 registers
;
BCF DIE_DIR, DIE_CTR_BIT ; Output
BCF DIE_DIR, DIE_LDIAG_BIT ; Output
BCF DIE_DIR, DIE_RDIAG_BIT ; Output
BCF DIE_DIR, DIE_SIDES_BIT ; Output
BCF DIE_DIR, DIE_SELECT_BIT ; Output
BSF BUTTON_DIR, BUTTON_BIT ; Input
;
; CALL H'3FF' ; SHOULD USE THIS
MOVLW H'38' ; Change value for each device
MOVFW OSCCAL ; Set Oscillator Calibration
;
; CLRF OPTION_REG ;
BSF OPTION_REG, NOT_GPPU ;
BCF OPTION_REG, INTEDG ;
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 BUTTON_PORT, BUTTON_BIT ; wait for button high (released)
GOTO $-1 ;
;
;***********************************************;
; Memory Next ;
;***********************************************;
;
CLRF Die1 ;
CLRF Die2 ;
CLRF Die_CURR ;
CLRF IV_Count ;
;
;***********************************************;
; Enable Timer0 Interrupt ;
;***********************************************;
;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
BSF INTCON, T0IE ; Enable timer0 interrupt
BSF INTCON, GIE ; Enable interrupts
;
RETURN ;
;***************************************************;
;***************************************************;
END ;
;***************************************************;
; Name: Electronic_Dice.ASM ;
; Use: Electronic Dice Simulator ;
;***************************************************;
; (C): 2012 Dysfunctional Technologies, Inc. ;
; All Rights Reserved ;
;***************************************************;
; Author: Timothy S. Carlson ;
; Dysfunctional Technologies, Inc. ;
; Date: October 27, 2012 ;
; Version: V2.01 ;
;***************************************************;
; 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 ;
;***************************************************;
;***************************************************;
; 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 ;
;***************************************************;
BANK0 MACRO ;
BCF STATUS, RP0 ;
ENDM ;
;
BANK1 MACRO ;
BSF STATUS, RP0 ;
ENDM ;
;
SET_DICE MACRO VAL1, VAL2, WAIT ;
MOVLW VAL1 ;
MOVWF Die1 ; Set Die 1 value
MOVLW VAL2 ;
MOVWF Die2 ; Set Die 2 value
IF (WAIT!=NOWAIT) ;
MOVLW WAIT ; Wait for specified time
CALL _Wait ; (allows ISR to display values)
ENDIF ;
ENDM ;
;
#DEFINE NOWAIT 0 ;
#DEFINE SUPERSLOW 100 ;
#DEFINE SLOW 50 ;
#DEFINE MEDIUM 25 ;
#DEFINE FAST 10 ;
#DEFINE SUPERFAST 3 ;
;
#DEFINE BUTTON_DIR TRISIO ;
#DEFINE BUTTON_PORT GPIO ;
#DEFINE BUTTON_BIT 3 ; GPIO 3 - Pin 4
;
#DEFINE DIE_DIR TRISIO ;
#DEFINE DIE_PORT GPIO ;
#DEFINE DIE_LDIAG_BIT 0 ; GPIO 0 - Pin 7
#DEFINE DIE_LDIAG H'01' ;
#DEFINE DIE_CTR_BIT 1 ; GPIO 1 - Pin 6
#DEFINE DIE_CTR H'02' ;
#DEFINE DIE_SELECT_BIT 2 ; GPIO 2 - Pin 5
#DEFINE DIE_SELECT H'04' ;
#DEFINE DIE_RDIAG_BIT 4 ; GPIO 4 - Pin 3
#DEFINE DIE_RDIAG H'10' ;
#DEFINE DIE_SIDES_BIT 5 ; GPIO 5 - Pin 2
#DEFINE DIE_SIDES H'20' ;
;
;***************************************************;
;***************************************************;
; Data ;
;***************************************************;
EDICE_DATA UDATA ;
sW res 1 ; 20
sSTATUS res 1 ; 21
sINTCON res 1 ; 22
;
Temp res 1 ; 23 general use
;
RAND_HI res 1 ; 24 16-bit random number
RAND_LO res 1 ; 25
;
Die1 res 1 ; 26
Die2 res 1 ; 27
Die_CURR res 1 ; 28
Die_TEMP res 1 ; 29
;
IV_Count res 1 ; 2A
Wait_Count res 1 ; 2B
;***************************************************;
;***************************************************;
; Reset Vector ;
;***************************************************;
RV_CODE CODE H'000' ;
;***************************************************;
CALL _Initialize_System ;
NOP ;
NOP ;
GOTO _Main ;
;***************************************************;
;***************************************************;
; Interrupt Vector ;
;***************************************************;
IV_CODE CODE H'004' ;
;***************************************************;
MOVWF sW ; Save W
MOVFW STATUS ; Retrieve STATUS
MOVWF sSTATUS ; and save it
;
IV_TIMER: ;
CALL _Die_BLANK ;
;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
;
MOVLW DIE_SELECT ; Toggle to other
XORWF DIE_PORT, F ; die face
CALL _Die_DISPLAY ; Display selected die
;
INCF IV_Count, F ;
;
IV_EXIT: ;
MOVFW sSTATUS ; Retrieve saved STATUS
MOVWF STATUS ; and restore
MOVFW sW ; Retrieve and restore saved W
RETFIE ;
;***************************************************;
;***************************************************;
MAIN_CODE CODE ;
;***************************************************;
_Main: ;
;***************************************************;
_Main_DIAG_LOOP: ;
MOVLW SLOW ; Delay, just in case
CALL _Wait ; PICKIT2 is attached
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
CALL _Diagnostics ;
BTFSC BUTTON_PORT, BUTTON_BIT ; Check Button LOW
GOTO _Main_DIAG_LOOP ; is not, DIAGS again
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
;
_Main_ROLL_DICE: ;
CALL _Die_ROLL ; Roll dice
_Main_WAIT: ;
BTFSC BUTTON_PORT, BUTTON_BIT ; Check Button LOW
GOTO _Main_WAIT ; if not, wait
BTFSS BUTTON_PORT, BUTTON_BIT ; Wait Button HIGH
GOTO $-1 ;
GOTO _Main_ROLL_DICE ;
;***************************************************;
;***************************************************;
_Wait: ;
; Time to wait is in W ;
; Time is counted in Timer 0 interrupts ;
;***************************************************;
MOVWF Wait_Count ;
CLRF IV_Count ;
Wait_Loop: ;
BTFSS BUTTON_PORT, BUTTON_BIT ;
RETURN ;
;
MOVFW Wait_Count ;
XORWF IV_Count, W ;
BTFSS STATUS, Z ;
GOTO Wait_Loop ;
;
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 ;
;***************************************************;
;***************************************************;
_Diagnostics: ;
;***************************************************;
; Flash all die dots ;
;***********************************************;
MOVLW 3 ;
MOVWF Temp ;
;
D1_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 7, 0, FAST ;
SET_DICE 0, 7, FAST ;
SET_DICE 7, 7, FAST ;
;
DECFSZ Temp, F ;
GOTO D1_Loop ;
;
SET_DICE 0, 0, NOWAIT ;
;
;***********************************************;
; Wobble Die Dots ;
;***********************************************;
MOVLW 3 ;
MOVWF Temp ;
;
D2a_Loop: ;
SET_DICE 3, 0, FAST ;
SET_DICE 8, 0, FAST ;
SET_DICE 9, 0, FAST ;
SET_DICE 8, 0, FAST ;
SET_DICE 3, 0, FAST ;
SET_DICE 0, 3, FAST ;
SET_DICE 0, 8, FAST ;
SET_DICE 0, 9, FAST ;
SET_DICE 0, 8, FAST ;
SET_DICE 0, 3, FAST ;
;
DECFSZ Temp, F ;
GOTO D2a_Loop ;
;
MOVLW 6 ;
MOVWF Temp ;
;
SET_DICE 0, 0, NOWAIT ;
;
D2b_Loop: ;
SET_DICE 3, 9, FAST ;
SET_DICE 8, 8, FAST ;
SET_DICE 9, 3, FAST ;
SET_DICE 8, 8, FAST ;
;
DECFSZ Temp, F ;
GOTO D2b_Loop ;
;
;***********************************************;
; Cycle through all die faces ;
;***********************************************;
MOVLW H'3' ;
MOVWF Temp ;
;
D3_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 1, 0, FAST ;
SET_DICE 2, 0, FAST ;
SET_DICE 3, 0, FAST ;
SET_DICE 4, 0, FAST ;
SET_DICE 5, 0, FAST ;
SET_DICE 6, 0, FAST ;
SET_DICE 0, 0, FAST ;
SET_DICE 0, 1, FAST ;
SET_DICE 0, 2, FAST ;
SET_DICE 0, 3, FAST ;
SET_DICE 0, 4, FAST ;
SET_DICE 0, 5, FAST ;
SET_DICE 0, 6, FAST ;
SET_DICE 0, 0, FAST ;
SET_DICE 6, 1, FAST ;
SET_DICE 5, 2, FAST ;
SET_DICE 4, 3, FAST ;
SET_DICE 3, 4, FAST ;
SET_DICE 2, 5, FAST ;
SET_DICE 1, 6, FAST ;
;
DECFSZ Temp, F ;
GOTO D3_Loop ;
;
CALL _Die_ROLL ;
;
RETURN ;
;***************************************************;
;***************************************************;
_Die_DISPLAY: ;
;***************************************************;
MOVLW HIGH DIE_TABLE ;
MOVWF PCLATH ;
MOVFW Die1 ; Die1 or Die2
BTFSC DIE_PORT, DIE_SELECT_BIT ; depending on
MOVFW Die2 ; die select bit
ANDLW H'0F' ; Limit to 16
ADDLW LOW DIE_TABLE ;
BTFSC STATUS, C ; Check for
INCF PCLATH, F ; boundary cross
MOVWF PCL ; Do the jump!
;***********************************************;
; Die Table ;
;***********************************************;
DIE_TABLE: ;
GOTO _Die_BLANK ; 0
GOTO _Die_ONE ; 1
GOTO _Die_TWO ; 2
GOTO _Die_THREE ; 3
GOTO _Die_FOUR ; 4
GOTO _Die_FIVE ; 5
GOTO _Die_SIX ; 6
GOTO _Die_SEVEN ; 7
GOTO _Die_EIGHT ; 8
GOTO _Die_NINE ; 9
GOTO _Die_TEN ; A
GOTO _Die_BLANK ; B
GOTO _Die_BLANK ; C
GOTO _Die_BLANK ; D
GOTO _Die_BLANK ; E
GOTO _Die_BLANK ; F
;***************************************************;
;***************************************************;
_Die_ROLL: ;
;***************************************************;
MOVLW 3 ;
MOVWF Temp ;
;
DR_Loop: ;
SET_DICE 0, 0, FAST ;
SET_DICE 1, 1, FAST ;
SET_DICE 8, 8, FAST ;
SET_DICE 10, 10, FAST ;
;
DECFSZ Temp, F ;
GOTO DR_Loop ;
;
CALL _Get_Dice ;
RETURN ;
;***************************************************;
;***************************************************;
_Get_Dice: ;
;***************************************************;
CALL _Random ;
;
MOVFW RAND_LO ;
MOVWF Die1 ;
;
MOVLW H'07' ;
ANDWF Die1, F ;
;
MOVLW 0 ;
XORWF Die1, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVLW 7 ;
XORWF Die1, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVFW RAND_HI ;
MOVWF Die2 ;
;
MOVLW H'07' ;
ANDWF Die2, F ;
;
MOVLW 0 ;
XORWF Die2, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
MOVLW 7 ;
XORWF Die2, W ;
BTFSC STATUS, Z ;
GOTO _Get_Dice ;
;
RETURN ;
;***************************************************;
;***************************************************;
_Die_BLANK: ;
;***************************************************;
; 0 0 ;
; 000 ;
; 0 0 ;
;***************************************************;
MOVLW B'00000000' ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_ONE: ;
;***************************************************;
; 0 0 ;
; 0X0 ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_TWO: ;
;***************************************************;
; X 0 ;
; 000 ;
; 0 X ;
;***************************************************;
MOVLW DIE_LDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_THREE: ;
;***************************************************;
; 0 X ;
; 0XO ;
; X 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_FOUR: ;
;***************************************************;
; X X ;
; 0OO ;
; X X ;
;***************************************************;
MOVLW DIE_LDIAG | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_FIVE: ;
;***************************************************;
; X X ;
; 0X0 ;
; X X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG | DIE_RDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_SIX: ;
;***************************************************;
; X X ;
; X0X ;
; X X ;
;***************************************************;
MOVLW DIE_LDIAG | DIE_RDIAG | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_SEVEN: ;
;***************************************************;
; X X ;
; XXX ;
; X X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG | DIE_RDIAG | DIE_SIDES
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_EIGHT: ;
;***************************************************;
; 0 0 ;
; XXX ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_NINE: ;
;***************************************************;
; X 0 ;
; 0X0 ;
; 0 X ;
;***************************************************;
MOVLW DIE_CTR | DIE_LDIAG ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_TEN: ;
;***************************************************;
; 0 0 ;
; X0X ;
; 0 0 ;
;***************************************************;
MOVLW DIE_CTR | DIE_SIDES ;
GOTO _Die_DRAW ;
;***************************************************;
;***************************************************;
_Die_DRAW: ;
;***************************************************;
MOVWF Die_TEMP ;
MOVLW DIE_SELECT ;
ANDWF DIE_PORT, F ;
MOVFW Die_TEMP ;
IORWF DIE_PORT, F ;
RETURN ;
;***************************************************;
;***************************************************;
_Initialize_System: ;
;***************************************************;
; Hardware First ;
;***********************************************;
BANK0 ; Bank 0 registers
;
CLRF INTCON ; No interrupts enabled
;
MOVLW B'00000111' ; Comparator disabled
MOVWF CMCON ;
;
BCF DIE_PORT, DIE_CTR_BIT ; Set LOW
BCF DIE_PORT, DIE_LDIAG_BIT ; Set LOW
BCF DIE_PORT, DIE_RDIAG_BIT ; Set LOW
BCF DIE_PORT, DIE_SIDES_BIT ; Set LOW
BCF DIE_PORT, DIE_SELECT_BIT ; Set LOW
BSF BUTTON_PORT, BUTTON_BIT ; Button HIGH (act as pull-up)
;
BANK1 ; Bank 1 registers
;
BCF DIE_DIR, DIE_CTR_BIT ; Output
BCF DIE_DIR, DIE_LDIAG_BIT ; Output
BCF DIE_DIR, DIE_RDIAG_BIT ; Output
BCF DIE_DIR, DIE_SIDES_BIT ; Output
BCF DIE_DIR, DIE_SELECT_BIT ; Output
BSF BUTTON_DIR, BUTTON_BIT ; Input
;
; CALL H'3FF' ; SHOULD USE THIS
MOVLW H'38' ; Change value for each device
MOVFW OSCCAL ; Set Oscillator Calibration
;
; CLRF OPTION_REG ;
BSF OPTION_REG, NOT_GPPU ;
BCF OPTION_REG, INTEDG ;
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 BUTTON_PORT, BUTTON_BIT ; wait for button high (released)
GOTO $-1 ;
;
;***********************************************;
; Memory Next ;
;***********************************************;
;
CLRF Die1 ;
CLRF Die2 ;
CLRF Die_CURR ;
CLRF IV_Count ;
;
;***********************************************;
; Enable Timer0 Interrupt ;
;***********************************************;
;
BCF INTCON, T0IF ; Clear timer0 interrupt flag
BSF INTCON, T0IE ; Enable timer0 interrupt
BSF INTCON, GIE ; Enable interrupts
;
RETURN ;
;***************************************************;
;***************************************************;
END ;
;***************************************************;
Update 12.1027 (even later in the day)
I have come up with a V2.0 schematic, thanks to all the folks at Hack-A-Day that have great ideas. I haven't built/programmed it yet, but when I do, I will do another post!
Update 12.1028
It's built. See the new post here.
Update 12.1028
It's built. See the new post here.
Any chance on sharing your code?
ReplyDeleteVery cool, i was wanting to look at the code. not that i can read much more complicated than arduino, but i could try :)
ReplyDeleteCode is now posted. Free to use for educational purposes, but - if you intend to use it in a product that will make money, please contact me first.
ReplyDeleteCool!
ReplyDeleteHow about adding a shake sensor to make it hands free.
http://www.electrodragon.com/?product=vibration-switch-sensor-sw-18020p
The shake sensor is a nice idea. I can do it with a weighted spring and a contact post. Maybe I'll work on that tonight.
ReplyDeleteHi. I tried to make hex fiel but it give allot of errors. Can anibody tell me what is the problem? I use MPLAB IDE 8.89
ReplyDeleteThanks
Ah, this is the 12F629. I use the following .LKR file, which is not standard:
Deletehttp://pastebin.com/EGXYMSvP
This should fix you data space errors.
I manage all error except that for the space.
ReplyDeleteWith your help I will try this evening again.
Thanks