From bba3635912b334e17b270907b5b4a1d6dfd4be1f Mon Sep 17 00:00:00 2001 From: user Date: Fri, 15 Dec 2023 14:59:50 +0100 Subject: initial commit. clock works + ntp, animations and fade --- src/main.cpp | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 src/main.cpp (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..a0bbc6f --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,235 @@ +// #define DEBUG 1 + +#include +#include + +#include +#include +#include + +// Define the array of leds +CRGB leds[LED_COUNT]; + +Timezone CopenhagenTime; + +int hue = 0; +int max_brightness = 255; +bool on_state[SEGMENT_COUNT * DIGIT_COUNT] = {false}; + +typedef enum : uint8_t { + seg_a = 1<<0, // 00000001 + seg_b = 1<<1, // 00000010 + seg_c = 1<<2, // 00000100 + seg_d = 1<<3, // ... + seg_e = 1<<4, + seg_f = 1<<5, + seg_g = 1<<6 +} segments; + +uint8_t symbols[] = { + /* 0 */ seg_a | seg_b | seg_c | seg_d | seg_e | seg_f, + /* 1 */ seg_b | seg_c, + /* 2 */ seg_a | seg_b | seg_g | seg_e | seg_d, + /* 3 */ seg_a | seg_b | seg_g | seg_c | seg_d, + /* 4 */ seg_f | seg_g | seg_c | seg_b, + /* 5 */ seg_a | seg_f | seg_g | seg_c | seg_d, + /* 6 */ seg_a | seg_f | seg_g | seg_c | seg_d | seg_e, + /* 7 */ seg_a | seg_b | seg_c, + /* 8 */ seg_a | seg_b | seg_c | seg_d | seg_e | seg_f | seg_g, + /* 9 */ seg_g | seg_f | seg_a | seg_b | seg_c | seg_d, + /* ° */ seg_a | seg_b | seg_g | seg_f, + /* C */ seg_a | seg_f | seg_e | seg_d +}; + +uint8_t spin_animation[] = { + seg_a, + seg_b, + seg_c, + seg_d, + seg_e, + seg_f, +}; + + +uint8_t dual_spin_animation[] = { + seg_a | seg_d, + seg_b | seg_e, + seg_c | seg_f, + seg_d | seg_a, + seg_e | seg_b, + seg_f | seg_c, +}; + +void display_symbols(uint8_t *symbols_mask) { + // Fades all at once + for (int brightness = 0; brightness <= max_brightness; brightness ++) { + for (uint8_t digit_index = 0; digit_index < DIGIT_COUNT; digit_index++) { + // Counts up by bitshifting + uint8_t seg_counter = 1; + + for (int segment_index = 0; segment_index < SEGMENT_COUNT; segment_index++) { + int digit_offset = digit_index * SEGMENT_COUNT; + int led_raw_index = digit_offset + segment_index; + int led_index = START_OFFSET + led_raw_index; + bool previously_on = on_state[led_raw_index]; + + // Compare the current segment bit with the mask for the symbol + bool turn_on = symbols_mask[digit_index] & seg_counter; + + if (turn_on) { + // Turn on LED + if(previously_on){ + // Previously on, allow hue change + leds[led_index] = CHSV(hue, SATURATION, max_brightness); + } else { + leds[led_index] = CHSV(hue, SATURATION, brightness); + } + } else { + // Turn off LED + if(previously_on) { + leds[led_index] = CHSV(hue, SATURATION, max_brightness - brightness); + } + } + + if (brightness == max_brightness) { + on_state[led_raw_index] = turn_on; + } + + seg_counter = seg_counter<<1; + } + } + FastLED.show(); + delay(2); + } +} + +void display_number(int number) { + uint8_t symbols_mask[DIGIT_COUNT]; + // Start from the last digit + for (int digit_index = DIGIT_COUNT - 1; digit_index >= 0; digit_index--) { + symbols_mask[digit_index] = symbols[number % 10]; + number /= 10; + } + display_symbols(symbols_mask); +} + +void display_symbol(int digit_index, uint8_t symbol) { + // Counts up by bitshifting + uint8_t seg_counter = 1; + for (int segment_index = 0; segment_index < SEGMENT_COUNT; segment_index++) { + int offset = digit_index * SEGMENT_COUNT; + int led_index = START_OFFSET + offset + segment_index; + + // Compare the current segment bit with the mask for the symbol + if (symbol & seg_counter) { + // Turn on LED + leds[led_index] = CHSV(hue, SATURATION, max_brightness); + FastLED.show(); + } + + seg_counter = seg_counter<<1; + } +} + +void play_animation(uint8_t *animation, int animation_size, int segment_delay) { + for (int i = 0; i < animation_size; i++){ + for (int digit_index = 0; digit_index < 4; digit_index++) { + display_symbol(digit_index, animation[i]); + } + + hue += 16; + FastLED.show(); + delay(segment_delay); + } +} + +void update_clock() { + // Format the time as a 4-digit integer + int timeInt = CopenhagenTime.dateTime("Hi").toInt(); // Sadly string format + display_number(timeInt); + hue++; +} + +void setup() { + FastLED.addLeds(leds, LED_COUNT).setCorrection( TypicalLEDStrip ); + FastLED.addLeds(leds, LED_COUNT); // GRB ordering is assumed + + // Turn off all LEDs + FastLED.clear(); + + #ifdef DEBUG + Serial.begin(9600); + #endif + + setServer(NTP_SERVER); + + WiFi.setHostname("7-segment-esp-ws2811"); //define hostname + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + Serial.print("Connecting"); + while (WiFi.status() != WL_CONNECTED) + { + if (millis() < WIFI_CONN_ANI_TIMEOUT) { + play_animation(spin_animation, sizeof(spin_animation), 100); + } else { + // Turn off all LEDs + FastLED.clear(); + } + } + + delay(100); + + hue = 0; + // Turn off all LEDs + FastLED.clear(); + + Serial.println(); + Serial.print("Connected, IP address: "); + Serial.println(WiFi.localIP()); + + waitForSync(); + Serial.println("UTC: " + UTC.dateTime()); + CopenhagenTime.setLocation("Europe/Copenhagen"); + Serial.println("Copenhagen time: " + CopenhagenTime.dateTime()); + + update_clock(); +} + +/* +// Test each segment +int i = 0; + +void loop() { + leds[i] = CRGB::Red; + FastLED.show(); + delay(500); + + leds[i] = CRGB::Black; + FastLED.show(); + delay(500); + i++; + if (i > LED_COUNT - 1) { + i = 0; + } +} +*/ + +void loop() { + // Only update on each hole minute to avoid flickering + int seconds = CopenhagenTime.dateTime("s").toInt(); + int minutes = CopenhagenTime.dateTime("i").toInt(); + + if(minutes == 59 && seconds >= 55) { //if(minutes == 59 && seconds >= 55) { + play_animation(dual_spin_animation, sizeof(spin_animation), 50); + FastLED.clear(); + } + + if(seconds != 0) { + delay(10); + return; + } + + update_clock(); + + delay(1000); +} + -- cgit v1.2.3