aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp235
1 files changed, 235 insertions, 0 deletions
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 <user_settings.h>
+#include <header.h>
+
+#include <FastLED.h>
+#include <ESP8266WiFi.h>
+#include <ezTime.h>
+
+// 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<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, LED_COUNT).setCorrection( TypicalLEDStrip );
+ FastLED.addLeds<NEOPIXEL, LED_PIN>(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);
+}
+