2026-03-30 22:09:23 +01:00
|
|
|
#include "radio.h"
|
2026-04-06 03:39:08 +01:00
|
|
|
|
2026-03-31 17:39:22 +01:00
|
|
|
#include "Esp.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "esp32-hal-gpio.h"
|
2026-04-12 16:52:29 +01:00
|
|
|
#include "esp32-hal-spi.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include "esp_log.h"
|
|
|
|
|
#include "freertos/idf_additions.h"
|
2026-04-06 03:39:08 +01:00
|
|
|
#include "packet_handler.h"
|
2026-03-30 22:09:23 +01:00
|
|
|
#include <RFM69.h>
|
|
|
|
|
#include <SPI.h>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
#include <drone_comms.h>
|
|
|
|
|
|
2026-04-12 16:52:29 +01:00
|
|
|
// Right to left on hardware.
|
|
|
|
|
|
2026-04-13 14:36:24 +01:00
|
|
|
#define RFM69_INT GPIO_NUM_8 // DI0
|
2026-04-18 01:29:08 +01:00
|
|
|
#define RFM69_CS GPIO_NUM_9 // NSS
|
2026-04-13 14:36:24 +01:00
|
|
|
#define RFM69_RST GPIO_NUM_10
|
2026-03-30 22:09:23 +01:00
|
|
|
|
2026-04-18 01:29:08 +01:00
|
|
|
#define RFM69_SCLK GPIO_NUM_11 // SCK
|
|
|
|
|
#define RFM69_MOSI GPIO_NUM_12
|
|
|
|
|
#define RFM69_MISO GPIO_NUM_13
|
|
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
#define FREQUENCY RF69_433MHZ
|
|
|
|
|
#define NODEID 1
|
2026-03-31 17:39:22 +01:00
|
|
|
#define GROUNDID 99
|
2026-03-30 22:09:23 +01:00
|
|
|
#define NETWORKID 100
|
|
|
|
|
|
|
|
|
|
static const char *TAG = "RADIO_TASK";
|
|
|
|
|
|
|
|
|
|
#define PACKET_QUEUE_CAP 10
|
|
|
|
|
|
2026-04-02 18:57:52 +01:00
|
|
|
static bool is_pending_switch = false;
|
|
|
|
|
static uint32_t target_bitrate = 0;
|
|
|
|
|
static uint32_t switch_at_ms = 0;
|
|
|
|
|
static uint32_t rollback_at_ms = 0;
|
|
|
|
|
static bool confirmed_at_new_rate = false;
|
|
|
|
|
|
2026-03-31 17:39:22 +01:00
|
|
|
void radio_task(void *pvParameters) {
|
2026-03-30 22:09:23 +01:00
|
|
|
ESP_LOGI(TAG, "Radio Task Started on Core %d", xPortGetCoreID());
|
2026-03-31 17:39:22 +01:00
|
|
|
packet_rx_queue = xQueueCreate(PACKET_QUEUE_CAP, MAX_PACKET_SIZE);
|
|
|
|
|
packet_tx_queue = xQueueCreate(PACKET_QUEUE_CAP, MAX_PACKET_SIZE);
|
2026-03-30 22:09:23 +01:00
|
|
|
controller_input_semaphore = xSemaphoreCreateMutex();
|
|
|
|
|
|
|
|
|
|
pinMode(RFM69_CS, OUTPUT);
|
|
|
|
|
pinMode(RFM69_INT, INPUT);
|
|
|
|
|
|
2026-04-12 16:52:29 +01:00
|
|
|
SPIClass hspi(HSPI);
|
|
|
|
|
hspi.begin(RFM69_SCLK, RFM69_MISO, RFM69_MOSI, RFM69_CS);
|
2026-03-30 22:09:23 +01:00
|
|
|
|
|
|
|
|
pinMode(RFM69_RST, OUTPUT);
|
|
|
|
|
digitalWrite(RFM69_RST, HIGH);
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
|
|
|
digitalWrite(RFM69_RST, LOW);
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(50));
|
|
|
|
|
|
2026-04-12 16:52:29 +01:00
|
|
|
RFM69 radio(RFM69_CS, RFM69_INT, true, &hspi);
|
2026-03-30 22:09:23 +01:00
|
|
|
|
|
|
|
|
if (radio.initialize(FREQUENCY, NODEID, NETWORKID)) {
|
2026-04-18 13:56:05 +01:00
|
|
|
radio.setPowerLevel(31);
|
2026-03-30 22:09:23 +01:00
|
|
|
radio.setHighPower(true);
|
2026-04-19 15:50:02 +01:00
|
|
|
// radio.setCustomBitrate(DEFAULT_COMMS_BITRATE);
|
2026-03-30 22:09:23 +01:00
|
|
|
ESP_LOGI(TAG, "Radio Initialized. Version: 0x%02X", radio.readReg(0x10));
|
2026-04-11 18:18:50 +01:00
|
|
|
radio.readAllRegsCompact();
|
2026-04-07 10:48:44 +01:00
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
} else {
|
2026-03-31 17:39:22 +01:00
|
|
|
ESP_LOGE(TAG, "Radio Init FAILED! Restarting.");
|
|
|
|
|
ESP.restart();
|
2026-03-30 22:09:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (1) {
|
2026-04-02 18:57:52 +01:00
|
|
|
uint32_t now = millis();
|
|
|
|
|
|
2026-03-30 22:09:23 +01:00
|
|
|
if (radio.receiveDone()) {
|
2026-04-02 18:57:52 +01:00
|
|
|
|
|
|
|
|
// If we receive ANY valid packet while in probation, confirm the switch
|
|
|
|
|
// (Bit-rate switching)
|
|
|
|
|
if (is_pending_switch && now > switch_at_ms) {
|
|
|
|
|
confirmed_at_new_rate = true;
|
|
|
|
|
ESP_LOGI(TAG, "New bitrate confirmed by valid packet.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "Packet [ID:%d] RSSI:%d LEN:%d", radio.SENDERID, radio.RSSI,
|
|
|
|
|
radio.DATALEN);
|
2026-03-30 22:09:23 +01:00
|
|
|
|
|
|
|
|
memset(packet_data, '\0', sizeof(packet_data));
|
|
|
|
|
memcpy(packet_data, radio.DATA, radio.DATALEN);
|
|
|
|
|
|
|
|
|
|
PACKET_TYPE packet_type = *((PACKET_TYPE *)&packet_data[0]);
|
2026-04-02 18:57:52 +01:00
|
|
|
if (packet_type == COMMAND_CHANGE_DATARATE) {
|
|
|
|
|
packet_command_datarate *cmd =
|
|
|
|
|
(packet_command_datarate *)(&packet_data[0] + sizeof(PACKET_TYPE));
|
|
|
|
|
target_bitrate = cmd->target_bitrate;
|
|
|
|
|
|
|
|
|
|
switch_at_ms = now + cmd->ms_delay;
|
|
|
|
|
rollback_at_ms = now + cmd->ms_rollback;
|
|
|
|
|
is_pending_switch = true;
|
|
|
|
|
confirmed_at_new_rate = false;
|
|
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Datarate change requested: %d. Switching in 100ms...",
|
|
|
|
|
target_bitrate);
|
2026-03-30 22:09:23 +01:00
|
|
|
} else {
|
2026-04-19 15:50:02 +01:00
|
|
|
ESP_LOGI(TAG, "RECVD PACKET");
|
2026-03-31 17:39:22 +01:00
|
|
|
xQueueSend(packet_rx_queue, &packet_data[0], portMAX_DELAY);
|
2026-03-30 22:09:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (radio.ACKRequested()) {
|
|
|
|
|
radio.sendACK();
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-02 18:57:52 +01:00
|
|
|
|
|
|
|
|
// Send packets that were queued up for sending
|
2026-03-31 17:39:22 +01:00
|
|
|
if (xQueueReceive(packet_tx_queue, &packet_data[0], 1)) {
|
|
|
|
|
PACKET_TYPE packet_type = *((PACKET_TYPE *)&packet_data[0]);
|
|
|
|
|
radio.send(GROUNDID, &packet_data[0], get_packet_size(packet_type));
|
|
|
|
|
}
|
2026-03-30 22:09:23 +01:00
|
|
|
|
2026-04-02 18:57:52 +01:00
|
|
|
// --- STATE MACHINE FOR BITRATE SWITCHING ---
|
|
|
|
|
|
|
|
|
|
// 1. Execute the Switch
|
|
|
|
|
if (is_pending_switch && now >= switch_at_ms && !confirmed_at_new_rate) {
|
|
|
|
|
// We only want to trigger the register write once
|
|
|
|
|
radio.setCustomBitrate(target_bitrate);
|
|
|
|
|
switch_at_ms = 0xFFFFFFFF; // Prevent re-triggering
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. The Rollback (The Fail-safe)
|
|
|
|
|
if (is_pending_switch && !confirmed_at_new_rate && now > rollback_at_ms) {
|
|
|
|
|
ESP_LOGE(TAG,
|
|
|
|
|
"ROLLBACK: No confirmation at new rate. Reverting to default.");
|
|
|
|
|
radio.setCustomBitrate(DEFAULT_COMMS_BITRATE);
|
|
|
|
|
is_pending_switch = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Clear pending flag once confirmed
|
|
|
|
|
if (confirmed_at_new_rate) {
|
|
|
|
|
is_pending_switch = false;
|
|
|
|
|
confirmed_at_new_rate = false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-19 15:50:02 +01:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(1));
|
2026-03-30 22:09:23 +01:00
|
|
|
}
|
|
|
|
|
}
|