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.

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?

UserRevisionLine numberNew 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 }