1 | /************************************************************************/
|
2 | /* */
|
3 | /* Dice with manual controlled random number */
|
4 | /* */
|
5 | /* Author: Peter Dannegger */
|
6 | /* */
|
7 | /************************************************************************/
|
8 |
|
9 | #pragma cd pl(9999) rom(small)
|
10 |
|
11 | #include"reg51.h"
|
12 | #include"types.h"
|
13 |
|
14 | #define XTAL 8.8e6
|
15 |
|
16 | #define DICE_TIMER 241 // roll dice (invisible)
|
17 | #define DISPLAY_TIMER 251 // roll display (visible)
|
18 | #define DISPLAY_SPEED ((uint)(XTAL / 12.0 / DISPLAY_TIMER / 10 + 0.5))
|
19 | // 10Hz
|
20 |
|
21 | #define BUTTON INT1
|
22 |
|
23 | #define _A BIN8(0,0,1,0,0,0,0,0) // Dice LEDs:
|
24 | #define _B BIN8(0,0,0,0,1,0,0,0)
|
25 | #define _C BIN8(0,1,0,0,0,0,0,0) // A B
|
26 | #define _D BIN8(0,0,0,1,0,0,0,0)
|
27 | #define _E BIN8(0,0,0,0,0,1,0,0) // C D E
|
28 | #define _F BIN8(1,0,0,0,0,0,0,0)
|
29 | #define _G BIN8(0,0,0,0,0,0,1,0) // F G
|
30 |
|
31 |
|
32 | #define PRESS_BUTTON 0 // roll dice
|
33 | #define ROLL_OUT 1 // roll out
|
34 | #define STOP 2 // stop dice
|
35 | #define WAIT 3 // minimum delay until next dice
|
36 | #define NEXT_DICE 4 // wait for next press
|
37 |
|
38 | #define T_POWER_OFF 250 // power off time
|
39 | #define T_ROLL_OUT 3 // minimum roll out count
|
40 | #define T_WAIT 10 // minimum delay time
|
41 |
|
42 |
|
43 | uchar dice_new; // new value, if key released
|
44 |
|
45 |
|
46 | void main( void )
|
47 | {
|
48 | uchar code DICE[] = { 0xFE - _D,
|
49 | 0xFE - _A - _G,
|
50 | 0xFE - _B - _D - _F,
|
51 | 0xFE - _A - _B - _F - _G,
|
52 | 0xFE - _A - _B - _D - _F - _G,
|
53 | 0xFE - _A - _B - _C - _E - _F - _G };
|
54 |
|
55 | uchar dice_view; // visible rolls every 100ms
|
56 | uchar dice_state; // dice state machine
|
57 | uchar timeout;
|
58 | uint timer_100ms; // 100ms time base
|
59 |
|
60 | timer_100ms = 1;
|
61 | TMOD = T0_M1_ + T1_M1_; // T0, T1: 8-bit reload
|
62 | TH0 = -DICE_TIMER;
|
63 | TH1 = -DISPLAY_TIMER;
|
64 | TCON = TR0_ + TR1_ + TF1_;
|
65 | IE = EA_ + ET0_;
|
66 | for(;;){ // main loop
|
67 | if( TF1 == 0 )
|
68 | continue;
|
69 | TF1 = 0;
|
70 | if( --timer_100ms )
|
71 | continue;
|
72 | timer_100ms = DISPLAY_SPEED;
|
73 |
|
74 | P1 = DICE[dice_view]; // display dice value
|
75 |
|
76 | switch( dice_state ){ // dice state machine
|
77 |
|
78 | case PRESS_BUTTON:
|
79 | if( --timeout == 0 ){ // key pressed too long
|
80 | dice_state = NEXT_DICE;
|
81 | timeout = T_POWER_OFF;
|
82 | P1 = 0xFE; // all LEDs off
|
83 | PCON = PD_; // enter power down
|
84 | }
|
85 | if( dice_new > 5 )
|
86 | break; // "break;" = run dice
|
87 | timeout = T_ROLL_OUT + 1;
|
88 | dice_state = ROLL_OUT; // button released
|
89 |
|
90 | case ROLL_OUT:
|
91 | if( --timeout ) // some further rolls
|
92 | break; // "break;" = run dice
|
93 | dice_state = STOP;
|
94 |
|
95 | case STOP:
|
96 | if( dice_new != dice_view ) // continue until new value reached
|
97 | break; // "break;" = run dice
|
98 | timeout = T_WAIT + 1;
|
99 | dice_state = WAIT;
|
100 |
|
101 | case WAIT: // display new value
|
102 | if( --timeout )
|
103 | continue; // "continue;" = stop dice
|
104 | timeout = T_POWER_OFF + 1;
|
105 | dice_state = NEXT_DICE;
|
106 |
|
107 | case NEXT_DICE:
|
108 | default:
|
109 | if( BUTTON ){ // key still released
|
110 | if( --timeout )
|
111 | continue; // "continue;" = stop dice
|
112 | // key released too long
|
113 | timeout = T_POWER_OFF;
|
114 | P1 = 0xFE; // all LEDs off
|
115 | PCON = PD_; // enter power down
|
116 | }
|
117 | dice_state = PRESS_BUTTON; // key pressed again
|
118 | dice_new = 6; // mark as invalid
|
119 | timeout = T_POWER_OFF;
|
120 | }
|
121 |
|
122 | if( ++dice_view > 5 ) // run visible dice
|
123 | dice_view = 0;
|
124 | }
|
125 | }
|
126 |
|
127 |
|
128 | void t0_interrupt( void ) interrupt INT_T0
|
129 | {
|
130 | static uchar dice; // real dice (invisible)
|
131 | if( BUTTON && dice_new > 5 ) // if key released
|
132 | dice_new = dice; // get new dice value
|
133 | if( ++dice > 5 ) // 0,1,2,3,4,5
|
134 | dice = 0;
|
135 | }
|