Electronic dice application for the mBuino platform. Notes: The mBuino starts in Demo mode. In Demo mode the LEDs are lighted, showing sweeps and demo rolls. Connect a button or tilt-switch between P0.4 and GND. No soldering required! When the switch is triggered mBuino goes into Roll mode. In Roll mode mBuino starts with rapid flickering LEDs. Each subsequent switch trigger will perform a roll of the dice, of which the result is shown for ten seconds unless the switch is triggered for another roll. To preserve power, Power down mode is entered after inactivity in Demo mode or Roll mode. Press any button to revive.

Dependencies:   mbed

Fork of mBuino_Dice by Valentin Ivanov

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 ** mBuino_Dice
00003 ** 
00004 ** This electronic dice application allows the user to throw an electronic dice by the press of a button
00005 ** Setup requirements: connect any type of switch between P0.4 and GND.
00006 ** On mBuino P0.4 is close to GND and the two pitch distance is exactly the same as a mini-switch! 
00007 **
00008 ** 0.1.140916 Using the Outrageous Circuits mBuino platform instead of LPC11U24 (available now)
00009 **            Renamed LED ports to newly available mBuino LED constants
00010 **            Earlier power down after dice roll, showing by flashes slowing down
00011 ** 0.1.140915 Energy use in power down mode down to 3 uA, credits: Andy A
00012 ** 0.1.140910 Power down after one iteration of demo or ten seconds of wating, credits: Andy A
00013 ** 0.1.140908 Added deep sleep mode after one iteration of demo or ten seconds of wating, credits: Andy A and Erik Olieman
00014 **            Added explanatory comments and incorporated suggestion by Erik Olieman
00015 **            Improved randomness as per suggestion of Andy A
00016 ** 0.1.140901 First version mad for mBuino on mbed.org by maxint on 1-sep-2014
00017 **
00018 ** Feel free to use this code anyway you want, but please acknowledge my work by mentioning maxint as creator.
00019 **
00020 */
00021 
00022 
00023 #include "mbed.h"
00024 
00025 DigitalOut LED[] = {(LED1), (LED2), (LED3), (LED4), (LED5), (LED6), (LED7)};// declare 7 LEDs
00026 
00027 InterruptIn ActionButton(P0_4);  // declare the input for the button (or for other single switch, such as movement switch). On mBuino P0.4 is close to GND
00028 AnalogIn RandomIn(P0_14); // use the random noise on this analog input to seed the random generator
00029 
00030 // Define the LED pattern of each dice number
00031 // Can be made more compact by using binary values instead of a nested array.
00032 bool DicePattern[6][7]=
00033 {
00034     {0, 0, 0, 1, 0, 0, 0 },
00035     {0, 1, 0, 0, 0, 1, 0 },
00036     {0, 1, 0, 1, 0, 1, 0 },
00037     {1, 0, 1, 0, 1, 0, 1 },
00038     {1, 0, 1, 1, 1, 0, 1 },
00039     {1, 1, 1, 0, 1, 1, 1 }
00040 };
00041 
00042 /*
00043 // TODO: Suggestion by Erik Olieman: alternatively BusOut can be used to combine all used pins in one bus that can be set using a single write
00044 BusOut LEDS(P0_7, P0_8, P0_2, P0_20, P1_19, P0_17, P0_23);
00045 char byteDice[6]=
00046 {
00047 0x08,   // 0B00001000
00048 0x22,   // 0B00100010
00049 0x2A,   // 0B00101010
00050 0x55,   // 0B01010101
00051 0x5D,   // 0B01011101
00052 0x77    // 0B01110111
00053 };
00054 */
00055 
00056 Timer tWait;    // time used for tickcounts
00057 
00058 DigitalIn progMode(P0_3);       // need to disable pull-down for minimal power deep sleep
00059 void myPowerDown(uint8_t uMode=0x02)
00060 {   // Go into power-down mode (0x2) to safe most power. Use onboard or off-board interrupt triggered button to revive
00061     // See https://mbed.org/forum/electronics/topic/5138/
00062     // Alternative: Go into deep sleep mode (0x1) to safe less power. Is quicker than power-down. Also revived using onboard button or interrupt.
00063     // See http://mbed.org/forum/repo-52552-mBuino_low_power_led_flasher-community/topic/5130/
00064     // Power usage (CR3032 battery life):
00065     //   Running 13mA (1.5 day) 
00066     //   Sleep 7mA (3 days)
00067     //   Deep-sleep 480uA (43 days)
00068     //   Power-down 120uA (170 days)
00069     //   Power-down with fix 3uA (years)
00070     progMode.mode(PullNone);    // fix the 120uA. see http://mbed.org/forum/electronics/topic/5138/?page=1#comment-25338
00071     
00072     LPC_PMU->PCON = uMode;     // 0x2 = power down, 0x1 = deep sleep
00073     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
00074     LPC_SYSCON->PDAWAKECFG &= 0xFFFFF800;
00075     __WFI();
00076 }
00077 
00078 void SwitchAllLeds(bool fOn)
00079 {   // switch all leds on or off
00080     // Suggestion by Erik Olieman: alternatively BusOut can be used to combine all used pins in one bus that can be set using a single write
00081     for(int x = 0; x < 7; x++)
00082     {
00083         LED[x] = fOn?1:0;   // turn on or off
00084     }
00085 }
00086 
00087 void BlinkAllLeds(float flDelay=0.2)
00088 {   // blink all leds
00089     SwitchAllLeds(true);
00090     wait(flDelay);
00091     SwitchAllLeds(false);
00092     wait(flDelay);
00093 }
00094 
00095 void BlinkOneLed(int nLed=0, float flDelayOn=0.2, float flDelayOff=0.2)
00096 {   // blink just one led once, for the specified time
00097     LED[nLed] = 1; // turn on
00098     wait(flDelayOn); // delay
00099 
00100     LED[nLed] = 0; // turn off
00101     wait(flDelayOff); // delay
00102 }
00103 
00104 void SweepSingleLed(bool fLeftToRight=true, float flDelay=0.2)
00105 {   // sweep a single led from left to rigth or vise-versa
00106     for(int n=0; n<7; n++)
00107         BlinkOneLed(fLeftToRight?n:6-n, flDelay, 0);
00108 }
00109 
00110 void SweepAllLeds(bool fLeftToRight=true, float flDelay=0.1)
00111 {   // light all leds up from left to rigth or vise-versa and then switch them of from reverse direction
00112     // leds on, left to right
00113     for(int n=0; n<7; n++)
00114     {
00115         LED[fLeftToRight?n:6-n] = 1; // turn on
00116         wait(flDelay); // delay
00117     }
00118     // leds off, right to left
00119     for(int n=0; n<7; n++)
00120     {
00121         LED[!fLeftToRight?n:6-n] = 0; // turn off
00122         wait(flDelay); // delay
00123     }
00124 }
00125 
00126 void SwitchDiceLed(int nNumber, bool fOn=true)
00127 {   // switch the leds of a particular dice-number on or off
00128     if(nNumber<1) nNumber=1;
00129     if(nNumber>6) nNumber=6;
00130     
00131     for(int n=0; n<7; n++)
00132         if(DicePattern[nNumber-1][n])
00133             LED[n]=fOn;
00134 }
00135 
00136 void BlinkDiceLed(int nNumber, float flDelayOn=0.6, float flDelayOff=0.1)
00137 {   // blink a particular dice value
00138     SwitchDiceLed(nNumber, true);
00139     wait(flDelayOn);
00140     SwitchDiceLed(nNumber, false);
00141     wait(flDelayOff);
00142 }
00143 
00144 int RollDice(int nRolls=10, int nBlinks=2, float flDelayRoll=0.15)
00145 {   // roll the dice and show the outcome value
00146     int nDiceValue;
00147 
00148     // improve randomness: seed the random generator with the background noise of an analog input combined with passed time at user triggered moment
00149     srand(RandomIn.read_u16()+tWait.read_us());
00150     
00151     // first roll the dice
00152     for(int n=0; n<nRolls; n++)
00153     {
00154         nDiceValue=rand()%6+1;
00155         BlinkDiceLed(nDiceValue, flDelayRoll, 0);
00156     }
00157     
00158     // then show the result
00159     nDiceValue=rand()%6+1;
00160     for(int n=0; n<nBlinks; n++)
00161         BlinkDiceLed(nDiceValue, flDelayRoll, 0);
00162     SwitchDiceLed(nDiceValue, true);        // return while keeping dice led's on
00163     
00164     return(nDiceValue);
00165 }
00166 
00167 bool fButtonPressed=false;      // if the button is pressed, mBuino will switch from demo mode to play mode. 
00168 bool fDemoDone=false;
00169 
00170 void interruptButtonPressed()
00171 {
00172     fButtonPressed=true;
00173 }
00174 
00175 void setup(void)
00176 {   // perform initialisations
00177     srand(RandomIn.read_u16());     // seed the random generator with the background noise of an analog input
00178     
00179     ActionButton.fall(interruptButtonPressed); // using the fall requires the button to be unpressed before the interrupt is triggered again
00180     tWait.start();      // start the timer
00181 }
00182 
00183 void loop(void)
00184 {   // run forever
00185     if(!fDemoDone && !fButtonPressed)
00186     {   // Run an entertaining demo show until button is pressed
00187         // For all parts of the show we check to see if the actionbutton was pressed to stop the show asap
00188         if(!fButtonPressed)
00189             SweepAllLeds(true);
00190         if(!fButtonPressed)
00191             SweepAllLeds(false);
00192         if(!fButtonPressed)
00193             SweepAllLeds(true, 0.05);
00194         if(!fButtonPressed)
00195             SweepAllLeds(false, 0.05);
00196         
00197         // show the dice numbers from one to six
00198         for(int n=1; n<=6; n++)
00199             if(!fButtonPressed)
00200                 BlinkDiceLed(n);
00201 
00202         if(!fButtonPressed)
00203             SweepSingleLed(true, 0.2);
00204         if(!fButtonPressed)
00205             SweepSingleLed(false, 0.1);
00206         
00207         // show three random dice throws
00208         for(int n=0; n<3; n++)
00209         {
00210             if(!fButtonPressed)
00211             {
00212                 RollDice();
00213                 wait(1);
00214                 SwitchAllLeds(false);
00215             }
00216         }
00217 
00218         // blink all leds as the same time at increasing and decreasing speeds
00219         for(float flDelay=0.3; flDelay>0; flDelay-=0.05)
00220             if(!fButtonPressed)
00221                 BlinkAllLeds(flDelay);
00222         for(float flDelay=0.05; flDelay<0.4; flDelay+=0.05)
00223             if(!fButtonPressed)
00224                 BlinkAllLeds(flDelay);
00225         
00226         if(!fButtonPressed)
00227             wait(1);
00228             
00229         if(!fButtonPressed)
00230             myPowerDown();   // enter dpower-down mode after one demo iteration
00231     }
00232     else
00233     {   // demo mode is ended, roll the dice upon each button press
00234         fDemoDone=true;
00235         fButtonPressed=false;
00236         
00237         unsigned uTickStop=tWait.read_ms()+10000;
00238         float ftDelay=0.01;
00239         while(!fButtonPressed)
00240         {   // flash the LEDS to show we wait for a roll call
00241             SweepAllLeds(true, ftDelay);
00242             SweepAllLeds(false, ftDelay);
00243 
00244             if(!fButtonPressed && tWait.read_ms()>uTickStop)
00245                 myPowerDown();   // enter power-down mode when waited for more than 10 seconds without button pressed
00246             else
00247                 ftDelay=(10-((float)uTickStop-tWait.read_ms())/1000)/100;  // make the fast flashes slow down while closer to power down mode
00248         }
00249         fButtonPressed=false;
00250         
00251         // roll the dice and show the outcome while waiting max. 10 seconds
00252         int nDiceValue=RollDice();
00253         wait(1);
00254         fButtonPressed=false;
00255         
00256         uTickStop=tWait.read_ms()+10000;
00257         ftDelay=0.01;
00258         while(!fButtonPressed && tWait.read_ms()<uTickStop)
00259         {
00260             BlinkDiceLed(nDiceValue, 0.2, ftDelay);  // to indicate waiting for a new roll, flash the thrown dice value...
00261             ftDelay=(10-((float)uTickStop-tWait.read_ms())/1000)/100;  // make the fast flashes slow down while closer to power down mode
00262         }
00263         SwitchAllLeds(false);
00264 
00265         if(!fButtonPressed)
00266             myPowerDown();   // enter power-down mode when waited for more than 10 seconds without button pressed
00267     }
00268 }
00269 
00270 int main()
00271 {   // implement Arduino-style setup() and loop()
00272     setup();
00273     while(true)
00274         loop();
00275 }