terseCRSF vendorizzata: rimosse initialise/sbus_initialise/readCrsfFrame/ decodeRC/printPWM/prepSBUS/bytesToPWM/pwmToBytes/sendSBUS e i membri/buffer SBUS-PWM (sb_bytes, pwm_val, crsf_port, sbus_port, RC_BUILD/SBUS machinery). Usiamo solo decodeTelemetry: mantenuti i decoder + helper (bytes2*, wrap360, crc8_dvb_s2[_sbuf_accum] usata dalla patch CRC, printByte/printBytes). ~283 righe in meno, nessun riferimento pendente (verificato con grep su 01/02/03). EspNowCrsf: rimosso sendRaw() e il peer broadcast in begin() (uplink sperimentale morto, il backpack e' downlink-only). Ora RX-only pulito. main.cpp: commento "MAVLink v1" -> "v2" (la lib emette v2). DA VERIFICARE A BANCO con un build (qui non compilabile). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
93 lines
2.6 KiB
C++
93 lines
2.6 KiB
C++
#include "EspNowCrsf.h"
|
|
#include <WiFi.h>
|
|
#include <esp_wifi.h>
|
|
#include <esp_now.h>
|
|
|
|
namespace EspNowCrsf {
|
|
|
|
// ---- Ring buffer dei frame CRSF ----------------------------
|
|
static const uint8_t RING_SLOTS = 8;
|
|
static const uint16_t SLOT_SIZE = 64;
|
|
|
|
struct Slot { uint8_t data[SLOT_SIZE]; uint16_t len; };
|
|
static Slot ring[RING_SLOTS];
|
|
static volatile uint8_t head = 0; // scritto dalla callback
|
|
static volatile uint8_t tail = 0; // letto dal loop
|
|
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
|
|
|
static volatile uint32_t s_received = 0;
|
|
static volatile uint32_t s_dropped = 0;
|
|
|
|
static uint8_t s_uid[6];
|
|
|
|
// ---- Callback ricezione (firma arduino-esp32 core 2.x) -----
|
|
static void onRecv(const uint8_t* mac, const uint8_t* in, int len) {
|
|
if (len <= 8 || in == nullptr) return;
|
|
// keep-alive: type/payload a zero subito dopo l'header di 8 byte
|
|
// (len > 9 prima degli accessi: con len==9 leggere in[9] sarebbe OOB)
|
|
if (len > 9 && in[8] == 0 && in[9] == 0) return;
|
|
|
|
uint16_t crsfLen = len - 8;
|
|
if (crsfLen > SLOT_SIZE) crsfLen = SLOT_SIZE;
|
|
|
|
portENTER_CRITICAL_ISR(&mux);
|
|
uint8_t next = (head + 1) % RING_SLOTS;
|
|
if (next == tail) { // pieno -> scarta il piu' vecchio
|
|
tail = (tail + 1) % RING_SLOTS;
|
|
s_dropped++;
|
|
}
|
|
memcpy(ring[head].data, in + 8, crsfLen);
|
|
ring[head].len = crsfLen;
|
|
head = next;
|
|
s_received++;
|
|
portEXIT_CRITICAL_ISR(&mux);
|
|
}
|
|
|
|
void begin(const uint8_t uid[6]) {
|
|
memcpy(s_uid, uid, 6);
|
|
s_uid[0] &= ~0x01; // MAC unicast
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.disconnect();
|
|
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B);
|
|
esp_wifi_set_mac(WIFI_IF_STA, s_uid);
|
|
esp_wifi_start();
|
|
esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
|
|
|
|
if (esp_now_init() != ESP_OK) return;
|
|
esp_now_register_recv_cb(onRecv);
|
|
}
|
|
|
|
bool poll(uint8_t* out, uint16_t* outLen, uint16_t maxLen) {
|
|
bool got = false;
|
|
portENTER_CRITICAL(&mux);
|
|
if (tail != head) {
|
|
uint16_t n = ring[tail].len;
|
|
if (n > maxLen) n = maxLen;
|
|
memcpy(out, ring[tail].data, n);
|
|
*outLen = n;
|
|
tail = (tail + 1) % RING_SLOTS;
|
|
got = true;
|
|
}
|
|
portEXIT_CRITICAL(&mux);
|
|
return got;
|
|
}
|
|
|
|
uint32_t framesReceived() { return s_received; }
|
|
uint32_t framesDropped() { return s_dropped; }
|
|
|
|
#ifdef UNIT_TEST
|
|
void test_injectRaw(const uint8_t* data, uint16_t len) { onRecv(nullptr, data, len); }
|
|
|
|
void test_reset() {
|
|
portENTER_CRITICAL(&mux);
|
|
head = 0;
|
|
tail = 0;
|
|
s_received = 0;
|
|
s_dropped = 0;
|
|
portEXIT_CRITICAL(&mux);
|
|
}
|
|
#endif
|
|
|
|
} // namespace EspNowCrsf
|