Fix various SX1280 issues, revamp RX ISR flow

This commit is contained in:
jacob.eva 2024-07-03 11:06:52 +01:00
parent 11c9522d53
commit 379dce99b3
No known key found for this signature in database
GPG Key ID: 0B92E083BBCCAA1E
7 changed files with 236 additions and 84 deletions

View File

@ -626,9 +626,8 @@
#define HAS_PMU true #define HAS_PMU true
#define HAS_NP false #define HAS_NP false
#define HAS_SD false #define HAS_SD false
#define HAS_RF_SWITCH_RX_TX true
#define CONFIG_UART_BUFFER_SIZE 6144 #define CONFIG_UART_BUFFER_SIZE 6144
#define CONFIG_QUEUE_SIZE 6144 #define CONFIG_QUEUE_0_SIZE 6144
#define CONFIG_QUEUE_MAX_LENGTH 200 #define CONFIG_QUEUE_MAX_LENGTH 200
#define EEPROM_SIZE 296 #define EEPROM_SIZE 296
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
@ -647,7 +646,7 @@
true // DIO2_AS_RF_SWITCH true // DIO2_AS_RF_SWITCH
} }
}; };
const uint8_t interface_pins[INTERFACE_COUNT][10] = { const int8_t interface_pins[INTERFACE_COUNT][10] = {
// SX1262 // SX1262
{ {
42, // pin_ss 42, // pin_ss

View File

@ -100,6 +100,9 @@
uint32_t stat_rx = 0; uint32_t stat_rx = 0;
uint32_t stat_tx = 0; uint32_t stat_tx = 0;
unsigned long last_tx = 0;
unsigned long last_rx = 0;
// Power management // Power management
#define BATTERY_STATE_DISCHARGING 0x01 #define BATTERY_STATE_DISCHARGING 0x01
#define BATTERY_STATE_CHARGING 0x02 #define BATTERY_STATE_CHARGING 0x02

View File

@ -143,6 +143,10 @@ const uint8_t pages = 3;
uint8_t disp_page = START_PAGE; uint8_t disp_page = START_PAGE;
uint8_t interface_page = START_PAGE; uint8_t interface_page = START_PAGE;
uint8_t* online_interface_list;
uint8_t online_interfaces = 0;
#if DISPLAY == OLED #if DISPLAY == OLED
#define WATERFALL_SIZE 46 #define WATERFALL_SIZE 46
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C) #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
@ -369,7 +373,7 @@ void draw_lora_icon(RadioInterface* radio, int px, int py) {
// todo: make display show other interfaces // todo: make display show other interfaces
if (radio_online) { if (radio_online) {
#if DISPLAY == OLED #if DISPLAY == OLED
if (interface_page == radio->getIndex()) { if (online_interface_list[interface_page] == radio->getIndex()) {
stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 18, 18, GxEPD_WHITE, GxEPD_BLACK); stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 18, 18, GxEPD_WHITE, GxEPD_BLACK);
// redraw stat area on next refresh // redraw stat area on next refresh
@ -381,7 +385,7 @@ void draw_lora_icon(RadioInterface* radio, int px, int py) {
stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, GxEPD_WHITE, GxEPD_BLACK); stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, GxEPD_WHITE, GxEPD_BLACK);
} }
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C) #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
if (interface_page == radio->getIndex()) { if (online_interface_list[interface_page] == radio->getIndex()) {
stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 34, 36, GxEPD_WHITE, GxEPD_BLACK); stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 34, 36, GxEPD_WHITE, GxEPD_BLACK);
// redraw stat area on next refresh // redraw stat area on next refresh
@ -666,19 +670,38 @@ void draw_stat_area() {
} }
if (millis()-last_interface_page_flip >= page_interval) { if (millis()-last_interface_page_flip >= page_interval) {
int online_interfaces = 0; int online_interfaces_check = 0;
// todo, is there a more efficient way of doing this?
for (int i = 0; i < INTERFACE_COUNT; i++) { for (int i = 0; i < INTERFACE_COUNT; i++) {
if (interface_obj[i]->getRadioOnline()) { if (interface_obj[i]->getRadioOnline()) {
online_interfaces++; online_interfaces_check++;
} }
} }
if (online_interfaces != online_interfaces_check) {
online_interfaces = online_interfaces_check;
}
// cap at two for now, as only two boxes to symbolise interfaces // cap at two for now, as only two boxes to symbolise interfaces
// available on display // available on display
if (online_interfaces > 2) { if (online_interfaces > 2) {
online_interfaces = 2; online_interfaces = 2;
} }
interface_page = (++interface_page%online_interfaces);
online_interface_list = (uint8_t*)malloc(online_interfaces);
uint8_t index = 0;
for (int i = 0; i < INTERFACE_COUNT; i++) {
if (interface_obj[i]->getRadioOnline()) {
online_interface_list[index] = i;
index++;
}
}
if (online_interfaces > 0) {
interface_page = (++interface_page%online_interfaces);
}
last_interface_page_flip = millis(); last_interface_page_flip = millis();
} }
@ -789,7 +812,7 @@ void draw_disp_area() {
if (!disp_ext_fb or bt_ssp_pin != 0) { if (!disp_ext_fb or bt_ssp_pin != 0) {
if (radio_online && display_diagnostics) { if (radio_online && display_diagnostics) {
#if DISPLAY == OLED #if DISPLAY == OLED
selected_radio = interface_obj[interface_page]; selected_radio = interface_obj[online_interface_list[interface_page]];
disp_area.fillRect(0,8,disp_area.width(),37, SSD1306_BLACK); disp_area.fillRect(0,37,disp_area.width(),27, SSD1306_WHITE); disp_area.fillRect(0,8,disp_area.width(),37, SSD1306_BLACK); disp_area.fillRect(0,37,disp_area.width(),27, SSD1306_WHITE);
disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(SSD1306_WHITE); disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(SSD1306_WHITE);
@ -845,7 +868,7 @@ void draw_disp_area() {
disp_area.drawBitmap(32+2, 50, bm_hg_high, 5, 9, SSD1306_BLACK, SSD1306_WHITE); disp_area.drawBitmap(32+2, 50, bm_hg_high, 5, 9, SSD1306_BLACK, SSD1306_WHITE);
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C) #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
selected_radio = interface_obj[interface_page]; selected_radio = interface_obj[online_interface_list[interface_page]];
disp_area.fillRect(0,12,disp_area.width(),57, GxEPD_BLACK); disp_area.fillRect(0,69,disp_area.width(),56, GxEPD_WHITE); disp_area.fillRect(0,12,disp_area.width(),57, GxEPD_BLACK); disp_area.fillRect(0,69,disp_area.width(),56, GxEPD_WHITE);
disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(GxEPD_WHITE); disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(GxEPD_WHITE);
disp_area.setTextSize(2); // scale text 2x disp_area.setTextSize(2); // scale text 2x
@ -1096,6 +1119,7 @@ void update_display(bool blank = false) {
update_disp_area(); update_disp_area();
display.display(true); display.display(true);
#endif #endif
free(online_interface_list);
last_disp_update = millis(); last_disp_update = millis();
} }
} }

View File

@ -20,17 +20,13 @@
FIFOBuffer serialFIFO; FIFOBuffer serialFIFO;
uint8_t serialBuffer[CONFIG_UART_BUFFER_SIZE+1]; uint8_t serialBuffer[CONFIG_UART_BUFFER_SIZE+1];
uint16_t packet_starts_buf[(CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT)+1]; uint16_t packet_starts_buf[(CONFIG_QUEUE_MAX_LENGTH)+1];
uint16_t packet_lengths_buf[(CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT)+1]; uint16_t packet_lengths_buf[(CONFIG_QUEUE_MAX_LENGTH)+1];
FIFOBuffer16 packet_starts[INTERFACE_COUNT]; FIFOBuffer16 packet_starts[INTERFACE_COUNT];
FIFOBuffer16 packet_lengths[INTERFACE_COUNT]; FIFOBuffer16 packet_lengths[INTERFACE_COUNT];
// The total queue size is split evenly between all the interfaces.
// todo, bias in size may be needed here for interfaces with higher data rates.
uint8_t packet_queue[INTERFACE_COUNT][CONFIG_QUEUE_SIZE/INTERFACE_COUNT];
volatile uint8_t queue_height[INTERFACE_COUNT] = {0}; volatile uint8_t queue_height[INTERFACE_COUNT] = {0};
volatile uint16_t queued_bytes[INTERFACE_COUNT] = {0}; volatile uint16_t queued_bytes[INTERFACE_COUNT] = {0};
@ -48,7 +44,11 @@ volatile bool serial_buffering = false;
char sbuf[128]; char sbuf[128];
bool packet_ready = false; bool packet_ready = false;
uint8_t packet_interface;
volatile bool process_packet = false;
volatile uint8_t packet_interface = 0;
uint8_t *packet_queue[INTERFACE_COUNT];
void setup() { void setup() {
#if MCU_VARIANT == MCU_ESP32 #if MCU_VARIANT == MCU_ESP32
@ -112,11 +112,11 @@ void setup() {
memset(packet_starts_buf, 0, sizeof(packet_starts_buf)); memset(packet_starts_buf, 0, sizeof(packet_starts_buf));
memset(packet_lengths_buf, 0, sizeof(packet_starts_buf)); memset(packet_lengths_buf, 0, sizeof(packet_starts_buf));
memset(packet_queue, 0, sizeof(packet_queue));
for (int i = 0; i < INTERFACE_COUNT; i++) { for (int i = 0; i < INTERFACE_COUNT; i++) {
fifo16_init(&packet_starts[i], packet_starts_buf, CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT); fifo16_init(&packet_starts[i], packet_starts_buf, CONFIG_QUEUE_MAX_LENGTH);
fifo16_init(&packet_lengths[i], packet_lengths_buf, CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT); fifo16_init(&packet_lengths[i], packet_lengths_buf, CONFIG_QUEUE_MAX_LENGTH);
packet_queue[i] = (uint8_t*)malloc(getQueueSize(i));
} }
// Create and configure interface objects // Create and configure interface objects
@ -378,6 +378,7 @@ void ISR_VECT receive_callback(uint8_t index, int packet_size) {
getPacketData(selected_radio, packet_size); getPacketData(selected_radio, packet_size);
packet_ready = true; packet_ready = true;
} }
last_rx = millis();
} }
bool startRadio(RadioInterface* radio) { bool startRadio(RadioInterface* radio) {
@ -442,7 +443,7 @@ void update_radio_lock(RadioInterface* radio) {
// Check if the queue is full for the selected radio. // Check if the queue is full for the selected radio.
// Returns true if full, false if not // Returns true if full, false if not
bool queueFull(RadioInterface* radio) { bool queueFull(RadioInterface* radio) {
return (queue_height[radio->getIndex()] >= (CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT) || queued_bytes[radio->getIndex()] >= (CONFIG_QUEUE_SIZE/INTERFACE_COUNT)); return (queue_height[radio->getIndex()] >= (CONFIG_QUEUE_MAX_LENGTH) || queued_bytes[radio->getIndex()] >= (getQueueSize(radio->getIndex())));
} }
volatile bool queue_flushing = false; volatile bool queue_flushing = false;
@ -463,7 +464,7 @@ void flushQueue(RadioInterface* radio) {
if (length >= MIN_L && length <= MTU) { if (length >= MIN_L && length <= MTU) {
for (uint16_t i = 0; i < length; i++) { for (uint16_t i = 0; i < length; i++) {
uint16_t pos = (start+i)%(CONFIG_QUEUE_SIZE/INTERFACE_COUNT); uint16_t pos = (start+i)%(getQueueSize(index));
tbuf[i] = packet_queue[index][pos]; tbuf[i] = packet_queue[index][pos];
} }
transmit(radio, length); transmit(radio, length);
@ -538,6 +539,7 @@ void transmit(RadioInterface* radio, uint16_t size) {
} }
radio->endPacket(); radio->addAirtime(written); radio->endPacket(); radio->addAirtime(written);
} }
last_tx = millis();
} else { } else {
kiss_indicate_error(ERROR_TXFAILED); kiss_indicate_error(ERROR_TXFAILED);
led_indicate_error(5); led_indicate_error(5);
@ -562,13 +564,13 @@ void serialCallback(uint8_t sbyte) {
if (getInterfaceIndex(command) < INTERFACE_COUNT) { if (getInterfaceIndex(command) < INTERFACE_COUNT) {
uint8_t index = getInterfaceIndex(command); uint8_t index = getInterfaceIndex(command);
if (!fifo16_isfull(&packet_starts[index]) && queued_bytes[index] < (CONFIG_QUEUE_SIZE/INTERFACE_COUNT)) { if (!fifo16_isfull(&packet_starts[index]) && queued_bytes[index] < (getQueueSize(index))) {
uint16_t s = current_packet_start[index]; uint16_t s = current_packet_start[index];
int16_t e = queue_cursor[index]-1; if (e == -1) e = (CONFIG_QUEUE_SIZE/INTERFACE_COUNT)-1; int16_t e = queue_cursor[index]-1; if (e == -1) e = (getQueueSize(index))-1;
uint16_t l; uint16_t l;
if (s != e) { if (s != e) {
l = (s < e) ? e - s + 1: (CONFIG_QUEUE_SIZE/INTERFACE_COUNT) - s + e + 1; l = (s < e) ? e - s + 1: (getQueueSize(index)) - s + e + 1;
} else { } else {
l = 1; l = 1;
} }
@ -631,10 +633,10 @@ void serialCallback(uint8_t sbyte) {
if (getInterfaceIndex(command) < INTERFACE_COUNT) { if (getInterfaceIndex(command) < INTERFACE_COUNT) {
uint8_t index = getInterfaceIndex(command); uint8_t index = getInterfaceIndex(command);
if (queue_height[index] < (CONFIG_QUEUE_MAX_LENGTH/INTERFACE_COUNT) && queued_bytes[index] < (CONFIG_QUEUE_SIZE/INTERFACE_COUNT)) { if (queue_height[index] < CONFIG_QUEUE_MAX_LENGTH && queued_bytes[index] < (getQueueSize(index))) {
queued_bytes[index]++; queued_bytes[index]++;
packet_queue[index][queue_cursor[index]++] = sbyte; packet_queue[index][queue_cursor[index]++] = sbyte;
if (queue_cursor[index] == (CONFIG_QUEUE_SIZE/INTERFACE_COUNT)) queue_cursor[index] = 0; if (queue_cursor[index] == (getQueueSize(index))) queue_cursor[index] = 0;
} }
} }
} }
@ -1133,43 +1135,39 @@ void validate_status() {
} }
} }
void loop() { void loop() {
packet_poll();
bool ready = false; bool ready = false;
for (int i = 0; i < INTERFACE_COUNT; i++) { for (int i = 0; i < INTERFACE_COUNT; i++) {
selected_radio = interface_obj[i]; selected_radio = interface_obj[i];
if (selected_radio->getRadioOnline()) { if (selected_radio->getRadioOnline()) {
selected_radio->checkModemStatus(); selected_radio->checkModemStatus();
ready = true; ready = true;
} }
} }
// if at least one radio is online then we can continue
// If at least one radio is online then we can continue
if (ready) { if (ready) {
#if MCU_VARIANT == MCU_ESP32
if (packet_ready) { if (packet_ready) {
selected_radio = interface_obj[packet_interface]; selected_radio = interface_obj[packet_interface];
#if MCU_VARIANT == MCU_ESP32
portENTER_CRITICAL(&update_lock); portENTER_CRITICAL(&update_lock);
last_rssi = selected_radio->packetRssi(); #elif MCU_VARIANT == MCU_NRF52
last_snr_raw = selected_radio->packetSnrRaw();
portEXIT_CRITICAL(&update_lock);
kiss_indicate_stat_rssi();
kiss_indicate_stat_snr();
kiss_write_packet(packet_interface);
}
#elif MCU_VARIANT == MCU_NRF52
if (packet_ready) {
selected_radio = interface_obj[packet_interface];
portENTER_CRITICAL(); portENTER_CRITICAL();
#endif
last_rssi = selected_radio->packetRssi(); last_rssi = selected_radio->packetRssi();
last_snr_raw = selected_radio->packetSnrRaw(); last_snr_raw = selected_radio->packetSnrRaw();
#if MCU_VARIANT == MCU_ESP32
portEXIT_CRITICAL(&update_lock);
#elif MCU_VARIANT == MCU_NRF52
portEXIT_CRITICAL(); portEXIT_CRITICAL();
#endif
kiss_indicate_stat_rssi(); kiss_indicate_stat_rssi();
kiss_indicate_stat_snr(); kiss_indicate_stat_snr();
kiss_write_packet(packet_interface); kiss_write_packet(packet_interface);
} }
#endif
for (int i = 0; i < INTERFACE_COUNT; i++) { for (int i = 0; i < INTERFACE_COUNT; i++) {
selected_radio = interface_obj_sorted[i]; selected_radio = interface_obj_sorted[i];
@ -1182,13 +1180,11 @@ void loop() {
// If a higher data rate interface has received a packet after its // If a higher data rate interface has received a packet after its
// loop, it still needs to be the first to transmit, so check if this // loop, it still needs to be the first to transmit, so check if this
// is the case. // is the case.
if (i != 0) { for (int j = 0; j < INTERFACE_COUNT; j++) {
for (int j = 0; j < INTERFACE_COUNT; j++) { if (!interface_obj_sorted[j]->calculateALock() || interface_obj_sorted[j]->getRadioOnline()) {
if (!interface_obj_sorted[j]->calculateALock() || interface_obj_sorted[j]->getRadioOnline()) { if (interface_obj_sorted[j]->getBitrate() > selected_radio->getBitrate()) {
if (interface_obj_sorted[j]->getBitrate() > selected_radio->getBitrate()) { if (queue_height[interface_obj_sorted[j]->getIndex()] > 0) {
if (queue_height[interface_obj_sorted[j]->getIndex()] > 0) { selected_radio = interface_obj_sorted[j];
selected_radio = interface_obj_sorted[j];
}
} }
} }
} }
@ -1241,7 +1237,24 @@ void loop() {
if (!fifo_isempty(&serialFIFO)) serial_poll(); if (!fifo_isempty(&serialFIFO)) serial_poll();
#if HAS_DISPLAY #if HAS_DISPLAY
#if DISPLAY == OLED
if (disp_ready) update_display(); if (disp_ready) update_display();
#elif DISPLAY == EINK_BW || DISPLAY == EINK_3C
// Display refreshes take so long on e-paper displays that they can disrupt
// the regular operation of the device. To combat this the time it is
// chosen to do so must be strategically chosen. Particularly on the
// RAK4631, the display and the potentially installed SX1280 modem share
// the same SPI bus. Thus it is not possible to solve this by utilising the
// callback functionality to poll the modem in this case. todo, this may be
// able to be improved in the future.
if (disp_ready) {
if (millis() - last_tx >= 4000) {
if (millis() - last_rx >= 1000) {
update_display();
}
}
}
#endif
#endif #endif
#if HAS_PMU #if HAS_PMU
@ -1283,6 +1296,30 @@ void button_event(uint8_t event, unsigned long duration) {
} }
} }
void poll_buffers() {
process_serial();
}
void packet_poll() {
#if MCU_VARIANT == MCU_ESP32
portENTER_CRITICAL(&update_lock);
#elif MCU_VARIANT == MCU_NRF52
portENTER_CRITICAL();
#endif
// If we have received a packet on an interface which needs to be processed
if (process_packet) {
selected_radio = interface_obj[packet_interface];
selected_radio->clearIRQStatus();
selected_radio->handleDio0Rise();
process_packet = false;
}
#if MCU_VARIANT == MCU_ESP32
portEXIT_CRITICAL(&update_lock);
#elif MCU_VARIANT == MCU_NRF52
portEXIT_CRITICAL();
#endif
}
volatile bool serial_polling = false; volatile bool serial_polling = false;
void serial_poll() { void serial_poll() {
serial_polling = true; serial_polling = true;

View File

@ -15,8 +15,6 @@
#define ISR_VECT #define ISR_VECT
#endif #endif
#define MAX_PKT_LENGTH 255
// SX126x registers // SX126x registers
#define OP_RF_FREQ_6X 0x86 #define OP_RF_FREQ_6X 0x86
#define OP_SLEEP_6X 0x84 #define OP_SLEEP_6X 0x84
@ -90,19 +88,19 @@
#define FREQ_DIV_6X (double)pow(2.0, 25.0) #define FREQ_DIV_6X (double)pow(2.0, 25.0)
#define FREQ_STEP_6X (double)(XTAL_FREQ_6X / FREQ_DIV_6X) #define FREQ_STEP_6X (double)(XTAL_FREQ_6X / FREQ_DIV_6X)
extern int packet_interface; extern bool process_packet;
extern uint8_t packet_interface;
extern RadioInterface* interface_obj[]; extern RadioInterface* interface_obj[];
// ISRs cannot provide parameters to the functions they call. Since we have // ISRs cannot provide parameters to the functions they call. Since we have
// multiple radio objects, we have to read each dio0 pin for each one and see // multiple interfaces, we have to read each dio0 pin for each one and see
// which one is high. We can then use the index of this pin in the 2D array to // which one is high. We can then use the index of this pin in the 2D array to
// call the correct object. // signal the correct interface to the main loop
void onDio0Rise() { void ISR_VECT onDio0Rise() {
for (int i = 0; i < INTERFACE_COUNT; i++) { for (int i = 0; i < INTERFACE_COUNT; i++) {
if (digitalRead(interface_pins[i][5]) == HIGH) { if (digitalRead(interface_pins[i][5]) == HIGH) {
process_packet = true;
packet_interface = i; packet_interface = i;
RadioInterface* obj = interface_obj[i];
obj->handleDio0Rise();
break; break;
} }
} }
@ -110,14 +108,13 @@ void onDio0Rise() {
sx126x::sx126x(uint8_t index, SPIClass spi, bool tcxo, bool dio2_as_rf_switch, int ss, int sclk, int mosi, int miso, int reset, int dio0, int busy, int rxen) : sx126x::sx126x(uint8_t index, SPIClass spi, bool tcxo, bool dio2_as_rf_switch, int ss, int sclk, int mosi, int miso, int reset, int dio0, int busy, int rxen) :
RadioInterface(index), RadioInterface(index),
_spiSettings(8E6, MSBFIRST, SPI_MODE0), _spiSettings(8E6, MSBFIRST, SPI_MODE0), _spiModem(spi), _ss(ss),
_spiModem(spi), _sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0),
_ss(ss), _sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0), _busy(busy), _rxen(rxen), _frequency(0), _txp(0), _sf(0x07), _bw(0x04),
_busy(busy), _rxen(rxen), _frequency(0), _txp(0), _sf(0x07), _bw(0x04), _cr(0x01), _ldro(0x00), _packetIndex(0), _implicitHeaderMode(0),
_cr(0x01), _ldro(0x00), _packetIndex(0), _implicitHeaderMode(0), _payloadLength(255), _crcMode(1), _fifo_tx_addr_ptr(0),
_payloadLength(255), _crcMode(1), _fifo_tx_addr_ptr(0), _fifo_rx_addr_ptr(0), _fifo_rx_addr_ptr(0), _preinit_done(false), _tcxo(tcxo),
_packet({0}), _preinit_done(false), _tcxo(tcxo), _dio2_as_rf_switch(dio2_as_rf_switch)
_dio2_as_rf_switch(dio2_as_rf_switch)
{ {
// overide Stream timeout value // overide Stream timeout value
setTimeout(0); setTimeout(0);
@ -966,7 +963,7 @@ void sx126x::implicitHeaderMode()
} }
void ISR_VECT sx126x::handleDio0Rise() void sx126x::handleDio0Rise()
{ {
uint8_t buf[2]; uint8_t buf[2];
@ -1017,6 +1014,16 @@ void sx126x::updateBitrate() {
} }
} }
void sx126x::clearIRQStatus() {
uint8_t buf[2];
buf[0] = 0x00;
buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2);
}
// SX127x registers // SX127x registers
#define REG_FIFO_7X 0x00 #define REG_FIFO_7X 0x00
#define REG_OP_MODE_7X 0x01 #define REG_OP_MODE_7X 0x01
@ -1507,7 +1514,7 @@ void sx127x::optimizeModemSensitivity() {
} }
} }
void ISR_VECT sx127x::handleDio0Rise() { void sx127x::handleDio0Rise() {
int irqFlags = readRegister(REG_IRQ_FLAGS_7X); int irqFlags = readRegister(REG_IRQ_FLAGS_7X);
// Clear IRQs // Clear IRQs
@ -1542,6 +1549,10 @@ void sx127x::updateBitrate() {
} }
} }
void sx127x::clearIRQStatus() {
// todo, implement
}
// SX128x registers // SX128x registers
#define OP_RF_FREQ_8X 0x86 #define OP_RF_FREQ_8X 0x86
#define OP_SLEEP_8X 0x84 #define OP_SLEEP_8X 0x84
@ -1590,10 +1601,10 @@ sx128x::sx128x(uint8_t index, SPIClass spi, bool tcxo, int ss, int sclk, int mos
_spiSettings(8E6, MSBFIRST, SPI_MODE0), _spiSettings(8E6, MSBFIRST, SPI_MODE0),
_spiModem(spi), _spiModem(spi),
_ss(ss), _sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0), _ss(ss), _sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0),
_busy(busy), _rxen(rxen), _txen(txen), _frequency(0), _txp(0), _sf(0x50), _busy(busy), _rxen(rxen), _txen(txen), _frequency(0), _txp(0), _sf(0x05),
_bw(0x34), _cr(0x01), _packetIndex(0), _implicitHeaderMode(0), _bw(0x34), _cr(0x01), _packetIndex(0), _implicitHeaderMode(0),
_payloadLength(255), _crcMode(0), _fifo_tx_addr_ptr(0), _fifo_rx_addr_ptr(0), _payloadLength(255), _crcMode(0), _fifo_tx_addr_ptr(0), _fifo_rx_addr_ptr(0),
_packet({0}), _rxPacketLength(0), _preinit_done(false), _rxPacketLength(0), _preinit_done(false),
_tcxo(tcxo) _tcxo(tcxo)
{ {
// overide Stream timeout value // overide Stream timeout value
@ -2137,7 +2148,7 @@ void sx128x::receive(int size)
implicitHeaderMode(); implicitHeaderMode();
// tell radio payload length // tell radio payload length
_rxPacketLength = size; //_rxPacketLength = size;
//_payloadLength = size; //_payloadLength = size;
//setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); //setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
} else { } else {
@ -2358,7 +2369,7 @@ void sx128x::implicitHeaderMode()
} }
void ISR_VECT sx128x::handleDio0Rise() void sx128x::handleDio0Rise()
{ {
uint8_t buf[2]; uint8_t buf[2];
@ -2392,8 +2403,14 @@ void sx128x::updateBitrate() {
_lora_symbol_time_ms = (1.0/_lora_symbol_rate)*1000.0; _lora_symbol_time_ms = (1.0/_lora_symbol_rate)*1000.0;
_bitrate = (uint32_t)(_sf * ( (4.0/(float)(_cr+4)) / ((float)(pow(2, _sf))/((float)getSignalBandwidth()/1000.0)) ) * 1000.0); _bitrate = (uint32_t)(_sf * ( (4.0/(float)(_cr+4)) / ((float)(pow(2, _sf))/((float)getSignalBandwidth()/1000.0)) ) * 1000.0);
_lora_us_per_byte = 1000000.0/((float)_bitrate/8.0); _lora_us_per_byte = 1000000.0/((float)_bitrate/8.0);
//_csma_slot_ms = _lora_symbol_time_ms*10; _csma_slot_ms = 10;
float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
float target_preamble_symbols;
if (_bitrate <= LORA_FAST_BITRATE_THRESHOLD) {
target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
} else {
target_preamble_symbols = (LORA_PREAMBLE_FAST_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
}
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) { if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN; target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
} else { } else {
@ -2405,3 +2422,14 @@ void sx128x::updateBitrate() {
_bitrate = 0; _bitrate = 0;
} }
} }
void sx128x::clearIRQStatus() {
uint8_t buf[2];
buf[0] = 0x00;
buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
}

16
Radio.h
View File

@ -12,6 +12,8 @@
#include "Interfaces.h" #include "Interfaces.h"
#include "Boards.h" #include "Boards.h"
#define MAX_PKT_LENGTH 255
// TX // TX
#define PA_OUTPUT_RFO_PIN 0 #define PA_OUTPUT_RFO_PIN 0
#define PA_OUTPUT_PA_BOOST_PIN 1 #define PA_OUTPUT_PA_BOOST_PIN 1
@ -31,6 +33,8 @@
#define LORA_PREAMBLE_SYMBOLS_HW 4 #define LORA_PREAMBLE_SYMBOLS_HW 4
#define LORA_PREAMBLE_SYMBOLS_MIN 18 #define LORA_PREAMBLE_SYMBOLS_MIN 18
#define LORA_PREAMBLE_TARGET_MS 15 #define LORA_PREAMBLE_TARGET_MS 15
#define LORA_PREAMBLE_FAST_TARGET_MS 1
#define LORA_FAST_BITRATE_THRESHOLD 40000
#define RSSI_OFFSET 157 #define RSSI_OFFSET 157
@ -46,6 +50,7 @@ const uint8_t RX_ONGOING = 0x04;
// forward declare Utilities.h LED functions // forward declare Utilities.h LED functions
void led_rx_on(); void led_rx_on();
void led_rx_off(); void led_rx_off();
void led_indicate_airtime_lock(); void led_indicate_airtime_lock();
@ -68,7 +73,7 @@ public:
_post_tx_yield_timeout(0), _csma_slot_ms(50), _csma_p_min(0.1), _post_tx_yield_timeout(0), _csma_slot_ms(50), _csma_p_min(0.1),
_csma_p_max(0.8), _preambleLength(6), _lora_symbol_time_ms(0.0), _csma_p_max(0.8), _preambleLength(6), _lora_symbol_time_ms(0.0),
_lora_symbol_rate(0.0), _lora_us_per_byte(0.0), _bitrate(0), _lora_symbol_rate(0.0), _lora_us_per_byte(0.0), _bitrate(0),
_onReceive(NULL) {}; _onReceive(NULL), _packet{0} {};
virtual int begin(); virtual int begin();
virtual void end(); virtual void end();
@ -123,6 +128,7 @@ public:
virtual void updateBitrate(); virtual void updateBitrate();
virtual void handleDio0Rise(); virtual void handleDio0Rise();
virtual void clearIRQStatus();
uint32_t getBitrate() { return _bitrate; }; uint32_t getBitrate() { return _bitrate; };
uint8_t getIndex() { return _index; }; uint8_t getIndex() { return _index; };
void setRadioLock(bool lock) { _radio_locked = lock; }; void setRadioLock(bool lock) { _radio_locked = lock; };
@ -249,6 +255,7 @@ public:
} }
} }
if (_dcd_led) { if (_dcd_led) {
led_rx_on(); led_rx_on();
} else { } else {
@ -320,6 +327,7 @@ protected:
float _lora_symbol_rate; float _lora_symbol_rate;
float _lora_us_per_byte; float _lora_us_per_byte;
uint32_t _bitrate; uint32_t _bitrate;
uint8_t _packet[255];
void (*_onReceive)(uint8_t, int); void (*_onReceive)(uint8_t, int);
}; };
@ -413,6 +421,7 @@ private:
void reset(void); void reset(void);
void calibrate(void); void calibrate(void);
void calibrate_image(uint32_t frequency); void calibrate_image(uint32_t frequency);
void clearIRQStatus();
private: private:
SPISettings _spiSettings; SPISettings _spiSettings;
@ -437,7 +446,6 @@ private:
int _crcMode; int _crcMode;
int _fifo_tx_addr_ptr; int _fifo_tx_addr_ptr;
int _fifo_rx_addr_ptr; int _fifo_rx_addr_ptr;
uint8_t _packet[255];
bool _preinit_done; bool _preinit_done;
uint8_t _index; uint8_t _index;
bool _tcxo; bool _tcxo;
@ -503,6 +511,7 @@ public:
void updateBitrate(); void updateBitrate();
void handleDio0Rise(); void handleDio0Rise();
void clearIRQStatus();
private: private:
void setSyncWord(uint8_t sw); void setSyncWord(uint8_t sw);
void explicitHeaderMode(); void explicitHeaderMode();
@ -598,6 +607,8 @@ public:
void updateBitrate(); void updateBitrate();
void handleDio0Rise(); void handleDio0Rise();
void clearIRQStatus();
private: private:
void writeBuffer(const uint8_t* buffer, size_t size); void writeBuffer(const uint8_t* buffer, size_t size);
void readBuffer(uint8_t* buffer, size_t size); void readBuffer(uint8_t* buffer, size_t size);
@ -647,7 +658,6 @@ private:
int _crcMode; int _crcMode;
int _fifo_tx_addr_ptr; int _fifo_tx_addr_ptr;
int _fifo_rx_addr_ptr; int _fifo_rx_addr_ptr;
uint8_t _packet[255];
bool _preinit_done; bool _preinit_done;
int _rxPacketLength; int _rxPacketLength;
uint8_t _index; uint8_t _index;

View File

@ -1076,6 +1076,57 @@ uint8_t getInterfaceCommandByte(uint8_t index) {
} }
} }
uint32_t getQueueSize(uint8_t index) {
switch (index) {
case 0:
return CONFIG_QUEUE_0_SIZE;
#if INTERFACE_COUNT > 1
case 1:
return CONFIG_QUEUE_1_SIZE;
#endif
#if INTERFACE_COUNT > 2
case 2:
return CONFIG_QUEUE_2_SIZE;
#endif
#if INTERFACE_COUNT > 3
case 3:
return CONFIG_QUEUE_3_SIZE;
#endif
#if INTERFACE_COUNT > 4
case 4:
return CONFIG_QUEUE_4_SIZE;
#endif
#if INTERFACE_COUNT > 5
case 5:
return CONFIG_QUEUE_5_SIZE;
#endif
#if INTERFACE_COUNT > 6
case 6:
return CONFIG_QUEUE_6_SIZE;
#endif
#if INTERFACE_COUNT > 7
case 7:
return CONFIG_QUEUE_7_SIZE;
#endif
#if INTERFACE_COUNT > 8
case 8:
return CONFIG_QUEUE_8_SIZE;
#endif
#if INTERFACE_COUNT > 9
case 9:
return CONFIG_QUEUE_9_SIZE;
#endif
#if INTERFACE_COUNT > 10
case 10:
return CONFIG_QUEUE_10_SIZE;
#endif
#if INTERFACE_COUNT > 11
case 11:
return CONFIG_QUEUE_11_SIZE;
#endif
}
}
void promisc_enable() { void promisc_enable() {
promisc = true; promisc = true;
} }