/* * Emulate the buttons of a car radio: * * - 3 preset buttons * - 1 tune-up button * - 1 tune-down button * * LongPress of a preset button stores the station. * LongPress of a tune-up or tune-down button scans the radio frequency. */ #include using namespace ace_button; const int NUM_PRESETS = 3; const int PRESET_1_PIN = 6; const int PRESET_2_PIN = 5; const int PRESET_3_PIN = 4; const int TUNE_DOWN_PIN = 3; const int TUNE_UP_PIN = 2; // Frequency range of the FM radio. const uint16_t FM_FREQ_MIN = 879; // 87.9 MHz const uint16_t FM_FREQ_MAX = 1079; // 107.9 MHz const uint16_t FM_FREQ_DELTA = 2; // 0.2 MHz increments in USA // Preset buttons use the SystemButtonConfig. AceButton presetButton1; AceButton presetButton2; AceButton presetButton3; // Tune up or down buttons use a different ButtonConfig. ButtonConfig tuneConfig; AceButton tuneDownButton(&tuneConfig); AceButton tuneUpButton(&tuneConfig); // Array to hold the stations associated with the button whose id is an // index into this array. The value is the 10 * station_frequency (e.g. 88.5 MHz // is stored as 885). // // NOTE: It might be tempting to subclass the AceButton to hold this information // but it's cleaner to keep this info separated from the AceButton class // hierarchy. uint16_t stations[NUM_PRESETS]; // The current station frequency. uint16_t currentStation = FM_FREQ_MIN; void handlePresetEvent(AceButton*, uint8_t, uint8_t); void handleTuneEvent(AceButton*, uint8_t, uint8_t); void setup() { delay(1000); // some boards reboot twice Serial.begin(115200); while (! Serial); // Wait until Serial is ready - Leonardo/Micro Serial.println(F("setup(): begin()")); // Configs for the preset buttons. Need Released event to change the station, // and LongPressed to memorize the current station. Don't need Clicked. ButtonConfig* presetConfig = ButtonConfig::getSystemButtonConfig(); presetConfig->setEventHandler(handlePresetEvent); presetConfig->setFeature(ButtonConfig::kFeatureLongPress); presetConfig->setFeature(ButtonConfig::kFeatureSuppressAfterLongPress); // Configs for the tune-up and tune-down buttons. Need RepeatPress instead of // LongPress. tuneConfig.setEventHandler(handleTuneEvent); tuneConfig.setFeature(ButtonConfig::kFeatureClick); tuneConfig.setFeature(ButtonConfig::kFeatureRepeatPress); // These suppressions not really necessary but cleaner. tuneConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick); tuneConfig.setFeature(ButtonConfig::kFeatureSuppressAfterRepeatPress); // Preset Button 1 pinMode(PRESET_1_PIN, INPUT_PULLUP); presetButton1.init(PRESET_1_PIN, HIGH, 0 /* id */); // Preset Button 2 pinMode(PRESET_2_PIN, INPUT_PULLUP); presetButton2.init(PRESET_2_PIN, HIGH, 1 /* id */); // Preset Button 3 pinMode(PRESET_3_PIN, INPUT_PULLUP); presetButton3.init(PRESET_3_PIN, HIGH, 2 /* id */); // Tune Down Button pinMode(TUNE_DOWN_PIN, INPUT_PULLUP); tuneDownButton.init(TUNE_DOWN_PIN); // Tune Up Button pinMode(TUNE_UP_PIN, INPUT_PULLUP); tuneUpButton.init(TUNE_UP_PIN); // init the stations associated with each button initStations(); Serial.println(F("setup(): tuner buttons ready")); printStation(currentStation); } void loop() { presetButton1.check(); presetButton2.check(); presetButton3.check(); tuneUpButton.check(); tuneDownButton.check(); } void initStations() { for (int i = 0; i < NUM_PRESETS; i++) { stations[i] = FM_FREQ_MIN; } } void printStation(uint16_t frequency) { Serial.print(F("station: ")); Serial.print(frequency / 10); Serial.print('.'); Serial.println(frequency % 10); } void handlePresetEvent(AceButton* button, uint8_t eventType, uint8_t /* buttonState */) { switch (eventType) { case AceButton::kEventReleased: // We trigger on the Released event not the Pressed event to distinguish // this event from the LongPressed event. retrievePreset(button->getId()); break; case AceButton::kEventLongPressed: setPreset(button->getId()); break; } } void handleTuneEvent(AceButton* button, uint8_t eventType, uint8_t /* buttonState */) { switch (eventType) { case AceButton::kEventPressed: case AceButton::kEventRepeatPressed: { uint8_t pin = button->getPin(); switch (pin) { case TUNE_UP_PIN: tuneUp(); break; case TUNE_DOWN_PIN: tuneDown(); break; } } } } void retrievePreset(uint8_t id) { if (id < NUM_PRESETS) { currentStation = stations[id]; Serial.print(F("memory ")); Serial.print(id + 1); Serial.print(F(": ")); printStation(currentStation); } } void setPreset(uint8_t id) { if (id < NUM_PRESETS) { stations[id] = currentStation; Serial.print(F("memory ")); Serial.print(id + 1); Serial.print(F(" set: ")); printStation(currentStation); } } void tuneUp() { currentStation += FM_FREQ_DELTA; if (currentStation > FM_FREQ_MAX) { currentStation = FM_FREQ_MIN; } printStation(currentStation); } void tuneDown() { currentStation -= FM_FREQ_DELTA; if (currentStation < FM_FREQ_MIN) { currentStation = FM_FREQ_MAX; } printStation(currentStation); }