basic led control with local btn
This commit is contained in:
@ -5,10 +5,6 @@ idf_component_register(
|
||||
"led.c"
|
||||
"rcsignal.c"
|
||||
"animation.c"
|
||||
"localbtn.c"
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_FILES
|
||||
"../webapp/index.html"
|
||||
"../webapp/app/app.js"
|
||||
"../webapp/css/style.css"
|
||||
"../webapp/data/favicon.ico"
|
||||
)
|
||||
|
||||
@ -190,7 +190,7 @@ static void anim_bpm(void)
|
||||
// PartyColors palette simulation
|
||||
const uint8_t palette_colors[] = {
|
||||
170, 240, 90, 150, 210, 30, 180, 0,
|
||||
210, 270, 150, 240, 330, 60, 300, 120};
|
||||
210, 255, 150, 240, 255, 60, 255, 120};
|
||||
|
||||
for (uint16_t i = 0; i < num_leds_a; i++)
|
||||
{
|
||||
|
||||
493
main/control.c
493
main/control.c
@ -1,26 +1,21 @@
|
||||
/**
|
||||
* @file control.c
|
||||
* @brief Control module implementation with BLE, NVS, and OTA
|
||||
* @brief Control module implementation
|
||||
*/
|
||||
|
||||
#include "control.h"
|
||||
#include "led.h"
|
||||
#include "rcsignal.h"
|
||||
#include "localbtn.h"
|
||||
#include "animation.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_gatts_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gatt_common_api.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -28,66 +23,19 @@ static const char *TAG = "CONTROL";
|
||||
|
||||
#define NVS_NAMESPACE "led_ctrl"
|
||||
#define CONFIG_MAGIC 0xDEADBEEF
|
||||
#define DEFAULT_NUM_LEDS_A 44
|
||||
#define DEFAULT_NUM_LEDS_B 44
|
||||
|
||||
// BLE Configuration
|
||||
#define GATTS_SERVICE_UUID 0x00FF
|
||||
#define GATTS_CHAR_UUID_CONFIG 0xFF01
|
||||
#define GATTS_CHAR_UUID_MODE 0xFF02
|
||||
#define GATTS_CHAR_UUID_PWM 0xFF03
|
||||
#define GATTS_CHAR_UUID_OTA 0xFF04
|
||||
#define GATTS_NUM_HANDLE_TEST 8
|
||||
|
||||
#define DEVICE_NAME "LED-Controller"
|
||||
#define ADV_CONFIG_FLAG (1 << 0)
|
||||
#define SCAN_RSP_CONFIG_FLAG (1 << 1)
|
||||
#define DEFAULT_NUM_LEDS_A 7
|
||||
#define DEFAULT_NUM_LEDS_B 7
|
||||
|
||||
// Global state
|
||||
static controller_config_t current_config = {
|
||||
.led_pin_strip_a = -1,
|
||||
.led_pin_strip_b = -1,
|
||||
.pwm_pin = -1,
|
||||
.ble_timeout = BLE_TIMEOUT_NEVER,
|
||||
.magic = CONFIG_MAGIC};
|
||||
|
||||
static bool ble_enabled = true;
|
||||
static uint8_t current_animation_mode = 0;
|
||||
static esp_timer_handle_t ble_timeout_timer = NULL;
|
||||
static bool ble_connected = false;
|
||||
|
||||
// OTA state
|
||||
static const esp_partition_t *update_partition = NULL;
|
||||
static esp_ota_handle_t update_handle = 0;
|
||||
static size_t ota_bytes_written = 0;
|
||||
|
||||
// BLE variables
|
||||
static uint8_t adv_config_done = 0;
|
||||
static uint16_t gatts_if_global = ESP_GATT_IF_NONE;
|
||||
static uint16_t conn_id_global = 0;
|
||||
static uint16_t service_handle = 0;
|
||||
|
||||
// BLE advertising parameters
|
||||
static esp_ble_adv_params_t adv_params = {
|
||||
.adv_int_min = 0x20,
|
||||
.adv_int_max = 0x40,
|
||||
.adv_type = ADV_TYPE_IND,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.channel_map = ADV_CHNL_ALL,
|
||||
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
||||
};
|
||||
|
||||
// Characteristic handles
|
||||
static struct
|
||||
{
|
||||
uint16_t config_handle;
|
||||
uint16_t mode_handle;
|
||||
uint16_t pwm_handle;
|
||||
uint16_t ota_handle;
|
||||
} char_handles = {0};
|
||||
|
||||
// Forward declarations
|
||||
static void ble_timeout_callback(void *arg);
|
||||
static void on_mode_change(uint8_t new_mode);
|
||||
|
||||
// NVS Functions
|
||||
@ -115,7 +63,6 @@ static esp_err_t load_config_from_nvs(void)
|
||||
ESP_LOGI(TAG, " Strip A: GPIO%d", current_config.led_pin_strip_a);
|
||||
ESP_LOGI(TAG, " Strip B: GPIO%d", current_config.led_pin_strip_b);
|
||||
ESP_LOGI(TAG, " PWM Pin: GPIO%d", current_config.pwm_pin);
|
||||
ESP_LOGI(TAG, " BLE Timeout: %d", current_config.ble_timeout);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -152,10 +99,9 @@ static esp_err_t save_config_to_nvs(void)
|
||||
|
||||
esp_err_t control_reset_config(void)
|
||||
{
|
||||
current_config.led_pin_strip_a = -1;
|
||||
current_config.led_pin_strip_b = -1;
|
||||
current_config.pwm_pin = -1;
|
||||
current_config.ble_timeout = BLE_TIMEOUT_NEVER;
|
||||
current_config.led_pin_strip_a = 12;
|
||||
current_config.led_pin_strip_b = 14;
|
||||
current_config.pwm_pin = 13;
|
||||
current_config.magic = CONFIG_MAGIC;
|
||||
|
||||
return save_config_to_nvs();
|
||||
@ -191,59 +137,6 @@ esp_err_t control_update_config(const controller_config_t *config)
|
||||
return err;
|
||||
}
|
||||
|
||||
// BLE timeout handling
|
||||
static void ble_timeout_callback(void *arg)
|
||||
{
|
||||
if (!ble_connected)
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE timeout reached, disabling BLE");
|
||||
control_disable_ble();
|
||||
}
|
||||
}
|
||||
|
||||
static void start_ble_timeout(void)
|
||||
{
|
||||
if (current_config.ble_timeout == BLE_TIMEOUT_NEVER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ble_timeout_timer == NULL)
|
||||
{
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = ble_timeout_callback,
|
||||
.name = "ble_timeout"};
|
||||
esp_timer_create(&timer_args, &ble_timeout_timer);
|
||||
}
|
||||
|
||||
esp_timer_stop(ble_timeout_timer);
|
||||
esp_timer_start_once(ble_timeout_timer, (uint64_t)current_config.ble_timeout * 1000000ULL);
|
||||
ESP_LOGI(TAG, "BLE timeout started: %d seconds", current_config.ble_timeout);
|
||||
}
|
||||
|
||||
void control_disable_ble(void)
|
||||
{
|
||||
if (!ble_enabled)
|
||||
return;
|
||||
|
||||
ble_enabled = false;
|
||||
|
||||
if (ble_timeout_timer)
|
||||
{
|
||||
esp_timer_stop(ble_timeout_timer);
|
||||
}
|
||||
|
||||
// Stop BLE advertising
|
||||
esp_ble_gap_stop_advertising();
|
||||
|
||||
ESP_LOGI(TAG, "BLE disabled");
|
||||
}
|
||||
|
||||
bool control_is_ble_enabled(void)
|
||||
{
|
||||
return ble_enabled;
|
||||
}
|
||||
|
||||
// Animation mode change callback
|
||||
static void on_mode_change(uint8_t new_mode)
|
||||
{
|
||||
@ -270,361 +163,6 @@ void control_emulate_pwm_pulse(void)
|
||||
rcsignal_trigger_mode_change();
|
||||
}
|
||||
|
||||
// Embedded web files (will be linked)
|
||||
extern const uint8_t index_html_start[] asm("_binary_index_html_start");
|
||||
extern const uint8_t index_html_end[] asm("_binary_index_html_end");
|
||||
extern const uint8_t app_js_start[] asm("_binary_app_js_start");
|
||||
extern const uint8_t app_js_end[] asm("_binary_app_js_end");
|
||||
extern const uint8_t style_css_start[] asm("_binary_style_css_start");
|
||||
extern const uint8_t style_css_end[] asm("_binary_style_css_end");
|
||||
extern const uint8_t favicon_ico_start[] asm("_binary_favicon_ico_start");
|
||||
extern const uint8_t favicon_ico_end[] asm("_binary_favicon_ico_end");
|
||||
|
||||
// BLE GAP event handler
|
||||
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
|
||||
{
|
||||
ESP_LOGI(TAG, "gap_event_handler() event: %i\n", event);
|
||||
switch (event)
|
||||
{
|
||||
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||
adv_config_done &= (~ADV_CONFIG_FLAG);
|
||||
if (adv_config_done == 0)
|
||||
{
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
|
||||
adv_config_done &= (~SCAN_RSP_CONFIG_FLAG);
|
||||
if (adv_config_done == 0)
|
||||
{
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||
if (param->adv_start_cmpl.status == ESP_BT_STATUS_SUCCESS)
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE advertising started");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// BLE GATTS event handler
|
||||
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESP_GATTS_REG_EVT:
|
||||
ESP_LOGI(TAG, "GATTS register, status %d, app_id %d", param->reg.status, param->reg.app_id);
|
||||
gatts_if_global = gatts_if;
|
||||
|
||||
// Set device name
|
||||
esp_ble_gap_set_device_name(DEVICE_NAME);
|
||||
|
||||
// Config advertising data
|
||||
esp_ble_adv_data_t adv_data = {
|
||||
.set_scan_rsp = false,
|
||||
.include_name = true,
|
||||
.include_txpower = true,
|
||||
.min_interval = 0x0006,
|
||||
.max_interval = 0x0010,
|
||||
.appearance = 0x00,
|
||||
.manufacturer_len = 0,
|
||||
.p_manufacturer_data = NULL,
|
||||
.service_data_len = 0,
|
||||
.p_service_data = NULL,
|
||||
.service_uuid_len = sizeof(uint16_t),
|
||||
.p_service_uuid = (uint8_t[]){GATTS_SERVICE_UUID & 0xFF, (GATTS_SERVICE_UUID >> 8) & 0xFF},
|
||||
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
|
||||
};
|
||||
esp_ble_gap_config_adv_data(&adv_data);
|
||||
adv_config_done |= ADV_CONFIG_FLAG;
|
||||
|
||||
// Create service
|
||||
esp_gatt_srvc_id_t service_id = {
|
||||
.is_primary = true,
|
||||
.id.inst_id = 0,
|
||||
.id.uuid.len = ESP_UUID_LEN_16,
|
||||
.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID,
|
||||
};
|
||||
esp_ble_gatts_create_service(gatts_if, &service_id, GATTS_NUM_HANDLE_TEST);
|
||||
break;
|
||||
|
||||
case ESP_GATTS_CREATE_EVT:
|
||||
ESP_LOGI(TAG, "CREATE_SERVICE_EVT, status %d, service_handle %d", param->create.status, param->create.service_handle);
|
||||
service_handle = param->create.service_handle;
|
||||
|
||||
esp_ble_gatts_start_service(service_handle);
|
||||
|
||||
// Add characteristics
|
||||
esp_bt_uuid_t char_uuid;
|
||||
char_uuid.len = ESP_UUID_LEN_16;
|
||||
|
||||
// Config characteristic
|
||||
char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_CONFIG;
|
||||
esp_ble_gatts_add_char(service_handle, &char_uuid,
|
||||
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
|
||||
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE,
|
||||
NULL, NULL);
|
||||
|
||||
// Mode characteristic
|
||||
char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_MODE;
|
||||
esp_ble_gatts_add_char(service_handle, &char_uuid,
|
||||
ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
|
||||
ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
|
||||
NULL, NULL);
|
||||
|
||||
// PWM emulation characteristic
|
||||
char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_PWM;
|
||||
esp_ble_gatts_add_char(service_handle, &char_uuid,
|
||||
ESP_GATT_PERM_WRITE,
|
||||
ESP_GATT_CHAR_PROP_BIT_WRITE,
|
||||
NULL, NULL);
|
||||
|
||||
// OTA characteristic
|
||||
char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_OTA;
|
||||
esp_ble_gatts_add_char(service_handle, &char_uuid,
|
||||
ESP_GATT_PERM_WRITE,
|
||||
ESP_GATT_CHAR_PROP_BIT_WRITE,
|
||||
NULL, NULL);
|
||||
break;
|
||||
|
||||
case ESP_GATTS_ADD_CHAR_EVT:
|
||||
ESP_LOGI(TAG, "ADD_CHAR_EVT, status %d, char_handle %d", param->add_char.status, param->add_char.attr_handle);
|
||||
|
||||
// Store handles
|
||||
if (param->add_char.char_uuid.uuid.uuid16 == GATTS_CHAR_UUID_CONFIG)
|
||||
{
|
||||
char_handles.config_handle = param->add_char.attr_handle;
|
||||
}
|
||||
else if (param->add_char.char_uuid.uuid.uuid16 == GATTS_CHAR_UUID_MODE)
|
||||
{
|
||||
char_handles.mode_handle = param->add_char.attr_handle;
|
||||
}
|
||||
else if (param->add_char.char_uuid.uuid.uuid16 == GATTS_CHAR_UUID_PWM)
|
||||
{
|
||||
char_handles.pwm_handle = param->add_char.attr_handle;
|
||||
}
|
||||
else if (param->add_char.char_uuid.uuid.uuid16 == GATTS_CHAR_UUID_OTA)
|
||||
{
|
||||
char_handles.ota_handle = param->add_char.attr_handle;
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GATTS_CONNECT_EVT:
|
||||
ESP_LOGI(TAG, "BLE device connected");
|
||||
conn_id_global = param->connect.conn_id;
|
||||
ble_connected = true;
|
||||
|
||||
// Stop timeout timer when connected
|
||||
if (ble_timeout_timer)
|
||||
{
|
||||
esp_timer_stop(ble_timeout_timer);
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GATTS_DISCONNECT_EVT:
|
||||
ESP_LOGI(TAG, "BLE device disconnected");
|
||||
ble_connected = false;
|
||||
|
||||
// Restart advertising and timeout
|
||||
if (ble_enabled)
|
||||
{
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
start_ble_timeout();
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_GATTS_READ_EVT:
|
||||
ESP_LOGI(TAG, "GATTS_READ_EVT, handle %d", param->read.handle);
|
||||
|
||||
esp_gatt_rsp_t rsp;
|
||||
memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
|
||||
rsp.attr_value.handle = param->read.handle;
|
||||
|
||||
if (param->read.handle == char_handles.config_handle)
|
||||
{
|
||||
rsp.attr_value.len = sizeof(controller_config_t);
|
||||
memcpy(rsp.attr_value.value, ¤t_config, sizeof(controller_config_t));
|
||||
}
|
||||
else if (param->read.handle == char_handles.mode_handle)
|
||||
{
|
||||
rsp.attr_value.len = 1;
|
||||
rsp.attr_value.value[0] = current_animation_mode;
|
||||
}
|
||||
|
||||
esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
|
||||
ESP_GATT_OK, &rsp);
|
||||
break;
|
||||
|
||||
case ESP_GATTS_WRITE_EVT:
|
||||
ESP_LOGI(TAG, "GATTS_WRITE_EVT, handle %d, len %d", param->write.handle, param->write.len);
|
||||
|
||||
if (param->write.handle == char_handles.config_handle)
|
||||
{
|
||||
// Update configuration
|
||||
if (param->write.len == sizeof(controller_config_t))
|
||||
{
|
||||
controller_config_t new_config;
|
||||
memcpy(&new_config, param->write.value, sizeof(controller_config_t));
|
||||
control_update_config(&new_config);
|
||||
}
|
||||
}
|
||||
else if (param->write.handle == char_handles.mode_handle)
|
||||
{
|
||||
// Set animation mode
|
||||
if (param->write.len == 1)
|
||||
{
|
||||
control_set_animation_mode(param->write.value[0]);
|
||||
}
|
||||
}
|
||||
else if (param->write.handle == char_handles.pwm_handle)
|
||||
{
|
||||
// Emulate PWM pulse
|
||||
control_emulate_pwm_pulse();
|
||||
}
|
||||
else if (param->write.handle == char_handles.ota_handle)
|
||||
{
|
||||
// Handle OTA data
|
||||
if (ota_bytes_written == 0)
|
||||
{
|
||||
// First packet - start OTA
|
||||
ESP_LOGI(TAG, "Starting OTA update...");
|
||||
update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
if (update_partition == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "No OTA partition found");
|
||||
break;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "OTA begin failed: %s", esp_err_to_name(err));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Write OTA data
|
||||
esp_err_t err = esp_ota_write(update_handle, param->write.value, param->write.len);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "OTA write failed: %s", esp_err_to_name(err));
|
||||
esp_ota_abort(update_handle);
|
||||
ota_bytes_written = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ota_bytes_written += param->write.len;
|
||||
ESP_LOGI(TAG, "OTA progress: %d bytes", ota_bytes_written);
|
||||
|
||||
// Check if this is the last packet (indicated by packet size < MTU)
|
||||
if (param->write.len < 512)
|
||||
{
|
||||
ESP_LOGI(TAG, "OTA complete, total bytes: %d", ota_bytes_written);
|
||||
|
||||
err = esp_ota_end(update_handle);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "OTA end failed: %s", esp_err_to_name(err));
|
||||
break;
|
||||
}
|
||||
|
||||
err = esp_ota_set_boot_partition(update_partition);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "OTA set boot partition failed: %s", esp_err_to_name(err));
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset configuration
|
||||
control_reset_config();
|
||||
|
||||
ESP_LOGI(TAG, "OTA successful, restarting...");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
|
||||
if (!param->write.is_prep)
|
||||
{
|
||||
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id,
|
||||
ESP_GATT_OK, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize BLE
|
||||
static esp_err_t init_ble(void)
|
||||
{
|
||||
if (!ble_enabled)
|
||||
{
|
||||
ESP_LOGI(TAG, "BLE disabled by configuration");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
|
||||
// Initialize BT controller
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
ret = esp_bt_controller_init(&bt_cfg);
|
||||
if (ret)
|
||||
{
|
||||
ESP_LOGE(TAG, "BT controller init failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||
if (ret)
|
||||
{
|
||||
ESP_LOGE(TAG, "BT controller enable failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bluedroid_init();
|
||||
if (ret)
|
||||
{
|
||||
ESP_LOGE(TAG, "Bluedroid init failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bluedroid_enable();
|
||||
if (ret)
|
||||
{
|
||||
ESP_LOGE(TAG, "Bluedroid enable failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Register callbacks
|
||||
esp_ble_gatts_register_callback(gatts_event_handler);
|
||||
esp_ble_gap_register_callback(gap_event_handler);
|
||||
esp_ble_gatts_app_register(0);
|
||||
|
||||
// Set MTU
|
||||
esp_ble_gatt_set_local_mtu(517);
|
||||
|
||||
// Start timeout timer
|
||||
start_ble_timeout();
|
||||
|
||||
esp_ble_gatts_app_register(0);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
|
||||
ESP_LOGI(TAG, "BLE initialized");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Main initialization
|
||||
esp_err_t control_init(void)
|
||||
{
|
||||
@ -669,17 +207,18 @@ esp_err_t control_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Register mode change callback
|
||||
rcsignal_register_callback(on_mode_change);
|
||||
|
||||
// Initialize BLE
|
||||
ret = init_ble();
|
||||
// Initialize local BTN
|
||||
ret = localbtn_init();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "BLE init failed: %s", esp_err_to_name(ret));
|
||||
ESP_LOGE(TAG, "Local BTN init failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Register mode change callback
|
||||
rcsignal_register_callback(on_mode_change);
|
||||
localbtn_register_callback(on_mode_change);
|
||||
|
||||
ESP_LOGI(TAG, "Control system initialized successfully");
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file control.h
|
||||
* @brief Control module for LED controller - handles initialization of LEDs, PWM, and Bluetooth
|
||||
* @brief Control module for LED controller - handles initialization of LEDs, PWM
|
||||
*/
|
||||
|
||||
#ifndef CONTROL_H
|
||||
@ -10,24 +10,15 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @brief BLE auto-off timeout options
|
||||
*/
|
||||
typedef enum {
|
||||
BLE_TIMEOUT_NEVER = 0,
|
||||
BLE_TIMEOUT_1MIN = 60,
|
||||
BLE_TIMEOUT_5MIN = 300
|
||||
} ble_timeout_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration structure stored in NVS
|
||||
*/
|
||||
typedef struct {
|
||||
int8_t led_pin_strip_a; // GPIO pin for LED strip A (-1 = not configured)
|
||||
int8_t led_pin_strip_b; // GPIO pin for LED strip B (-1 = not configured)
|
||||
int8_t pwm_pin; // GPIO pin for PWM input (-1 = not configured)
|
||||
ble_timeout_t ble_timeout; // BLE auto-off timeout
|
||||
uint32_t magic; // Magic number to validate config (0xDEADBEEF)
|
||||
typedef struct
|
||||
{
|
||||
int8_t led_pin_strip_a; // GPIO pin for LED strip A (-1 = not configured)
|
||||
int8_t led_pin_strip_b; // GPIO pin for LED strip B (-1 = not configured)
|
||||
int8_t pwm_pin; // GPIO pin for PWM input (-1 = not configured)
|
||||
uint32_t magic; // Magic number to validate config (0xDEADBEEF)
|
||||
} controller_config_t;
|
||||
|
||||
/**
|
||||
@ -41,14 +32,14 @@ esp_err_t control_init(void);
|
||||
* @brief Get current configuration
|
||||
* @return Pointer to current configuration (read-only)
|
||||
*/
|
||||
const controller_config_t* control_get_config(void);
|
||||
const controller_config_t *control_get_config(void);
|
||||
|
||||
/**
|
||||
* @brief Update configuration and save to NVS
|
||||
* @param config New configuration
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t control_update_config(const controller_config_t* config);
|
||||
esp_err_t control_update_config(const controller_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Reset configuration to defaults
|
||||
@ -56,22 +47,6 @@ esp_err_t control_update_config(const controller_config_t* config);
|
||||
*/
|
||||
esp_err_t control_reset_config(void);
|
||||
|
||||
/**
|
||||
* @brief Get BLE enabled status
|
||||
* @return true if BLE is enabled
|
||||
*/
|
||||
bool control_is_ble_enabled(void);
|
||||
|
||||
/**
|
||||
* @brief Manually disable BLE
|
||||
*/
|
||||
void control_disable_ble(void);
|
||||
|
||||
/**
|
||||
* @brief Emulate PWM pulse (for web button)
|
||||
*/
|
||||
void control_emulate_pwm_pulse(void);
|
||||
|
||||
/**
|
||||
* @brief Set animation mode manually
|
||||
* @param mode Animation mode (0-13)
|
||||
|
||||
85
main/localbtn.c
Normal file
85
main/localbtn.c
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @file localbtn.c
|
||||
* @brief Local GPIO0 BTN reading implementation using edge capture
|
||||
*/
|
||||
|
||||
#include "localbtn.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/gpio_num.h"
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "LOCALBTN";
|
||||
uint8_t current_mode;
|
||||
localbtn_mode_change_callback_t callback;
|
||||
|
||||
#define BOOT_BTN GPIO_NUM_0
|
||||
#define MAX_MODES 14 // TODO: get from control
|
||||
|
||||
bool boot_button_pressed(void)
|
||||
{
|
||||
return gpio_get_level(BOOT_BTN) == 0; // active LOW
|
||||
}
|
||||
|
||||
static void monitor_task(void *arg)
|
||||
{
|
||||
bool lastState = false;
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
bool currentState = boot_button_pressed();
|
||||
if ((currentState) && (lastState != currentState))
|
||||
{
|
||||
printf("BOOT button pressed\n");
|
||||
|
||||
current_mode = (current_mode + 1) % MAX_MODES;
|
||||
|
||||
ESP_LOGI(TAG, "Mode changed to: %d ", current_mode);
|
||||
|
||||
if (callback)
|
||||
{
|
||||
callback(current_mode);
|
||||
}
|
||||
}
|
||||
|
||||
lastState = currentState;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t localbtn_init()
|
||||
{
|
||||
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = 1ULL << BOOT_BTN,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE, // safe even if external pull-up exists
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE};
|
||||
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||
|
||||
// Create monitor task
|
||||
BaseType_t ret = xTaskCreate(monitor_task, "localbtn_monitor", 2048, NULL, 5, NULL);
|
||||
if (ret != pdPASS)
|
||||
{
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// TODO: rcsignal.initialized = true;
|
||||
ESP_LOGI(TAG, "local btn initialized on GPIO%d", BOOT_BTN);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void localbtn_deinit(void)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void localbtn_register_callback(localbtn_mode_change_callback_t cb)
|
||||
{
|
||||
callback = cb;
|
||||
}
|
||||
36
main/localbtn.h
Normal file
36
main/localbtn.h
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file localbtn.h
|
||||
* @brief Local GPIO0 BTN reading implementation using edge capture
|
||||
*/
|
||||
|
||||
#ifndef LOCALBTN_H
|
||||
#define LOCALBTN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Callback function type for mode changes
|
||||
* @param new_mode New animation mode (0-13)
|
||||
*/
|
||||
typedef void (*localbtn_mode_change_callback_t)(uint8_t new_mode);
|
||||
|
||||
/**
|
||||
* @brief Initialize local btn reading
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t localbtn_init();
|
||||
|
||||
/**
|
||||
* @brief Deinitialize local btn reading
|
||||
*/
|
||||
void localbtn_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Register callback for mode changes
|
||||
* @param callback Callback function
|
||||
*/
|
||||
void localbtn_register_callback(localbtn_mode_change_callback_t cb);
|
||||
|
||||
#endif // LOCALBTN_H
|
||||
12
main/main.c
12
main/main.c
@ -44,7 +44,7 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, " ESP32 LED Controller for Model Aircraft");
|
||||
ESP_LOGI(TAG, "==============================================");
|
||||
|
||||
// Initialize control system (LEDs, PWM, BLE)
|
||||
// Initialize control system (LEDs, PWM)
|
||||
esp_err_t ret = control_init();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
@ -56,6 +56,8 @@ void app_main(void)
|
||||
}
|
||||
}
|
||||
|
||||
control_reset_config();
|
||||
|
||||
// Create animation update task
|
||||
BaseType_t task_ret = xTaskCreate(
|
||||
animation_task,
|
||||
@ -76,8 +78,6 @@ void app_main(void)
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "System initialized successfully");
|
||||
ESP_LOGI(TAG, "BLE Device Name: LED-Controller");
|
||||
ESP_LOGI(TAG, "Connect via Web-BLE to configure");
|
||||
|
||||
// Main loop - just monitor system status
|
||||
while (1)
|
||||
@ -85,10 +85,6 @@ void app_main(void)
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
|
||||
// Periodic status logging
|
||||
//const controller_config_t *config = control_get_config();
|
||||
ESP_LOGI(TAG, "Status - Mode: %d, BLE: %s, PWM Active: %s",
|
||||
control_get_animation_mode(),
|
||||
control_is_ble_enabled() ? "ON" : "OFF",
|
||||
"N/A"); // Could add rcsignal_is_active() here
|
||||
ESP_LOGI(TAG, "Status - Mode: %d", control_get_animation_mode());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user