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@0:24177fc1e0e3, 2014-09-17 (annotated)
- Committer:
- AndyA
- Date:
- Wed Sep 17 13:48:57 2014 +0000
- Revision:
- 0:24177fc1e0e3
- Child:
- 1:05f369319854
Dice
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 | 0:24177fc1e0e3 | 15 | |
AndyA | 0:24177fc1e0e3 | 16 | BusOut LEDOuts(LED1, LED2, LED3, LED4, LED5, LED6, LED7);// declare 7 LEDs |
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 | 0:24177fc1e0e3 | 21 | uint8_t LEDs = 0; |
AndyA | 0:24177fc1e0e3 | 22 | |
AndyA | 0:24177fc1e0e3 | 23 | // fix power draw |
AndyA | 0:24177fc1e0e3 | 24 | DigitalIn progMode(P0_3); |
AndyA | 0:24177fc1e0e3 | 25 | |
AndyA | 0:24177fc1e0e3 | 26 | // sleep can be sleep, deepsleep or power down. |
AndyA | 0:24177fc1e0e3 | 27 | // clean power down and cleen deep sleep do a clean shutdown of the PLL. |
AndyA | 0:24177fc1e0e3 | 28 | // However any code called during the wakeup IRQ will then run at a slower speed. |
AndyA | 0:24177fc1e0e3 | 29 | enum sleepMode_t {powerDown=0, deepSleep, lightSleep, cleanPowerDown, cleanDeepSleep}; |
AndyA | 0:24177fc1e0e3 | 30 | |
AndyA | 0:24177fc1e0e3 | 31 | |
AndyA | 0:24177fc1e0e3 | 32 | // idle time to wait before sleeping |
AndyA | 0:24177fc1e0e3 | 33 | const float timeoutBeforeSleep = 15; |
AndyA | 0:24177fc1e0e3 | 34 | |
AndyA | 0:24177fc1e0e3 | 35 | |
AndyA | 0:24177fc1e0e3 | 36 | const uint8_t DicePattern[6] = { 0x08, // 0b 000_1_000 |
AndyA | 0:24177fc1e0e3 | 37 | 0x22, // 0b 010_0_010 |
AndyA | 0:24177fc1e0e3 | 38 | 0x2a, // 0b 010_1_010 |
AndyA | 0:24177fc1e0e3 | 39 | 0x55, // 0b 101_0_101 |
AndyA | 0:24177fc1e0e3 | 40 | 0x5d, // 0b 101_1_101 |
AndyA | 0:24177fc1e0e3 | 41 | 0x77 // 0b 111_0_111 |
AndyA | 0:24177fc1e0e3 | 42 | }; |
AndyA | 0:24177fc1e0e3 | 43 | |
AndyA | 0:24177fc1e0e3 | 44 | volatile bool fButtonPressed; |
AndyA | 0:24177fc1e0e3 | 45 | |
AndyA | 0:24177fc1e0e3 | 46 | volatile bool sleepNow=false; |
AndyA | 0:24177fc1e0e3 | 47 | |
AndyA | 0:24177fc1e0e3 | 48 | Timer timeTracker; |
AndyA | 0:24177fc1e0e3 | 49 | Timeout sleepMode; |
AndyA | 0:24177fc1e0e3 | 50 | |
AndyA | 0:24177fc1e0e3 | 51 | |
AndyA | 0:24177fc1e0e3 | 52 | // this cycles the LEDs so they are on for 1/7th of the time with only one lit at a time. |
AndyA | 0:24177fc1e0e3 | 53 | // but since it does it at 1kHz they just look a little dimmer to the human eye. |
AndyA | 0:24177fc1e0e3 | 54 | // This can give a big power saving when running on a battery. |
AndyA | 0:24177fc1e0e3 | 55 | Ticker ledCycle; |
AndyA | 0:24177fc1e0e3 | 56 | |
AndyA | 0:24177fc1e0e3 | 57 | void on1msTick() |
AndyA | 0:24177fc1e0e3 | 58 | { |
AndyA | 0:24177fc1e0e3 | 59 | static uint8_t ledIndex = 0; |
AndyA | 0:24177fc1e0e3 | 60 | LEDOuts = LEDs & 0x01<<ledIndex++; |
AndyA | 0:24177fc1e0e3 | 61 | if (ledIndex == 7) |
AndyA | 0:24177fc1e0e3 | 62 | ledIndex = 0; |
AndyA | 0:24177fc1e0e3 | 63 | } |
AndyA | 0:24177fc1e0e3 | 64 | |
AndyA | 0:24177fc1e0e3 | 65 | |
AndyA | 0:24177fc1e0e3 | 66 | |
AndyA | 0:24177fc1e0e3 | 67 | // LED state setting functions. |
AndyA | 0:24177fc1e0e3 | 68 | |
AndyA | 0:24177fc1e0e3 | 69 | void SetLeds(bool on) |
AndyA | 0:24177fc1e0e3 | 70 | { |
AndyA | 0:24177fc1e0e3 | 71 | if (on) |
AndyA | 0:24177fc1e0e3 | 72 | LEDs=0x7f; |
AndyA | 0:24177fc1e0e3 | 73 | else |
AndyA | 0:24177fc1e0e3 | 74 | LEDs=0; |
AndyA | 0:24177fc1e0e3 | 75 | } |
AndyA | 0:24177fc1e0e3 | 76 | |
AndyA | 0:24177fc1e0e3 | 77 | void SetLed(uint8_t ledID, bool on) |
AndyA | 0:24177fc1e0e3 | 78 | { |
AndyA | 0:24177fc1e0e3 | 79 | if (ledID <= 6) { |
AndyA | 0:24177fc1e0e3 | 80 | if (on) |
AndyA | 0:24177fc1e0e3 | 81 | LEDs = LEDs | (0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 82 | else |
AndyA | 0:24177fc1e0e3 | 83 | LEDs = LEDs & ~(0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 84 | } |
AndyA | 0:24177fc1e0e3 | 85 | } |
AndyA | 0:24177fc1e0e3 | 86 | |
AndyA | 0:24177fc1e0e3 | 87 | void ToggleLeds() |
AndyA | 0:24177fc1e0e3 | 88 | { |
AndyA | 0:24177fc1e0e3 | 89 | LEDs = ~LEDs; |
AndyA | 0:24177fc1e0e3 | 90 | } |
AndyA | 0:24177fc1e0e3 | 91 | |
AndyA | 0:24177fc1e0e3 | 92 | void ToggleLed(uint8_t ledID) |
AndyA | 0:24177fc1e0e3 | 93 | { |
AndyA | 0:24177fc1e0e3 | 94 | if (ledID <= 6) |
AndyA | 0:24177fc1e0e3 | 95 | LEDs = LEDs ^ (0x01 << ledID); |
AndyA | 0:24177fc1e0e3 | 96 | } |
AndyA | 0:24177fc1e0e3 | 97 | |
AndyA | 0:24177fc1e0e3 | 98 | void BlinkLeds(bool on=true, float delay=0.1) |
AndyA | 0:24177fc1e0e3 | 99 | { |
AndyA | 0:24177fc1e0e3 | 100 | uint8_t state = LEDs; |
AndyA | 0:24177fc1e0e3 | 101 | SetLeds(on); |
AndyA | 0:24177fc1e0e3 | 102 | wait(delay); |
AndyA | 0:24177fc1e0e3 | 103 | LEDs = state; |
AndyA | 0:24177fc1e0e3 | 104 | wait(delay); |
AndyA | 0:24177fc1e0e3 | 105 | } |
AndyA | 0:24177fc1e0e3 | 106 | |
AndyA | 0:24177fc1e0e3 | 107 | void ShowDice(uint8_t nNumber) |
AndyA | 0:24177fc1e0e3 | 108 | { |
AndyA | 0:24177fc1e0e3 | 109 | // switch the leds of a particular dice-number on or off |
AndyA | 0:24177fc1e0e3 | 110 | if(nNumber<1) nNumber=1; |
AndyA | 0:24177fc1e0e3 | 111 | if(nNumber>6) nNumber=6; |
AndyA | 0:24177fc1e0e3 | 112 | |
AndyA | 0:24177fc1e0e3 | 113 | LEDs=DicePattern[nNumber - 1]; |
AndyA | 0:24177fc1e0e3 | 114 | } |
AndyA | 0:24177fc1e0e3 | 115 | |
AndyA | 0:24177fc1e0e3 | 116 | |
AndyA | 0:24177fc1e0e3 | 117 | void BlinkOneLed(uint8_t ledID, float delay = 0.1) |
AndyA | 0:24177fc1e0e3 | 118 | { |
AndyA | 0:24177fc1e0e3 | 119 | ToggleLed(ledID); |
AndyA | 0:24177fc1e0e3 | 120 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 121 | ToggleLed(ledID); |
AndyA | 0:24177fc1e0e3 | 122 | wait(delay); // delay |
AndyA | 0:24177fc1e0e3 | 123 | } |
AndyA | 0:24177fc1e0e3 | 124 | |
AndyA | 0:24177fc1e0e3 | 125 | void SweepSingleLed(bool leftToRight = true, float delay = 0.2) |
AndyA | 0:24177fc1e0e3 | 126 | { |
AndyA | 0:24177fc1e0e3 | 127 | SetLeds(false); |
AndyA | 0:24177fc1e0e3 | 128 | for(int n=0; n<7; n++) |
AndyA | 0:24177fc1e0e3 | 129 | BlinkOneLed(leftToRight?n:6-n, delay); |
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 | 0:24177fc1e0e3 | 160 | void mySleep() // ONLY CALL FROM MAIN LOOP |
AndyA | 0:24177fc1e0e3 | 161 | { |
AndyA | 0:24177fc1e0e3 | 162 | |
AndyA | 0:24177fc1e0e3 | 163 | LPC_PMU->PCON = 0x0; |
AndyA | 0:24177fc1e0e3 | 164 | SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; |
AndyA | 0:24177fc1e0e3 | 165 | __WFI(); |
AndyA | 0:24177fc1e0e3 | 166 | } |
AndyA | 0:24177fc1e0e3 | 167 | |
AndyA | 0:24177fc1e0e3 | 168 | // deepSleep is higher power but faster wakeup |
AndyA | 0:24177fc1e0e3 | 169 | // clean PLL shutdown is technically needed but seems to work without it. |
AndyA | 0:24177fc1e0e3 | 170 | // Note - If using clean PLL shutdown the IRQ that wakes us runs on the IRC |
AndyA | 0:24177fc1e0e3 | 171 | // not the system clock because the clock isn't set up until after the IRQ is complete. |
AndyA | 0:24177fc1e0e3 | 172 | void myPowerDown(bool cleanPLLShutdown = false, bool deepSleep = false) |
AndyA | 0:24177fc1e0e3 | 173 | { |
AndyA | 0:24177fc1e0e3 | 174 | |
AndyA | 0:24177fc1e0e3 | 175 | if (deepSleep) |
AndyA | 0:24177fc1e0e3 | 176 | LPC_PMU->PCON = 0x1; |
AndyA | 0:24177fc1e0e3 | 177 | else |
AndyA | 0:24177fc1e0e3 | 178 | LPC_PMU->PCON = 0x2; |
AndyA | 0:24177fc1e0e3 | 179 | |
AndyA | 0:24177fc1e0e3 | 180 | |
AndyA | 0:24177fc1e0e3 | 181 | LPC_SYSCON->PDSLEEPCFG |= 0x7f; // shut off everything we can. |
AndyA | 0:24177fc1e0e3 | 182 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; |
AndyA | 0:24177fc1e0e3 | 183 | |
AndyA | 0:24177fc1e0e3 | 184 | bool IRCPowered = (LPC_SYSCON->PDRUNCFG & 0x01); // only used for cleen shutdown but defined here for scope reasons. |
AndyA | 0:24177fc1e0e3 | 185 | |
AndyA | 0:24177fc1e0e3 | 186 | if (cleanPLLShutdown) { |
AndyA | 0:24177fc1e0e3 | 187 | if (!IRCPowered) |
AndyA | 0:24177fc1e0e3 | 188 | LPC_SYSCON->PDRUNCFG &= 0xfffffffe; // power up the IRC |
AndyA | 0:24177fc1e0e3 | 189 | |
AndyA | 0:24177fc1e0e3 | 190 | LPC_SYSCON->MAINCLKSEL = 0x00; // switch to IRC to avoid glitches |
AndyA | 0:24177fc1e0e3 | 191 | LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */ |
AndyA | 0:24177fc1e0e3 | 192 | LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */ |
AndyA | 0:24177fc1e0e3 | 193 | LPC_SYSCON->MAINCLKUEN = 0x01; |
AndyA | 0:24177fc1e0e3 | 194 | while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */ |
AndyA | 0:24177fc1e0e3 | 195 | } |
AndyA | 0:24177fc1e0e3 | 196 | |
AndyA | 0:24177fc1e0e3 | 197 | LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; // switch on everything that is currently on when we wake up. |
AndyA | 0:24177fc1e0e3 | 198 | |
AndyA | 0:24177fc1e0e3 | 199 | __WFI(); |
AndyA | 0:24177fc1e0e3 | 200 | |
AndyA | 0:24177fc1e0e3 | 201 | if (cleanPLLShutdown) { |
AndyA | 0:24177fc1e0e3 | 202 | LPC_SYSCON->MAINCLKSEL = 0x03; // switch to PLL output |
AndyA | 0:24177fc1e0e3 | 203 | LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */ |
AndyA | 0:24177fc1e0e3 | 204 | LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */ |
AndyA | 0:24177fc1e0e3 | 205 | LPC_SYSCON->MAINCLKUEN = 0x01; |
AndyA | 0:24177fc1e0e3 | 206 | while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */ |
AndyA | 0:24177fc1e0e3 | 207 | |
AndyA | 0:24177fc1e0e3 | 208 | if (!IRCPowered) |
AndyA | 0:24177fc1e0e3 | 209 | LPC_SYSCON->PDRUNCFG |= 0x01; // power down the IRC |
AndyA | 0:24177fc1e0e3 | 210 | } |
AndyA | 0:24177fc1e0e3 | 211 | } |
AndyA | 0:24177fc1e0e3 | 212 | |
AndyA | 0:24177fc1e0e3 | 213 | |
AndyA | 0:24177fc1e0e3 | 214 | void enterSleep(enum sleepMode_t mode = powerDown) |
AndyA | 0:24177fc1e0e3 | 215 | { |
AndyA | 0:24177fc1e0e3 | 216 | |
AndyA | 0:24177fc1e0e3 | 217 | SweepSingleLed(0.1); |
AndyA | 0:24177fc1e0e3 | 218 | |
AndyA | 0:24177fc1e0e3 | 219 | // all LEDs off. |
AndyA | 0:24177fc1e0e3 | 220 | SetLeds(false); |
AndyA | 0:24177fc1e0e3 | 221 | // stop timers. |
AndyA | 0:24177fc1e0e3 | 222 | timeTracker.stop(); |
AndyA | 0:24177fc1e0e3 | 223 | ledCycle.detach(); |
AndyA | 0:24177fc1e0e3 | 224 | |
AndyA | 0:24177fc1e0e3 | 225 | switch (mode) { |
AndyA | 0:24177fc1e0e3 | 226 | case powerDown: |
AndyA | 0:24177fc1e0e3 | 227 | case cleanPowerDown: |
AndyA | 0:24177fc1e0e3 | 228 | default: |
AndyA | 0:24177fc1e0e3 | 229 | myPowerDown(mode == cleanPowerDown); |
AndyA | 0:24177fc1e0e3 | 230 | break; |
AndyA | 0:24177fc1e0e3 | 231 | case lightSleep: |
AndyA | 0:24177fc1e0e3 | 232 | mySleep(); |
AndyA | 0:24177fc1e0e3 | 233 | break; |
AndyA | 0:24177fc1e0e3 | 234 | case deepSleep: |
AndyA | 0:24177fc1e0e3 | 235 | case cleanDeepSleep: |
AndyA | 0:24177fc1e0e3 | 236 | myPowerDown(mode == cleanDeepSleep, true); |
AndyA | 0:24177fc1e0e3 | 237 | break; |
AndyA | 0:24177fc1e0e3 | 238 | } |
AndyA | 0:24177fc1e0e3 | 239 | |
AndyA | 0:24177fc1e0e3 | 240 | // awake again amd running at full speed at this point. |
AndyA | 0:24177fc1e0e3 | 241 | timeTracker.start(); |
AndyA | 0:24177fc1e0e3 | 242 | ledCycle.attach_us(on1msTick,1000); |
AndyA | 0:24177fc1e0e3 | 243 | sleepNow = false; |
AndyA | 0:24177fc1e0e3 | 244 | StackLEDs(0.1); |
AndyA | 0:24177fc1e0e3 | 245 | // SweepAllLeds(); |
AndyA | 0:24177fc1e0e3 | 246 | } |
AndyA | 0:24177fc1e0e3 | 247 | |
AndyA | 0:24177fc1e0e3 | 248 | |
AndyA | 0:24177fc1e0e3 | 249 | void enterSleepTimeout(void) |
AndyA | 0:24177fc1e0e3 | 250 | { |
AndyA | 0:24177fc1e0e3 | 251 | sleepNow = true; |
AndyA | 0:24177fc1e0e3 | 252 | } |
AndyA | 0:24177fc1e0e3 | 253 | |
AndyA | 0:24177fc1e0e3 | 254 | |
AndyA | 0:24177fc1e0e3 | 255 | void buttonPressedIRQ() |
AndyA | 0:24177fc1e0e3 | 256 | { |
AndyA | 0:24177fc1e0e3 | 257 | sleepMode.detach(); |
AndyA | 0:24177fc1e0e3 | 258 | fButtonPressed=true; |
AndyA | 0:24177fc1e0e3 | 259 | } |
AndyA | 0:24177fc1e0e3 | 260 | |
AndyA | 0:24177fc1e0e3 | 261 | |
AndyA | 0:24177fc1e0e3 | 262 | |
AndyA | 0:24177fc1e0e3 | 263 | void setup(void) |
AndyA | 0:24177fc1e0e3 | 264 | { |
AndyA | 0:24177fc1e0e3 | 265 | // perform initialisations |
AndyA | 0:24177fc1e0e3 | 266 | |
AndyA | 0:24177fc1e0e3 | 267 | // ensure no pullup on the progMode pin |
AndyA | 0:24177fc1e0e3 | 268 | progMode.mode(PullNone); |
AndyA | 0:24177fc1e0e3 | 269 | |
AndyA | 0:24177fc1e0e3 | 270 | // create a 32 bit number out of 32 LSBs from the ADC |
AndyA | 0:24177fc1e0e3 | 271 | uint32_t seedValue = 0; |
AndyA | 0:24177fc1e0e3 | 272 | uint16_t value; |
AndyA | 0:24177fc1e0e3 | 273 | uint8_t counter; |
AndyA | 0:24177fc1e0e3 | 274 | |
AndyA | 0:24177fc1e0e3 | 275 | for (counter = 0; counter < 32; counter++) { |
AndyA | 0:24177fc1e0e3 | 276 | seedValue = seedValue<<1; |
AndyA | 0:24177fc1e0e3 | 277 | value = RandomIn.read_u16(); // reads a 10 bit ADC normalised to 16 bits. |
AndyA | 0:24177fc1e0e3 | 278 | if (value & 0x0040) // LSB of ADC output = 1 |
AndyA | 0:24177fc1e0e3 | 279 | seedValue++; |
AndyA | 0:24177fc1e0e3 | 280 | } |
AndyA | 0:24177fc1e0e3 | 281 | |
AndyA | 0:24177fc1e0e3 | 282 | srand(seedValue); // seed the random generator with the background noise of an analog input |
AndyA | 0:24177fc1e0e3 | 283 | |
AndyA | 0:24177fc1e0e3 | 284 | // start a timer used to determin delay between button presses, used to increase randomness. |
AndyA | 0:24177fc1e0e3 | 285 | timeTracker.start(); |
AndyA | 0:24177fc1e0e3 | 286 | |
AndyA | 0:24177fc1e0e3 | 287 | // start LED cycling ticker |
AndyA | 0:24177fc1e0e3 | 288 | ledCycle.attach_us(on1msTick,1000); |
AndyA | 0:24177fc1e0e3 | 289 | |
AndyA | 0:24177fc1e0e3 | 290 | // startup animation. |
AndyA | 0:24177fc1e0e3 | 291 | StackLEDs(); |
AndyA | 0:24177fc1e0e3 | 292 | |
AndyA | 0:24177fc1e0e3 | 293 | // vibration sensor/button |
AndyA | 0:24177fc1e0e3 | 294 | ActionButton.fall(buttonPressedIRQ); |
AndyA | 0:24177fc1e0e3 | 295 | |
AndyA | 0:24177fc1e0e3 | 296 | // Sleep timeout. |
AndyA | 0:24177fc1e0e3 | 297 | sleepMode.attach(enterSleepTimeout,timeoutBeforeSleep); |
AndyA | 0:24177fc1e0e3 | 298 | } |
AndyA | 0:24177fc1e0e3 | 299 | |
AndyA | 0:24177fc1e0e3 | 300 | int main() |
AndyA | 0:24177fc1e0e3 | 301 | { |
AndyA | 0:24177fc1e0e3 | 302 | setup(); |
AndyA | 0:24177fc1e0e3 | 303 | while(true) { |
AndyA | 0:24177fc1e0e3 | 304 | |
AndyA | 0:24177fc1e0e3 | 305 | while(!fButtonPressed) { |
AndyA | 0:24177fc1e0e3 | 306 | if (sleepNow) enterSleep(cleanPowerDown); |
AndyA | 0:24177fc1e0e3 | 307 | } |
AndyA | 0:24177fc1e0e3 | 308 | |
AndyA | 0:24177fc1e0e3 | 309 | uint8_t cycles = (timeTracker.read_us() % 20) + 30; |
AndyA | 0:24177fc1e0e3 | 310 | uint8_t value = 1; |
AndyA | 0:24177fc1e0e3 | 311 | |
AndyA | 0:24177fc1e0e3 | 312 | while (cycles > 0) { |
AndyA | 0:24177fc1e0e3 | 313 | value = rand()%6+1; |
AndyA | 0:24177fc1e0e3 | 314 | ShowDice(value); |
AndyA | 0:24177fc1e0e3 | 315 | wait_ms((55-cycles)*2); |
AndyA | 0:24177fc1e0e3 | 316 | cycles--; |
AndyA | 0:24177fc1e0e3 | 317 | } |
AndyA | 0:24177fc1e0e3 | 318 | |
AndyA | 0:24177fc1e0e3 | 319 | // clear the button flag now rather than as soon as we see it to avoid the need for de-bouncing. |
AndyA | 0:24177fc1e0e3 | 320 | fButtonPressed=false; |
AndyA | 0:24177fc1e0e3 | 321 | |
AndyA | 0:24177fc1e0e3 | 322 | wait(0.5); |
AndyA | 0:24177fc1e0e3 | 323 | |
AndyA | 0:24177fc1e0e3 | 324 | for (int i = 0; i<3; i++) { |
AndyA | 0:24177fc1e0e3 | 325 | BlinkLeds(false,0.2); |
AndyA | 0:24177fc1e0e3 | 326 | } |
AndyA | 0:24177fc1e0e3 | 327 | |
AndyA | 0:24177fc1e0e3 | 328 | sleepMode.attach(enterSleepTimeout,timeoutBeforeSleep); |
AndyA | 0:24177fc1e0e3 | 329 | } |
AndyA | 0:24177fc1e0e3 | 330 | } |