From b998e37c3cc98609293ec9b59c2765f2160f83a9 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 13 Dec 2025 10:25:17 -0600 Subject: [PATCH 1/2] Added ESP-NOW task. --- components/ESP-NOW/CMakeLists.txt | 15 +++ components/ESP-NOW/ESP-NOW.c | 180 ++++++++++++++++++++++++++++++ components/ESP-NOW/ESP-NOW.h | 24 ++++ main/main.c | 3 + 4 files changed, 222 insertions(+) create mode 100644 components/ESP-NOW/CMakeLists.txt create mode 100644 components/ESP-NOW/ESP-NOW.c create mode 100644 components/ESP-NOW/ESP-NOW.h diff --git a/components/ESP-NOW/CMakeLists.txt b/components/ESP-NOW/CMakeLists.txt new file mode 100644 index 0000000..f666de7 --- /dev/null +++ b/components/ESP-NOW/CMakeLists.txt @@ -0,0 +1,15 @@ +idf_component_register( + SRCS + "ESP-NOW.c" + INCLUDE_DIRS + "." + REQUIRES + "SystemK" + "esp_wifi" + "nvs_flash" + "esp_netif" + "esp_event" + "esp_system" + "freertos" + "NVM" +) \ No newline at end of file diff --git a/components/ESP-NOW/ESP-NOW.c b/components/ESP-NOW/ESP-NOW.c new file mode 100644 index 0000000..c116ca0 --- /dev/null +++ b/components/ESP-NOW/ESP-NOW.c @@ -0,0 +1,180 @@ +/* + * This program source code file is part of the KTag project. + * + * 🛡️ 🃞 + * + * Copyright © 2025 Joseph P. Kearney and the KTag developers. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program 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 Affero General Public License for more + * details. + * + * There should be a copy of the GNU Affero General Public License in the LICENSE + * file in the root of this repository. If not, see . + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_mac.h" +#include "esp_event.h" +#include "esp_now.h" +// +#include "nvs_flash.h" + +static const char *TAG = "ESP-NOW"; + +// Broadcast address (all 0xFF sends to all devices) +static uint8_t Broadcast_MAC[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +// Structure for the data to send +typedef struct +{ + uint32_t counter; + char message[32]; +} broadcast_data_t; + +// ESP-NOW receive callback +static void ESPNOW_Recv_CB(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len) +{ + if (recv_info == NULL || data == NULL || len <= 0) + { + KLOG_ERROR(TAG, "Receive callback error"); + return; + } + + // Log sender MAC address + KLOG_INFO(TAG, "Received from: " MACSTR ", RSSI: %d", + MAC2STR(recv_info->src_addr), recv_info->rx_ctrl->rssi); + + // Parse received data + if (len == sizeof(broadcast_data_t)) + { + broadcast_data_t *recv_data = (broadcast_data_t *)data; + KLOG_INFO(TAG, "Counter: %lu, Message: %s", + recv_data->counter, recv_data->message); + } + else + { + KLOG_WARN(TAG, "Unexpected data length: %d", len); + } +} + +// ESP-NOW send callback +static void ESPNOW_Send_CB(const wifi_tx_info_t *tx_info, esp_now_send_status_t status) +{ + if (tx_info == NULL) + { + KLOG_ERROR(TAG, "Send callback error: tx_info is NULL"); + return; + } + + if (status == ESP_NOW_SEND_SUCCESS) + { + KLOG_INFO(TAG, "Send success to " MACSTR, MAC2STR(tx_info->des_addr)); + } + else + { + KLOG_WARN(TAG, "Send failed to " MACSTR, MAC2STR(tx_info->des_addr)); + } +} + +static esp_err_t Initialize_ESPNOW(void) +{ + esp_err_t ret = esp_now_init(); + if (ret != ESP_OK) + { + KLOG_ERROR(TAG, "ESP-NOW init failed: %s", esp_err_to_name(ret)); + return ret; + } + + // Register send and receive callbacks + esp_now_register_send_cb(ESPNOW_Send_CB); + esp_now_register_recv_cb(ESPNOW_Recv_CB); + + // Add broadcast peer + esp_now_peer_info_t peer_info = {}; + memcpy(peer_info.peer_addr, Broadcast_MAC, ESP_NOW_ETH_ALEN); + peer_info.channel = 0; // Use current channel + peer_info.ifidx = WIFI_IF_STA; + peer_info.encrypt = false; + + ret = esp_now_add_peer(&peer_info); + if (ret != ESP_OK) + { + KLOG_ERROR(TAG, "Failed to add broadcast peer: %s", esp_err_to_name(ret)); + return ret; + } + + KLOG_INFO(TAG, "ESP-NOW initialized successfully"); + return ESP_OK; +} + +// FreeRTOS task for periodic broadcast +static void ESPNOW_Task(void *pvParameters) +{ + broadcast_data_t data = {0}; + TickType_t last_wake = xTaskGetTickCount(); + const TickType_t period = pdMS_TO_TICKS(2000); + + KLOG_INFO(TAG, "ESP-NOW task started"); + + while (1) + { + // Update data + data.counter++; + snprintf(data.message, sizeof(data.message), "Broadcast #%lu", data.counter); + + // Send broadcast + esp_err_t ret = esp_now_send(Broadcast_MAC, (uint8_t *)&data, sizeof(data)); + if (ret != ESP_OK) + { + KLOG_ERROR(TAG, "Send error: %s", esp_err_to_name(ret)); + } + + // Wait for next period + vTaskDelayUntil(&last_wake, period); + } +} + +static void Initialize_WiFi(void) +{ + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); + + KLOG_INFO(TAG, "WiFi initialized in station mode"); +} + +void Initialize_ESP_NOW(void) +{ + Initialize_WiFi(); + + // Initialize ESP-NOW + if (Initialize_ESPNOW() != ESP_OK) + { + KLOG_ERROR(TAG, "ESP-NOW initialization failed"); + return; + } + + // Enable Long Range mode + esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); + esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_LR); + + // Create broadcast task + xTaskCreate(ESPNOW_Task, "ESP-NOW", 4096, NULL, 5, NULL); +} \ No newline at end of file diff --git a/components/ESP-NOW/ESP-NOW.h b/components/ESP-NOW/ESP-NOW.h new file mode 100644 index 0000000..24e9697 --- /dev/null +++ b/components/ESP-NOW/ESP-NOW.h @@ -0,0 +1,24 @@ +/* + * This program source code file is part of the KTag project. + * + * 🛡️ 🃞 + * + * Copyright © 2025 Joseph P. Kearney and the KTag developers. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program 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 Affero General Public License for more + * details. + * + * There should be a copy of the GNU Affero General Public License in the LICENSE + * file in the root of this repository. If not, see . + */ + +#pragma once + +void Initialize_ESP_NOW(void); \ No newline at end of file diff --git a/main/main.c b/main/main.c index 9b0069e..5d80d4f 100644 --- a/main/main.c +++ b/main/main.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "nvs_flash.h" #include "HW_NeoPixels.h" #include "Version.h" @@ -119,6 +120,8 @@ void app_main(void) // Initialize the switches after SystemK, so xQueueEvents will have already been created. Initialize_Switches(); + Initialize_ESP_NOW(); + KLOG_INFO(TAG, "Initialization complete."); } From 9885cbc4197c9464b170b1305f721a0b0fcc8b54 Mon Sep 17 00:00:00 2001 From: Joe Kearney Date: Sat, 10 Jan 2026 18:23:35 -0600 Subject: [PATCH 2/2] Additional SystemK config. --- sdkconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdkconfig b/sdkconfig index b4eb3d9..1613bf3 100644 --- a/sdkconfig +++ b/sdkconfig @@ -2636,6 +2636,13 @@ CONFIG_KTAG_ANIMATION_STEP_TIME_IN_ms=10 CONFIG_KTAG_T_DEFAULT_START_GAME_in_ms=30000 CONFIG_KTAG_MAX_AUDIO_VOLUME=100 CONFIG_KTAG_MIN_AUDIO_VOLUME=0 +CONFIG_SYSTEMK_LOG_LEVEL=5 +# CONFIG_SYSTEMK_LOG_LEVEL_NONE is not set +# CONFIG_SYSTEMK_LOG_LEVEL_ERROR is not set +# CONFIG_SYSTEMK_LOG_LEVEL_WARN is not set +# CONFIG_SYSTEMK_LOG_LEVEL_INFO is not set +# CONFIG_SYSTEMK_LOG_LEVEL_DEBUG is not set +CONFIG_SYSTEMK_LOG_LEVEL_VERBOSE=y # end of KTag SystemK #