|
|
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <AT24C32.h>
#include <DS3231.h>
#include <States.h>
#include <ViewStates.h>
#include <ControlStates.h>
#include <Button.h>
// debug
#define DEBUG 1
// Neopixel
#define MATRIX_PIN 12
#define MATRIX_SIZE 121
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(MATRIX_SIZE, MATRIX_PIN, NEO_GRB + NEO_KHZ800);
// Date view delimiter
#define DATE_DELIMITER '.'
// Buttons
#define LEFT_PIN 11
#define DECREMENT_PIN 10
#define ENTER_PIN 9
#define INCREMENT_PIN 8
#define RIGHT_PIN 7
Button leftBtn = Button(LEFT_PIN, LOW); Button decrementBtn = Button(DECREMENT_PIN, LOW); Button enterBtn = Button(ENTER_PIN, LOW); Button incrementBtn = Button(INCREMENT_PIN, LOW); Button rightBtn = Button(RIGHT_PIN, LOW);
// LED matrix
uint8_t matrix[MATRIX_SIZE];
// EPROMM AT24C32
AT24C32 at24c32;
// RTC DS3231
DS3231 ds3231;
// states
ControlStates controlState = ControlStates::VIEW; ControlStates oldControlState = ControlStates::VIEW; ViewStates viewState = ViewStates::TIME; ViewStates oldViewState = ViewStates::TIME;
// control state
ControlState *currentControlState = new ControlViewState(at24c32);
// view state
ViewState *currentViewState = new ViewTimeState(ds3231, at24c32);
/**
setup */ void setup() { #ifdef DEBUG
Serial.begin(9600); #endif
pixels.begin(); ds3231.begin(); at24c32.begin();
leftBtn.begin(); decrementBtn.begin(); enterBtn.begin(); incrementBtn.begin(); rightBtn.begin();
viewState = ViewStates(at24c32.read(VIEW_STATE_ADDRESS) % 6);
printStatus(); }
/**
loop */ void loop() { checkControlState(); controls(); checkViewState(); // render
renderInterval(); }
/**
check current control state and change eventually */ void checkControlState() { if (controlState != oldControlState) { delete currentControlState; switch (controlState) { case ControlStates::VIEW: currentControlState = new ControlViewState(at24c32); break; case ControlStates::TIME_HOURS: currentControlState = new ControlTimeState(ds3231, at24c32); break; case ControlStates::TIME_MINUTES: currentControlState = new ControlTimeState(ds3231, at24c32); break; case ControlStates::TIME_MODE: currentControlState = new ControlTimeState(ds3231, at24c32); break; case ControlStates::TIME_SECONDS: currentControlState = new ControlSecondsState(ds3231); break; case ControlStates::DATE_DATE: currentControlState = new ControlDateState(ds3231); break; case ControlStates::DATE_MONTH: currentControlState = new ControlDateState(ds3231); break; case ControlStates::DATE_YEAR: currentControlState = new ControlDateState(ds3231); break; case ControlStates::COLOR_R: currentControlState = new ControlColorState(at24c32); break; case ControlStates::COLOR_G: currentControlState = new ControlColorState(at24c32); break; case ControlStates::COLOR_B: currentControlState = new ControlColorState(at24c32); break; case ControlStates::TEXT: currentControlState = new ControlTextState(at24c32); break; default: currentControlState = new ControlViewState(at24c32); } oldControlState = controlState;
printStatus(); } }
/**
check current view state and change eventually */ void checkViewState() { if (viewState != oldViewState) { delete currentViewState; switch (viewState) { case ViewStates::TIME: currentViewState = new ViewTimeState(ds3231, at24c32); break; case ViewStates::SECONDS: currentViewState = new ViewSecondsState(ds3231, at24c32); break; case ViewStates::TEMPERATURE: currentViewState = new ViewTemperatureState(ds3231, at24c32); break; case ViewStates::DATE: currentViewState = new ViewDateState(ds3231, at24c32, DATE_DELIMITER); break; case ViewStates::TEXT: currentViewState = new ViewTextState(at24c32); break; case ViewStates::LED_DEMO: currentViewState = new ViewLEDState(); break; default: currentViewState = new ViewTimeState(ds3231, at24c32); }
oldViewState = viewState; at24c32.write(VIEW_STATE_ADDRESS, uint8_t(viewState));
printStatus(); } }
/**
check inputs */ void controls() { leftBtn.loop(leftCallback); decrementBtn.loop(decrementCallback); enterBtn.loop(enterCallback); incrementBtn.loop(incrementCallback); rightBtn.loop(rightCallback); }
/**
left callback */ void leftCallback() { // delegate to current control state
currentControlState->leftPressed(viewState, controlState); #ifdef DEBUG
Serial.print(F("< ")); #endif
}
/**
decrement callback */ void decrementCallback() { // delegate to current control state
currentControlState->decrementPressed(viewState, controlState); #ifdef DEBUG
Serial.print(F("- ")); #endif
}
/**
enter callback */ void enterCallback() { // delegate to current control state
currentControlState->enterPressed(viewState, controlState); #ifdef DEBUG
Serial.print(F("# ")); #endif
}
/**
increment callback */ void incrementCallback() { // delegate to current control state
currentControlState->incrementPressed(viewState, controlState); #ifdef DEBUG
Serial.print(F("+ ")); #endif
}
/**
right callback */ void rightCallback() { // delegate to current control state
currentControlState->rightPressed(viewState, controlState); #ifdef DEBUG
Serial.print(F("> ")); #endif
}
/**
periodic rendering */ void renderInterval() { static const unsigned long REFRESH_INTERVAL = 100; static unsigned long lastRefreshTime = 0;
if (millis() - lastRefreshTime >= REFRESH_INTERVAL) { lastRefreshTime += REFRESH_INTERVAL; render(); } }
/**
render */ void render() { // set default color
uint8_t const color = at24c32.read(COLOR_ADDRESS); currentViewState->setColor(color);
// set brightness
uint8_t const brightness = at24c32.read(BRIGHTNESS_ADDRESS); pixels.setBrightness(brightness);
// reset matrix (to black)
for (int i = 0; i < MATRIX_SIZE; i++) { matrix[i] = 0x00; }
// render matrix
currentViewState->render(matrix, controlState);
// set pixel
for (int i = 0; i < MATRIX_SIZE; i++) { uint8_t const r = (matrix[i] >> 5) * 255 / 7; uint8_t const g = ((matrix[i] >> 2) & 0x07) * 255 / 7; uint8_t const b = (matrix[i] & 0x03) * 255 / 3; pixels.setPixelColor(i, pixels.Color(r, g, b)); }
pixels.show(); }
/**
print current status VIEW STATE \t CONTROL STATE \t FREE RAM */ void printStatus() { #ifdef DEBUG
switch (viewState) { case ViewStates::TIME: Serial.print(F("TIME")); break; case ViewStates::SECONDS: Serial.print(F("SECS")); break; case ViewStates::TEMPERATURE: Serial.print(F("TEMP")); break; case ViewStates::DATE: Serial.print(F("DATE")); break; case ViewStates::TEXT: Serial.print(F("TEXT")); break; case ViewStates::LED_DEMO: Serial.print(F("LEDS")); break; default: Serial.print(F("TIME")); }
Serial.print(F("\t")); switch (controlState) { case ControlStates::VIEW: Serial.print(F("VIEW ")); break; case ControlStates::TIME_HOURS: Serial.print(F("HOURS")); break; case ControlStates::TIME_MINUTES: Serial.print(F("MINS ")); break; case ControlStates::TIME_MODE: Serial.print(F("MODE ")); break; case ControlStates::TIME_SECONDS: Serial.print(F("SECS ")); break; case ControlStates::DATE_DATE: Serial.print(F("DATE ")); break; case ControlStates::DATE_MONTH: Serial.print(F("MONTH")); break; case ControlStates::DATE_YEAR: Serial.print(F("YEAR ")); break; case ControlStates::COLOR_R: Serial.print(F("COLOR_R")); break; case ControlStates::COLOR_G: Serial.print(F("COLOR_G")); break; case ControlStates::COLOR_B: Serial.print(F("COLOR_B")); break; case ControlStates::TEXT: Serial.print(F("TEXT ")); break; default: Serial.print(F("VIEW ")); }
extern int __heap_start, *__brkval; int v; Serial.print(F("\tRAM: ")); Serial.println((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval)); #endif
}
|