From 27733d9c70f09c04e3a93e3a777e10bd2c355eb8 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Sat, 18 Nov 2023 12:10:18 -0600 Subject: [PATCH 01/10] adding generic timer --- hardware/targets.json | 11 ++ lib/MSP/msptypes.h | 1 + lib/WIFI/devWIFI.cpp | 13 +- lib/config/config.cpp | 96 +++++++++ lib/config/config.h | 47 +++++ platformio.ini | 1 + src/Timer_main.cpp | 451 ++++++++++++++++++++++++++++++++++++++++++ targets/common.ini | 24 ++- targets/debug.ini | 17 ++ targets/timer_esp.ini | 15 ++ 10 files changed, 667 insertions(+), 9 deletions(-) create mode 100644 src/Timer_main.cpp create mode 100644 targets/timer_esp.ini diff --git a/hardware/targets.json b/hardware/targets.json index 6211d81..018fb86 100644 --- a/hardware/targets.json +++ b/hardware/targets.json @@ -385,5 +385,16 @@ "platform": "esp8285" } } + }, + "timer": { + "name": "Generic backpack for any Race Timer", + "timer": { + "esp32": { + "product_name": "RotorHazard ESP32 (DIY)", + "firmware": "ESP_TIMER_Backpack", + "upload_methods": ["uart", "wifi"], + "platform": "esp32" + } + } } } diff --git a/lib/MSP/msptypes.h b/lib/MSP/msptypes.h index dea1621..f56329b 100644 --- a/lib/MSP/msptypes.h +++ b/lib/MSP/msptypes.h @@ -20,6 +20,7 @@ #define MSP_ELRS_SET_RX_LOAN_MODE 0x0F #define MSP_ELRS_GET_BACKPACK_VERSION 0x10 #define MSP_ELRS_BACKPACK_CRSF_TLM 0x11 +#define MSP_ELRS_SET_SEND_UID 0x00B5 #define MSP_ELRS_SET_OSD 0x00B6 // CRSF encapsulated msp defines diff --git a/lib/WIFI/devWIFI.cpp b/lib/WIFI/devWIFI.cpp index 71813e5..e4ca29c 100644 --- a/lib/WIFI/devWIFI.cpp +++ b/lib/WIFI/devWIFI.cpp @@ -33,8 +33,12 @@ #if defined(TARGET_VRX_BACKPACK) extern VrxBackpackConfig config; extern bool sendRTCChangesToVrx; -#else +#elif defined(TARGET_TX_BACKPACK) extern TxBackpackConfig config; +#elif defined(TARGET_TIMER_BACKPACK) +extern TimerBackpackConfig config; +#else +#error Unknown target #endif extern unsigned long rebootTime; @@ -44,6 +48,9 @@ static const char *wifi_ap_ssid = "ExpressLRS VRx Backpack"; #elif defined(TARGET_TX_BACKPACK) static const char *myHostname = "elrs_txbp"; static const char *wifi_ap_ssid = "ExpressLRS TX Backpack"; +#elif defined(TARGET_TIMER_BACKPACK) +static const char *myHostname = "elrs_timerbp"; +static const char *wifi_ap_ssid = "ExpressLRS Timer Backpack"; #else #error Unknown target #endif @@ -509,6 +516,8 @@ static void startMDNS() MDNS.addServiceTxt(service, "type", "vrx"); #elif defined(TARGET_TX_BACKPACK) MDNS.addServiceTxt(service, "type", "txbp"); + #elif defined(TARGET_TIMER_BACKPACK) + MDNS.addServiceTxt(service, "type", "timer"); #endif // If the probe result fails because there is another device on the network with the same name // use our unique instance name as the hostname. A better way to do this would be to use @@ -530,6 +539,8 @@ static void startMDNS() MDNS.addServiceTxt("http", "tcp", "type", "vrx"); #elif defined(TARGET_TX_BACKPACK) MDNS.addServiceTxt("http", "tcp", "type", "txbp"); + #elif defined(TARGET_TIMER_BACKPACK) + MDNS.addServiceTxt("http", "tcp", "type", "timer"); #endif #endif } diff --git a/lib/config/config.cpp b/lib/config/config.cpp index 0fc1266..33d3c54 100644 --- a/lib/config/config.cpp +++ b/lib/config/config.cpp @@ -181,3 +181,99 @@ VrxBackpackConfig::SetStartWiFiOnBoot(bool startWifi) } #endif + +///////////////////////////////////////////////////// + +#if defined(TARGET_TIMER_BACKPACK) + +void +TimerBackpackConfig::Load() +{ + m_eeprom->Get(0, m_config); + m_modified = 0; + + // Check if version number matches + if (m_config.version != (uint32_t)(TX_BACKPACK_CONFIG_VERSION | TX_BACKPACK_CONFIG_MAGIC)) + { + // If not, revert to defaults for this version + DBGLN("EEPROM version mismatch! Resetting to defaults..."); + SetDefaults(); + } + + m_modified = false; +} + +void +TimerBackpackConfig::Commit() +{ + if (!m_modified) + { + // No changes + return; + } + // Write the struct to eeprom + m_eeprom->Put(0, m_config); + m_eeprom->Commit(); + + m_modified = false; +} + +// Setters +void +TimerBackpackConfig::SetStorageProvider(ELRS_EEPROM *eeprom) +{ + if (eeprom) + { + m_eeprom = eeprom; + } +} + +void +TimerBackpackConfig::SetDefaults() +{ + m_config.version = TX_BACKPACK_CONFIG_VERSION | TX_BACKPACK_CONFIG_MAGIC; + m_config.bootCount = 0; + m_config.startWiFi = false; + m_config.ssid[0] = 0; + m_config.password[0] = 0; + memset(m_config.address, 0, 6); + m_modified = true; + Commit(); +} + +void +TimerBackpackConfig::SetStartWiFiOnBoot(bool startWifi) +{ + m_config.startWiFi = startWifi; + m_modified = true; +} + +void +TimerBackpackConfig::SetSSID(const char *ssid) +{ + strcpy(m_config.ssid, ssid); + m_modified = true; +} + +void +TimerBackpackConfig::SetPassword(const char *password) +{ + strcpy(m_config.password, password); + m_modified = true; +} + +void +TimerBackpackConfig::SetGroupAddress(const uint8_t address[6]) +{ + memcpy(m_config.address, address, 6); + m_modified = true; +} + +void +TimerBackpackConfig::SetBootCount(uint8_t count) +{ + m_config.bootCount = count; + m_modified = true; +} + +#endif \ No newline at end of file diff --git a/lib/config/config.h b/lib/config/config.h index ae8f9e1..8eb66b3 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -5,9 +5,11 @@ // CONFIG_MAGIC is ORed with CONFIG_VERSION in the version field #define TX_BACKPACK_CONFIG_MAGIC (0b01 << 30) #define VRX_BACKPACK_CONFIG_MAGIC (0b10 << 30) +#define TIMER_BACKPACK_CONFIG_MAGIC (0b01 << 30) #define TX_BACKPACK_CONFIG_VERSION 3 #define VRX_BACKPACK_CONFIG_VERSION 3 +#define TIMER_BACKPACK_CONFIG_VERSION 3 #if defined(TARGET_TX_BACKPACK) typedef struct { @@ -93,3 +95,48 @@ class VrxBackpackConfig extern VrxBackpackConfig config; #endif + +/////////////////////////////////////////////////// + +#if defined(TARGET_TIMER_BACKPACK) +typedef struct { + uint32_t version; + uint8_t bootCount; + bool startWiFi; + char ssid[33]; + char password[65]; + uint8_t address[6]; +} timer_backpack_config_t; + +class TimerBackpackConfig +{ +public: + void Load(); + void Commit(); + + // Getters + bool IsModified() const { return m_modified; } + uint8_t GetBootCount() { return m_config.bootCount; } + bool GetStartWiFiOnBoot() { return m_config.startWiFi; } + char *GetSSID() { return m_config.ssid; } + char *GetPassword() { return m_config.password; } + uint8_t *GetGroupAddress() { return m_config.address; } + + // Setters + void SetStorageProvider(ELRS_EEPROM *eeprom); + void SetDefaults(); + void SetBootCount(uint8_t count); + void SetStartWiFiOnBoot(bool startWifi); + void SetSSID(const char *ssid); + void SetPassword(const char *ssid); + void SetGroupAddress(const uint8_t address[6]); + +private: + timer_backpack_config_t m_config; + ELRS_EEPROM *m_eeprom; + bool m_modified; +}; + +extern TimerBackpackConfig config; + +#endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 2b26767..b0a6b9f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,6 +7,7 @@ extra_configs = targets/debug.ini targets/txbp_esp.ini targets/txbp_stm.ini + targets/timer_esp.ini # defined one by one to maintain the order targets/fusion.ini targets/hdzero.ini diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp new file mode 100644 index 0000000..fd5a69d --- /dev/null +++ b/src/Timer_main.cpp @@ -0,0 +1,451 @@ +#include + +#if defined(PLATFORM_ESP8266) + #include + #include +#elif defined(PLATFORM_ESP32) + #include + #include + #include +#endif + +#include "msp.h" +#include "msptypes.h" +#include "logging.h" +#include "config.h" +#include "common.h" +#include "options.h" +#include "helpers.h" + +#include "device.h" +#include "devWIFI.h" +#include "devButton.h" +#include "devLED.h" + +/////////// DEFINES /////////// + +#define BINDING_TIMEOUT 30000 +#define NO_BINDING_TIMEOUT 120000 +#define BINDING_LED_PAUSE 1000 + +/////////// GLOBALS /////////// + +uint8_t sendAddress[6]; + +const uint8_t version[] = {LATEST_VERSION}; + +connectionState_e connectionState = starting; +unsigned long bindingStart = 0; +unsigned long rebootTime = 0; + +bool cacheFull = false; +bool sendCached = false; +bool tempUID = false; +bool isBinding = false; + +device_t *ui_devices[] = { +#ifdef PIN_LED + &LED_device, +#endif +#ifdef PIN_BUTTON + &Button_device, +#endif + &WIFI_device, +}; + +/////////// CLASS OBJECTS /////////// + +MSP msp; +ELRS_EEPROM eeprom; +TimerBackpackConfig config; +mspPacket_t cachedVTXPacket; +mspPacket_t cachedHTPacket; + +/////////// FUNCTION DEFS /////////// + +int sendMSPViaEspnow(mspPacket_t *packet); +void resetBootCounter(); + +///////////////////////////////////// + +#if defined(PLATFORM_ESP32) +// This seems to need to be global, as per this page, +// otherwise we get errors about invalid peer: +// https://rntlab.com/question/espnow-peer-interface-is-invalid/ +esp_now_peer_info_t peerInfo; +#endif + +void RebootIntoWifi() +{ + DBGLN("Rebooting into wifi update mode..."); + config.SetStartWiFiOnBoot(true); + config.Commit(); + rebootTime = millis(); +} + +void ProcessMSPPacketFromPeer(mspPacket_t *packet) +{ + if (connectionState == binding) + { + DBGLN("Processing Binding Packet..."); + if (packet->function == MSP_ELRS_BIND) + { + config.SetGroupAddress(packet->payload); + DBGLN("MSP_ELRS_BIND MAC = "); + for (int i = 0; i < 6; i++) + { + DBG("%x", packet->payload[i]); // Debug prints + DBG(","); + } + DBG(""); // Extra line for serial output readability + resetBootCounter(); + connectionState = running; + rebootTime = millis() + 200; // Add 200ms to allow for any response message(s) to be sent back to device + } + return; + } + + switch (packet->function) { + case MSP_ELRS_BACKPACK_SET_RECORDING_STATE: { + mspPacket_t out; + out.reset(); + out.makeResponse(); + out.function = MSP_ELRS_BACKPACK_SET_RECORDING_STATE; + msp.sendPacket(packet, &Serial); + } + } +} + +// espnow on-receive callback +#if defined(PLATFORM_ESP8266) +void OnDataRecv(uint8_t * mac_addr, uint8_t *data, uint8_t data_len) +#elif defined(PLATFORM_ESP32) +void OnDataRecv(const uint8_t * mac_addr, const uint8_t *data, int data_len) +#endif +{ + DBGLN("ESP NOW DATA:"); + for(int i = 0; i < data_len; i++) + { + if (msp.processReceivedByte(data[i])) + { + // Finished processing a complete packet + // Only process packets from a bound MAC address + if (connectionState == binding || + ( + firmwareOptions.uid[0] == mac_addr[0] && + firmwareOptions.uid[1] == mac_addr[1] && + firmwareOptions.uid[2] == mac_addr[2] && + firmwareOptions.uid[3] == mac_addr[3] && + firmwareOptions.uid[4] == mac_addr[4] && + firmwareOptions.uid[5] == mac_addr[5] + ) + ) + { + ProcessMSPPacketFromPeer(msp.getReceivedPacket()); + } + msp.markPacketReceived(); + } + } + blinkLED(); +} + +void SendVersionResponse() +{ + mspPacket_t out; + out.reset(); + out.makeResponse(); + out.function = MSP_ELRS_BACKPACK_SET_MODE; + for (size_t i = 0 ; i < sizeof(version) ; i++) + { + out.addByte(version[i]); + } + msp.sendPacket(&out, &Serial); +} + +void SendInProgressResponse() +{ + mspPacket_t out; + const uint8_t *response = (const uint8_t *)"P"; + out.reset(); + out.makeResponse(); + out.function = MSP_ELRS_GET_BACKPACK_VERSION; + for (uint32_t i = 0 ; i < 1 ; i++) + { + out.addByte(response[i]); + } + msp.sendPacket(&out, &Serial); +} + +void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) +{ + if (connectionState == binding) + { + DBGLN("Processing Binding Packet..."); + if (packet->function == MSP_ELRS_BIND) + { + config.SetGroupAddress(packet->payload); + DBGLN("MSP_ELRS_BIND MAC = "); + for (int i = 0; i < 6; i++) + { + DBG("%x", packet->payload[i]); // Debug prints + DBG(","); + } + DBG(""); // Extra line for serial output readability + resetBootCounter(); + connectionState = running; + rebootTime = millis() + 200; // Add 200ms to allow for any response message(s) to be sent back to device + } + return; + } + + switch (packet->function) + { + case MSP_ELRS_BACKPACK_SET_MODE: + { + if (packet->payloadSize == 1) + { + if (packet->payload[0] == 'B') + { + DBGLN("Enter binding mode..."); + bindingStart = now; + connectionState = binding; + isBinding = true; + } + else if (packet->payload[0] == 'W') + { + DBGLN("Enter WIFI mode..."); + connectionState = wifiUpdate; + devicesTriggerEvent(); + } + SendInProgressResponse(); + } + } + case MSP_ELRS_GET_BACKPACK_VERSION: + DBGLN("Processing MSP_ELRS_GET_BACKPACK_VERSION..."); + SendVersionResponse(); + break; + case MSP_ELRS_SET_SEND_UID: + DBGLN("Processing MSP_ELRS_SET_SEND_UID..."); + { + uint8_t function = packet->readByte(); + + // Set target Send address + if (function == 0x0001) + { + uint8_t receivedAddress[6]; + receivedAddress[0] = packet->readByte(); + receivedAddress[1] = packet->readByte(); + receivedAddress[2] = packet->readByte(); + receivedAddress[3] = packet->readByte(); + receivedAddress[4] = packet->readByte(); + receivedAddress[5] = packet->readByte(); + + // Register peer address + memset(&peerInfo, 0, sizeof(peerInfo)); + memcpy(peerInfo.peer_addr, receivedAddress, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + esp_now_add_peer(&peerInfo); + + // Set Send address for new target + memset(&sendAddress, 0, sizeof(sendAddress)); + memcpy(sendAddress, receivedAddress, 6); + } + + // Return to normal for recieving messages + else + { + // Unregister Peer + esp_now_del_peer(sendAddress); + + // Set Send address for normal target + memset(&sendAddress, 0, sizeof(sendAddress)); + memcpy(sendAddress, firmwareOptions.uid, 6); + } + + // Configure MAC address + #if defined(PLATFORM_ESP8266) + wifi_set_macaddr(STATION_IF, sendAddress); + #elif defined(PLATFORM_ESP32) + esp_wifi_set_mac(WIFI_IF_STA, sendAddress); + #endif + break; + } + default: + // transparently forward MSP packets via espnow to any subscribers + sendMSPViaEspnow(packet); + break; + } +} + +int sendMSPViaEspnow(mspPacket_t *packet) +{ + int esp_err = -1; + uint8_t packetSize = msp.getTotalPacketSize(packet); + uint8_t nowDataOutput[packetSize]; + + uint8_t result = msp.convertToByteArray(packet, nowDataOutput); + + if (!result) + { + // packet could not be converted to array, bail out + return esp_err; + } + + esp_err = esp_now_send(sendAddress, (uint8_t *) &nowDataOutput, packetSize); + + blinkLED(); + return esp_err; +} + +void SetSoftMACAddress() +{ + DBGLN("EEPROM MAC = "); + for (int i = 0; i < 6; i++) + { + #ifndef MY_UID + memcpy(firmwareOptions.uid, config.GetGroupAddress(), 6); + #endif + DBG("%x", firmwareOptions.uid[i]); // Debug prints + DBG(","); + } + DBGLN(""); // Extra line for serial output readability + + // MAC address can only be set with unicast, so first byte must be even, not odd + firmwareOptions.uid[0] = firmwareOptions.uid[0] & ~0x01; + + WiFi.mode(WIFI_STA); + WiFi.begin("network-name", "pass-to-network", 1); + WiFi.disconnect(); + + // Soft-set the MAC address to the passphrase UID for binding + #if defined(PLATFORM_ESP8266) + wifi_set_macaddr(STATION_IF, firmwareOptions.uid); + #elif defined(PLATFORM_ESP32) + esp_wifi_set_mac(WIFI_IF_STA, firmwareOptions.uid); + #endif +} + +void resetBootCounter() +{ + config.SetBootCount(0); + config.Commit(); +} + +bool BindingExpired(uint32_t now) +{ + return (connectionState == binding) && ((now - bindingStart) > NO_BINDING_TIMEOUT); +} + +#if defined(PLATFORM_ESP8266) +// Called from core's user_rf_pre_init() function (which is called by SDK) before setup() +RF_PRE_INIT() +{ + // Set whether the chip will do RF calibration or not when power up. + // I believe the Arduino core fakes this (byte 114 of phy_init_data.bin) + // to be 1, but the TX power calibration can pull over 300mA which can + // lock up receivers built with a underspeced LDO (such as the EP2 "SDG") + // Option 2 is just VDD33 measurement + #if defined(RF_CAL_MODE) + system_phy_set_powerup_option(RF_CAL_MODE); + #else + system_phy_set_powerup_option(2); + #endif +} +#endif + +void setup() +{ + #ifdef DEBUG_LOG + Serial1.begin(115200); + Serial1.setDebugOutput(true); + #endif + Serial.begin(460800); + + options_init(); + + eeprom.Begin(); + config.SetStorageProvider(&eeprom); + config.Load(); + + devicesInit(ui_devices, ARRAY_SIZE(ui_devices)); + + #ifdef DEBUG_ELRS_WIFI + config.SetStartWiFiOnBoot(true); + #endif + + if (config.GetStartWiFiOnBoot()) + { + config.SetStartWiFiOnBoot(false); + config.Commit(); + connectionState = wifiUpdate; + devicesTriggerEvent(); + } + else + { + SetSoftMACAddress(); + + if (esp_now_init() != 0) + { + DBGLN("Error initializing ESP-NOW"); + rebootTime = millis(); + } + + esp_now_register_recv_cb(OnDataRecv); + } + + devicesStart(); + if (connectionState == starting) + { + connectionState = running; + } + DBGLN("Setup completed"); +} + +void loop() +{ + uint32_t now = millis(); + + devicesUpdate(now); + + if (BindingExpired(now)) + { + connectionState = running; + isBinding = false; + DBGLN("Bind timeout"); + } + if (isBinding && connectionState == running) + { + DBGLN("Bind completed"); + isBinding = false; + } + + #if defined(PLATFORM_ESP8266) || defined(PLATFORM_ESP32) + // If the reboot time is set and the current time is past the reboot time then reboot. + if (rebootTime != 0 && now > rebootTime) { + ESP.restart(); + } + #endif + + if (connectionState == wifiUpdate) + { + return; + } + + if (BindingExpired(now)) + { + connectionState = running; + } + + if (Serial.available()) + { + uint8_t c = Serial.read(); + if (msp.processReceivedByte(c)) + { + // Finished processing a complete packet + ProcessMSPPacketFromTimer(msp.getReceivedPacket(), now); + msp.markPacketReceived(); + } + } + +} diff --git a/targets/common.ini b/targets/common.ini index 84488f7..d951083 100644 --- a/targets/common.ini +++ b/targets/common.ini @@ -51,7 +51,7 @@ build_flags = build_flags = ${common_env_data.build_flags} -D TARGET_TX_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - - # ------------------------- COMMON RAPIDFIRE-BACKPACK DEFINITIONS ----------------- [rapidfire_vrx_backpack_common] @@ -59,7 +59,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D RAPIDFIRE_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON RX5808-BACKPACK DEFINITIONS ----------------- @@ -68,7 +68,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D RX5808_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON STEADYVIEW-BACKPACK DEFINITIONS ----------------- @@ -77,7 +77,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D STEADYVIEW_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON FUSION-BACKPACK DEFINITIONS ----------------- @@ -86,7 +86,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D FUSION_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON HDZERO-BACKPACK DEFINITIONS ----------------- @@ -95,7 +95,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D HDZERO_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON SKYZONE-MSP-BACKPACK DEFINITIONS ----------------- @@ -104,7 +104,7 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D SKYZONE_MSP_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE # ------------------------- COMMON ORQA-BACKPACK DEFINITIONS ------------------- @@ -113,5 +113,13 @@ build_flags = ${common_env_data.build_flags} -D TARGET_VRX_BACKPACK -D ORQA_BACKPACK -build_src_filter = ${common_env_data.build_src_filter} - - - - - - - +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - lib_ignore = STM32UPDATE + +# ------------------------- COMMON TIMER-BACKPACK DEFINITIONS ----------------- +[timer_backpack_common] +build_flags = + ${common_env_data.build_flags} + -D TARGET_TIMER_BACKPACK +build_src_filter = ${common_env_data.build_src_filter} - - - - - - - - - +lib_ignore = STM32UPDATE \ No newline at end of file diff --git a/targets/debug.ini b/targets/debug.ini index 55b8a17..fc6edee 100644 --- a/targets/debug.ini +++ b/targets/debug.ini @@ -47,3 +47,20 @@ lib_ignore = STM32UPDATE [env:DEBUG_ESP32_TX_Backpack_via_WIFI] extends = env:DEBUG_ESP32_TX_Backpack_via_UART + +# ******************************** +# Timer backpack targets +# ******************************** + +[env:DEBUG_ESP_TIMER_Backpack_via_UART] +extends = env_common_esp32, timer_backpack_common +build_flags = + ${env_common_esp32.build_flags} + ${timer_backpack_common.build_flags} + -D DEBUG_LOG + -D PIN_BUTTON=0 + -D PIN_LED=4 +lib_ignore = STM32UPDATE + +[env:DEBUG_ESP_TIMER_Backpack_via_WIFI] +extends = env:DEBUG_ESP_TIMER_Backpack_via_UART \ No newline at end of file diff --git a/targets/timer_esp.ini b/targets/timer_esp.ini new file mode 100644 index 0000000..ca965e0 --- /dev/null +++ b/targets/timer_esp.ini @@ -0,0 +1,15 @@ +# ******************************** +# Timer backpack targets +# ******************************** + +[env:ESP_TIMER_Backpack_via_UART] +extends = env_common_esp32, timer_backpack_common +build_flags = + ${env_common_esp32.build_flags} + ${timer_backpack_common.build_flags} + -D PIN_BUTTON=0 + -D PIN_LED=4 +upload_resetmethod = nodemcu + +[env:ESP_TIMER_Backpack_via_WIFI] +extends = env:ESP_TIMER_Backpack_via_UART From 04cae103f8d1b5b9bd4cf5181dc4e4af82a8fe35 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Sat, 18 Nov 2023 13:48:28 -0600 Subject: [PATCH 02/10] config updates --- lib/config/config.cpp | 4 ++-- lib/config/config.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/config/config.cpp b/lib/config/config.cpp index 33d3c54..4a8b62d 100644 --- a/lib/config/config.cpp +++ b/lib/config/config.cpp @@ -193,7 +193,7 @@ TimerBackpackConfig::Load() m_modified = 0; // Check if version number matches - if (m_config.version != (uint32_t)(TX_BACKPACK_CONFIG_VERSION | TX_BACKPACK_CONFIG_MAGIC)) + if (m_config.version != (uint32_t)(TIMER_BACKPACK_CONFIG_VERSION | TIMER_BACKPACK_CONFIG_MAGIC)) { // If not, revert to defaults for this version DBGLN("EEPROM version mismatch! Resetting to defaults..."); @@ -231,7 +231,7 @@ TimerBackpackConfig::SetStorageProvider(ELRS_EEPROM *eeprom) void TimerBackpackConfig::SetDefaults() { - m_config.version = TX_BACKPACK_CONFIG_VERSION | TX_BACKPACK_CONFIG_MAGIC; + m_config.version = TIMER_BACKPACK_CONFIG_VERSION | TIMER_BACKPACK_CONFIG_MAGIC; m_config.bootCount = 0; m_config.startWiFi = false; m_config.ssid[0] = 0; diff --git a/lib/config/config.h b/lib/config/config.h index 8eb66b3..b33a96c 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -5,7 +5,7 @@ // CONFIG_MAGIC is ORed with CONFIG_VERSION in the version field #define TX_BACKPACK_CONFIG_MAGIC (0b01 << 30) #define VRX_BACKPACK_CONFIG_MAGIC (0b10 << 30) -#define TIMER_BACKPACK_CONFIG_MAGIC (0b01 << 30) +#define TIMER_BACKPACK_CONFIG_MAGIC (0b11 << 30) #define TX_BACKPACK_CONFIG_VERSION 3 #define VRX_BACKPACK_CONFIG_VERSION 3 From f90e7af2a7adf5d40c2131e0c19d8f7a38210d70 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Sun, 19 Nov 2023 21:45:23 -0600 Subject: [PATCH 03/10] SetSoftMACAddress change --- src/Timer_main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index fd5a69d..1841215 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -300,12 +300,13 @@ int sendMSPViaEspnow(mspPacket_t *packet) void SetSoftMACAddress() { - DBGLN("EEPROM MAC = "); - for (int i = 0; i < 6; i++) + if (!firmwareOptions.hasUID) { - #ifndef MY_UID memcpy(firmwareOptions.uid, config.GetGroupAddress(), 6); - #endif + } + DBG("EEPROM MAC = "); + for (int i = 0; i < 6; i++) + { DBG("%x", firmwareOptions.uid[i]); // Debug prints DBG(","); } From efb7ccad79fbd361c9ddc723d71055c05f2f8d12 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Mon, 20 Nov 2023 19:55:52 -0600 Subject: [PATCH 04/10] send to bound backpack --- src/Timer_main.cpp | 54 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index 1841215..e393d3a 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -229,7 +229,7 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) { uint8_t function = packet->readByte(); - // Set target Send address + // Set target send address if (function == 0x0001) { uint8_t receivedAddress[6]; @@ -240,24 +240,50 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) receivedAddress[4] = packet->readByte(); receivedAddress[5] = packet->readByte(); + esp_now_del_peer(sendAddress); + // Register peer address memset(&peerInfo, 0, sizeof(peerInfo)); - memcpy(peerInfo.peer_addr, receivedAddress, 6); - peerInfo.channel = 0; - peerInfo.encrypt = false; - esp_now_add_peer(&peerInfo); + + #if defined(PLATFORM_ESP8266) + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); + esp_now_add_peer(receivedAddress, ESP_NOW_ROLE_COMBO, 1, NULL, 0); + #elif defined(PLATFORM_ESP32) + memcpy(peerInfo.peer_addr, receivedAddress, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + if (esp_now_add_peer(&peerInfo) != ESP_OK) + { + DBGLN("ESP-NOW failed to add peer"); + return; + } + #endif // Set Send address for new target memset(&sendAddress, 0, sizeof(sendAddress)); memcpy(sendAddress, receivedAddress, 6); } - // Return to normal for recieving messages + // Return to bound send address else { // Unregister Peer esp_now_del_peer(sendAddress); + #if defined(PLATFORM_ESP8266) + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); + esp_now_add_peer(firmwareOptions.uid, ESP_NOW_ROLE_COMBO, 1, NULL, 0); + #elif defined(PLATFORM_ESP32) + memcpy(peerInfo.peer_addr, firmwareOptions.uid, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + if (esp_now_add_peer(&peerInfo) != ESP_OK) + { + DBGLN("ESP-NOW failed to add peer"); + return; + } + #endif + // Set Send address for normal target memset(&sendAddress, 0, sizeof(sendAddress)); memcpy(sendAddress, firmwareOptions.uid, 6); @@ -393,6 +419,22 @@ void setup() } esp_now_register_recv_cb(OnDataRecv); + + #if defined(PLATFORM_ESP8266) + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); + esp_now_add_peer(firmwareOptions.uid, ESP_NOW_ROLE_COMBO, 1, NULL, 0); + #elif defined(PLATFORM_ESP32) + memcpy(peerInfo.peer_addr, firmwareOptions.uid, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + if (esp_now_add_peer(&peerInfo) != ESP_OK) + { + DBGLN("ESP-NOW failed to add peer"); + return; + } + #endif + + memcpy(sendAddress, firmwareOptions.uid, 6); } devicesStart(); From 124fd189e2d38e1bd91a96420d123164a37302cc Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Mon, 20 Nov 2023 21:27:33 -0600 Subject: [PATCH 05/10] add timer html --- html/timer_index.html | 121 ++++++++++++++++++++++++++++++++++++++++++ python/build_html.py | 2 + 2 files changed, 123 insertions(+) create mode 100644 html/timer_index.html diff --git a/html/timer_index.html b/html/timer_index.html new file mode 100644 index 0000000..3d421bb --- /dev/null +++ b/html/timer_index.html @@ -0,0 +1,121 @@ + + + + + Welcome to your ExpressLRS System + + + + + + + +
+ +

Welcome to your ExpressLRS update page
+

+

From here you can update your Race Timer Backpack module with @PLATFORM@ firmware
+

+ Firmware Rev. @VERSION@ +

+ +
+
+
+ + + +
+

Backpack Firmware Update

+ Here you can update your backpack firmware, + be careful to upload the correct file otherwise a bad flash may occur. If this happens you will need + to reflash via USB/Serial. +
+
+
+
+ + +
+
+

+ +
+
+ +
+ + + +
+
+
+ + + + + diff --git a/python/build_html.py b/python/build_html.py index a57178e..a788335 100644 --- a/python/build_html.py +++ b/python/build_html.py @@ -63,3 +63,5 @@ def build_common(env, mainfile): build_common(env, "vrx_index.html") elif fnmatch.filter(env['BUILD_FLAGS'], '*TARGET_TX_BACKPACK*'): build_common(env, "txbp_index.html") +elif fnmatch.filter(env['BUILD_FLAGS'], '*TARGET_TIMER_BACKPACK*'): + build_common(env, "timer_index.html") From 5db3111c64690bb77f070104d09bc2255cece8d3 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Tue, 21 Nov 2023 23:03:19 -0600 Subject: [PATCH 06/10] adjust targets & cleaned up peer registering - more generic targets - rotorhazard targets - registerPeer function --- hardware/targets.json | 39 ++++++++++++++++++++-- lib/WIFI/devWIFI.cpp | 2 +- platformio.ini | 2 +- python/binary_flash.py | 21 +++++++++++- src/Timer_main.cpp | 75 +++++++++++++++--------------------------- targets/debug.ini | 6 ++-- targets/timer.ini | 36 ++++++++++++++++++++ targets/timer_esp.ini | 15 --------- 8 files changed, 125 insertions(+), 71 deletions(-) create mode 100644 targets/timer.ini delete mode 100644 targets/timer_esp.ini diff --git a/hardware/targets.json b/hardware/targets.json index 018fb86..4530efd 100644 --- a/hardware/targets.json +++ b/hardware/targets.json @@ -390,10 +390,45 @@ "name": "Generic backpack for any Race Timer", "timer": { "esp32": { - "product_name": "RotorHazard ESP32 (DIY)", - "firmware": "ESP_TIMER_Backpack", + "product_name": "Backpack for Race Timer with ESP32", + "firmware": "TIMER_ESP32_Backpack", "upload_methods": ["uart", "wifi"], "platform": "esp32" + }, + "esp82": { + "product_name": "Backpack for Race Timer with ESP82", + "firmware": "TIMER_ESP82_Backpack", + "upload_methods": ["uart", "wifi"], + "platform": "esp8285" + }, + "esp12f": { + "product_name": "Backpack for Race Timer with ESP12F", + "firmware": "TIMER_ESP12F_Backpack", + "upload_methods": ["uart", "wifi"], + "platform": "esp8285" + } + } + }, + "rotorhazard": { + "name": "RotorHazard", + "timer": { + "esp32": { + "product_name": "ESP32 Module (DIY)", + "firmware": "TIMER_ESP32_Backpack", + "upload_methods": ["uart", "wifi"], + "platform": "esp32" + }, + "esp82": { + "product_name": "EP82 Module (DIY)", + "firmware": "TIMER_ESP82_Backpack", + "upload_methods": ["uart", "wifi"], + "platform": "esp8285" + }, + "NuclearHazard": { + "product_name": "NuclearHazard", + "firmware": "TIMER_ESP32_Backpack", + "upload_methods": ["wifi"], + "platform": "esp32" } } } diff --git a/lib/WIFI/devWIFI.cpp b/lib/WIFI/devWIFI.cpp index e4ca29c..98cd24f 100644 --- a/lib/WIFI/devWIFI.cpp +++ b/lib/WIFI/devWIFI.cpp @@ -49,7 +49,7 @@ static const char *wifi_ap_ssid = "ExpressLRS VRx Backpack"; static const char *myHostname = "elrs_txbp"; static const char *wifi_ap_ssid = "ExpressLRS TX Backpack"; #elif defined(TARGET_TIMER_BACKPACK) -static const char *myHostname = "elrs_timerbp"; +static const char *myHostname = "elrs_timer"; static const char *wifi_ap_ssid = "ExpressLRS Timer Backpack"; #else #error Unknown target diff --git a/platformio.ini b/platformio.ini index b0a6b9f..2933eb5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,7 +7,7 @@ extra_configs = targets/debug.ini targets/txbp_esp.ini targets/txbp_stm.ini - targets/timer_esp.ini + targets/timer.ini # defined one by one to maintain the order targets/fusion.ini targets/hdzero.ini diff --git a/python/binary_flash.py b/python/binary_flash.py index 14ff5a6..30d0f28 100644 --- a/python/binary_flash.py +++ b/python/binary_flash.py @@ -30,6 +30,7 @@ class ElrsUploadResult: class DeviceType(Enum): VRX = 'vrx' TXBP = 'txbp' + TIMER = 'timer' def __str__(self): return self.value @@ -145,6 +146,17 @@ def upload(deviceType: DeviceType, mcuType: MCUType, args): return upload_esp32_uart(args) elif args.flash == UploadMethod.wifi: return upload_wifi(args, mcuType, ['elrs_vrx', 'elrs_vrx.local']) + elif deviceType == DeviceType.TIMER: + if mcuType == MCUType.ESP8266: + if args.flash == UploadMethod.uart: + return upload_esp8266_uart(args) + elif args.flash == UploadMethod.wifi: + return upload_wifi(args, mcuType, ['elrs_timer', 'elrs_timer.local']) + elif mcuType == MCUType.ESP32: + if args.flash == UploadMethod.uart: + return upload_esp32_uart(args) + elif args.flash == UploadMethod.wifi: + return upload_wifi(args, mcuType, ['elrs_timer', 'elrs_timer.local']) else: if mcuType == MCUType.ESP8266: if args.flash == UploadMethod.edgetx: @@ -249,7 +261,14 @@ def main(): json_flags['flash-discriminator'] = randint(1,2**32-1) UnifiedConfiguration.appendToFirmware(args.file, JSONEncoder().encode(json_flags)) - ret = upload(DeviceType.TXBP if hardware == 'txbp' else DeviceType.VRX, mcu, args) + if hardware == 'txbp': + devicetype = DeviceType.TXBP + elif hardware == 'timer': + devicetype = DeviceType.TIMER + else: + devicetype = DeviceType.VRX + + ret = upload(devicetype, mcu, args) sys.exit(ret) if __name__ == '__main__': diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index e393d3a..0c78f1b 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -65,6 +65,7 @@ mspPacket_t cachedHTPacket; int sendMSPViaEspnow(mspPacket_t *packet); void resetBootCounter(); +void registerPeer(uint8_t* address); ///////////////////////////////////// @@ -229,8 +230,11 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) { uint8_t function = packet->readByte(); + // Unregister current peer + esp_now_del_peer(sendAddress); + // Set target send address - if (function == 0x0001) + if (function == 0x01) { uint8_t receivedAddress[6]; receivedAddress[0] = packet->readByte(); @@ -240,24 +244,8 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) receivedAddress[4] = packet->readByte(); receivedAddress[5] = packet->readByte(); - esp_now_del_peer(sendAddress); - - // Register peer address - memset(&peerInfo, 0, sizeof(peerInfo)); - - #if defined(PLATFORM_ESP8266) - esp_now_set_self_role(ESP_NOW_ROLE_COMBO); - esp_now_add_peer(receivedAddress, ESP_NOW_ROLE_COMBO, 1, NULL, 0); - #elif defined(PLATFORM_ESP32) - memcpy(peerInfo.peer_addr, receivedAddress, 6); - peerInfo.channel = 0; - peerInfo.encrypt = false; - if (esp_now_add_peer(&peerInfo) != ESP_OK) - { - DBGLN("ESP-NOW failed to add peer"); - return; - } - #endif + // Register new peer address + registerPeer(receivedAddress); // Set Send address for new target memset(&sendAddress, 0, sizeof(sendAddress)); @@ -267,22 +255,8 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) // Return to bound send address else { - // Unregister Peer - esp_now_del_peer(sendAddress); - - #if defined(PLATFORM_ESP8266) - esp_now_set_self_role(ESP_NOW_ROLE_COMBO); - esp_now_add_peer(firmwareOptions.uid, ESP_NOW_ROLE_COMBO, 1, NULL, 0); - #elif defined(PLATFORM_ESP32) - memcpy(peerInfo.peer_addr, firmwareOptions.uid, 6); - peerInfo.channel = 0; - peerInfo.encrypt = false; - if (esp_now_add_peer(&peerInfo) != ESP_OK) - { - DBGLN("ESP-NOW failed to add peer"); - return; - } - #endif + // Re-register stored address + registerPeer(firmwareOptions.uid); // Set Send address for normal target memset(&sendAddress, 0, sizeof(sendAddress)); @@ -359,6 +333,23 @@ void resetBootCounter() config.Commit(); } +void registerPeer(uint8_t* address){ + #if defined(PLATFORM_ESP8266) + esp_now_set_self_role(ESP_NOW_ROLE_COMBO); + esp_now_add_peer(address, ESP_NOW_ROLE_COMBO, 1, NULL, 0); + #elif defined(PLATFORM_ESP32) + memset(&peerInfo, 0, sizeof(peerInfo)); + memcpy(peerInfo.peer_addr, address, 6); + peerInfo.channel = 0; + peerInfo.encrypt = false; + if (esp_now_add_peer(&peerInfo) != ESP_OK) + { + DBGLN("ESP-NOW failed to add peer"); + return; + } + #endif +} + bool BindingExpired(uint32_t now) { return (connectionState == binding) && ((now - bindingStart) > NO_BINDING_TIMEOUT); @@ -420,19 +411,7 @@ void setup() esp_now_register_recv_cb(OnDataRecv); - #if defined(PLATFORM_ESP8266) - esp_now_set_self_role(ESP_NOW_ROLE_COMBO); - esp_now_add_peer(firmwareOptions.uid, ESP_NOW_ROLE_COMBO, 1, NULL, 0); - #elif defined(PLATFORM_ESP32) - memcpy(peerInfo.peer_addr, firmwareOptions.uid, 6); - peerInfo.channel = 0; - peerInfo.encrypt = false; - if (esp_now_add_peer(&peerInfo) != ESP_OK) - { - DBGLN("ESP-NOW failed to add peer"); - return; - } - #endif + registerPeer(firmwareOptions.uid); memcpy(sendAddress, firmwareOptions.uid, 6); } diff --git a/targets/debug.ini b/targets/debug.ini index fc6edee..cf5bbff 100644 --- a/targets/debug.ini +++ b/targets/debug.ini @@ -52,7 +52,7 @@ extends = env:DEBUG_ESP32_TX_Backpack_via_UART # Timer backpack targets # ******************************** -[env:DEBUG_ESP_TIMER_Backpack_via_UART] +[env:DEBUG_TIMER_ESP32_Backpack_via_UART] extends = env_common_esp32, timer_backpack_common build_flags = ${env_common_esp32.build_flags} @@ -62,5 +62,5 @@ build_flags = -D PIN_LED=4 lib_ignore = STM32UPDATE -[env:DEBUG_ESP_TIMER_Backpack_via_WIFI] -extends = env:DEBUG_ESP_TIMER_Backpack_via_UART \ No newline at end of file +[env:DEBUG_TIMER_ESP32_Backpack_via_WIFI] +extends = env:DEBUG_TIMER_ESP32_Backpack_via_UART \ No newline at end of file diff --git a/targets/timer.ini b/targets/timer.ini new file mode 100644 index 0000000..b220036 --- /dev/null +++ b/targets/timer.ini @@ -0,0 +1,36 @@ +# ******************************** +# Timer backpack targets +# ******************************** + +[env:TIMER_ESP32_Backpack_via_UART] +extends = env_common_esp32, timer_backpack_common +build_flags = + ${env_common_esp32.build_flags} + ${timer_backpack_common.build_flags} + -D PIN_BUTTON=0 + -D PIN_LED=4 + +[env:TIMER_ESP32_Backpack_via_WIFI] +extends = env:TIMER_ESP32_Backpack_via_UART + +[env:TIMER_ESP82_Backpack_via_UART] +extends = env_common_esp8285, timer_backpack_common +build_flags = + ${env_common_esp8285.build_flags} + ${timer_backpack_common.build_flags} + -D PIN_BUTTON=0 + -D PIN_LED=16 + +[env:TIMER_ESP82_Backpack_via_WIFI] +extends = env:TIMER_ESP82_Backpack_via_UART + +[env:TIMER_ESP12F_Backpack_via_UART] +extends = env_common_esp12e, timer_backpack_common +build_flags = + ${env_common_esp12e.build_flags} + ${timer_backpack_common.build_flags} + -D PIN_BUTTON=0 + -D PIN_LED=2 + +[env:TIMER_ESP12F_Backpack_via_WIFI] +extends = env:TIMER_ESP12F_Backpack_via_UART \ No newline at end of file diff --git a/targets/timer_esp.ini b/targets/timer_esp.ini deleted file mode 100644 index ca965e0..0000000 --- a/targets/timer_esp.ini +++ /dev/null @@ -1,15 +0,0 @@ -# ******************************** -# Timer backpack targets -# ******************************** - -[env:ESP_TIMER_Backpack_via_UART] -extends = env_common_esp32, timer_backpack_common -build_flags = - ${env_common_esp32.build_flags} - ${timer_backpack_common.build_flags} - -D PIN_BUTTON=0 - -D PIN_LED=4 -upload_resetmethod = nodemcu - -[env:ESP_TIMER_Backpack_via_WIFI] -extends = env:ESP_TIMER_Backpack_via_UART From 0e383d6cafc5a0e6eba9afdb412e386a8be5f07e Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Tue, 2 Jan 2024 22:09:58 -0600 Subject: [PATCH 07/10] packet queue & send retry on fail --- src/Timer_main.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index 0c78f1b..2fd0946 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -9,6 +9,7 @@ #include #endif +#include #include "msp.h" #include "msptypes.h" #include "logging.h" @@ -37,11 +38,16 @@ const uint8_t version[] = {LATEST_VERSION}; connectionState_e connectionState = starting; unsigned long bindingStart = 0; unsigned long rebootTime = 0; +int maxAttempt = 5; +int sendAttempt = 0; +uint32_t sendTime = 0; bool cacheFull = false; bool sendCached = false; bool tempUID = false; bool isBinding = false; +bool espnowCTS = true; +bool sendSuccess = false; device_t *ui_devices[] = { #ifdef PIN_LED @@ -53,6 +59,8 @@ device_t *ui_devices[] = { &WIFI_device, }; +std::queue sendQueue; + /////////// CLASS OBJECTS /////////// MSP msp; @@ -117,6 +125,26 @@ void ProcessMSPPacketFromPeer(mspPacket_t *packet) } } +#if defined(PLATFORM_ESP8266) +void OnDataSent(uint8_t *mac_addr, uint8_t status) +{ + espnowCTS = true; + if (status == 0) + sendSuccess = true; + else + sendSuccess = false; +} +#elif defined(PLATFORM_ESP32) +void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) +{ + espnowCTS = true; + if (status == ESP_NOW_SEND_SUCCESS) + sendSuccess = true; + else + sendSuccess = false; +} +#endif + // espnow on-receive callback #if defined(PLATFORM_ESP8266) void OnDataRecv(uint8_t * mac_addr, uint8_t *data, uint8_t data_len) @@ -155,7 +183,7 @@ void SendVersionResponse() mspPacket_t out; out.reset(); out.makeResponse(); - out.function = MSP_ELRS_BACKPACK_SET_MODE; + out.function = MSP_ELRS_GET_BACKPACK_VERSION; for (size_t i = 0 ; i < sizeof(version) ; i++) { out.addByte(version[i]); @@ -169,7 +197,7 @@ void SendInProgressResponse() const uint8_t *response = (const uint8_t *)"P"; out.reset(); out.makeResponse(); - out.function = MSP_ELRS_GET_BACKPACK_VERSION; + out.function = MSP_ELRS_BACKPACK_SET_MODE; for (uint32_t i = 0 ; i < 1 ; i++) { out.addByte(response[i]); @@ -409,6 +437,7 @@ void setup() rebootTime = millis(); } + esp_now_register_send_cb(OnDataSent); esp_now_register_recv_cb(OnDataRecv); registerPeer(firmwareOptions.uid); @@ -464,10 +493,42 @@ void loop() uint8_t c = Serial.read(); if (msp.processReceivedByte(c)) { - // Finished processing a complete packet - ProcessMSPPacketFromTimer(msp.getReceivedPacket(), now); + // Store the recieved packet + sendQueue.push(*msp.getReceivedPacket()); msp.markPacketReceived(); } } + // Process packets in sendQueue + if (!sendQueue.empty() && espnowCTS) + { + mspPacket_t *packet = &sendQueue.front(); + uint16_t function = packet->function; + + if (function == MSP_ELRS_GET_BACKPACK_VERSION || + function == MSP_ELRS_BACKPACK_SET_MODE || + function == MSP_ELRS_SET_SEND_UID) + { + ProcessMSPPacketFromTimer(packet, now); + sendQueue.pop(); + } + else if (now - sendTime > 5) + { + if (++sendAttempt > maxAttempt || sendSuccess) + { + espnowCTS = false; + sendAttempt = 0; + ProcessMSPPacketFromTimer(packet, now); + sendTime = now; + sendQueue.pop(); + } + else + { + espnowCTS = false; + ProcessMSPPacketFromTimer(packet, now); + sendTime = now; + } + } + } + } From 80bb51fd7262e2f6d264a58baccced99b09bfd14 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Wed, 3 Apr 2024 20:52:35 -0500 Subject: [PATCH 08/10] Timer Changes - Add recieving queues for timer and HDZero Gogggles - Switched Timer queue(s) to FreeRTOS - Checking incoming serial buffer before reset - Reset ESP32 only when queues are empty - Synchronization of esp32 multi-core actions (wifi & main loop) --- src/Timer_main.cpp | 142 ++++++++++++++++++++++++++------------------- src/Vrx_main.cpp | 40 ++++++++++--- 2 files changed, 115 insertions(+), 67 deletions(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index 2fd0946..02a8dc2 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -9,7 +9,6 @@ #include #endif -#include #include "msp.h" #include "msptypes.h" #include "logging.h" @@ -38,9 +37,6 @@ const uint8_t version[] = {LATEST_VERSION}; connectionState_e connectionState = starting; unsigned long bindingStart = 0; unsigned long rebootTime = 0; -int maxAttempt = 5; -int sendAttempt = 0; -uint32_t sendTime = 0; bool cacheFull = false; bool sendCached = false; @@ -59,7 +55,13 @@ device_t *ui_devices[] = { &WIFI_device, }; -std::queue sendQueue; +#if defined(PLATFORM_ESP32) + int maxAttempt = 5; + int sendAttempt = 0; + QueueHandle_t rxqueue = xQueueCreate(10, sizeof(mspPacket_t)); + QueueHandle_t txqueue = xQueueCreate(500, sizeof(mspPacket_t)); + SemaphoreHandle_t semaphore = xSemaphoreCreateBinary(); +#endif /////////// CLASS OBJECTS /////////// @@ -125,24 +127,17 @@ void ProcessMSPPacketFromPeer(mspPacket_t *packet) } } -#if defined(PLATFORM_ESP8266) -void OnDataSent(uint8_t *mac_addr, uint8_t status) -{ - espnowCTS = true; - if (status == 0) - sendSuccess = true; - else - sendSuccess = false; -} -#elif defined(PLATFORM_ESP32) -void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) -{ - espnowCTS = true; - if (status == ESP_NOW_SEND_SUCCESS) - sendSuccess = true; - else - sendSuccess = false; -} +#if defined(PLATFORM_ESP32) + void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) + { + xSemaphoreTake(semaphore, (TickType_t)512); + espnowCTS = true; + if (status == ESP_NOW_SEND_SUCCESS) + sendSuccess = true; + else + sendSuccess = false; + xSemaphoreGive(semaphore); + } #endif // espnow on-receive callback @@ -170,7 +165,11 @@ void OnDataRecv(const uint8_t * mac_addr, const uint8_t *data, int data_len) ) ) { - ProcessMSPPacketFromPeer(msp.getReceivedPacket()); + #if defined(PLATFORM_ESP8266) + ProcessMSPPacket(msp.getReceivedPacket()); + #elif defined(PLATFORM_ESP32) + xQueueSend(rxqueue, msp.getReceivedPacket(), (TickType_t)1024); + #endif } msp.markPacketReceived(); } @@ -437,9 +436,13 @@ void setup() rebootTime = millis(); } - esp_now_register_send_cb(OnDataSent); esp_now_register_recv_cb(OnDataRecv); - + + #if defined(PLATFORM_ESP32) + esp_now_register_send_cb(OnDataSent); + xSemaphoreGive(semaphore); + #endif + registerPeer(firmwareOptions.uid); memcpy(sendAddress, firmwareOptions.uid, 6); @@ -471,13 +474,6 @@ void loop() isBinding = false; } - #if defined(PLATFORM_ESP8266) || defined(PLATFORM_ESP32) - // If the reboot time is set and the current time is past the reboot time then reboot. - if (rebootTime != 0 && now > rebootTime) { - ESP.restart(); - } - #endif - if (connectionState == wifiUpdate) { return; @@ -488,47 +484,75 @@ void loop() connectionState = running; } - if (Serial.available()) + while (Serial.available()) { uint8_t c = Serial.read(); if (msp.processReceivedByte(c)) { - // Store the recieved packet - sendQueue.push(*msp.getReceivedPacket()); + #if defined(PLATFORM_ESP8266) + ProcessMSPPacketFromTimer(msp.getReceivedPacket(), now); + #elif defined(PLATFORM_ESP32) + xQueueSend(txqueue, msp.getReceivedPacket(), (TickType_t)1024); + #endif msp.markPacketReceived(); } } - // Process packets in sendQueue - if (!sendQueue.empty() && espnowCTS) - { - mspPacket_t *packet = &sendQueue.front(); - uint16_t function = packet->function; + // If the reboot time is set and the current time is past the reboot time then reboot. + #if defined(PLATFORM_ESP8266) + if (rebootTime != 0 && now > rebootTime) + ESP.restart(); + #elif defined(PLATFORM_ESP32) + if (rebootTime != 0 && now > rebootTime && uxQueueMessagesWaiting(txqueue) == 0 && uxQueueMessagesWaiting(rxqueue) == 0) + ESP.restart(); + #endif - if (function == MSP_ELRS_GET_BACKPACK_VERSION || - function == MSP_ELRS_BACKPACK_SET_MODE || - function == MSP_ELRS_SET_SEND_UID) - { - ProcessMSPPacketFromTimer(packet, now); - sendQueue.pop(); - } - else if (now - sendTime > 5) + #if defined(PLATFORM_ESP32) + // Process packets in sendQueue + xSemaphoreTake(semaphore, (TickType_t)512); + if (uxQueueMessagesWaiting(txqueue) > 0 && espnowCTS) { - if (++sendAttempt > maxAttempt || sendSuccess) + mspPacket_t packet; + xQueuePeek(txqueue, &packet, (TickType_t)512); + uint16_t function = packet.function; + + if (function == MSP_ELRS_GET_BACKPACK_VERSION || + function == MSP_ELRS_BACKPACK_SET_MODE || + function == MSP_ELRS_SET_SEND_UID) { - espnowCTS = false; - sendAttempt = 0; - ProcessMSPPacketFromTimer(packet, now); - sendTime = now; - sendQueue.pop(); + xSemaphoreGive(semaphore); + ProcessMSPPacketFromTimer(&packet, now); + xQueueReceive(txqueue, &packet, (TickType_t)512); } else { - espnowCTS = false; - ProcessMSPPacketFromTimer(packet, now); - sendTime = now; + if (++sendAttempt >= maxAttempt || sendSuccess) + { + espnowCTS = false; + xSemaphoreGive(semaphore); + sendAttempt = 0; + ProcessMSPPacketFromTimer(&packet, now); + xQueueReceive(txqueue, &packet, (TickType_t)512); + } + else + { + espnowCTS = false; + xSemaphoreGive(semaphore); + ProcessMSPPacketFromTimer(&packet, now); + } } } - } + else + { + xSemaphoreGive(semaphore); + } + if (uxQueueMessagesWaiting(rxqueue) > 0 && Serial.availableForWrite() == 128) + { + mspPacket_t rxPacket; + if (xQueueReceive(rxqueue, &rxPacket, (TickType_t)512) == pdTRUE) + ProcessMSPPacketFromPeer(&rxPacket); + } + + #endif } diff --git a/src/Vrx_main.cpp b/src/Vrx_main.cpp index d6c7e23..2ca6ddf 100644 --- a/src/Vrx_main.cpp +++ b/src/Vrx_main.cpp @@ -85,6 +85,10 @@ device_t *ui_devices[] = { // otherwise we get errors about invalid peer: // https://rntlab.com/question/espnow-peer-interface-is-invalid/ esp_now_peer_info_t peerInfo; + +// Add FreeRTOS queue for recieving espnow messages +QueueHandle_t rxqueue = xQueueCreate(20, sizeof(mspPacket_t)); + #endif /////////// CLASS OBJECTS /////////// @@ -158,7 +162,11 @@ void OnDataRecv(const uint8_t * mac_addr, const uint8_t *data, int data_len) ) { gotInitialPacket = true; - ProcessMSPPacket(msp.getReceivedPacket()); + #if defined(PLATFORM_ESP8266) + ProcessMSPPacket(msp.getReceivedPacket()); + #elif defined(PLATFORM_ESP32) + xQueueSend(rxqueue, msp.getReceivedPacket(), (TickType_t)1024); + #endif } else { @@ -450,13 +458,19 @@ void loop() devicesUpdate(now); vrxModule.Loop(now); - #if defined(PLATFORM_ESP8266) || defined(PLATFORM_ESP32) - // If the reboot time is set and the current time is past the reboot time then reboot. - if (rebootTime != 0 && now > rebootTime) { - turnOffLED(); - ESP.restart(); - } - #endif + #if defined(PLATFORM_ESP8266) + if (rebootTime != 0 && now > rebootTime) + { + turnOffLED(); + ESP.restart(); + } + #elif defined(PLATFORM_ESP32) + if (rebootTime != 0 && now > rebootTime && uxQueueMessagesWaiting(rxqueue) == 0) + { + turnOffLED(); + ESP.restart(); + } + #endif if (connectionState == wifiUpdate) { @@ -505,4 +519,14 @@ void loop() resetBootCounter(); } #endif + +#if defined(PLATFORM_ESP32) + if (uxQueueMessagesWaiting(rxqueue) > 0 && Serial.availableForWrite() == 128) + { + mspPacket_t rxPacket; + if (xQueueReceive(rxqueue, &rxPacket, (TickType_t)512) == pdTRUE) + ProcessMSPPacket(&rxPacket); + } +#endif + } From e04c7a39f07197c44e7b3fe667b1ca9932764027 Mon Sep 17 00:00:00 2001 From: Bryce Gruber Date: Tue, 23 Apr 2024 22:43:08 -0500 Subject: [PATCH 09/10] removing reboot --- src/Timer_main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index 02a8dc2..6d43c2d 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -111,7 +111,6 @@ void ProcessMSPPacketFromPeer(mspPacket_t *packet) DBG(""); // Extra line for serial output readability resetBootCounter(); connectionState = running; - rebootTime = millis() + 200; // Add 200ms to allow for any response message(s) to be sent back to device } return; } @@ -221,7 +220,6 @@ void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now) DBG(""); // Extra line for serial output readability resetBootCounter(); connectionState = running; - rebootTime = millis() + 200; // Add 200ms to allow for any response message(s) to be sent back to device } return; } From d5a6e2f7729ae13fb11302706656138978e4960a Mon Sep 17 00:00:00 2001 From: Paul Kendall Date: Sun, 28 Apr 2024 16:15:49 +1200 Subject: [PATCH 10/10] Fix compilation on ESP8266 devices --- src/Timer_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Timer_main.cpp b/src/Timer_main.cpp index 6d43c2d..dec612e 100644 --- a/src/Timer_main.cpp +++ b/src/Timer_main.cpp @@ -73,6 +73,7 @@ mspPacket_t cachedHTPacket; /////////// FUNCTION DEFS /////////// +void ProcessMSPPacketFromTimer(mspPacket_t *packet, uint32_t now); int sendMSPViaEspnow(mspPacket_t *packet); void resetBootCounter(); void registerPeer(uint8_t* address); @@ -165,7 +166,7 @@ void OnDataRecv(const uint8_t * mac_addr, const uint8_t *data, int data_len) ) { #if defined(PLATFORM_ESP8266) - ProcessMSPPacket(msp.getReceivedPacket()); + ProcessMSPPacketFromTimer(msp.getReceivedPacket(), millis()); #elif defined(PLATFORM_ESP32) xQueueSend(rxqueue, msp.getReceivedPacket(), (TickType_t)1024); #endif