Initial code commit
This commit is contained in:
11
src/button.cpp
Normal file
11
src/button.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "button.hpp"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
bool AnalogButton::is_button_pressed(void) {
|
||||
return analogRead(_aPin) < _vRef;
|
||||
}
|
||||
|
||||
void AnalogButton::calibrate(void) {
|
||||
|
||||
}
|
16
src/button.hpp
Normal file
16
src/button.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __BUTTON_HPP__
|
||||
#define __BUTTON_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class AnalogButton {
|
||||
public:
|
||||
AnalogButton(uint8_t analogPin, int vRef) : _aPin{analogPin}, _vRef{vRef} {};
|
||||
bool is_button_pressed(void);
|
||||
void calibrate(void);
|
||||
private:
|
||||
uint8_t _aPin;
|
||||
int _vRef;
|
||||
};
|
||||
|
||||
#endif /* __BUTTON_HPP__ */
|
346
src/main.cpp
Normal file
346
src/main.cpp
Normal file
@@ -0,0 +1,346 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <Encoder.h>
|
||||
|
||||
#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<Mode_e>(static_cast<int>(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.h>
|
||||
SoftwareSerial debugSerial{RxPin, TxPin}; // RX, TX
|
||||
#endif /*ARDUINO_AVR_ATTINYX5*/
|
||||
#ifdef ARDUINO_AVR_UNO
|
||||
#include <HardwareSerial.h>
|
||||
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<int>(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<int>(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);
|
||||
}
|
||||
|
||||
}
|
27
src/pin_map.hpp
Normal file
27
src/pin_map.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifdef ARDUINO_AVR_ATTINYX5
|
||||
/* Led output pin */
|
||||
uint8_t const LedPin{PB0};
|
||||
|
||||
/* Button analog input pin */
|
||||
uint8_t const AnalogButtonPin{0};
|
||||
/* Rotary encoder input pins */
|
||||
uint8_t const EncoderPinA{PB3};
|
||||
uint8_t const EncoderPinB{PB4};
|
||||
|
||||
/* Uart for serial debug pins */
|
||||
#ifdef DEBUG
|
||||
uint8_t const TxPin{PB1};
|
||||
uint8_t const RxPin{PB2};
|
||||
#endif /*DEBUG*/
|
||||
#endif /*ARDUINO_AVR_ATTINYX5*/
|
||||
|
||||
#ifdef ARDUINO_AVR_UNO
|
||||
/* Led output pin */
|
||||
uint8_t const LedPin{6};
|
||||
|
||||
/* Button analog input pin */
|
||||
uint8_t const AnalogButtonPin{A0};
|
||||
/* Rotary encoder input pins */
|
||||
uint8_t const EncoderPinA{8};
|
||||
uint8_t const EncoderPinB{9};
|
||||
#endif /*ARDUINO_AVR_UNO*/
|
Reference in New Issue
Block a user