// -------------------------------------------------------------------------------------------------------------------- /// \file main /// \brief Description // -------------------------------------------------------------------------------------------------------------------- // // vbchaos software design // // -------------------------------------------------------------------------------------------------------------------- /// $Revision: $ /// $Author: $ /// $Date: $ // (c) 2023 vbchaos // -------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------- // Include files // -------------------------------------------------------------------------------------------------------------------- #include "string.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_event.h" #include "esp_log.h" #include "esp_wifi.h" #include "nvs_flash.h" #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" #include "inc/ledmatrix.h" #include "inc/logger.h" #include "inc/wifi.h" #include "clock.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 TaskHandle_t colourMapTaskHandle = NULL; // 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; 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(int delay); // Timer Callback for the LEDMatrix refresh static bool timerCallback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data); static void devTask(void* parameters); static void colourMapTask(void* parameters); // -------------------------------------------------------------------------------------------------------------------- // Function definitions // -------------------------------------------------------------------------------------------------------------------- extern "C" void app_main(void) { esp_log_level_set("*", ESP_LOG_WARN); esp_err_t ret = nvs_flash_init(); if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } //-------------------------------------------- // UART // const uart_config_t uartConfig = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .rx_flow_ctrl_thresh = 0, .source_clk = UART_SCLK_DEFAULT }; ESP_ERROR_CHECK(uart_param_config(uartPort, &uartConfig)); ESP_ERROR_CHECK(uart_set_pin(uartPort, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); ESP_ERROR_CHECK(uart_driver_install(uartPort, 1024, 1024, 0, NULL, 0)); //-------------------------------------------- // LOGGER // Logger logger(10, uartPort); LOGGER_DEBUG("Let's start the WORDCLOCK"); //-------------------------------------------- // RMT Channel // LOGGER_INFO("Create RMT TX channel"); rmt_tx_channel_config_t tx_chan_config; memset(&tx_chan_config, 0, sizeof(tx_chan_config)); tx_chan_config.clk_src = RMT_CLK_SRC_DEFAULT; // select source clock tx_chan_config.gpio_num = RMT_LED_STRIP_GPIO_NUM; tx_chan_config.mem_block_symbols = 64; // increase the block size can make the LED less flickering tx_chan_config.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ; tx_chan_config.trans_queue_depth = 4; ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan)); LOGGER_INFO("Install led strip encoder"); led_strip_encoder_config_t encoder_config; memset(&encoder_config, 0, sizeof(encoder_config)); encoder_config.resolution = RMT_LED_STRIP_RESOLUTION_HZ; ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder)); LOGGER_INFO("Enable RMT TX channel"); ESP_ERROR_CHECK(rmt_enable(led_chan)); memset(&tx_config, 0, sizeof(tx_config)); tx_config.loop_count = 0; //-------------------------------------------- // LED Matrix // 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) { LOGGER_ERROR("Task not created"); } // Create the colour Map task if(xTaskCreate(colourMapTask, "ColourTask", 2048, NULL, 3, &colourMapTaskHandle) != pdPASS) { LOGGER_ERROR("Task not created"); } Wifi wifi; wifi.start_client(); Clock clock(Clock::mode::TEN_BEFORE_HALF); countdown(200); list wordlist; while (true) { clock.generateWordlist(&wordlist); LEDMatrix.clear(); std::list::iterator it; for(it = wordlist.begin(); it != wordlist.end(); it++) { map.setWord(Wordmap::Language_t::NL, *it, true); } // Add a seconds indicator LEDMatrix.setPixelValue(10, 9, clock.getTime() % 2); // Update the clock every second (1000 ms) vTaskDelay(1000); } } static void devTask(void* parameters) { uint32_t counter = 0; printf("DevTask created"); while (true) { (void)led_orange.SetOutput((GPIO_Value_t)(counter % 2)); counter++; vTaskDelay(500); } } static void colourMapTask(void* parameters) { uint8_t red = 0; uint8_t green = 0; uint8_t blue = 0; uint32_t counter = 0; while (true) { LEDMatrix.setGlobalColour(red, green, blue); red = counter & 0xFF; green = (counter >> 8) & 0xFF; blue = (counter >> 16) & 0xFF; counter++; vTaskDelay(30); } } static void countdown(int delay) { map.setWord(Wordmap::Language_t::NL, "ten", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "ten", false); map.setWord(Wordmap::Language_t::NL, "nine", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "nine", false); map.setWord(Wordmap::Language_t::NL, "eight", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "eight", false); map.setWord(Wordmap::Language_t::NL, "seven", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "seven", false); map.setWord(Wordmap::Language_t::NL, "six", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "six", false); map.setWord(Wordmap::Language_t::NL, "five", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "five", false); map.setWord(Wordmap::Language_t::NL, "four", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "four", false); map.setWord(Wordmap::Language_t::NL, "three", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "three", false); map.setWord(Wordmap::Language_t::NL, "two", true); vTaskDelay(delay); map.setWord(Wordmap::Language_t::NL, "two", false); map.setWord(Wordmap::Language_t::NL, "one", true); vTaskDelay(delay); 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; }