diff --git a/code/.cproject b/code/.cproject index a566ec8..67ae2ab 100644 --- a/code/.cproject +++ b/code/.cproject @@ -14,4 +14,6 @@ + + \ No newline at end of file diff --git a/code/main/CMakeLists.txt b/code/main/CMakeLists.txt index d9827e0..ac40a77 100644 --- a/code/main/CMakeLists.txt +++ b/code/main/CMakeLists.txt @@ -10,7 +10,7 @@ idf_component_register( "src/led_strip_encoder.c" "src/ledmatrix.cpp" "src/clock.cpp" - "src/wordclock.cpp" + "src/wordmap.cpp" INCLUDE_DIRS # optional, add here public include directories "inc" PRIV_INCLUDE_DIRS # optional, add here private include directories diff --git a/code/main/inc/ledmatrix.h b/code/main/inc/ledmatrix.h index a1c5880..a953e80 100644 --- a/code/main/inc/ledmatrix.h +++ b/code/main/inc/ledmatrix.h @@ -117,18 +117,33 @@ class LEDMatrix void clear(void); + BaseType_t tick(void); + private: + LEDMatrix_Parameters_t parameters; LEDMatrix_Pixel_t* matrix; uint8_t* tx_matrix; unsigned int numberOfPixels; + static bool initialized; static TaskHandle_t matrixTaskHandle; static SemaphoreHandle_t taskSemaphore; static void matrixTask(void* parameters); }; +inline BaseType_t LEDMatrix::tick(void) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (LEDMatrix::initialized) + { + xSemaphoreGiveFromISR(LEDMatrix::taskSemaphore, &xHigherPriorityTaskWoken); + } + + return xHigherPriorityTaskWoken; +} + /** @} */ diff --git a/code/main/inc/wordclock.h b/code/main/inc/wordclock.h deleted file mode 100644 index 6b70984..0000000 --- a/code/main/inc/wordclock.h +++ /dev/null @@ -1,130 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -/// \file wordclock.h -/// \brief File description -// -------------------------------------------------------------------------------------------------------------------- -// -// vbchaos software design -// -// -------------------------------------------------------------------------------------------------------------------- -/// $Revision: $ -/// $Author: $ -/// $Date: $ -// (c) 2023 vbchaos -// -------------------------------------------------------------------------------------------------------------------- - - -#ifndef MAIN_INC_WORDCLOCK_H_ -#define MAIN_INC_WORDCLOCK_H_ - -/** - * wordclock implementation - * \defgroup wordclock - * \brief {group_description} - * \addtogroup {Layer} - * - * Detailed description - * @{ - */ - - - -// -------------------------------------------------------------------------------------------------------------------- -// Include files -// -------------------------------------------------------------------------------------------------------------------- - -// CompilerIncludes -// All include files that are provided by the compiler directly - - - -// ProjectIncludes -// All include files that are provided by the project -#include "ledmatrix.h" -#include "clock.h" - -// -------------------------------------------------------------------------------------------------------------------- -// Constant and macro definitions -// -------------------------------------------------------------------------------------------------------------------- - - - -// -------------------------------------------------------------------------------------------------------------------- -// Type definitions. -// -------------------------------------------------------------------------------------------------------------------- - - - -// -------------------------------------------------------------------------------------------------------------------- -// Function declarations -// -------------------------------------------------------------------------------------------------------------------- - -class Wordclock -{ - public: - enum language - { - NL = 0, - EN, - NumberOfLanguages - }; - - Wordclock(LEDMatrix* matrix); - - void update(Clock::TimeStructure* timestructure); - - private: - - LEDMatrix* matrix; - language language; - - struct word - { - LEDMatrix::coordinate position; - int length; - }; - - struct wordmap - { - struct word prefix; - struct word prefix_additional; - struct word almost; - struct word five; - struct word ten; - struct word quarter; - struct word before; - struct word after; - struct word half; - struct word hour[12]; - struct word hourPostfix; - - }; - - struct wordmap languagemaps[NumberOfLanguages] - { - { - // prefix - {0,0,3}, {4,0,2}, - // almost - {0,0,0}, - // five/ten/quarter - {7,0,4}, {0,1,4}, {6,2,5}, - // before/after - {7,1,4}, {0,2,4}, -// {0,4,4}, {7,3,4}, - // half - {0,3,4}, - // hours - {{7,4,3},{0,5,4},{7,5,4},{0,6,4},{4,6,4},{6,8,3},{0,7,5},{0,8,4},{6,7,5},{4,8,4},{8,8,3},{0,9,6}}, - // hour postfix - {8,9,3} - } - }; - - - -}; - - -/** @} */ - -#endif /* MAIN_INC_WORDCLOCK_H_ */ diff --git a/code/main/main.cpp b/code/main/main.cpp index 3ddb403..31e4427 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -1,3 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +/// \file main +/// \brief Description +// -------------------------------------------------------------------------------------------------------------------- +// +// vbchaos software design +// +// -------------------------------------------------------------------------------------------------------------------- +/// $Revision: $ +/// $Author: $ +/// $Date: $ +// (c) 2023 vbchaos +// -------------------------------------------------------------------------------------------------------------------- + + +// -------------------------------------------------------------------------------------------------------------------- +// Include files +// -------------------------------------------------------------------------------------------------------------------- + #include "string.h" #include "freertos/FreeRTOS.h" @@ -12,6 +31,7 @@ #include "driver/gpio.h" #include "driver/rmt_tx.h" #include "driver/uart_select.h" +#include "driver/gptimer.h" #include "inc/gpio.h" #include "inc/led_strip_encoder.h" @@ -20,20 +40,73 @@ #include "inc/wifi.h" #include "clock.h" -#include "wordclock.h" +#include "wordmap.h" + +// -------------------------------------------------------------------------------------------------------------------- +// Constant and macro definitions +// -------------------------------------------------------------------------------------------------------------------- + +#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) +#define RMT_LED_STRIP_GPIO_NUM 0 + +// -------------------------------------------------------------------------------------------------------------------- +// Type definitions +// -------------------------------------------------------------------------------------------------------------------- + + + +// -------------------------------------------------------------------------------------------------------------------- +// File-scope variables +// -------------------------------------------------------------------------------------------------------------------- static const uart_port_t uartPort = UART_NUM_0; static TaskHandle_t devTaskHandle = NULL; static void devTask(void* parameters); -static GPIO gpio0(4, GPIO_DIRECTION_OUTPUT); -static GPIO gpio1(18, GPIO_DIRECTION_OUTPUT); +// GPIOs +static GPIO led_rgb_red(3, GPIO_DIRECTION_OUTPUT); +static GPIO led_rgb_green(4, GPIO_DIRECTION_OUTPUT); +static GPIO led_rgb_blue(5, GPIO_DIRECTION_OUTPUT); +static GPIO led_orange(18, GPIO_DIRECTION_OUTPUT); + +// ------------------------------------------------------- +// LED Matrix components static rmt_channel_handle_t led_chan = NULL; static rmt_transmit_config_t tx_config; static rmt_encoder_handle_t led_encoder = NULL; -#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) -#define RMT_LED_STRIP_GPIO_NUM 0 +static LEDMatrix_Parameters_t ledmatrix_parameters = +{ + LEDMATRIX_ORIENTATION_ROW_LEFT_RIGHT, + LEDMATRIX_ORIENTATION_COLUM_DOWN_UP, + LEDMATRIX_ORIENTATION_COLUM, + 11, + 10, + &led_chan, + &led_encoder, + &tx_config +}; +static LEDMatrix LEDMatrix(&ledmatrix_parameters); + +static Wordmap map(&LEDMatrix); + +static gptimer_handle_t matrixRefreshTimer = NULL; + +// -------------------------------------------------------------------------------------------------------------------- +// Function declarations +// -------------------------------------------------------------------------------------------------------------------- + +// Simple countdown on display +static void countdown(void); + +// Timer Callback for the LEDMatrix refresh +static bool timerCallback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data); + + +// -------------------------------------------------------------------------------------------------------------------- +// Function definitions +// -------------------------------------------------------------------------------------------------------------------- + extern "C" void app_main(void) { @@ -104,20 +177,30 @@ extern "C" void app_main(void) //-------------------------------------------- // LED Matrix // - LEDMatrix_Parameters_t ledmatrix_parameters; - ledmatrix_parameters.columOrientation = LEDMATRIX_ORIENTATION_COLUM_DOWN_UP; - ledmatrix_parameters.height = 10; - ledmatrix_parameters.matrixOrientation = LEDMATRIX_ORIENTATION_COLUM; - ledmatrix_parameters.rmtChannel = &led_chan; - ledmatrix_parameters.rmtConfig = &tx_config; - ledmatrix_parameters.rmtEncoder = &led_encoder; - ledmatrix_parameters.rowOrientation = LEDMATRIX_ORIENTATION_ROW_LEFT_RIGHT; - ledmatrix_parameters.width = 11; - LEDMatrix LEDMatrix(&ledmatrix_parameters); - - // Set an initial colour map LEDMatrix.setGlobalColour(0x10, 0, 0x04); + //-------------------------------------------- + // GP Timer for automatic matrix re-draw trigger + // + gptimer_config_t timer_config = { }; + gptimer_event_callbacks_t cbs = { }; + gptimer_alarm_config_t alarm_config = { }; + + timer_config.clk_src = GPTIMER_CLK_SRC_DEFAULT; + timer_config.direction = GPTIMER_COUNT_UP; + timer_config.resolution_hz = 1000000; // 1 MHz + cbs.on_alarm = timerCallback; + alarm_config.reload_count = 0; + alarm_config.alarm_count = timer_config.resolution_hz / 60; + alarm_config.flags.auto_reload_on_alarm = true; + + ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &matrixRefreshTimer)); + ESP_ERROR_CHECK(gptimer_register_event_callbacks(matrixRefreshTimer, &cbs, NULL)); + ESP_ERROR_CHECK(gptimer_enable(matrixRefreshTimer)); + ESP_ERROR_CHECK(gptimer_set_alarm_action(matrixRefreshTimer, &alarm_config)); + ESP_ERROR_CHECK(gptimer_start(matrixRefreshTimer)); + + // Create the development task if(xTaskCreate(devTask, "DevTask", 2048, NULL, 3, &devTaskHandle) != pdPASS) { @@ -130,31 +213,72 @@ extern "C" void app_main(void) Clock clock; Clock::TimeStructure time; - Wordclock wordclock(&LEDMatrix); + countdown(); + while (true) { time = clock.updateTime(); - wordclock.update(&time); + // Update the clock every second (1000 ms) vTaskDelay(1000); } } - static void devTask(void* parameters) { uint32_t counter = 0; - printf("DevTask created"); while (true) { - (void)gpio0.SetOutput((GPIO_Value_t)(counter % 2)); - (void)gpio1.SetOutput((GPIO_Value_t)(counter % 7)); + (void)led_orange.SetOutput((GPIO_Value_t)(counter % 2)); counter++; - - vTaskDelay(100); + vTaskDelay(500); } } + + +static void countdown(void) +{ + map.setWord(Wordmap::Language_t::NL, "ten", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "ten", false); + map.setWord(Wordmap::Language_t::NL, "nine", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "nine", false); + map.setWord(Wordmap::Language_t::NL, "eight", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "eight", false); + map.setWord(Wordmap::Language_t::NL, "seven", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "seven", false); + map.setWord(Wordmap::Language_t::NL, "six", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "six", false); + map.setWord(Wordmap::Language_t::NL, "five", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "five", false); + map.setWord(Wordmap::Language_t::NL, "four", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "four", false); + map.setWord(Wordmap::Language_t::NL, "three", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "three", false); + map.setWord(Wordmap::Language_t::NL, "two", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "two", false); + map.setWord(Wordmap::Language_t::NL, "one", true); + vTaskDelay(1000); + map.setWord(Wordmap::Language_t::NL, "one", false); +} + +static bool IRAM_ATTR timerCallback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + xHigherPriorityTaskWoken = LEDMatrix.tick(); + + return xHigherPriorityTaskWoken == pdTRUE; +} diff --git a/code/main/src/ledmatrix.cpp b/code/main/src/ledmatrix.cpp index bd8b7a7..6798bd8 100644 --- a/code/main/src/ledmatrix.cpp +++ b/code/main/src/ledmatrix.cpp @@ -50,6 +50,7 @@ SemaphoreHandle_t LEDMatrix::taskSemaphore = 0; TaskHandle_t LEDMatrix::matrixTaskHandle = NULL; +bool LEDMatrix::initialized = false; LEDMatrix::LEDMatrix(LEDMatrix_Parameters_t* parameters) { @@ -70,6 +71,8 @@ LEDMatrix::LEDMatrix(LEDMatrix_Parameters_t* parameters) // Clear the matrix initially LEDMatrix::clear(); + + initialized = true; } bool LEDMatrix::setPixelValue(unsigned int colum, unsigned int row, bool value) @@ -121,10 +124,6 @@ bool LEDMatrix::setPixelValue(unsigned int colum, unsigned int row, bool value) // Update the pixel value matrix[pixelAddress].on = value; - - - // Release the semaphore to trigger an matrix update - xSemaphoreGive(LEDMatrix::taskSemaphore); } return returnValue; } @@ -146,12 +145,8 @@ void LEDMatrix::clear(void) for (int i = 0; i < numberOfPixels; i++) { matrix[i].on = false; -// matrix[i].red = 0; -// matrix[i].green = 0; -// matrix[i].blue = 0; } - // Release the semaphore to trigger an matrix update - xSemaphoreGive(LEDMatrix::taskSemaphore); + } @@ -164,7 +159,7 @@ void LEDMatrix::matrixTask(void* parameters) while(1) { - xSemaphoreTake(ledmatrix->taskSemaphore, 1000); + xSemaphoreTake(ledmatrix->taskSemaphore, portMAX_DELAY); for (int i = 0; i < ledmatrix->numberOfPixels; i++) { @@ -182,7 +177,6 @@ void LEDMatrix::matrixTask(void* parameters) } } - // Re-draw the matrix every 10 seconds anyhow rmt_transmit(*ledmatrix->parameters.rmtChannel, *ledmatrix->parameters.rmtEncoder, matrix, sizeof(matrix), ledmatrix->parameters.rmtConfig); } diff --git a/code/main/src/wordclock.cpp b/code/main/src/wordclock.cpp deleted file mode 100644 index c19d2cb..0000000 --- a/code/main/src/wordclock.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -/// \file wordclock.cpp -/// \brief Description -// -------------------------------------------------------------------------------------------------------------------- -// -// vbchaos software design -// -// -------------------------------------------------------------------------------------------------------------------- -/// $Revision: $ -/// $Author: $ -/// $Date: $ -// (c) 2023 vbchaos -// -------------------------------------------------------------------------------------------------------------------- - - -// -------------------------------------------------------------------------------------------------------------------- -// Include files -// -------------------------------------------------------------------------------------------------------------------- - -#include "wordclock.h" - -// -------------------------------------------------------------------------------------------------------------------- -// Constant and macro definitions -// -------------------------------------------------------------------------------------------------------------------- - - - -// -------------------------------------------------------------------------------------------------------------------- -// Type definitions -// -------------------------------------------------------------------------------------------------------------------- - - -// -------------------------------------------------------------------------------------------------------------------- -// File-scope variables -// -------------------------------------------------------------------------------------------------------------------- - - - -// -------------------------------------------------------------------------------------------------------------------- -// Function declarations -// -------------------------------------------------------------------------------------------------------------------- - - - -// -------------------------------------------------------------------------------------------------------------------- -// Function definitions -// -------------------------------------------------------------------------------------------------------------------- - -Wordclock::Wordclock(LEDMatrix* matrix) -{ - Wordclock::matrix = matrix; - // Initial language set - Wordclock::language = NL; -} - - -void Wordclock::update(Clock::TimeStructure* time) -{ - // Clear the matrix before setting a new time - matrix->clear(); - - if (time->prefix) - { - if (languagemaps[language].prefix.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].prefix.length; i++) - { - matrix->setPixelValue(languagemaps[language].prefix.position.x + i, languagemaps[language].prefix.position.y, true); - } - } - - if (languagemaps[language].prefix_additional.length > 0) - { - // Enable Prefix addition on the matrix - for (int i = 0; i < languagemaps[language].prefix_additional.length; i++) - { - matrix->setPixelValue(languagemaps[language].prefix_additional.position.x + i, languagemaps[language].prefix_additional.position.y, true); - } - } - } - - if (time->almost) - { - if (languagemaps[language].almost.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].almost.length; i++) - { - matrix->setPixelValue(languagemaps[language].almost.position.x + i, languagemaps[language].almost.position.y, true); - } - } - } - - if (time->fifths == Clock::Five) - { - if (languagemaps[language].five.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].five.length; i++) - { - matrix->setPixelValue(languagemaps[language].five.position.x + i, languagemaps[language].five.position.y, true); - } - } - } - else if (time->fifths == Clock::Ten) - { - if (languagemaps[language].ten.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].ten.length; i++) - { - matrix->setPixelValue(languagemaps[language].ten.position.x + i, languagemaps[language].ten.position.y, true); - } - } - } - else if (time->fifths == Clock::Quarter) - { - if (languagemaps[language].quarter.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].quarter.length; i++) - { - matrix->setPixelValue(languagemaps[language].quarter.position.x + i, languagemaps[language].quarter.position.y, true); - } - } - } - - if (time->beforeAfter == Clock::Before) - { - if (languagemaps[language].before.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].before.length; i++) - { - matrix->setPixelValue(languagemaps[language].before.position.x + i, languagemaps[language].before.position.y, true); - } - } - } - else if (time->beforeAfter == Clock::After) - { - if (languagemaps[language].after.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].after.length; i++) - { - matrix->setPixelValue(languagemaps[language].after.position.x + i, languagemaps[language].after.position.y, true); - } - } - } - - if (time->half) - { - if (languagemaps[language].half.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].half.length; i++) - { - matrix->setPixelValue(languagemaps[language].half.position.x + i, languagemaps[language].half.position.y, true); - } - } - } - - if ((time->hours > 0) && (time->hours < 12)) - { - if (languagemaps[language].hour[time->hours - 1].length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].hour[time->hours - 1].length; i++) - { - matrix->setPixelValue(languagemaps[language].hour[time->hours - 1].position.x + i, languagemaps[language].hour[time->hours - 1].position.y, true); - } - } - } - - - if (time->hourPostfix) - { - if (languagemaps[language].hourPostfix.length > 0) - { - // Enable Prefix on the matrix - for (int i = 0; i < languagemaps[language].hourPostfix.length; i++) - { - matrix->setPixelValue(languagemaps[language].hourPostfix.position.x + i, languagemaps[language].hourPostfix.position.y, true); - } - } - } - - -} - diff --git a/code/sdkconfig b/code/sdkconfig index 97a81f8..540bb06 100644 --- a/code/sdkconfig +++ b/code/sdkconfig @@ -901,7 +901,7 @@ CONFIG_FATFS_PER_FILE_CACHE=y # # CONFIG_FREERTOS_SMP is not set CONFIG_FREERTOS_UNICORE=y -CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set diff --git a/code/sdkconfig.old b/code/sdkconfig.old index 423b4e2..97a81f8 100644 --- a/code/sdkconfig.old +++ b/code/sdkconfig.old @@ -762,15 +762,11 @@ CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 # CONFIG_ESP_CONSOLE_UART_DEFAULT is not set # CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set -CONFIG_ESP_CONSOLE_UART_CUSTOM=y -# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +CONFIG_ESP_CONSOLE_NONE=y CONFIG_ESP_CONSOLE_SECONDARY_NONE=y # CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is not set -CONFIG_ESP_CONSOLE_UART=y CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_TX_GPIO=0 -CONFIG_ESP_CONSOLE_UART_RX_GPIO=1 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 CONFIG_ESP_INT_WDT=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 CONFIG_ESP_TASK_WDT_EN=y @@ -1539,14 +1535,10 @@ CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_MAIN_TASK_STACK_SIZE=3584 # CONFIG_CONSOLE_UART_DEFAULT is not set -CONFIG_CONSOLE_UART_CUSTOM=y -# CONFIG_CONSOLE_UART_NONE is not set -# CONFIG_ESP_CONSOLE_UART_NONE is not set -CONFIG_CONSOLE_UART=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +CONFIG_CONSOLE_UART_NONE=y +CONFIG_ESP_CONSOLE_UART_NONE=y CONFIG_CONSOLE_UART_NUM=0 -CONFIG_CONSOLE_UART_TX_GPIO=0 -CONFIG_CONSOLE_UART_RX_GPIO=1 -CONFIG_CONSOLE_UART_BAUDRATE=115200 CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_ESP_TASK_WDT=y