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

TunerButtons.ino (5269B)

      1 /*
      2  * Emulate the buttons of a car radio:
      3  *
      4  *    - 3 preset buttons
      5  *    - 1 tune-up button
      6  *    - 1 tune-down button
      7  *
      8  * LongPress of a preset button stores the station.
      9  * LongPress of a tune-up or tune-down button scans the radio frequency.
     10  */
     11 
     12 #include <AceButton.h>
     13 
     14 using namespace ace_button;
     15 
     16 const int NUM_PRESETS = 3;
     17 
     18 const int PRESET_1_PIN = 6;
     19 const int PRESET_2_PIN = 5;
     20 const int PRESET_3_PIN = 4;
     21 const int TUNE_DOWN_PIN = 3;
     22 const int TUNE_UP_PIN = 2;
     23 
     24 // Frequency range of the FM radio.
     25 const uint16_t FM_FREQ_MIN = 879; // 87.9 MHz
     26 const uint16_t FM_FREQ_MAX = 1079; // 107.9 MHz
     27 const uint16_t FM_FREQ_DELTA = 2; // 0.2 MHz increments in USA
     28 
     29 // Preset buttons use the SystemButtonConfig.
     30 AceButton presetButton1;
     31 AceButton presetButton2;
     32 AceButton presetButton3;
     33 
     34 // Tune up or down buttons use a different ButtonConfig.
     35 ButtonConfig tuneConfig;
     36 AceButton tuneDownButton(&tuneConfig);
     37 AceButton tuneUpButton(&tuneConfig);
     38 
     39 // Array to hold the stations associated with the button whose id is an
     40 // index into this array. The value is the 10 * station_frequency (e.g. 88.5 MHz
     41 // is stored as 885).
     42 //
     43 // NOTE: It might be tempting to subclass the AceButton to hold this information
     44 // but it's cleaner to keep this info separated from the AceButton class
     45 // hierarchy.
     46 uint16_t stations[NUM_PRESETS];
     47 
     48 // The current station frequency.
     49 uint16_t currentStation = FM_FREQ_MIN;
     50 
     51 void handlePresetEvent(AceButton*, uint8_t, uint8_t);
     52 void handleTuneEvent(AceButton*, uint8_t, uint8_t);
     53 
     54 void setup() {
     55   delay(1000); // some boards reboot twice
     56   Serial.begin(115200);
     57   while (! Serial); // Wait until Serial is ready - Leonardo/Micro
     58   Serial.println(F("setup(): begin()"));
     59 
     60   // Configs for the preset buttons. Need Released event to change the station,
     61   // and LongPressed to memorize the current station. Don't need Clicked.
     62   ButtonConfig* presetConfig = ButtonConfig::getSystemButtonConfig();
     63   presetConfig->setEventHandler(handlePresetEvent);
     64   presetConfig->setFeature(ButtonConfig::kFeatureLongPress);
     65   presetConfig->setFeature(ButtonConfig::kFeatureSuppressAfterLongPress);
     66 
     67   // Configs for the tune-up and tune-down buttons. Need RepeatPress instead of
     68   // LongPress.
     69   tuneConfig.setEventHandler(handleTuneEvent);
     70   tuneConfig.setFeature(ButtonConfig::kFeatureClick);
     71   tuneConfig.setFeature(ButtonConfig::kFeatureRepeatPress);
     72   // These suppressions not really necessary but cleaner.
     73   tuneConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick);
     74   tuneConfig.setFeature(ButtonConfig::kFeatureSuppressAfterRepeatPress);
     75 
     76   // Preset Button 1
     77   pinMode(PRESET_1_PIN, INPUT_PULLUP);
     78   presetButton1.init(PRESET_1_PIN, HIGH, 0 /* id */);
     79 
     80   // Preset Button 2
     81   pinMode(PRESET_2_PIN, INPUT_PULLUP);
     82   presetButton2.init(PRESET_2_PIN, HIGH, 1 /* id */);
     83 
     84   // Preset Button 3
     85   pinMode(PRESET_3_PIN, INPUT_PULLUP);
     86   presetButton3.init(PRESET_3_PIN, HIGH, 2 /* id */);
     87 
     88   // Tune Down Button
     89   pinMode(TUNE_DOWN_PIN, INPUT_PULLUP);
     90   tuneDownButton.init(TUNE_DOWN_PIN);
     91 
     92   // Tune Up Button
     93   pinMode(TUNE_UP_PIN, INPUT_PULLUP);
     94   tuneUpButton.init(TUNE_UP_PIN);
     95 
     96   // init the stations associated with each button
     97   initStations();
     98 
     99   Serial.println(F("setup(): tuner buttons ready"));
    100   printStation(currentStation);
    101 }
    102 
    103 void loop() {
    104   presetButton1.check();
    105   presetButton2.check();
    106   presetButton3.check();
    107   tuneUpButton.check();
    108   tuneDownButton.check();
    109 }
    110 
    111 void initStations() {
    112   for (int i = 0; i < NUM_PRESETS; i++) {
    113     stations[i] = FM_FREQ_MIN;
    114   }
    115 }
    116 
    117 void printStation(uint16_t frequency) {
    118   Serial.print(F("station: "));
    119   Serial.print(frequency / 10);
    120   Serial.print('.');
    121   Serial.println(frequency % 10);
    122 }
    123 
    124 void handlePresetEvent(AceButton* button, uint8_t eventType,
    125     uint8_t /* buttonState */) {
    126   switch (eventType) {
    127     case AceButton::kEventReleased:
    128       // We trigger on the Released event not the Pressed event to distinguish
    129       // this event from the LongPressed event.
    130       retrievePreset(button->getId());
    131       break;
    132     case AceButton::kEventLongPressed:
    133       setPreset(button->getId());
    134       break;
    135   }
    136 }
    137 
    138 void handleTuneEvent(AceButton* button, uint8_t eventType,
    139     uint8_t /* buttonState */) {
    140   switch (eventType) {
    141     case AceButton::kEventPressed:
    142     case AceButton::kEventRepeatPressed: {
    143       uint8_t pin = button->getPin();
    144       switch (pin) {
    145         case TUNE_UP_PIN:
    146           tuneUp();
    147           break;
    148         case TUNE_DOWN_PIN:
    149           tuneDown();
    150           break;
    151       }
    152     }
    153   }
    154 }
    155 
    156 void retrievePreset(uint8_t id) {
    157   if (id < NUM_PRESETS) {
    158     currentStation = stations[id];
    159     Serial.print(F("memory "));
    160     Serial.print(id + 1);
    161     Serial.print(F(": "));
    162     printStation(currentStation);
    163   }
    164 }
    165 
    166 void setPreset(uint8_t id) {
    167   if (id < NUM_PRESETS) {
    168     stations[id] = currentStation;
    169 
    170     Serial.print(F("memory "));
    171     Serial.print(id + 1);
    172     Serial.print(F(" set: "));
    173     printStation(currentStation);
    174   }
    175 }
    176 
    177 void tuneUp() {
    178   currentStation += FM_FREQ_DELTA;
    179   if (currentStation > FM_FREQ_MAX) {
    180     currentStation = FM_FREQ_MIN;
    181   }
    182   printStation(currentStation);
    183 }
    184 
    185 void tuneDown() {
    186   currentStation -= FM_FREQ_DELTA;
    187   if (currentStation < FM_FREQ_MIN) {
    188     currentStation = FM_FREQ_MAX;
    189   }
    190   printStation(currentStation);
    191 }