Another dice program for the mbuino.
Dependencies: mbed mBuino_Sleep
You probably want http://mbed.org/users/maxint/code/mBuino_Dice/ rather than this one, that was the original mbuino dice program.
This version is based off the original release of the project above. It was then significantly re-written for a mixture of power consumption, randomness and coding style reasons. Most of the changes and improvements have since been incorporated into later versions of maxint's dice program (together with a few of his later ideas being copied into this version) so there are no meaningful functional differences between the two.
This version is posted mainly to provide an example of a slightly different way to do the same thing.
dice.cpp@1:05f369319854, 2014-09-23 (annotated)
- Committer:
- AndyA
- Date:
- Tue Sep 23 15:43:29 2014 +0000
- Revision:
- 1:05f369319854
- Parent:
- 0:24177fc1e0e3
Changed to using sleep library.; Fixed sweep single to look nicer. Dropped delays for wake/sleep animations.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AndyA | 0:24177fc1e0e3 | 1 | /* |
AndyA | 0:24177fc1e0e3 | 2 | ** mBuino_Dice |
AndyA | 0:24177fc1e0e3 | 3 | ** |
AndyA | 0:24177fc1e0e3 | 4 | ** This electronic dice application allows the user to throw an electronic dice by the press of a button |
AndyA | 0:24177fc1e0e3 | 5 | ** |
AndyA | 0:24177fc1e0e3 | 6 | ** On mBuino P0.4 is close to GND and the two pitch distance is exactly the same as a mini-switch! |
AndyA | 0:24177fc1e0e3 | 7 | ** |
AndyA | 0:24177fc1e0e3 | 8 | ** Base code from version 1 of http://mbed.org/users/maxint/code/mBuino_Dice/ |
AndyA | 0:24177fc1e0e3 | 9 | ** |
AndyA | 0:24177fc1e0e3 | 10 | ** Modifed to improve randomness and decrease power draw and a few random changes to coding style |
AndyA | 0:24177fc1e0e3 | 11 | ** Most meaningful changes are now implimented in the later versions of the above code. |
AndyA | 0:24177fc1e0e3 | 12 | */ |
AndyA | 0:24177fc1e0e3 | 13 | |
AndyA | 0:24177fc1e0e3 | 14 | #include "mbed.h" |
AndyA | 1:05f369319854 | 15 | #include "mBuinoSleep.h" |
AndyA | 0:24177fc1e0e3 | 16 | |
AndyA | 0:24177fc1e0e3 | 17 | InterruptIn ActionButton(P0_4); // Vibration sensor |
AndyA | 0:24177fc1e0e3 | 18 | AnalogIn RandomIn(P0_14); // use the random noise on this analog input to seed the random generator |
AndyA | 0:24177fc1e0e3 | 19 | |
AndyA | 0:24177fc1e0e3 | 20 | // LED bus value to display |
AndyA | 1:05f369319854 | 21 | uint8_t LEDValue = 0; |
AndyA | 0:24177fc1e0e3 | 22 | |
AndyA | 0:24177fc1e0e3 | 23 | // sleep can be sleep, deepsleep or power down. |
AndyA | 0:24177fc1e0e3 | 24 | // clean power down and cleen deep sleep do a clean shutdown of the PLL. |
AndyA | 0:24177fc1e0e3 | 25 | // However any code called during the wakeup IRQ will then run at a slower speed. |
AndyA | 1:05f369319854 | 26 | //enum sleepMode_t {powerDown=0, deepSleep, lightSleep, cleanPowerDown, cleanDeepSleep}; |
AndyA | 0:24177fc1e0e3 | 27 | |
AndyA | 0:24177fc1e0e3 | 28 | |
AndyA | 0:24177fc1e0e3 | 29 | // idle time to wait before sleeping |
AndyA | 0:24177fc1e0e3 | 30 | const float timeoutBeforeSleep = 15; |
AndyA | 0:24177fc1e0e3 | 31 | |
AndyA | 0:24177fc1e0e3 | 32 | |
AndyA | 0:24177fc1e0e3 | 33 | const uint8_t DicePattern[6] = { 0x08, // 0b 000_1_000 |
AndyA | 0:24177fc1e0e3 | 34 | 0x22, // 0b 010_0_010 |
AndyA | 0:24177fc1e0e3 | 35 | 0x2a, // 0b 010_1_010 |
AndyA | 0:24177fc1e0e3 | 36 | 0x55, // 0b 101_0_101 |
AndyA | 0:24177fc1e0e3 | 37 | 0x5d, // 0b 101_1_101 |
AndyA | 0:24177fc1e0e3 | 38 | 0x77 // 0b 111_0_111 |
AndyA | 0:24177fc1e0e3 | 39 | }; |
AndyA | 0:24177fc1e0e3 | 40 | |
AndyA | 0:24177fc1e0e3 | 41 | volatile bool fButtonPressed; |
AndyA | 0:24177fc1e0e3 | 42 | |
AndyA | 0:24177fc1e0e3 | 43 | volatile bool sleepNow=false; |
AndyA | 0:24177fc1e0e3 | 44 | |
AndyA | 0:24177fc1e0e3 | 45 | Timer timeTracker; |
AndyA | 0:24177fc1e0e3 | 46 | Timeout sleepMode; |
AndyA | 0:24177fc1e0e3 | 47 | |
AndyA | 0:24177fc1e0e3 | 48 | |
AndyA | 0:24177fc1e0e3 | 49 | // this cycles the LEDs so they are on for 1/7th of the time with only one lit at a time. |
AndyA | 0:24177fc1e0e3 | 50 | // but since it does it at 1kHz they just look a little dimmer to the human eye. |
AndyA | 0:24177fc1e0e3 | 51 | // This can give a big power saving when running on a battery. |
AndyA | 0:24177fc1e0e3 | 52 | Ticker ledCycle; |
AndyA | 0:24177fc1e0e3 | 53 | |
AndyA | 0:24177fc1e0e3 | 54 | void on1msTick() |
AndyA | 0:24177fc1e0e3 | 55 | { |
AndyA | 0:24177fc1e0e3 | 56 | static uint8_t ledIndex = 0; |
AndyA | 1:05f369319854 | 57 | LEDs = LEDValue & 0x01<<ledIndex++; |
AndyA | 0:24177fc1e0e3 | 58 | if (ledIndex == 7) |
AndyA | 0:24177fc1e0e3 | 59 | ledIndex = 0; |
AndyA | 0:24177fc1e0e3 | 60 | } |
AndyA | 0:24177fc1e0e3 | 61 | |
AndyA | 0:24177fc1e0e3 | 62 | |
AndyA | 0:24177fc1e0e3 | 63 | |
AndyA | 0:24177fc1e0e3 | 64 | // LED state setting functions. |
AndyA | 0:24177fc1e0e3 | 65 | |
AndyA | 0:24177fc1e0e3 | 66 | void SetLeds(bool on) |
AndyA | 0:24177fc1e0e3 | 67 | { |
AndyA | 0:24177fc1e0e3 | 68 | if (on) |
AndyA | 1:05f369319854 | 69 | LEDValue=0x7f; |
AndyA | 0:24177fc1e0e3 | 70 | else |
AndyA | 1:05f369319854 | 71 | LEDValue=0; |
AndyA | 0:24177fc1e0e3 | 72 | } |
AndyA | 0:24177fc1e0e3 | 73 | |
AndyA | 0:24177fc1e0e3 | 74 | void SetLed(uint8_t ledID, bool on) |
AndyA | 0:24177fc1e0e3 | 75 | { |
AndyA | 0:24177fc1e0e3 | 76 | if (ledID <= 6) { |
AndyA | 0:24177fc1e0e3 | 77 | if (on) |
AndyA | 1:05f369319854 | 78 | LEDValue = LEDValue | (0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 79 | else |
AndyA | 1:05f369319854 | 80 | LEDValue = LEDValue & ~(0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 81 | } |
AndyA | 0:24177fc1e0e3 | 82 | } |
AndyA | 0:24177fc1e0e3 | 83 | |
AndyA | 0:24177fc1e0e3 | 84 | void ToggleLeds() |
AndyA | 0:24177fc1e0e3 | 85 | { |
AndyA | 1:05f369319854 | 86 | LEDValue = ~LEDValue; |
AndyA | 0:24177fc1e0e3 | 87 | } |
AndyA | 0:24177fc1e0e3 | 88 | |
AndyA | 0:24177fc1e0e3 | 89 | void ToggleLed(uint8_t ledID) |
AndyA | 0:24177fc1e0e3 | 90 | { |
AndyA | 0:24177fc1e0e3 | 91 | if (ledID <= 6) |
AndyA | 1:05f369319854 | 92 | LEDValue = LEDValue ^ (0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 93 | } |
AndyA | 0:24177fc1e0e3 | 94 | |
AndyA | 0:24177fc1e0e3 | 95 | void BlinkLeds(bool on=true, float delay=0.1) |
AndyA | 0:24177fc1e0e3 | 96 | { |
AndyA | 1:05f369319854 | 97 | uint8_t state = LEDValue; |
AndyA | 0:24177fc1e0e3 | 98 | SetLeds(on); |
AndyA | 0:24177fc1e0e3 | 99 | wait(delay); |
AndyA | 1:05f369319854 | 100 | LEDValue = state; |
AndyA | 0:24177fc1e0e3 | 101 | wait(delay); |
AndyA | 0:24177fc1e0e3 | 102 | } |
AndyA | 0:24177fc1e0e3 | 103 | |
AndyA | 0:24177fc1e0e3 | 104 | void ShowDice(uint8_t nNumber) |
AndyA | 0:24177fc1e0e3 | 105 | { |
AndyA | 0:24177fc1e0e3 | 106 | // switch the leds of a particular dice-number on or off |
AndyA | 0:24177fc1e0e3 | 107 | if(nNumber<1) nNumber=1; |
AndyA | 0:24177fc1e0e3 | 108 | if(nNumber>6) nNumber=6; |
AndyA | 0:24177fc1e0e3 | 109 | |
AndyA | 1:05f369319854 | 110 | LEDValue=DicePattern[nNumber - 1]; |
AndyA | 0:24177fc1e0e3 | 111 | } |
AndyA | 0:24177fc1e0e3 | 112 | |
AndyA | 0:24177fc1e0e3 | 113 | |
AndyA | 0:24177fc1e0e3 | 114 | void BlinkOneLed(uint8_t ledID, float delay = 0.1) |
AndyA | 0:24177fc1e0e3 | 115 | { |
AndyA | 0:24177fc1e0e3 | 116 | ToggleLed(ledID); |
AndyA | 0:24177fc1e0e3 | 117 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 118 | ToggleLed(ledID); |
AndyA | 0:24177fc1e0e3 | 119 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 120 | } |
AndyA | 0:24177fc1e0e3 | 121 | |
AndyA | 0:24177fc1e0e3 | 122 | void SweepSingleLed(bool leftToRight = true, float delay = 0.2) |
AndyA | 0:24177fc1e0e3 | 123 | { |
AndyA | 0:24177fc1e0e3 | 124 | SetLeds(false); |
AndyA | 1:05f369319854 | 125 | for(int n=0; n<7; n++) { |
AndyA | 1:05f369319854 | 126 | SetLed(leftToRight?n:6-n,true); |
AndyA | 1:05f369319854 | 127 | wait(delay); |
AndyA | 1:05f369319854 | 128 | SetLed(leftToRight?n:6-n,false); |
AndyA | 1:05f369319854 | 129 | } |
AndyA | 0:24177fc1e0e3 | 130 | } |
AndyA | 0:24177fc1e0e3 | 131 | |
AndyA | 0:24177fc1e0e3 | 132 | void StackLEDs(float delay = 0.2) |
AndyA | 0:24177fc1e0e3 | 133 | { |
AndyA | 0:24177fc1e0e3 | 134 | SetLeds(false); |
AndyA | 0:24177fc1e0e3 | 135 | int i; |
AndyA | 0:24177fc1e0e3 | 136 | int j; |
AndyA | 0:24177fc1e0e3 | 137 | for (i = 7; i > 0; i--) { |
AndyA | 0:24177fc1e0e3 | 138 | for (j=0; j<i; j++) { |
AndyA | 0:24177fc1e0e3 | 139 | SetLed(6-j,true); |
AndyA | 0:24177fc1e0e3 | 140 | wait(delay); |
AndyA | 0:24177fc1e0e3 | 141 | SetLed(6-j,false); |
AndyA | 0:24177fc1e0e3 | 142 | } |
AndyA | 0:24177fc1e0e3 | 143 | SetLed(7-j,true); |
AndyA | 0:24177fc1e0e3 | 144 | } |
AndyA | 0:24177fc1e0e3 | 145 | } |
AndyA | 0:24177fc1e0e3 | 146 | |
AndyA | 0:24177fc1e0e3 | 147 | void SweepAllLeds(bool leftToRight = true, float delay=0.2) |
AndyA | 0:24177fc1e0e3 | 148 | { |
AndyA | 0:24177fc1e0e3 | 149 | for(int n=0; n<7; n++) { |
AndyA | 0:24177fc1e0e3 | 150 | SetLed(leftToRight?n:6-n, true); |
AndyA | 0:24177fc1e0e3 | 151 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 152 | } |
AndyA | 0:24177fc1e0e3 | 153 | for(int n=0; n<7; n++) { |
AndyA | 0:24177fc1e0e3 | 154 | SetLed(leftToRight?6-n:n, false); |
AndyA | 0:24177fc1e0e3 | 155 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 156 | } |
AndyA | 0:24177fc1e0e3 | 157 | } |
AndyA | 0:24177fc1e0e3 | 158 | |
AndyA | 0:24177fc1e0e3 | 159 | |
AndyA | 1:05f369319854 | 160 | void enterSleep(enum sleepMode_t mode) |
AndyA | 0:24177fc1e0e3 | 161 | { |
AndyA | 0:24177fc1e0e3 | 162 | |
AndyA | 1:05f369319854 | 163 | SweepSingleLed(true, 0.1); |
AndyA | 1:05f369319854 | 164 | SweepSingleLed(false, 0.1); |
AndyA | 0:24177fc1e0e3 | 165 | |
AndyA | 0:24177fc1e0e3 | 166 | // stop timers. |
AndyA | 0:24177fc1e0e3 | 167 | timeTracker.stop(); |
AndyA | 0:24177fc1e0e3 | 168 | ledCycle.detach(); |
AndyA | 0:24177fc1e0e3 | 169 | |
AndyA | 1:05f369319854 | 170 | // enter sleep |
AndyA | 1:05f369319854 | 171 | mBuinoSleep(mode); |
AndyA | 1:05f369319854 | 172 | |
AndyA | 1:05f369319854 | 173 | // awake again amd running at full speed at this point. |
AndyA | 1:05f369319854 | 174 | sleepNow = false; |
AndyA | 0:24177fc1e0e3 | 175 | |
AndyA | 1:05f369319854 | 176 | // restart timers |
AndyA | 0:24177fc1e0e3 | 177 | timeTracker.start(); |
AndyA | 0:24177fc1e0e3 | 178 | ledCycle.attach_us(on1msTick,1000); |
AndyA | 1:05f369319854 | 179 | |
AndyA | 1:05f369319854 | 180 | // show startup animation. |
AndyA | 1:05f369319854 | 181 | StackLEDs(0.05); |
AndyA | 0:24177fc1e0e3 | 182 | } |
AndyA | 0:24177fc1e0e3 | 183 | |
AndyA | 0:24177fc1e0e3 | 184 | |
AndyA | 0:24177fc1e0e3 | 185 | void enterSleepTimeout(void) |
AndyA | 0:24177fc1e0e3 | 186 | { |
AndyA | 0:24177fc1e0e3 | 187 | sleepNow = true; |
AndyA | 0:24177fc1e0e3 | 188 | } |
AndyA | 0:24177fc1e0e3 | 189 | |
AndyA | 0:24177fc1e0e3 | 190 | |
AndyA | 0:24177fc1e0e3 | 191 | void buttonPressedIRQ() |
AndyA | 0:24177fc1e0e3 | 192 | { |
AndyA | 0:24177fc1e0e3 | 193 | sleepMode.detach(); |
AndyA | 0:24177fc1e0e3 | 194 | fButtonPressed=true; |
AndyA | 0:24177fc1e0e3 | 195 | } |
AndyA | 0:24177fc1e0e3 | 196 | |
AndyA | 0:24177fc1e0e3 | 197 | |
AndyA | 0:24177fc1e0e3 | 198 | void setup(void) |
AndyA | 0:24177fc1e0e3 | 199 | { |
AndyA | 0:24177fc1e0e3 | 200 | // perform initialisations |
AndyA | 0:24177fc1e0e3 | 201 | |
AndyA | 0:24177fc1e0e3 | 202 | // create a 32 bit number out of 32 LSBs from the ADC |
AndyA | 0:24177fc1e0e3 | 203 | uint32_t seedValue = 0; |
AndyA | 0:24177fc1e0e3 | 204 | uint16_t value; |
AndyA | 0:24177fc1e0e3 | 205 | uint8_t counter; |
AndyA | 0:24177fc1e0e3 | 206 | |
AndyA | 0:24177fc1e0e3 | 207 | for (counter = 0; counter < 32; counter++) { |
AndyA | 0:24177fc1e0e3 | 208 | seedValue = seedValue<<1; |
AndyA | 0:24177fc1e0e3 | 209 | value = RandomIn.read_u16(); // reads a 10 bit ADC normalised to 16 bits. |
AndyA | 0:24177fc1e0e3 | 210 | if (value & 0x0040) // LSB of ADC output = 1 |
AndyA | 0:24177fc1e0e3 | 211 | seedValue++; |
AndyA | 0:24177fc1e0e3 | 212 | } |
AndyA | 0:24177fc1e0e3 | 213 | |
AndyA | 0:24177fc1e0e3 | 214 | srand(seedValue); // seed the random generator with the background noise of an analog input |
AndyA | 0:24177fc1e0e3 | 215 | |
AndyA | 0:24177fc1e0e3 | 216 | // start a timer used to determin delay between button presses, used to increase randomness. |
AndyA | 0:24177fc1e0e3 | 217 | timeTracker.start(); |
AndyA | 0:24177fc1e0e3 | 218 | |
AndyA | 0:24177fc1e0e3 | 219 | // start LED cycling ticker |
AndyA | 0:24177fc1e0e3 | 220 | ledCycle.attach_us(on1msTick,1000); |
AndyA | 0:24177fc1e0e3 | 221 | |
AndyA | 0:24177fc1e0e3 | 222 | // startup animation. |
AndyA | 0:24177fc1e0e3 | 223 | StackLEDs(); |
AndyA | 0:24177fc1e0e3 | 224 | |
AndyA | 0:24177fc1e0e3 | 225 | // vibration sensor/button |
AndyA | 1:05f369319854 | 226 | ActionButton.mode(PullUp); |
AndyA | 0:24177fc1e0e3 | 227 | ActionButton.fall(buttonPressedIRQ); |
AndyA | 0:24177fc1e0e3 | 228 | |
AndyA | 0:24177fc1e0e3 | 229 | // Sleep timeout. |
AndyA | 0:24177fc1e0e3 | 230 | sleepMode.attach(enterSleepTimeout,timeoutBeforeSleep); |
AndyA | 0:24177fc1e0e3 | 231 | } |
AndyA | 0:24177fc1e0e3 | 232 | |
AndyA | 0:24177fc1e0e3 | 233 | int main() |
AndyA | 0:24177fc1e0e3 | 234 | { |
AndyA | 0:24177fc1e0e3 | 235 | setup(); |
AndyA | 0:24177fc1e0e3 | 236 | while(true) { |
AndyA | 0:24177fc1e0e3 | 237 | |
AndyA | 0:24177fc1e0e3 | 238 | while(!fButtonPressed) { |
AndyA | 1:05f369319854 | 239 | if (sleepNow) enterSleep(PowerDown); |
AndyA | 0:24177fc1e0e3 | 240 | } |
AndyA | 0:24177fc1e0e3 | 241 | |
AndyA | 0:24177fc1e0e3 | 242 | uint8_t cycles = (timeTracker.read_us() % 20) + 30; |
AndyA | 0:24177fc1e0e3 | 243 | uint8_t value = 1; |
AndyA | 0:24177fc1e0e3 | 244 | |
AndyA | 0:24177fc1e0e3 | 245 | while (cycles > 0) { |
AndyA | 0:24177fc1e0e3 | 246 | value = rand()%6+1; |
AndyA | 0:24177fc1e0e3 | 247 | ShowDice(value); |
AndyA | 0:24177fc1e0e3 | 248 | wait_ms((55-cycles)*2); |
AndyA | 0:24177fc1e0e3 | 249 | cycles--; |
AndyA | 0:24177fc1e0e3 | 250 | } |
AndyA | 0:24177fc1e0e3 | 251 | |
AndyA | 0:24177fc1e0e3 | 252 | // clear the button flag now rather than as soon as we see it to avoid the need for de-bouncing. |
AndyA | 0:24177fc1e0e3 | 253 | fButtonPressed=false; |
AndyA | 0:24177fc1e0e3 | 254 | |
AndyA | 0:24177fc1e0e3 | 255 | wait(0.5); |
AndyA | 0:24177fc1e0e3 | 256 | |
AndyA | 0:24177fc1e0e3 | 257 | for (int i = 0; i<3; i++) { |
AndyA | 0:24177fc1e0e3 | 258 | BlinkLeds(false,0.2); |
AndyA | 0:24177fc1e0e3 | 259 | } |
AndyA | 0:24177fc1e0e3 | 260 | |
AndyA | 0:24177fc1e0e3 | 261 | sleepMode.attach(enterSleepTimeout,timeoutBeforeSleep); |
AndyA | 0:24177fc1e0e3 | 262 | } |
AndyA | 0:24177fc1e0e3 | 263 | } |