//
// Referring to https://forum.arduino.cc/t/how-to-build-a-byte-from-bits/1313284/36
//
#include <Button_SL.hpp> // Description: https://github.com/DoImant/Button_SL
#include <Streaming.h> // Description: https://github.com/janelia-arduino/Streaming
#include <LedControl.h>
Print &cout {Serial};
using namespace Btn;
//
// Global constants
//
constexpr uint8_t PIN_BLE_LEDS[] {22, 23, 24, 25};
constexpr uint8_t PIN_GRN_LEDS[] {37, 38, 39, 40, 41, 42, 43};
constexpr uint8_t BLE_BTN_START {0};
constexpr uint8_t GRN_BTN_START {sizeof(PIN_BLE_LEDS) / sizeof(PIN_BLE_LEDS[0])};
constexpr uint8_t GRN_BTN_END {(GRN_BTN_START + sizeof(PIN_GRN_LEDS) / sizeof(PIN_GRN_LEDS[0])) - 1};
constexpr uint8_t ADJUST_SW_PIN[] {11,10}; // Adj 1 and 2
constexpr uint8_t DIN {6};
constexpr uint8_t CS {7};
constexpr uint8_t CLK {8};
// constexpr uint8_t SMILE[8] {0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C};
// constexpr uint8_t SAD[8] {0x3C, 0x42, 0xA5, 0x81, 0x99, 0xA5, 0x42, 0x3C};
constexpr uint8_t EMOTION_DATA[2][8] {
{0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C}, // smile
{0x3C, 0x42, 0xA5, 0x81, 0x99, 0xA5, 0x42, 0x3C} // sad
};
//
// Global variables/ objects
//
enum Emotion : uint8_t {smile, sad, none};
uint8_t stateBleLeds {0};
uint8_t stateGrnLeds {0};
// Define an array of button objects for querying the blue and green buttons.
ButtonSL btnArray[] {{26}, {27}, {28}, {29}, {30}, {31}, {32}, {33}, {34}, {35}, {36}};
LedControl lc(DIN, CLK, CS, 0);
//
// Button query
// Returns number of pressed button or -1 if no button is pressed
//
template <size_t N> int8_t checkButtons(ButtonSL (&btns)[N]) {
for (uint8_t i = 0; i < N; ++i) {
if (btns[i].tick() != ButtonState::notPressed) { return i; }
}
return -1;
}
//
// Switch the LEDs depending on the set bits
// of the status byte for the respective LED color
//
template <size_t N> void switchLeds(const uint8_t (&pin)[N], uint16_t bitMask) {
for (size_t bits {0}; bits < N; ++bits) { digitalWrite(pin[bits], bitMask & (1 << bits)); }
}
//
// Set the bits in the status byte for the LEDs
//
uint8_t getLedState(uint8_t state, uint8_t bitMask) {
// If bit already set delete it otherwise set it
return (state & bitMask) ? state &= ~bitMask : state |= bitMask;
}
//
// Set a given pattern on the LED Dot Matrix
//
template <size_t N> void setDotMatrix(const uint8_t (&pattern)[N] ) {
for (size_t i = 0; i < N; i++) { lc.setRow(0, i, pattern[i]); }
}
void setup() {
Serial.begin(115200);
// INPUTS
// Init Buttons
for (auto &btn : btnArray) {
btn.begin();
btn.setDebounceTime_ms(40);
}
for (auto &pin : ADJUST_SW_PIN) { pinMode(pin, INPUT_PULLUP); }
// OUTPUTS
for (auto &pin : PIN_GRN_LEDS) { pinMode(pin, OUTPUT); }
for (auto &pin : PIN_BLE_LEDS) { pinMode(pin, OUTPUT); }
cout << "Start..." << endl;
setDotMatrix(EMOTION_DATA[Emotion::sad]);
}
void loop() {
static uint8_t prevEmotion {Emotion::none};
int8_t btnNum = checkButtons(btnArray);
switch (btnNum) {
case BLE_BTN_START ... GRN_BTN_START - 1: // Blue buttons array index 0 ... 3
stateBleLeds = getLedState(stateBleLeds, 1 << btnNum); // Shift bit x (btnNum) positions to the left
switchLeds(PIN_BLE_LEDS, stateBleLeds);
cout << " Blue Button Nr: " << _WIDTH(btnNum, 2) << " ";
cout << " Blue LED Status: " << _WIDTHZ(_BIN(stateBleLeds), 8) << " 0x" << _WIDTHZ(_HEX(stateBleLeds),2) << endl;
break;
case GRN_BTN_START ... GRN_BTN_END: // Green buttons array index 4 ... 10
{ // The curly bracket block is necessary if a new (local) variable is defined within the switch statement.
uint8_t greenBtnNum = btnNum - GRN_BTN_START; // Subtract the offset so that the button number starts at 0
stateGrnLeds = getLedState(stateGrnLeds, 1 << greenBtnNum);
switchLeds(PIN_GRN_LEDS, stateGrnLeds);
cout << "Green Button Nr: " << _WIDTH(greenBtnNum, 2) << " ";
cout << "Green LED Status: " << _WIDTHZ(_BIN(stateGrnLeds), 8) << " 0x" << _WIDTHZ(_HEX(stateGrnLeds),2) << endl;
} break;
default: break;
}
uint8_t emotion = (!digitalRead(ADJUST_SW_PIN[smile]) && stateBleLeds == 0x01 && stateGrnLeds == 0x40) ? Emotion::smile : Emotion::sad;
if (emotion != prevEmotion) {
prevEmotion == emotion;
setDotMatrix(EMOTION_DATA[emotion]);
}
}