acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Stopwatch.ino (5413B)

      1 /*
      2  * A demo app that calculates the ammount of time taken by the
      3  * AceButton::check() method. It acts like a stopwatch, supporting the following
      4  * operations:
      5  *
      6  * - press: start the stopwatch
      7  * - press: stop the stopwatch, printing out the result
      8  * - long press: reset the stopwatch, allowing press to start the process again
      9  *
     10  * Each 'long press' alternates between enableAllEvents() and disableAllEvents()
     11  * so that we can compare the timing of check() when all events are off (except
     12  * Pressed and Released) and when all events are on.
     13  */
     14 
     15 #include <AceButton.h>
     16 
     17 using namespace ace_button;
     18 
     19 // The pin number attached to the button.
     20 const uint8_t BUTTON_PIN = 2;
     21 
     22 // Create one button.
     23 AceButton button;
     24 
     25 // counters to determine the duration of a single call to AceButton::check()
     26 uint16_t innerLoopCounter = 0;
     27 uint16_t outerLoopCounter = 0;
     28 unsigned long startMillis = 0;
     29 unsigned long stopMillis  = 0;
     30 
     31 // states of the stopwatch
     32 const uint8_t STOPWATCH_INIT = 0;
     33 const uint8_t STOPWATCH_STARTED = 1;
     34 const uint8_t STOPWATCH_STOPPED = 2;
     35 
     36 // implements a finite state machine (FSM)
     37 uint8_t stopwatchState = STOPWATCH_INIT;
     38 
     39 bool allEventsEnabled = false;
     40 
     41 void handleEvent(AceButton*, uint8_t, uint8_t);
     42 
     43 void setup() {
     44   delay(1000); // some boards reboot twice
     45   Serial.begin(115200);
     46   while (! Serial); // Wait until Serial is ready - Leonardo/Micro
     47   Serial.println(F("setup(): begin"));
     48 
     49   // Button uses the built-in pull up register.
     50   pinMode(BUTTON_PIN, INPUT_PULLUP);
     51   button.init(BUTTON_PIN);
     52 
     53   // Configure the ButtonConfig with the event handler and enable LongPress.
     54   // SupressAfterLongPress is optional since we don't do anything if we get it.
     55   ButtonConfig* buttonConfig = button.getButtonConfig();
     56   buttonConfig->setEventHandler(handleEvent);
     57   buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
     58   buttonConfig->setLongPressDelay(2000);
     59 
     60   Serial.println(F("setup(): stopwatch ready"));
     61 }
     62 
     63 void loop() {
     64   // We split the loop into an inner loop and an outer loop. The inner loop
     65   // allows us to measure the speed of button.check() without the overhead of
     66   // the outer loop. However, we must allow the outer loop() method to return
     67   // periodically to allow the microcontroller to its own stuff. This is
     68   // especially true on an ESP8266 board, where a Watch Dog Timer will
     69   // soft-reset the board if loop() doesn't return every few seconds.
     70   do {
     71     // button.check() Should be called every 20ms or faster for the default
     72     // debouncing time of ~50ms.
     73     button.check();
     74 
     75     // increment loop counter
     76     if (stopwatchState == STOPWATCH_STARTED) {
     77       innerLoopCounter++;
     78     }
     79   } while (innerLoopCounter);
     80 
     81   // Each time the innerLoopCounter rolls over (65536), increment the outer loop
     82   // counter, and return from loop(), to prevent WDT errors on ESP8266.
     83   outerLoopCounter++;
     84 }
     85 
     86 // The event handler for the button.
     87 void handleEvent(AceButton* /* button */, uint8_t eventType,
     88     uint8_t /* buttonState */) {
     89   unsigned long now = millis();
     90   switch (eventType) {
     91     case AceButton::kEventPressed:
     92       if (stopwatchState == STOPWATCH_INIT) {
     93 
     94         // enable or disable higher level events, to get different performance
     95         // numbers
     96         if (allEventsEnabled) {
     97           enableAllEvents();
     98         } else {
     99           disableAllEvents();
    100         }
    101 
    102         Serial.println(F("handleEvent(): stopwatch started"));
    103         startMillis = now;
    104         innerLoopCounter = 0;
    105         outerLoopCounter = 0;
    106         stopwatchState = STOPWATCH_STARTED;
    107       } else if (stopwatchState == STOPWATCH_STARTED) {
    108         stopMillis = now;
    109         stopwatchState = STOPWATCH_STOPPED;
    110         unsigned long duration = stopMillis - startMillis;
    111         uint32_t loopCounter = ((uint32_t) outerLoopCounter << 16) +
    112             innerLoopCounter;
    113         float microsPerLoop = duration * 1000.0f / loopCounter;
    114 
    115         // reenable all events after stopping
    116         enableAllEvents();
    117 
    118         Serial.println(F("handleEvent(): stopwatch stopped"));
    119         Serial.print(F("handleEvent(): duration (ms): "));
    120         Serial.print(duration);
    121         Serial.print(F("; loopCount: "));
    122         Serial.print(loopCounter);
    123         Serial.print(F("; micros/loop: "));
    124         Serial.println(microsPerLoop);
    125 
    126         // Setting 0 allows the loop() function to return periodically.
    127         innerLoopCounter = 0;
    128       }
    129       break;
    130     case AceButton::kEventLongPressed:
    131       if (stopwatchState == STOPWATCH_STOPPED) {
    132         stopwatchState = STOPWATCH_INIT;
    133         Serial.println(F("handleEvent(): stopwatch reset"));
    134         allEventsEnabled = !allEventsEnabled;
    135       }
    136       break;
    137   }
    138 }
    139 
    140 void enableAllEvents() {
    141   Serial.println(F("enabling high level events"));
    142   button.getButtonConfig()->setFeature(ButtonConfig::kFeatureClick);
    143   button.getButtonConfig()->setFeature(ButtonConfig::kFeatureDoubleClick);
    144   button.getButtonConfig()->setFeature(ButtonConfig::kFeatureLongPress);
    145   button.getButtonConfig()->setFeature(ButtonConfig::kFeatureRepeatPress);
    146 }
    147 
    148 void disableAllEvents() {
    149   Serial.println(F("disabling high level events"));
    150   button.getButtonConfig()->clearFeature(ButtonConfig::kFeatureClick);
    151   button.getButtonConfig()->clearFeature(ButtonConfig::kFeatureDoubleClick);
    152   button.getButtonConfig()->clearFeature(ButtonConfig::kFeatureLongPress);
    153   button.getButtonConfig()->clearFeature(ButtonConfig::kFeatureRepeatPress);
    154 }