Add selectable ESP-NOW send path for accel/tap input.
Expose best_effort/fast/wait/reliable via UART, dashboard, and CLI so loss vs latency can be compared under real multi-pod load. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+66
-7
@@ -24,9 +24,9 @@
|
||||
/** While master or slave OTA is in progress (discover may be sparse). */
|
||||
#define SLAVE_MASTER_OTA_GRACE_MS 300000u
|
||||
/**
|
||||
* Best-effort gaming input cadence (loss OK; send_best_effort).
|
||||
* Must be >= one FreeRTOS tick (CONFIG_FREERTOS_HZ=100 → 10 ms); shorter
|
||||
* values become 0 ticks and assert in vTaskDelayUntil.
|
||||
* Accel stream cadence. TX path is selectable (INPUT_SEND_MODE; default
|
||||
* best_effort). Must be >= one FreeRTOS tick (CONFIG_FREERTOS_HZ=100 → 10 ms);
|
||||
* shorter values become 0 ticks and assert in vTaskDelayUntil.
|
||||
*/
|
||||
#define ESPNOW_ACCEL_INTERVAL_MS 10
|
||||
#define ESPNOW_BATTERY_INTERVAL_MS 30000
|
||||
@@ -40,6 +40,9 @@ static bool s_accel_stream_enabled;
|
||||
static bool s_tap_notify_single;
|
||||
static bool s_tap_notify_double;
|
||||
static bool s_tap_notify_triple;
|
||||
/** Accel/tap TX path; default matches historical best-effort gaming input. */
|
||||
static uint32_t s_input_send_mode =
|
||||
(uint32_t)alox_InputSendMode_INPUT_SEND_BEST_EFFORT;
|
||||
static uint8_t s_master_mac[ESP_NOW_ETH_ALEN];
|
||||
static uint32_t s_last_discover_ms;
|
||||
/** Logical id assigned by current/last master (0 = unbound). */
|
||||
@@ -161,6 +164,21 @@ static void send_presence(const uint8_t *dest_mac, alox_EspNowMessageType type)
|
||||
esp_now_core_send(dest_mac, &msg);
|
||||
}
|
||||
|
||||
static esp_err_t send_input_message(const uint8_t *dest_mac,
|
||||
const alox_EspNowMessage *msg) {
|
||||
switch (s_input_send_mode) {
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_FAST:
|
||||
return esp_now_core_send_fast(dest_mac, msg);
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_WAIT:
|
||||
return esp_now_core_send_wait(dest_mac, msg);
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_RELIABLE:
|
||||
return esp_now_core_send_reliable(dest_mac, msg);
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_BEST_EFFORT:
|
||||
default:
|
||||
return esp_now_core_send_best_effort(dest_mac, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t send_accel_sample(const uint8_t *dest_mac, uint32_t slave_id,
|
||||
int16_t x, int16_t y, int16_t z) {
|
||||
alox_EspNowMessage msg = alox_EspNowMessage_init_zero;
|
||||
@@ -170,8 +188,7 @@ static esp_err_t send_accel_sample(const uint8_t *dest_mac, uint32_t slave_id,
|
||||
msg.payload.accel_sample.x = x;
|
||||
msg.payload.accel_sample.y = y;
|
||||
msg.payload.accel_sample.z = z;
|
||||
/* Fire-and-forget: controller input prefers low latency over delivery. */
|
||||
return esp_now_core_send_best_effort(dest_mac, &msg);
|
||||
return send_input_message(dest_mac, &msg);
|
||||
}
|
||||
|
||||
static esp_err_t send_tap_event(const uint8_t *dest_mac, uint32_t slave_id,
|
||||
@@ -181,7 +198,7 @@ static esp_err_t send_tap_event(const uint8_t *dest_mac, uint32_t slave_id,
|
||||
msg.which_payload = alox_EspNowMessage_tap_event_tag;
|
||||
msg.payload.tap_event.slave_id = slave_id;
|
||||
msg.payload.tap_event.kind = kind;
|
||||
return esp_now_core_send_best_effort(dest_mac, &msg);
|
||||
return send_input_message(dest_mac, &msg);
|
||||
}
|
||||
|
||||
static esp_err_t send_battery_report(const uint8_t *dest_mac,
|
||||
@@ -429,6 +446,43 @@ static void handle_accel_stream(const uint8_t *master_mac,
|
||||
cfg->enable ? "on" : "off", mac_str, (unsigned long)my_client_id());
|
||||
}
|
||||
|
||||
static const char *input_send_mode_name(uint32_t mode) {
|
||||
switch (mode) {
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_BEST_EFFORT:
|
||||
return "best_effort";
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_FAST:
|
||||
return "fast";
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_WAIT:
|
||||
return "wait";
|
||||
case (uint32_t)alox_InputSendMode_INPUT_SEND_RELIABLE:
|
||||
return "reliable";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_input_send_mode(const uint8_t *master_mac,
|
||||
const alox_EspNowInputSendMode *cfg) {
|
||||
if (!client_id_matches(cfg->client_id)) {
|
||||
return;
|
||||
}
|
||||
if (s_joined && !esp_now_core_mac_equal(master_mac, s_master_mac)) {
|
||||
return;
|
||||
}
|
||||
if (cfg->mode > (uint32_t)alox_InputSendMode_INPUT_SEND_RELIABLE) {
|
||||
ESP_LOGW(TAG, "input send mode %lu invalid (id=%lu)",
|
||||
(unsigned long)cfg->mode, (unsigned long)my_client_id());
|
||||
return;
|
||||
}
|
||||
s_input_send_mode = cfg->mode;
|
||||
char mac_str[18];
|
||||
esp_now_core_mac_to_str(master_mac, mac_str, sizeof(mac_str));
|
||||
ESP_LOGI(TAG, "input send mode %s (%lu) from master %s (id=%lu)",
|
||||
input_send_mode_name(s_input_send_mode),
|
||||
(unsigned long)s_input_send_mode, mac_str,
|
||||
(unsigned long)my_client_id());
|
||||
}
|
||||
|
||||
static void handle_tap_notify(const uint8_t *master_mac,
|
||||
const alox_EspNowTapNotify *cfg) {
|
||||
if (!client_id_matches(cfg->client_id)) {
|
||||
@@ -585,7 +639,7 @@ static void check_master_timeout(void) {
|
||||
static void accel_stream_task(void *param) {
|
||||
(void)param;
|
||||
|
||||
ESP_LOGI(TAG, "accel stream task (interval %u ms, best-effort)",
|
||||
ESP_LOGI(TAG, "accel stream task (interval %u ms, mode selectable)",
|
||||
(unsigned)ESPNOW_ACCEL_INTERVAL_MS);
|
||||
|
||||
TickType_t last_wake = xTaskGetTickCount();
|
||||
@@ -733,6 +787,11 @@ void esp_now_slave_on_recv(const esp_now_recv_info_t *info, const uint8_t *data,
|
||||
handle_tap_notify(info->src_addr, &msg.payload.tap_notify);
|
||||
}
|
||||
break;
|
||||
case alox_EspNowMessage_input_send_mode_tag:
|
||||
if (from_joined_master(info->src_addr)) {
|
||||
handle_input_send_mode(info->src_addr, &msg.payload.input_send_mode);
|
||||
}
|
||||
break;
|
||||
case alox_EspNowMessage_battery_query_tag:
|
||||
if (from_joined_master(info->src_addr)) {
|
||||
handle_battery_query(info->src_addr, &msg.payload.battery_query);
|
||||
|
||||
Reference in New Issue
Block a user