diff --git a/klock4.ino b/klock4.ino new file mode 100644 index 0000000..08b4aa5 --- /dev/null +++ b/klock4.ino @@ -0,0 +1,125 @@ +#include +#define DATA_PIN 13 + +#include +#include +#include + +#define ROWS 10 +#define COLS 11 + +typedef struct {uint8_t start; uint16_t len;} word_t; + +#define ES ((word_t) {.start= 0, .len=2}) +#define IST ((word_t) {.start= 3, .len=3}) +#define FUNF_PRE ((word_t) {.start= 7, .len=4}) +#define ZEHN_PRE ((word_t) {.start= 11, .len=4}) +#define ZWANZIG ((word_t) {.start= 15, .len=7}) +#define VIERTEL ((word_t) {.start= 26, .len=7}) +#define VOR ((word_t) {.start= 33, .len=3}) +#define NACH ((word_t) {.start= 40, .len=4}) +#define HALB ((word_t) {.start= 44, .len=4}) +#define ELF ((word_t) {.start= 49, .len=3}) +#define FUNF_UHR ((word_t) {.start= 51, .len=4}) +#define EINS ((word_t) {.start= 55, .len=4}) +#define ZWEI ((word_t) {.start= 62, .len=4}) +#define DREI ((word_t) {.start= 66, .len=4}) +#define VIER ((word_t) {.start= 73, .len=4}) +#define SECHS ((word_t) {.start= 77, .len=5}) +#define ACHT ((word_t) {.start= 84, .len=4}) +#define SIEBEN ((word_t) {.start= 88, .len=6}) +#define ZWOLF ((word_t) {.start= 94, .len=5}) +#define ZEHN_UHR ((word_t) {.start= 99, .len=4}) +#define NEUN ((word_t) {.start=102, .len=4}) +#define UHR ((word_t) {.start=107, .len=3}) + +word_t HOURS[] = { + ZWOLF, EINS, ZWEI, DREI, VIER, FUNF_UHR, + SECHS, SIEBEN, ACHT, NEUN, ZEHN_UHR, ELF +}; +word_t PARTS[] = { + UHR, FUNF_PRE, ZEHN_PRE, VIERTEL, + ZWANZIG, FUNF_PRE, HALB +}; + + +CRGB leds[ROWS*COLS]; + +void set(word_t word) { + CRGB color = CRGB(255,255,255); + int dir = 1; + // because of the snaking LED layout, we need to reverse every second row + // i.e. flip the start on the other side and then count backwards + if (word.start % 22 >= 11) { + word.start = (word.start/11)*11 + 10 - (word.start % 11); + dir = -1; + } + for (unsigned int i = 0; i < word.len; i++) + leds[word.start + dir*i] = color; +} + +void reset(void) { + memset(&leds, 0, sizeof(leds)); + set(ES); + set(IST); +} + + +void settime(time_t ts) { + + unsigned int second = ts % 60; + + unsigned int minute = (ts / 60) % 60; + float fminute = (float) minute + (float) second / 60; + minute = 5 * (unsigned int) roundf(fminute / 5); + + unsigned int timezone = 1; + unsigned int daylight_savings = 1; + unsigned int hour = (ts / (60*60) + timezone + daylight_savings) % 12; + + int before = 0; + + if (minute >= 25) { + hour = (hour+1) % 12; + before = 1; + minute = 60-minute; + if (minute == 35) { + minute = 25; + before = 0; + } + } + + if (minute == 25) + before = !before; + + reset(); + + if (minute != 0 && minute != 30) + set(before ? VOR : NACH); + + set(HOURS[hour]); + set(PARTS[minute/5]); + + if (minute/5 == 5) + set(HALB); // '5 before half' requires additional set + +} + +void setup() { + FastLED.addLeds(leds, ROWS*COLS); + FastLED.setBrightness(64); +} + +void loop() { + + // TODO: Get actual time from somewhere + time_t ts = 1616970481; // UTC + + while (1) { + settime(ts); + FastLED.show(); + delay(200); + ts += 5 * 60; + }; + +}