diff --git a/dependencies.lock b/dependencies.lock new file mode 100644 index 0000000..aa1a1d2 --- /dev/null +++ b/dependencies.lock @@ -0,0 +1,21 @@ +dependencies: + espressif/led_strip: + component_hash: 28621486f77229aaf81c71f5e15d6fbf36c2949cf11094e07090593e659e7639 + dependencies: + - name: idf + require: private + version: '>=5.0' + source: + registry_url: https://components.espressif.com/ + type: service + version: 3.0.3 + idf: + source: + type: idf + version: 5.5.1 +direct_dependencies: +- espressif/led_strip +- idf +manifest_hash: 66f0d1a5019d1277f845b61ed7ecd51b2f8a000d6fb5b32b40131928bf590fba +target: esp32s3 +version: 2.0.0 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 0e51f06..3e491e4 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "powerpod.c" +idf_component_register(SRCS "powerpod.c" "led_ring.c" INCLUDE_DIRS ".") diff --git a/main/idf_component.yml b/main/idf_component.yml new file mode 100644 index 0000000..09ab3d2 --- /dev/null +++ b/main/idf_component.yml @@ -0,0 +1,17 @@ +## IDF Component Manager Manifest File +dependencies: + ## Required IDF version + idf: + version: '>=4.1.0' + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true + espressif/led_strip: '*' diff --git a/main/led_ring.c b/main/led_ring.c new file mode 100644 index 0000000..f945de8 --- /dev/null +++ b/main/led_ring.c @@ -0,0 +1,96 @@ +#include "led_ring.h" +#include "driver/i2c_master.h" +#include "driver/i2c_types.h" +#include "esp_err.h" +#include "esp_log.h" +#include "led_strip.h" +#include + +typedef struct { + const uint8_t *leds; + uint8_t count; +} digit_definition_t; + +static const char *TAG = "[LED_RING]"; +static led_strip_handle_t led_ring; + +#define RING_LEDS 95 +#define LED_RING_PIN 7 + +static QueueHandle_t led_queue; + +// Led Matrix Maps +const uint8_t d0[] = {46, 47, 60, 61, 62, 75, 78, 79, + 80, 81, 82, 86, 87, 88, 89, 90}; +const uint8_t d1[] = {23, 46, 47, 48, 61, 62, 74, 75, 76, 84, 86, 93, 95}; +const uint8_t d2[] = {21, 22, 23, 24, 25, 26, 46, 47, 48, 49, 59, + 64, 71, 72, 73, 74, 75, 83, 89, 92, 95}; +const uint8_t d3[] = {1, 2, 21, 22, 23, 24, 25, 26, 27, 41, 42, + 43, 44, 45, 48, 59, 77, 83, 92, 93, 95}; +const uint8_t d4[] = {21, 26, 47, 59, 64, 77, 82, 86, 94, 95}; +const uint8_t d5[] = {19, 20, 21, 22, 23, 24, 25, 26, 63, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 90, 91}; +const uint8_t d6[] = {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 65, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91}; +const uint8_t d7[] = {1, 47, 58, 59, 60, 61, 62, 63, + 64, 65, 77, 80, 82, 92, 94}; +const uint8_t d8[] = {1, 2, 3, 4, 5, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 41, 42, 43, 44, 45, 49, 58, 64, + 73, 78, 82, 86, 90, 92, 93, 94, 95}; +const uint8_t d9[] = {19, 20, 21, 22, 23, 24, 25, 26, 27, 46, 47, 58, + 64, 71, 72, 73, 74, 75, 77, 82, 86, 94, 95}; + +const uint8_t d10[] = {46, 50, 57, 61, 65, 72, 76, 78, 80, + 82, 84, 86, 88, 90, 92, 93, 94, 95}; + +// Lookup Array for the Digits +const digit_definition_t digit_lookup[] = { + {d0, sizeof(d0)}, {d1, sizeof(d1)}, {d2, sizeof(d2)}, {d3, sizeof(d3)}, + {d4, sizeof(d4)}, {d5, sizeof(d5)}, {d6, sizeof(d6)}, {d7, sizeof(d7)}, + {d8, sizeof(d8)}, {d9, sizeof(d9)}, {d10, sizeof(d10)}}; + +void vTaskLedRing(void *pvParameters) { + /* LED Ring config */ + led_strip_config_t ring_config = { + .strip_gpio_num = LED_RING_PIN, + .max_leds = RING_LEDS, + }; + led_strip_rmt_config_t rmt_ring_config = { + .resolution_hz = 10 * 1000 * 1000, // 10 MHz + }; + esp_err_t err = + led_strip_new_rmt_device(&ring_config, &rmt_ring_config, &led_ring); + if (err == ESP_OK) { + ESP_LOGI(TAG, "GPIO_RING_TASK started"); + } + + led_command_t cmd; + while (1) { + if (xQueueReceive(led_queue, &cmd, portMAX_DELAY)) { + // Clear all LEDS + led_strip_clear(led_ring); + + if (cmd.mode == LED_CMD_SET_DIGIT && cmd.value <= 10) { + digit_definition_t digit = digit_lookup[cmd.value]; + + for (int i = 0; i < digit.count; i++) { + // Invert LED Counting for Now + led_strip_set_pixel(led_ring, RING_LEDS - digit.leds[i], cmd.r, cmd.g, + cmd.b); + } + } + led_strip_refresh(led_ring); + } + } +} + +void led_ring_init(void) { + led_queue = xQueueCreate(10, sizeof(led_command_t)); + xTaskCreate(vTaskLedRing, "led_task", 4096, NULL, 5, NULL); +} + +void led_ring_send_command(led_command_t *cmd) { + if (led_queue != NULL) { + xQueueSend(led_queue, cmd, portMAX_DELAY); + } +} diff --git a/main/led_ring.h b/main/led_ring.h new file mode 100644 index 0000000..72ce130 --- /dev/null +++ b/main/led_ring.h @@ -0,0 +1,12 @@ +#include + +typedef enum { LED_CMD_CLEAR, LED_CMD_SET_DIGIT, LED_CMD_SET_COLOR } led_mode_t; + +typedef struct { + led_mode_t mode; + uint8_t value; + uint8_t r, g, b; +} led_command_t; + +void led_ring_send_command(led_command_t *cmd); +void led_ring_init(void); diff --git a/main/powerpod.c b/main/powerpod.c index 7b42410..8f0e570 100644 --- a/main/powerpod.c +++ b/main/powerpod.c @@ -6,6 +6,8 @@ #include "esp_flash_partitions.h" #include "esp_log.h" #include "esp_ota_ops.h" +#include "freertos/FreeRTOS.h" +#include "led_ring.h" #include "nvs.h" #include "nvs_flash.h" #include @@ -107,14 +109,6 @@ void app_main(void) { 1; // map network to 0-8, 0 is not a valid network } - 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(); - } - ESP_ERROR_CHECK(ret); - const esp_partition_t *running = esp_ota_get_running_partition(); App_Config.Master = (master == true); @@ -126,4 +120,21 @@ void app_main(void) { ESP_LOGI(TAG, "Master: %d", App_Config.Master); ESP_LOGI(TAG, "Network: %d", App_Config.Network); ESP_LOGI(TAG, "Running Partition: %s", App_Config.RunningPartition); + + led_ring_init(); + + uint8_t current_digit = 10; + while (1) { + led_command_t cmd = { + .mode = LED_CMD_SET_DIGIT, + .value = current_digit, + .r = 5, + .g = 5, + .b = 0 + }; + + led_ring_send_command(&cmd); + current_digit = (current_digit + 1) % 11; + vTaskDelay(pdMS_TO_TICKS(500)); + } }