#include #include #include #include "pin_map.hpp" #include "Button.hpp" /* Types and Constants */ /* ---------------------------------------------------------------------------------------------- */ /* State machine */ #define FOREACH_MODE(MODE) \ MODE(ControlOff) \ MODE(LightOn) \ MODE(SetColor) \ MODE(SetSaturation) \ MODE(SetBrightness) \ MODE(Shift) \ #define GENERATE_MODE_ENUM(ENUM) ENUM, enum class Mode_e {FOREACH_MODE(GENERATE_MODE_ENUM)}; Mode_e& operator++(Mode_e& mode) { if (mode == Mode_e::Shift) { return mode = Mode_e::ControlOff; } return mode = static_cast(static_cast(mode) + 1); } #ifdef DEBUG #define GENERATE_MODE_STRING(STRING) #STRING, char static const * mode_str[] = {FOREACH_MODE(GENERATE_MODE_STRING)}; #endif /*DEBUG*/ /* Leds */ uint16_t static const LedCount{24}; uint8_t static const ColorSaturation{128}; uint8_t static const ColorArray[3][3] = {{ColorSaturation, 0, 0}, {0, ColorSaturation, 0}, {0, 0, ColorSaturation}}; /* Led ring state */ typedef struct { uint16_t ledOnCounter; uint16_t ledOnShift; uint16_t hue; uint8_t saturation; uint8_t brightness; } LedRingState_t; /* Button */ int const AnalogButtonVRef{970}; /* Global variables */ /* ---------------------------------------------------------------------------------------------- */ /* State machine */ Mode_e currentMode{Mode_e::ControlOff}; /* Led ring state */ LedRingState_t ledRingState { .ledOnCounter = 1, .ledOnShift = 0, .hue = 0, .saturation = 255, .brightness = 16, }; /* IO Objects */ Adafruit_NeoPixel ledRing{LedCount, LedPin, NEO_GRB + NEO_KHZ800}; Encoder encoder{EncoderPinA, EncoderPinB}; AnalogButton button{AnalogButtonPin, AnalogButtonVRef}; /* debug Serial definition */ #ifdef DEBUG #ifdef ARDUINO_AVR_ATTINYX5 #include SoftwareSerial debugSerial{RxPin, TxPin}; // RX, TX #endif /*ARDUINO_AVR_ATTINYX5*/ #ifdef ARDUINO_AVR_UNO #include HardwareSerial &debugSerial = Serial; #endif /*ARDUINO_AVR_UNO*/ #endif /*DEBUG*/ /* Private function declarations */ /* ---------------------------------------------------------------------------------------------- */ /* State machine */ #define GENERATE_MODE_EXEC_DECLARTION(MODE) void MODE ## _execute (int shift); FOREACH_MODE(GENERATE_MODE_EXEC_DECLARTION) /* Encoder */ int get_encoder_shift(void); void refresh_led_ring(void); void analog_button_calibration(void); /* Function definitions */ /* ---------------------------------------------------------------------------------------------- */ void setup() { #ifdef DEBUG debugSerial.begin(9600); while(!debugSerial.available()); debugSerial.println("Init ... "); #endif /*DEBUG*/ analog_button_calibration(); ledRing.begin(); ledRing.setBrightness(50); ledRing.show(); get_encoder_shift(); #ifdef DEBUG debugSerial.println(mode_str[static_cast(currentMode)]); #endif /*DEBUG*/ } void loop() { int shift{get_encoder_shift()}; if (button.is_button_pressed()) { while(button.is_button_pressed()){ delay(150); } ++currentMode; #ifdef DEBUG debugSerial.println(mode_str[static_cast(currentMode)]); #endif /*DEBUG*/ } if (shift != 0) { switch (currentMode) { case Mode_e::ControlOff: ControlOff_execute(shift); break; case Mode_e::LightOn: LightOn_execute(shift); break; case Mode_e::SetColor: SetColor_execute(shift); break; case Mode_e::SetBrightness: SetBrightness_execute(shift); break; case Mode_e::SetSaturation: SetSaturation_execute(shift); break; case Mode_e::Shift: Shift_execute(shift); break; default: break; } } if (currentMode != Mode_e::ControlOff && shift != 0) { refresh_led_ring(); } } void ControlOff_execute (int shift) { } void LightOn_execute (int shift) { uint16_t & ledOnCounter = ledRingState.ledOnCounter; if (shift > 0) { ++ledOnCounter; if (ledOnCounter > LedCount) { ledOnCounter = 0; } } else { --ledOnCounter; if (ledOnCounter == UINT16_MAX) { ledOnCounter = LedCount; } } #if defined(DEBUG) && defined(ARDUINO_AVR_UNO) if (shift != 0) { debugSerial.print(__func__); debugSerial.print(" : shift="); debugSerial.print(shift, DEC); debugSerial.print(", ledOnCounter="); debugSerial.println(ledOnCounter, DEC); } #endif /*defined(DEBUG) && defined(ARDUINO_AVR_UNO)*/ } void SetColor_execute (int shift) { uint16_t & hue = ledRingState.hue; hue += (shift << 8); #if defined(DEBUG) && defined(ARDUINO_AVR_UNO) if (shift != 0) { debugSerial.print(__func__); debugSerial.print(" : shift="); debugSerial.print(shift, DEC); debugSerial.print(", hue="); debugSerial.println(hue, DEC); } #endif /*defined(DEBUG) && defined(ARDUINO_AVR_UNO)*/ } void SetBrightness_execute (int shift) { uint8_t & brightness = ledRingState.brightness; brightness += (shift << 2); #if defined(DEBUG) && defined(ARDUINO_AVR_UNO) if (shift != 0) { debugSerial.print(__func__); debugSerial.print(" : shift="); debugSerial.print(shift, DEC); debugSerial.print(", brightness="); debugSerial.println(brightness, DEC); } #endif /*defined(DEBUG) && defined(ARDUINO_AVR_UNO)*/ } void Shift_execute (int shift) { uint16_t & ledOnShift = ledRingState.ledOnShift; if (shift > 0) { ++ledOnShift; if (ledOnShift == LedCount) { ledOnShift = 0; } } else { --ledOnShift; if (ledOnShift == UINT16_MAX) { ledOnShift = LedCount - 1; } } #if defined(DEBUG) && defined(ARDUINO_AVR_UNO) if (shift != 0) { debugSerial.print(__func__); debugSerial.print(" : shift="); debugSerial.print(shift, DEC); debugSerial.print(", ledOnShift="); debugSerial.println(ledOnShift, DEC); } #endif /*defined(DEBUG) && defined(ARDUINO_AVR_UNO)*/ } void SetSaturation_execute (int shift) { uint8_t & saturation = ledRingState.saturation; saturation += (shift << 2); #if defined(DEBUG) && defined(ARDUINO_AVR_UNO) if (shift != 0) { debugSerial.print(__func__); debugSerial.print(" : shift="); debugSerial.print(shift, DEC); debugSerial.print(", saturation="); debugSerial.println(saturation, DEC); } #endif /*defined(DEBUG) && defined(ARDUINO_AVR_UNO)*/ } int get_encoder_shift(void) { int32_t static _previousValue{encoder.read()}; int32_t currentValue{encoder.read()}; int32_t diff{currentValue - _previousValue}; if (diff <= -4) { _previousValue = currentValue; return diff >> 2; } else if (diff >= 4) { _previousValue = currentValue; return diff >> 2; } else { return 0; } } void refresh_led_ring(void) { ledRing.fill(0); for (size_t i = 0; i < ledRingState.ledOnCounter; ++i) { unsigned int ledId = i + ledRingState.ledOnShift; if (ledId >= LedCount) { ledId -= LedCount; } ledRing.setPixelColor(ledId, Adafruit_NeoPixel::ColorHSV (ledRingState.hue, ledRingState.saturation, ledRingState.brightness)); } ledRing.show(); } void analog_button_calibration(void) { int hRef; do { hRef = analogRead(AnalogButtonPin); delay(300); #ifdef DEBUG debugSerial.println(hRef); #endif /*DEBUG*/ } while (hRef < 1000); int lRef = analogRead(AnalogButtonPin); while (hRef - lRef < 50) { #ifdef DEBUG debugSerial.println(lRef); #endif /*DEBUG*/ lRef = analogRead(AnalogButtonPin); delay(300); } #ifdef DEBUG debugSerial.println(lRef); #endif /*DEBUG*/ button = AnalogButton{AnalogButtonPin, lRef + 10}; while(analogRead(AnalogButtonPin) < lRef + 10){ delay(150); } }