/* Example SPI transfert * * This sample code is in the public domain. */ #include "espressif/esp_common.h" #include "esp/uart.h" #include "FreeRTOS.h" #include "task.h" #include "esp8266.h" #include #include "esp/spi.h" #include "math.h" #include #include #include "ntp.h" #include "log.h" #define DAYTIME(h, m, s) (h*3600+m*60+s) struct { time_t sunrise_start = DAYTIME(8, 30, 0); time_t sunrise_end = DAYTIME(9, 0, 0); time_t sunrise_shutdown = DAYTIME(7, 0, 0); time_t sunset_time = DAYTIME(22, 0, 0); } settings; struct { uint8_t r = 255; uint8_t g = 160; uint8_t b = 80; } white; extern "C" time_t day_seconds() { time_t t1, t2; struct tm tms; time(&t1); localtime_r(&t1, &tms); tms.tm_hour = 0; tms.tm_min = 0; tms.tm_sec = 0; t2 = mktime(&tms); return t1 - t2; } struct led_t { struct { unsigned int mod: 5, marker: 3; } __attribute__((packed)) global = {0x1F, 0x7}; uint8_t b = 0; uint8_t g = 0; uint8_t r = 0; }; led_t leds[4][10]; float square(float x) { return x * x; } float lerp(float a, float b, float x) { return (1. - x) * a + x * b; } float clamp(float x, float a, float b) { if(x < a) return a; if(x > b) return b; return x; } float fade(float x, float offset, float factor) { float val = (x * factor - offset); return lerp(square(clamp(val, 0, 1)), square(1 - clamp(1 - val, 0, 1)), val); } void write_leds() { spi_transfer_32(1, 0x00000000); for (int i = 0; i < 10; i++) spi_transfer_32(1, *(uint32_t *) &leds[0][i]); for (int i = 0; i < 10; i++) spi_transfer_32(1, *(uint32_t *) &leds[1][9 - i]); for (int i = 0; i < 10; i++) spi_transfer_32(1, *(uint32_t *) &leds[2][i]); for (int i = 0; i < 10; i++) spi_transfer_32(1, *(uint32_t *) &leds[3][9 - i]); spi_transfer_32(1, 0xFFFFFFFF); spi_transfer_32(1, 0xFFFFFFFF); } enum state_t { BOOT_S, SUNRISE_S, MORNING_S, DAY_S, NIGHT_S }; volatile state_t s = BOOT_S; volatile bool maual_mode = false; extern "C" void manual_switch() { maual_mode = !maual_mode; printf("int %d\n", (int) maual_mode); if(maual_mode) { if(s == NIGHT_S) { for (int j = 0; j < 4; j++) for (int i = 0; i < 8; i += 2) { leds[j][i].global.mod = 2; leds[j][i].r = 128; leds[j][i].g = 30; leds[j][i].b = 15; } } else { for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 31; leds[j][i].r = white.r; leds[j][i].g = white.g; leds[j][i].b = white.b; } } write_leds(); } else { for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 0; leds[j][i].r = 0; leds[j][i].g = 0; leds[j][i].b = 0; } write_leds(); } } [[noreturn]] void loop(void *pvParameters) { spi_init(1, SPI_MODE0, SPI_FREQ_DIV_1M, 1, SPI_LITTLE_ENDIAN, false); while (!uxSemaphoreGetCount(time_available_semaphore)) vTaskDelay(500 / portTICK_PERIOD_MS); maual_mode = false; for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 0; leds[j][i].r = 0; leds[j][i].g = 0; leds[j][i].b = 0; } write_leds(); vTaskDelay(1000 / portTICK_PERIOD_MS); syslog("START>\n"); while (true) { time_t rt = day_seconds(); if(maual_mode) { if(s == NIGHT_S) { for (int j = 0; j < 4; j++) for (int i = 0; i < 8; i += 2) { leds[j][i].global.mod = 2; leds[j][i].r = 128; leds[j][i].g = 30; leds[j][i].b = 15; } } else { for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 31; leds[j][i].r = white.r; leds[j][i].g = white.g; leds[j][i].b = white.b; } } write_leds(); } else { if(s == BOOT_S) { if(rt >= settings.sunrise_start) { s = SUNRISE_S; syslog("SUNRISE_S\n"); } if(rt >= settings.sunrise_end) { s = MORNING_S; syslog("MORNING_S\n"); } if(rt >= settings.sunset_time || rt < settings.sunrise_start) { s = NIGHT_S; syslog("NIGHT_S\n"); } printf("%ld | %ld %ld %ld %ld\n", rt, settings.sunrise_start, settings.sunrise_end, settings.sunset_time, settings.sunrise_shutdown); } else if(s == SUNRISE_S) { if(rt >= settings.sunrise_end) { s = MORNING_S; syslog("MORNING_S\n"); } else { int steps = (settings.sunrise_end - settings.sunrise_start) * (1000 / 50); int t = (rt - settings.sunrise_start) * (1000 / 50); for (; t < steps && !maual_mode; t++) { for (auto &led: leds) for (int i = 0; i < 10; i++) { float val = (-i * 30. + t * 3. * (4. / 5.)) / (float) steps; led[i].global.mod = 8 + fade(val, 0., 0.5) * 23; led[i].r = fade(val, 0.01, 1.) * white.r; led[i].g = fade(val, 0.1, 0.5) * white.g; led[i].b = fade(val, 0.6, 0.7) * white.b; } write_leds(); if((t % 25) == 0) { printf("Time: %d%% %d %d/%d\n", (t * 100) / steps, (int) day_seconds(), t, steps); printf("%d %d %d %d\n", leds[0][0].global.mod, leds[0][0].r, leds[0][0].g, leds[0][0].b); } vTaskDelay(50 / portTICK_PERIOD_MS); } } } else if(s == MORNING_S) { if(rt >= settings.sunrise_shutdown) { s = DAY_S; syslog("DAY_S\n"); } else { for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 31; leds[j][i].r = white.r; leds[j][i].g = white.g; leds[j][i].b = white.b; } write_leds(); } } else if(s == DAY_S) { if(rt >= settings.sunset_time) { s = NIGHT_S; syslog("NIGHT_S\n"); } else { for (int j = 0; j < 4; j++) for (int i = 0; i < 10; i++) { leds[j][i].global.mod = 0; leds[j][i].r = 0; leds[j][i].g = 0; leds[j][i].b = 0; } write_leds(); } } else if(s == NIGHT_S) { if(rt >= settings.sunrise_start && rt < settings.sunset_time) { s = SUNRISE_S; syslog("SUNRISE_S\n"); } } } vTaskDelay(1000 / portTICK_PERIOD_MS); /*time_t ts = time(nullptr); int t = ts; printf("TIME: %d %d %s", t, (int) day_seconds(), ctime(&ts));*/ } } extern "C" void register_app(void) { xTaskCreate(loop, "loop", 512, nullptr, 2, NULL); }