#include <EncButton.h>
#include <U8x8lib.h>
#include <FastLED.h>
#include <SPI.h>
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(A5,A4);
#define NUM_LEDS 60
CRGB leds[NUM_LEDS];
EncButton eb(8, 9, 10);
typedef enum Action{
turnUp= 1,
turnDown = -1,
pressButton = 2
}Action;
int statesCount = 4;
typedef struct State {
uint8_t stateNum;
uint8_t value = 0;
uint8_t mx;
bool hasChanged = true;
} State;
bool chosen = false;
int mode;
int modesCount = 3;
State current;
String names[3][4] = {{String("Static"),String("red"),String("green"),String("blue")},
{String("Dynamic"),String("speed"),String(""),String("")},
String("D_other"),String("speed"),String(""),String("")};
State states[3][4];
char strTmp[16] = {0};
void display() {
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setInverseFont(0);
u8x8.drawString(0,0,"Mode:");
for (int i = 0; i< statesCount;i++){
u8x8.setInverseFont(0);
if (names[mode][i] == ""){
break;
}
char cur[10] = {0};
names[mode][i].getBytes(cur,10);
if (current.stateNum == i && chosen){
u8x8.setInverseFont(1);
}
if (i == 0){
sprintf(strTmp, "%s%s ", current.stateNum == i? "-" : " ",cur);
u8x8.drawString(5,0,strTmp);
}else{
sprintf(strTmp, "%s%s %3d ", current.stateNum == i? "-" : " ",cur,states[mode][i].value);
u8x8.drawString(0,i+1,strTmp);
}
}
}
long dyn1 = 0;
long dyn2 = 0;
int current_number = 0;
void led(){
if (mode == 0 && current.hasChanged){
current_number = 0;
CRGB color = CRGB(states[mode][1].value, states[mode][2].value, states[mode][3].value);
for (int i = 0;i<NUM_LEDS;i++){
leds[i] = color;
}
FastLED.show();
}else if(mode == 1 && millis() - dyn1 > (states[mode][1].mx - states[mode][1].value)*100){
current_number = 0;
for (int i = 0;i<NUM_LEDS;i++){
int x = random16();
int y = random16();
int z = random16();
CRGB color = CRGB( x, y, z );
leds[i] = color;
}
dyn1 = millis();
FastLED.show();
}else if(mode == 2 && millis() - dyn2 > (states[mode][1].mx - states[mode][1].value)*100){
if (current_number == 0){
for (int i = 0;i<NUM_LEDS;i++){
CRGB color = CRGB( 0, 0, 0);
leds[i] = color;
}
FastLED.show();
}
int x = random16();
int y = random16();
int z = random16();
CRGB color = CRGB( x, y, z );
leds[current_number] = color;
dyn2 = millis();
current_number++;
if (current_number >= NUM_LEDS){
current_number = 0;
}
FastLED.show();
}
}
int prev = 0;
void setup(void) {
FastLED.addLeds<NEOPIXEL, 6>(leds, NUM_LEDS);
states[0][1].mx = 255;
states[0][2].mx = 255;
states[0][3].mx = 255;
states[1][1].mx = 10;
states[2][1].mx = 10;
mode = 0;
u8x8.begin();
current.stateNum = 0;
current.hasChanged = true;
}
void handleAction(Action action){
if (action == Action::turnUp){
if (!chosen){
if (current.stateNum == 0){
current.stateNum = statesCount - 1;
}
else {
current.stateNum--;
}
}
else {
if (current.stateNum == 0){
mode = (mode +1)% modesCount;
u8x8.clear();
}else {
states[mode][current.stateNum].value = (states[mode][current.stateNum].value+1)%states[mode][current.stateNum].mx;
}
}
}
if (action == Action::turnDown){
if (!chosen){
current.stateNum = (current.stateNum+1)%statesCount;
}
else{
if (current.stateNum == 0){
if (mode == 0){
mode = modesCount-1;
}else{
mode--;
}
u8x8.clear();
}else {
if (states[mode][current.stateNum].value > 0){
states[mode][current.stateNum].value--;
} else{
states[mode][current.stateNum].value = states[mode][current.stateNum].mx;
}
}
}
}
if (action == Action::pressButton){
chosen = true ^ chosen;
}
current.hasChanged = true;
}
long last = 0;
void loop(void) {
eb.tick();
if(eb.turn()) {
if (eb.dir() == -1){
handleAction(Action::turnUp);
}
if (eb.dir() == 1){
handleAction(Action::turnDown);
}
}
if (eb.pressing()){
if (millis() - last > 300){
handleAction(Action::pressButton);
last = millis();
}
}
led();
// как часто стоит обновлять ленту уже зависит от режима
// не стоит каждый раз перерисовывать дисплей.
// Только если состояние изменилось
if (current.hasChanged) {
display();
current.hasChanged = false;
}
}