113 lines
3.5 KiB
C
113 lines
3.5 KiB
C
/**
|
||
* @file rf_task.c
|
||
* @brief RF task - NRF24L01 communication
|
||
*/
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include "freertos/FreeRTOS.h"
|
||
#include "freertos/task.h"
|
||
#include "esp_log.h"
|
||
#include "app_main.h"
|
||
|
||
static const char *TAG = "rf";
|
||
|
||
/* NRF24L01 protocol constants (matching AliceRX_STC) */
|
||
#define FRAME_ID_CHANNELS 0xA0
|
||
#define FRAME_ID_TELEMETRY 0xB0
|
||
#define RF_PAYLOAD_SIZE 32
|
||
#define RF_CHANNEL_DEFAULT 100
|
||
#define RF_DATA_RATE RF_1MBPS
|
||
#define RF_TX_POWER RF_PA_MAX
|
||
|
||
/* RF frame structure */
|
||
typedef struct __attribute__((packed)) {
|
||
uint8_t frame_id; /* 0xA0 = FRAME_ID_CHANNELS */
|
||
uint8_t seq; /* Sequence number */
|
||
uint8_t model_id; /* Model ID */
|
||
uint8_t flags; /* Flags */
|
||
uint8_t sbus_data[22]; /* 16 channels × 11bit = 22 bytes little-endian bitstream */
|
||
uint8_t reserved[6]; /* Reserved */
|
||
} rf_payload_t;
|
||
|
||
/* Telemetry data from receiver */
|
||
typedef struct __attribute__((packed)) {
|
||
uint8_t frame_id; /* 0xB0 = FRAME_ID_TELEMETRY */
|
||
uint8_t seq; /* Sequence number */
|
||
uint16_t battery_mv; /* Battery voltage (big-endian, mV) */
|
||
uint8_t reserved[28]; /* Reserved */
|
||
} rf_telemetry_t;
|
||
|
||
/* RF state */
|
||
static uint8_t rf_seq = 0;
|
||
static uint8_t rf_model_id = 0;
|
||
|
||
void rf_send_channels(adc_data_t *adc_data)
|
||
{
|
||
rf_payload_t payload;
|
||
memset(&payload, 0, sizeof(payload));
|
||
|
||
payload.frame_id = FRAME_ID_CHANNELS;
|
||
payload.seq = rf_seq++;
|
||
payload.model_id = rf_model_id;
|
||
|
||
/* Convert 8 ADC channels to SBUS-like 11-bit format */
|
||
/* Map 12-bit ADC (0-4095) to SBUS range (200-1844) */
|
||
uint16_t sbus_channels[16] = {0};
|
||
for (int i = 0; i < 8; i++) {
|
||
uint32_t val = adc_data->channels[i];
|
||
/* Map 0-4095 to 200-1844 */
|
||
sbus_channels[i] = 200 + (val * 1644 / 4096);
|
||
if (sbus_channels[i] > 1844) sbus_channels[i] = 1844;
|
||
}
|
||
/* Center unused channels */
|
||
for (int i = 8; i < 16; i++) {
|
||
sbus_channels[i] = 1024;
|
||
}
|
||
|
||
/* Pack 16 × 11bit into 22 bytes little-endian */
|
||
for (int i = 0; i < 16; i++) {
|
||
uint16_t ch = sbus_channels[i];
|
||
int byte_idx = (i * 11) / 8;
|
||
int bit_off = (i * 11) % 8;
|
||
payload.sbus_data[byte_idx] |= (ch << bit_off) & 0xFF;
|
||
payload.sbus_data[byte_idx + 1] |= (ch >> (8 - bit_off)) & 0xFF;
|
||
if (bit_off > 5) {
|
||
payload.sbus_data[byte_idx + 2] |= (ch >> (16 - bit_off)) & 0xFF;
|
||
}
|
||
}
|
||
|
||
/* TODO: Send via NRF24L01 hardware */
|
||
ESP_LOGD(TAG, "RF TX seq=%d ch1=%d", payload.seq, sbus_channels[0]);
|
||
}
|
||
|
||
void rf_task(void *pvParameters)
|
||
{
|
||
ESP_LOGI(TAG, "RF task started");
|
||
|
||
/* TODO: Initialize NRF24L01 hardware */
|
||
/* nrf24_init(); */
|
||
/* nrf24_set_channel(100); */
|
||
/* nrf24_set_data_rate(RF_DATA_RATE); */
|
||
/* nrf24_set_power(RF_TX_POWER); */
|
||
|
||
while (1) {
|
||
/* Read latest ADC data */
|
||
adc_data_t adc_data;
|
||
if (adc_data_queue && xQueuePeek(adc_data_queue, &adc_data, 0)) {
|
||
/* Send channel data over RF */
|
||
rf_send_channels(&adc_data);
|
||
}
|
||
|
||
/* TODO: Check for ACK/telemetry from receiver */
|
||
/* rf_telemetry_t telemetry; */
|
||
/* if (nrf24_read_ack(&telemetry)) { */
|
||
/* linked = 1; */
|
||
/* lost_count = 0; */
|
||
/* } else { */
|
||
/* if (++lost_count > 50) linked = 0; */
|
||
/* } */
|
||
|
||
vTaskDelay(pdMS_TO_TICKS(20)); /* 50Hz RF update rate */
|
||
}
|
||
}
|