From 0543b9c0c7542bd79e57dfe1977a9b3f7f007c1f Mon Sep 17 00:00:00 2001 From: Markus Ransberger Date: Wed, 3 Apr 2024 01:10:15 +0200 Subject: [PATCH] Replace base64 files with library. Major refactoring. --- include/animation_functions.h | 2 + include/base64_wrapper.h | 26 --- include/led_matrix.h | 4 +- include/wordclock_constants.h | 8 + include/wordclock_esp8266.h | 19 +- platformio.ini | 9 +- src/matrix/animation_functions.cpp | 2 + src/wordclock_esp8266.cpp | 349 ++++++++++++++++------------- src/wrapper/base64_wrapper.cpp | 143 ------------ 9 files changed, 220 insertions(+), 342 deletions(-) delete mode 100644 include/base64_wrapper.h delete mode 100644 src/wrapper/base64_wrapper.cpp diff --git a/include/animation_functions.h b/include/animation_functions.h index 8f1a900..62f4d38 100644 --- a/include/animation_functions.h +++ b/include/animation_functions.h @@ -4,6 +4,8 @@ #include #include "wordclock_constants.h" +extern bool spiral_direction; // Direction of sprial animation + enum Direction { RIGHT, diff --git a/include/base64_wrapper.h b/include/base64_wrapper.h deleted file mode 100644 index 801f731..0000000 --- a/include/base64_wrapper.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright (C) 2016 Arturo Guadalupi. All right reserved. - -This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -*/ - -#ifndef BASE64_WRAPPER_H -#define BASE64_WRAPPER_H - -class Base64Class{ - public: - int encode(char *output, char *input, int inputLength); - int decode(char * output, char * input, int inputLength); - int encodedLength(int plainLength); - int decodedLength(char * input, int inputLength); - - private: - inline void fromA3ToA4(unsigned char * A4, unsigned char * A3); - inline void fromA4ToA3(unsigned char * A3, unsigned char * A4); - inline unsigned char lookupTable(char c); -}; -extern Base64Class Base64; - -#endif /* BASE64_WRAPPER_H */ diff --git a/include/led_matrix.h b/include/led_matrix.h index 7084e8c..5b57598 100644 --- a/include/led_matrix.h +++ b/include/led_matrix.h @@ -43,10 +43,10 @@ private: // current representation of matrix as 2D array uint32_t _current_grid[MATRIX_HEIGHT][MATRIX_WIDTH] = {0}; - // target representation of minutes indicator leds + // target representation of minutes indicator LEDs uint32_t _target_minute_indicators[4] = {0, 0, 0, 0}; - // current representation of minutes indicator leds + // current representation of minutes indicator LEDs uint32_t _current_minute_indicators[4] = {0, 0, 0, 0}; void _draw_on_matrix(float factor); diff --git a/include/wordclock_constants.h b/include/wordclock_constants.h index 8ba4745..202b652 100644 --- a/include/wordclock_constants.h +++ b/include/wordclock_constants.h @@ -67,4 +67,12 @@ #define MATRIX_WIDTH (11) #define MATRIX_HEIGHT (11) +// NTP macros +#define BUILD_YEAR (__DATE__ + 7) /* Will expand to current year at compile time as string. */ +#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) /* Will expand to current year at compile time minus one. */ +#define NTP_MININUM_YEAR (1900) // NTP minimum year is 1900 +#define NTP_MAX_UPDATE_TIME_US (500000) // 500ms max update time +#define NTP_NEXT_UPDATE_DELAY_US (10000000) // 10s delay time between updates +#define NTP_WATCHDOG_COUNTER_INIT (30) // Watchdog value, count of retries before restart + #endif /* WORDCLOCK_CONSTANTS_H */ diff --git a/include/wordclock_esp8266.h b/include/wordclock_esp8266.h index fec7519..7bcc84b 100644 --- a/include/wordclock_esp8266.h +++ b/include/wordclock_esp8266.h @@ -12,13 +12,9 @@ #define EEPROM_SIZE (sizeof(EepromLayout_st) / sizeof(uint8_t)) -#define BUILD_YEAR (__DATE__ + 7) /* Will expand to current year at compile time as string. */ -#define NTP_MININUM_RX_YEAR (atoi(BUILD_YEAR) - 1) /* Will expand to current year at compile time minus one. */ -#define NTP_MININUM_YEAR (1900) // NTP minimum year is 1900 -#define NTP_MAX_UPDATE_TIME_US (500000) // 500ms max update time -#define NTP_NEXT_UPDATE_DELAY_US (10000000) // 10s delay time between updates -#define NTP_WATCHDOG_COUNTER_INIT (30) // Watchdog value, count of retries before restart - +// ---------------------------------------------------------------------------------- +// TYPEDEFS +// ---------------------------------------------------------------------------------- typedef struct { int start_hour; @@ -32,7 +28,7 @@ typedef struct uint8_t red; uint8_t green; uint8_t blue; - uint8_t alpha; + uint8_t alpha; // note: unused } Color_st; typedef struct @@ -62,12 +58,16 @@ typedef enum NUM_STATES } ClockState_en; -bool get_ntp_time(uint32 usec); +// ---------------------------------------------------------------------------------- +// FUNCTIONS DECLARATIONS +// ---------------------------------------------------------------------------------- +bool get_ntp_time(uint32 timeout); String leading_zero2digit(int value); uint8_t calculate_dynamic_brightness(uint8_t min_brightness, uint8_t max_brightness, int hours, int minutes, bool summertime); uint8_t update_brightness(void); void check_night_mode(void); void check_wifi_status(void); +void cold_start_setup(void); void draw_main_color(void); void handle_button(void); void handle_command(void); @@ -75,6 +75,7 @@ void handle_current_state(void); void handle_data_request(void); void handle_led_direct(void); void limit_value_ranges(void); +void log_data(void); void log_time(tm local_time); void ntp_time_update(uint32 max_update_time); void on_state_entry(uint8_t state); diff --git a/platformio.ini b/platformio.ini index b37a518..5c21c7d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,10 +16,11 @@ platform = espressif8266 board = nodemcuv2 framework = arduino lib_deps = - adafruit/Adafruit BusIO@^1.15.0 - adafruit/Adafruit NeoMatrix@^1.3.0 - adafruit/Adafruit NeoPixel@^1.11.0 - tzapu/WiFiManager@^0.16.0 + adafruit/Adafruit BusIO@^1.15.0 + adafruit/Adafruit NeoMatrix@^1.3.0 + adafruit/Adafruit NeoPixel@^1.11.0 + densaugeo/base64@^1.4.0 + tzapu/WiFiManager@^0.16.0 [env:nodemcuv2] monitor_speed = 115200 diff --git a/src/matrix/animation_functions.cpp b/src/matrix/animation_functions.cpp index 5dfb59f..d6d0984 100644 --- a/src/matrix/animation_functions.cpp +++ b/src/matrix/animation_functions.cpp @@ -10,6 +10,8 @@ extern LEDMatrix led_matrix; const int8_t dx[] = {1, -1, 0, 0}; const int8_t dy[] = {0, 0, -1, 1}; +bool spiral_direction = false; // Direction of sprial animation + /** * @brief Function to draw a spiral step (from center) * diff --git a/src/wordclock_esp8266.cpp b/src/wordclock_esp8266.cpp index 67e2291..900e5e6 100644 --- a/src/wordclock_esp8266.cpp +++ b/src/wordclock_esp8266.cpp @@ -26,7 +26,8 @@ #include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit_NeoMatrix #include // NeoPixel library used to run the NeoPixel LEDs: https://github.com/adafruit/Adafruit_NeoPixel -#include //from ESP8266 Arduino Core (automatically installed when ESP8266 was installed via Boardmanager) +#include +#include //from ESP8266 Arduino Core (automatically installed when ESP8266 was installed via Boardmanager) #include #include #include @@ -34,7 +35,6 @@ // own libraries #include "animation_functions.h" -#include "base64_wrapper.h" // copied from https://github.com/Xander-Electronics/Base64 #include "led_matrix.h" #include "littlefs_wrapper.h" #include "ota_functions.h" @@ -54,43 +54,43 @@ Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT + 1, NEO_GRB + NEO_KHZ800); // NeoMatrix ESP8266WebServer webserver(HTTP_PORT); // Webserver LEDMatrix led_matrix = LEDMatrix(&matrix, DEFAULT_BRIGHTNESS, &logger); // NeoMatrix wrapper -struct tm time_info; // Structure tm holds time information -time_t time_now; // Seconds since Epoch (1970) - UTC // ---------------------------------------------------------------------------------- // STATIC VARIABLES // ---------------------------------------------------------------------------------- +// EEPROM values static EepromLayout_st eeprom_buffer = {{0, 0, 0, 0}, {0U, 0U, 0U, false}, {0U, 0U, 0U, 0U}}; -static Brightness_st *brightness_ps = &eeprom_buffer.brightness_values; -static Color_st *colors_ps = &eeprom_buffer.color_values; -static NightModeTimes_st *night_mode_times_ps = &eeprom_buffer.night_mode_times; +static Brightness_st *const brightness_ps = &eeprom_buffer.brightness_values; +static Color_st *const colors_ps = &eeprom_buffer.color_values; +static NightModeTimes_st *const night_mode_times_ps = &eeprom_buffer.night_mode_times; +// Games static Pong pong = Pong(&led_matrix, &logger); static Snake snake = Snake(&led_matrix, &logger); static Tetris tetris = Tetris(&led_matrix, &logger); -static uint32 last_ntp_update_us = 0; // Time of last NTP update -static char strftime_buf[64]; // Time string buffer +// Time +static struct tm time_info; // Structure tm holds time information +static time_t time_now; // Seconds since Epoch (1970) - UTC -static bool flg_night_mode = false; // State of nightmode -static bool flg_reset_wifi_creds = false; // Used to reset stored wifi credentials -static bool spiral_direction = false; +// NTP +static uint32 last_ntp_update_us = 0; // Time of last NTP update + +// State variables +static bool flg_night_mode = false; // State of nightmode +static bool flg_reset_wifi_creds = false; // Used to reset stored wifi credentials static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // Stores smoothing factor for led transition, value of 1 represents no smoothing. -static int watchdog_counter = 30; // Watchdog counter to trigger restart if NTP update was not possible 30 times in a row (5min) -static uint32 last_led_direct_us = 0; // Time of last direct LED command (=> fall back to normal mode after timeout) -static uint32_t heartbeat_counter = 0; // Heartbeat on-time in seconds static uint32_t main_color_clock = colors_24bit[2]; // Color of the clock and digital clock -static uint32_t main_color_snake = colors_24bit[1]; // Color of the random snake animation static uint8_t current_brightness = DEFAULT_BRIGHTNESS; // Current brightness of LEDs static uint8_t current_state = (uint8_t)ST_CLOCK; // Stores current state -static const String state_names[NUM_STATES] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong", "Hearts"}; -static const uint32_t period_timings[NUM_STATES] = {PERIOD_CLOCK_UPDATE_US, PERIOD_CLOCK_UPDATE_US, - PERIOD_ANIMATION_US, PERIOD_TETRIS_US, PERIOD_SNAKE_US, - PERIOD_PONG_US, PERIOD_ANIMATION_US}; +// Other variables +static uint32 last_led_direct_us = 0; // Time of last direct LED command (=> fall back to normal mode after timeout) +static uint32_t heartbeat_counter = 0; // Heartbeat on-time in seconds -// Quarterly brightness factor for dynamic brightness (4 quarters a 24 hours) -static const float qtly_brightness_factor[96] = { +// Const definitions +static const String state_names[NUM_STATES] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong", "Hearts"}; // all clock states +static const float qtly_brightness_factor[96] = { // Quarterly brightness factor for dynamic brightness (4 quarters a 24 hours) 0.0f, 0.0f, 0.0f, 0.001f, 0.003f, 0.007f, 0.014f, 0.026f, 0.044f, 0.069f, 0.101f, 0.143f, 0.194f, 0.253f, 0.32f, 0.392f, 0.468f, 0.545f, 0.62f, 0.691f, 0.755f, 0.811f, 0.858f, 0.896f, 0.927f, 0.949f, 0.966f, 0.978f, 0.986f, 0.991f, 0.995f, 0.997f, 0.998f, 0.999f, 0.999f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, @@ -98,7 +98,9 @@ static const float qtly_brightness_factor[96] = { 0.998f, 0.997f, 0.995f, 0.991f, 0.986f, 0.978f, 0.966f, 0.949f, 0.927f, 0.896f, 0.858f, 0.811f, 0.755f, 0.691f, 0.62f, 0.545f, 0.468f, 0.392f, 0.32f, 0.253f, 0.194f, 0.143f, 0.101f, 0.069f, 0.044f, 0.026f, 0.014f, 0.007f, 0.003f, 0.001f, 0.0f, 0.0f}; - +static const uint32_t period_timings[NUM_STATES] = {PERIOD_CLOCK_UPDATE_US, PERIOD_CLOCK_UPDATE_US, + PERIOD_ANIMATION_US, PERIOD_TETRIS_US, PERIOD_SNAKE_US, + PERIOD_PONG_US, PERIOD_ANIMATION_US}; // ---------------------------------------------------------------------------------- // SETUP // ---------------------------------------------------------------------------------- @@ -112,10 +114,10 @@ void setup() Serial.println(); // Reset info - rst_info *resetInfo = ESP.getResetInfoPtr(); - Serial.printf("Reset reason: %u\n", resetInfo->reason); - Serial.printf("Reset cause: %u\n", resetInfo->exccause); - Serial.printf("Reset address: %u\n", resetInfo->excvaddr); + rst_info *reset_info = ESP.getResetInfoPtr(); + Serial.printf("Reset reason: %u\n", reset_info->reason); + Serial.printf("Reset cause: %u\n", reset_info->exccause); + Serial.printf("Reset address: %u\n", reset_info->excvaddr); Serial.println(); // Init EEPROM @@ -134,7 +136,7 @@ void setup() led_matrix.setup_matrix(); led_matrix.set_current_limit(CURRENT_LIMIT_LED); - // Turn on minutes leds (blue) + // Turn on minutes LEDs (blue) led_matrix.set_min_indicator(15, colors_24bit[6]); led_matrix.draw_on_matrix_instant(); @@ -148,11 +150,12 @@ void setup() // If you get here you have connected to the WiFi Serial.printf("Connected, IP address: "); Serial.println(WiFi.localIP()); + // ESP8266 tries to reconnect automatically when the connection is lost WiFi.setAutoReconnect(true); WiFi.persistent(true); - // Turn off minutes leds + // Turn off minutes LEDs led_matrix.set_min_indicator(15, 0); led_matrix.draw_on_matrix_instant(); @@ -169,44 +172,10 @@ void setup() // create UDP Logger to send logging messages via UDP multicast logger = UDPLogger(WiFi.localIP(), LOGGER_MULTICAST_IP, LOGGER_MULTICAST_PORT, "Wordclock 2.0"); - logger.log_string("Start program\n"); - logger.log_string("Sketchname: " + String(__FILE__)); - logger.log_string("Build: " + String(__TIMESTAMP__)); - logger.log_string("IP: " + WiFi.localIP().toString()); - logger.log_string("Reset Reason: " + ESP.getResetReason()); - if (resetInfo->reason != REASON_SOFT_RESTART) // only if there was a cold start/hard reset + if (reset_info->reason != REASON_SOFT_RESTART) // only if there was a cold start/hard reset { - // quickly test each LED - for (int16_t row = 0; row < MATRIX_HEIGHT; row++) - { - for (int16_t col = 0; col < MATRIX_WIDTH; col++) - { - matrix.fillScreen(0); - matrix.drawPixel(col, row, LEDMatrix::color_24_to_16bit(colors_24bit[2])); - matrix.show(); - delay(10); - } - } - - // clear Matrix - matrix.fillScreen(0); - matrix.show(); - delay(200); - - // display IP - uint8_t address = WiFi.localIP()[3]; - led_matrix.print_char(1, 0, 'I', main_color_clock); - led_matrix.print_char(5, 0, 'P', main_color_clock); - led_matrix.print_number(0, 6, (address / 100), main_color_clock); - led_matrix.print_number(4, 6, (address / 10) % 10, main_color_clock); - led_matrix.print_number(8, 6, address % 10, main_color_clock); - led_matrix.draw_on_matrix_instant(); - delay(2000); - - // clear matrix - led_matrix.flush(); - led_matrix.draw_on_matrix_instant(); + cold_start_setup(); } // setup NTP @@ -230,12 +199,11 @@ void setup() // Set range limits limit_value_ranges(); - logger.log_string("Nightmode starts at: " + String(night_mode_times_ps->start_hour) + ":" + String(night_mode_times_ps->start_min)); - logger.log_string("Nightmode ends at: " + String(night_mode_times_ps->end_hour) + ":" + String(night_mode_times_ps->end_min)); - // Update brightness current_brightness = update_brightness(); - logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%"); + + // Send logging data + log_data(); } // ---------------------------------------------------------------------------------- @@ -305,89 +273,155 @@ void loop() // ---------------------------------------------------------------------------------- // OTHER FUNCTIONS // ---------------------------------------------------------------------------------- +/** + * @brief Log information + * + */ +void log_data() +{ + logger.log_string("Start program\n"); + logger.log_string("Sketchname: " + String(__FILE__)); + logger.log_string("Build: " + String(__TIMESTAMP__)); + logger.log_string("IP: " + WiFi.localIP().toString()); + logger.log_string("Reset Reason: " + ESP.getResetReason()); + + logger.log_string("Nightmode starts at: " + String(night_mode_times_ps->start_hour) + ":" + String(night_mode_times_ps->start_min)); + logger.log_string("Nightmode ends at: " + String(night_mode_times_ps->end_hour) + ":" + String(night_mode_times_ps->end_min)); + + logger.log_string("Brightness: " + String(((uint16_t)current_brightness * 100) / UINT8_MAX) + "%"); +} + +/** + * @brief Test all LEDs and display IP address + * + */ +void cold_start_setup() +{ + // quickly test each LED + for (int16_t row = 0; row < MATRIX_HEIGHT; row++) + { + for (int16_t col = 0; col < MATRIX_WIDTH; col++) + { + matrix.fillScreen(0); + matrix.drawPixel(col, row, LEDMatrix::color_24_to_16bit(colors_24bit[2])); + matrix.show(); + delay(10); + } + } + + // clear Matrix + matrix.fillScreen(0); + matrix.show(); + delay(200); + + // display IP + uint8_t address = WiFi.localIP()[3]; + led_matrix.print_char(1, 0, 'I', main_color_clock); + led_matrix.print_char(5, 0, 'P', main_color_clock); + led_matrix.print_number(0, 6, (address / 100), main_color_clock); + led_matrix.print_number(4, 6, (address / 10) % 10, main_color_clock); + led_matrix.print_number(8, 6, address % 10, main_color_clock); + led_matrix.draw_on_matrix_instant(); + delay(2000); + + // clear matrix + led_matrix.flush(); + led_matrix.draw_on_matrix_instant(); +} /** * @brief Updates the NTP time * * @return boolean - true if NTP update was successful, false otherwise */ -bool get_ntp_time(uint32 usec) +bool get_ntp_time(uint32 timeout) { uint32 start_time_us = system_get_time(); do { time(&time_now); localtime_r(&time_now, &time_info); - delay(10); - } while (((system_get_time() - start_time_us) <= usec) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR))); + yield(); + } while (((system_get_time() - start_time_us) <= timeout) && (time_info.tm_year < (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR))); + + logger.log_string(String("NTP-Update duration: " + String(system_get_time() - start_time_us) + String("us"))); return ((time_info.tm_year <= (NTP_MININUM_RX_YEAR - NTP_MININUM_YEAR)) ? false : true); } +/** + * @brief Log local_time. + * + * @param local_time + */ void log_time(tm local_time) { + char strftime_buf[64]; // Time string buffer strftime(strftime_buf, sizeof(strftime_buf), "%c", &time_info); logger.log_string(String(strftime_buf)); } +/** + * @brief Update and control word clock states. + */ void handle_current_state() { switch (current_state) { - case ST_CLOCK: // state clock + case ST_CLOCK: // state clock + { + (void)show_string_on_clock(time_to_string((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min), main_color_clock); + draw_minute_indicator((uint8_t)time_info.tm_min, main_color_clock); + break; + } + case ST_DICLOCK: // state diclock + { + show_digital_clock((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min, main_color_clock); + break; + } + case ST_SPIRAL: // state spiral + { + int res = draw_spiral(false, spiral_direction, MATRIX_WIDTH - 2); + if ((bool)res && spiral_direction == 0) { - (void)show_string_on_clock(time_to_string((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min), main_color_clock); - draw_minute_indicator((uint8_t)time_info.tm_min, main_color_clock); - break; + // change spiral direction to closing (draw empty LEDs) + spiral_direction = true; + // init spiral with new spiral direction + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); } - case ST_DICLOCK: // state diclock + else if (res && spiral_direction == 1) { - show_digital_clock((uint8_t)time_info.tm_hour, (uint8_t)time_info.tm_min, main_color_clock); - break; - } - case ST_SPIRAL: // state spiral - { - int res = draw_spiral(false, spiral_direction, MATRIX_WIDTH - 2); - if ((bool)res && spiral_direction == 0) - { - // change spiral direction to closing (draw empty leds) - spiral_direction = true; - // init spiral with new spiral direction - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); - } - else if (res && spiral_direction == 1) - { - // reset spiral direction to normal drawing leds - spiral_direction = false; - // init spiral with new spiral direction - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); - } - break; - } - case ST_TETRIS: // state tetris - { - tetris.loopCycle(); - break; - } - case ST_SNAKE: // state snake - { - snake.loopCycle(); - break; - } - case ST_PINGPONG: // state ping pong - { - pong.loopCycle(); - break; - } - case ST_HEARTS: - { - draw_heart_animation(); - break; - } - default: - { - break; + // reset spiral direction to normal drawing LEDs + spiral_direction = false; + // init spiral with new spiral direction + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); } + break; + } + case ST_TETRIS: // state tetris + { + tetris.loopCycle(); + break; + } + case ST_SNAKE: // state snake + { + snake.loopCycle(); + break; + } + case ST_PINGPONG: // state ping pong + { + pong.loopCycle(); + break; + } + case ST_HEARTS: + { + draw_heart_animation(); + break; + } + default: + { + break; + } } } @@ -456,8 +490,8 @@ void check_night_mode() */ void ntp_time_update(uint32 max_update_time) { - // NTP time update - bool ntp_retval = get_ntp_time(max_update_time); + static int watchdog_counter = NTP_WATCHDOG_COUNTER_INIT; // Watchdog counter to trigger restart if NTP update was not possible 30 times in a row (5min) + bool ntp_retval = get_ntp_time(max_update_time); // NTP time update if (ntp_retval == true) { @@ -491,34 +525,34 @@ void on_state_entry(uint8_t state) filter_factor = DEFAULT_SMOOTHING_FACTOR; switch (state) { - case ST_SPIRAL: - { - spiral_direction = 0; // Init spiral with normal drawing mode - draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); - break; - } - case ST_TETRIS: - { - filter_factor = 1.0f; // no smoothing - tetris.ctrlStart(); - break; - } - case ST_SNAKE: - { - filter_factor = 1.0f; // no smoothing - snake.initGame(); - break; - } - case ST_PINGPONG: - { - filter_factor = 1.0f; // no smoothing - pong.initGame(1); - break; - } - default: - { - break; - } + case ST_SPIRAL: + { + spiral_direction = 0; // Init spiral with normal drawing mode + draw_spiral(true, spiral_direction, MATRIX_WIDTH - 1); + break; + } + case ST_TETRIS: + { + filter_factor = 1.0f; // no smoothing + tetris.ctrlStart(); + break; + } + case ST_SNAKE: + { + filter_factor = 1.0f; // no smoothing + snake.initGame(); + break; + } + case ST_PINGPONG: + { + filter_factor = 1.0f; // no smoothing + pong.initGame(1); + break; + } + default: + { + break; + } } } @@ -566,10 +600,9 @@ void handle_led_direct() // base64 decoding char base64data[dataLength]; data.toCharArray(base64data, dataLength); - int base64dataLen = (int)dataLength; - int decodedLength = Base64.decodedLength(base64data, base64dataLen); - char byteArray[decodedLength]; - Base64.decode(byteArray, base64data, base64dataLen); + unsigned int decodedLength = decode_base64_length((unsigned char *)base64data, dataLength); + unsigned char byteArray[decodedLength]; + decode_base64((unsigned char *)base64data, dataLength, byteArray); for (unsigned int i = 0; i < dataLength; i += 4) { @@ -645,11 +678,11 @@ void handle_button() void set_main_color(uint8_t red, uint8_t green, uint8_t blue) { main_color_clock = LEDMatrix::color_24bit(red, green, blue); + + // Update colors and save color settings to EEPROM colors_ps->blue = blue; colors_ps->red = red; colors_ps->green = green; - - // save color settings to EEPROM write_settings_to_EEPROM(); } diff --git a/src/wrapper/base64_wrapper.cpp b/src/wrapper/base64_wrapper.cpp deleted file mode 100644 index 75a4be4..0000000 --- a/src/wrapper/base64_wrapper.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (C) 2016 Arturo Guadalupi. All right reserved. - -This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -*/ - -#include -#include "base64_wrapper.h" -#if (defined(__AVR__)) -#include -#else -#include -#endif - -const char PROGMEM _Base64AlphabetTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -int Base64Class::encode(char *output, char *input, int inputLength) { - int i = 0, j = 0; - int encodedLength = 0; - unsigned char A3[3]; - unsigned char A4[4]; - - while(inputLength--) { - A3[i++] = *(input++); - if(i == 3) { - fromA3ToA4(A4, A3); - - for(i = 0; i < 4; i++) { - output[encodedLength++] = pgm_read_byte(&_Base64AlphabetTable[A4[i]]); - } - - i = 0; - } - } - - if(i) { - for(j = i; j < 3; j++) { - A3[j] = '\0'; - } - - fromA3ToA4(A4, A3); - - for(j = 0; j < i + 1; j++) { - output[encodedLength++] = pgm_read_byte(&_Base64AlphabetTable[A4[j]]); - } - - while((i++ < 3)) { - output[encodedLength++] = '='; - } - } - output[encodedLength] = '\0'; - return encodedLength; -} - -int Base64Class::decode(char * output, char * input, int inputLength) { - int i = 0, j = 0; - int decodedLength = 0; - unsigned char A3[3]; - unsigned char A4[4]; - - - while (inputLength--) { - if(*input == '=') { - break; - } - - A4[i++] = *(input++); - if (i == 4) { - for (i = 0; i <4; i++) { - A4[i] = lookupTable(A4[i]); - } - - fromA4ToA3(A3,A4); - - for (i = 0; i < 3; i++) { - output[decodedLength++] = A3[i]; - } - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) { - A4[j] = '\0'; - } - - for (j = 0; j <4; j++) { - A4[j] = lookupTable(A4[j]); - } - - fromA4ToA3(A3,A4); - - for (j = 0; j < i - 1; j++) { - output[decodedLength++] = A3[j]; - } - } - output[decodedLength] = '\0'; - return decodedLength; -} - -int Base64Class::encodedLength(int plainLength) { - int n = plainLength; - return (n + 2 - ((n + 2) % 3)) / 3 * 4; -} - -int Base64Class::decodedLength(char * input, int inputLength) { - int i = 0; - int numEq = 0; - for(i = inputLength - 1; input[i] == '='; i--) { - numEq++; - } - - return ((6 * inputLength) / 8) - numEq; -} - -//Private utility functions -inline void Base64Class::fromA3ToA4(unsigned char * A4, unsigned char * A3) { - A4[0] = (A3[0] & 0xfc) >> 2; - A4[1] = ((A3[0] & 0x03) << 4) + ((A3[1] & 0xf0) >> 4); - A4[2] = ((A3[1] & 0x0f) << 2) + ((A3[2] & 0xc0) >> 6); - A4[3] = (A3[2] & 0x3f); -} - -inline void Base64Class::fromA4ToA3(unsigned char * A3, unsigned char * A4) { - A3[0] = (A4[0] << 2) + ((A4[1] & 0x30) >> 4); - A3[1] = ((A4[1] & 0xf) << 4) + ((A4[2] & 0x3c) >> 2); - A3[2] = ((A4[2] & 0x3) << 6) + A4[3]; -} - -inline unsigned char Base64Class::lookupTable(char c) { - if(c >='A' && c <='Z') return c - 'A'; - if(c >='a' && c <='z') return c - 71; - if(c >='0' && c <='9') return c + 4; - if(c == '+') return 62; - if(c == '/') return 63; - return -1; -} - -Base64Class Base64;