Gotta Go Faster, Part 3.


The first logical block - Input selection and button debounce can be done in many ways but this is how I solved it. It persists the input selection between power cycles but software based debounce and the controlling a set of relays from a micro controller is still a bit flaky. I would prefer a pure hardware solution for input selection if I had to do it all over again.

The code is quite straight forward and I think it speaks for itself in combination with my previous post outlining the support classes in "SupportClasses.h". I use four push buttons as a set of radio buttons for input selection and a toggle switch to select between two different modes. The code is quite easy to adapt to any number of buttons or switches.

// PIN
const uint8_t   INPUT_PINS[]  = {2, 3, 4, 5};
const uint8_t   MODE_PIN      = 6;
// pin 8 used for I2S IN1 on Teensy 4.0
const uint8_t   OUTPUT_PINS[] = {16, 17, 18, 19};
// MEM
const uint8_t   BUFFER_LEN    = 20;
const uint8_t   BUFFER_ADR    = 0x10;
// BTN
const uint8_t   NUM_INPUT     = sizeof(INPUT_PINS) / sizeof(INPUT_PINS[0]);
const uint8_t   DEF_INPUT     = 0;
// ETC
const uint16_t  POWERUP_MS    = 2000;
const uint8_t   UPDATE_FPS    = 60;
const uint8_t   UPDATE_MS     = 1000 / UPDATE_FPS;

#include "SupportClasses.h"

bool                    altMode = false;
Persistent<uint8_t>     selectedInput;
Debounce                modeButton;
Debounce                inputButton[NUM_INPUT];

// set selected output and save to eeprom
void setOutput(uint8_t selection) {
  selection = selection < NUM_INPUT ? selection : DEF_INPUT;
  for (byte i = 0; i < NUM_INPUT; i++) {
    if (selection == i) {
      digitalWrite(OUTPUT_PINS[i], HIGH);
    } else {
      digitalWrite(OUTPUT_PINS[i], LOW);
    }
  }
  if (selection != selectedInput.get()) {
    selectedInput.put(selection);
  }
}

// input selection callback
void inputCallback(uint8_t pin, uint8_t mode) {
  if (mode == LOW) return;
  for (byte i = 0; i < NUM_INPUT; i++) {
    if (pin == INPUT_PINS[i]) {
      setOutput(i);
      break;
    }
  }
}

// mode selection callback
void modeCallback(uint8_t pin, uint8_t mode) {
  altMode = (mode == HIGH);
}

void setup() {
  // init output pins and input buttons
  modeButton.setup(MODE_PIN, modeCallback);
  for (byte i = 0; i < NUM_INPUT; i++) {
    pinMode(OUTPUT_PINS[i], OUTPUT);
    inputButton[i].setup(INPUT_PINS[i], inputCallback);
  }
  // get persisted data
  selectedInput.setup(DEF_INPUT, BUFFER_ADR, BUFFER_LEN);
  // output selected input
  setOutput(selectedInput.get());
}

void loop() {
  modeButton.update();
  for (byte i = 0; i < NUM_INPUT; i++) {
    inputButton[i].update();
  }
}