mirror of
https://github.com/liberatedsystems/RNode_Firmware_CE.git
synced 2025-02-24 00:40:07 -05:00
Inital RadioLib support
This commit is contained in:
parent
2cdf2951e6
commit
f93c400eef
8
Boards.h
8
Boards.h
@ -699,7 +699,7 @@
|
|||||||
#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 CONFIG_UART_BUFFER_SIZE 40000
|
#define CONFIG_UART_BUFFER_SIZE 6144
|
||||||
#define CONFIG_QUEUE_0_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
|
||||||
@ -711,7 +711,7 @@
|
|||||||
#define INTERFACE_COUNT 1
|
#define INTERFACE_COUNT 1
|
||||||
|
|
||||||
// first interface in list is the primary
|
// first interface in list is the primary
|
||||||
const uint8_t interfaces[INTERFACE_COUNT] = {SX126X};
|
const uint8_t interfaces[INTERFACE_COUNT] = {SX1262};
|
||||||
const bool interface_cfg[INTERFACE_COUNT][3] = {
|
const bool interface_cfg[INTERFACE_COUNT][3] = {
|
||||||
// SX1262
|
// SX1262
|
||||||
{
|
{
|
||||||
@ -738,10 +738,10 @@
|
|||||||
#elif BOARD_VARIANT == MODEL_13 || BOARD_VARIANT == MODEL_14 || BOARD_VARIANT == MODEL_21
|
#elif BOARD_VARIANT == MODEL_13 || BOARD_VARIANT == MODEL_14 || BOARD_VARIANT == MODEL_21
|
||||||
#define INTERFACE_COUNT 2
|
#define INTERFACE_COUNT 2
|
||||||
|
|
||||||
#define CONFIG_QUEUE_1_SIZE 40000
|
#define CONFIG_QUEUE_1_SIZE 37500
|
||||||
|
|
||||||
// first interface in list is the primary
|
// first interface in list is the primary
|
||||||
const uint8_t interfaces[INTERFACE_COUNT] = {SX126X, SX128X};
|
const uint8_t interfaces[INTERFACE_COUNT] = {INT_SX1262, INT_SX1280};
|
||||||
const bool interface_cfg[INTERFACE_COUNT][3] = {
|
const bool interface_cfg[INTERFACE_COUNT][3] = {
|
||||||
// SX1262
|
// SX1262
|
||||||
{
|
{
|
||||||
|
61
Config.h
61
Config.h
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "ROM.h"
|
#include "ROM.h"
|
||||||
#include "Boards.h"
|
#include "Boards.h"
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
@ -95,10 +96,6 @@
|
|||||||
|
|
||||||
bool serial_in_frame = false;
|
bool serial_in_frame = false;
|
||||||
|
|
||||||
FIFOBuffer packet_rdy_interfaces;
|
|
||||||
|
|
||||||
uint8_t packet_rdy_interfaces_buf[MAX_INTERFACES];
|
|
||||||
|
|
||||||
// Incoming packet buffer
|
// Incoming packet buffer
|
||||||
uint8_t pbuf[MTU];
|
uint8_t pbuf[MTU];
|
||||||
|
|
||||||
@ -141,7 +138,57 @@
|
|||||||
// Subinterfaces
|
// Subinterfaces
|
||||||
// select interface 0 by default
|
// select interface 0 by default
|
||||||
uint8_t interface = 0;
|
uint8_t interface = 0;
|
||||||
RadioInterface* selected_radio;
|
PhysicalLayer* selected_radio;
|
||||||
RadioInterface* interface_obj[INTERFACE_COUNT];
|
PhysicalLayer* interface_obj[INTERFACE_COUNT];
|
||||||
RadioInterface* interface_obj_sorted[INTERFACE_COUNT];
|
PhysicalLayer* interface_obj_sorted[INTERFACE_COUNT];
|
||||||
|
|
||||||
|
// \todo move to another file
|
||||||
|
struct radio_vars {
|
||||||
|
bool radio_locked = false;
|
||||||
|
bool radio_online = false;
|
||||||
|
float st_airtime_limit = 0.0;
|
||||||
|
float lt_airtime_limit = 0.0;
|
||||||
|
bool airtime_lock = false;
|
||||||
|
uint16_t airtime_bins[AIRTIME_BINS] = {0};
|
||||||
|
uint16_t longterm_bins[AIRTIME_BINS] = {0};
|
||||||
|
float airtime = 0.0;
|
||||||
|
float longterm_airtime = 0.0;
|
||||||
|
float local_channel_util = 0.0;
|
||||||
|
float total_channel_util = 0.0;
|
||||||
|
float longterm_channel_util = 0.0;
|
||||||
|
uint32_t last_status_update = 0;
|
||||||
|
bool stat_signal_detected = false;
|
||||||
|
bool stat_signal_synced = false;
|
||||||
|
bool stat_rx_ongoing = false;
|
||||||
|
uint32_t last_dcd = 0;
|
||||||
|
uint16_t dcd_count = 0;
|
||||||
|
bool dcd = false;
|
||||||
|
bool dcd_led = false;
|
||||||
|
bool dcd_waiting = false;
|
||||||
|
long dcd_wait_until = 0;
|
||||||
|
bool util_samples[DCD_SAMPLES] = {false};
|
||||||
|
int dcd_sample = 0;
|
||||||
|
uint32_t post_tx_yield_timeout = 0;
|
||||||
|
uint8_t csma_p = 0;
|
||||||
|
int csma_slot_ms = 50;
|
||||||
|
float csma_p_min = 0.1;
|
||||||
|
float csma_p_max = 0.8;
|
||||||
|
long preamble_length = 0;
|
||||||
|
float lora_symbol_time_ms = 0.0;
|
||||||
|
float lora_symbol_rate = 0.0;
|
||||||
|
float lora_us_per_byte = 0.0;
|
||||||
|
uint32_t bitrate = 0;
|
||||||
|
int8_t txp = 0;
|
||||||
|
uint8_t sf = 0;
|
||||||
|
uint8_t cr = 0;
|
||||||
|
float bw = 0.0;
|
||||||
|
float freq = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct radio_vars radio_details[INTERFACE_COUNT];
|
||||||
|
|
||||||
|
SX1280* sx1280_interfaces[INTERFACE_COUNT];
|
||||||
|
SX1262* sx1262_interfaces[INTERFACE_COUNT];
|
||||||
|
|
||||||
|
volatile bool tx_flag = false;
|
||||||
#endif
|
#endif
|
||||||
|
58
Display.h
58
Display.h
@ -378,11 +378,11 @@ void draw_bt_icon(int px, int py) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_lora_icon(RadioInterface* radio, int px, int py) {
|
void draw_lora_icon(uint8_t index, 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 (online_interface_list[interface_page] != radio->getIndex()) {
|
if (online_interface_list[interface_page] != index) {
|
||||||
stat_area.drawBitmap(px - 1, py-1, bm_dot_sqr, 18, 19, SSD1306_WHITE, SSD1306_BLACK);
|
stat_area.drawBitmap(px - 1, py-1, bm_dot_sqr, 18, 19, SSD1306_WHITE, SSD1306_BLACK);
|
||||||
|
|
||||||
// redraw stat area on next refresh
|
// redraw stat area on next refresh
|
||||||
@ -394,13 +394,13 @@ void draw_lora_icon(RadioInterface* radio, int px, int py) {
|
|||||||
stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
|
stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
|
||||||
}
|
}
|
||||||
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
||||||
if (online_interface_list[interface_page] != radio->getIndex()) {
|
if (online_interface_list[interface_page] != index) {
|
||||||
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
|
||||||
stat_area_initialised = false;
|
stat_area_initialised = false;
|
||||||
}
|
}
|
||||||
if (radio->getRadioOnline()) {
|
if (radio_details[index].radio_online) {
|
||||||
stat_area.drawBitmap(px, py, bm_rf+1*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
|
stat_area.drawBitmap(px, py, bm_rf+1*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
|
||||||
} else {
|
} else {
|
||||||
stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
|
stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
|
||||||
@ -417,7 +417,7 @@ void draw_lora_icon(RadioInterface* radio, int px, int py) {
|
|||||||
|
|
||||||
void draw_mw_icon(int px, int py) {
|
void draw_mw_icon(int px, int py) {
|
||||||
if (INTERFACE_COUNT >= 2) {
|
if (INTERFACE_COUNT >= 2) {
|
||||||
if (interface_obj[1]->getRadioOnline()) {
|
if (radio_details[1].radio_online) {
|
||||||
#if DISPLAY == OLED
|
#if DISPLAY == OLED
|
||||||
stat_area.drawBitmap(px, py, bm_rf+3*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
|
stat_area.drawBitmap(px, py, bm_rf+3*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
|
||||||
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
||||||
@ -527,7 +527,7 @@ void draw_battery_bars(int px, int py) {
|
|||||||
void draw_quality_bars(int px, int py) {
|
void draw_quality_bars(int px, int py) {
|
||||||
signed char t_snr = (signed int)last_snr_raw;
|
signed char t_snr = (signed int)last_snr_raw;
|
||||||
int snr_int = (int)t_snr;
|
int snr_int = (int)t_snr;
|
||||||
float snr_min = Q_SNR_MIN_BASE-(int)interface_obj[interface_page]->getSpreadingFactor()*Q_SNR_STEP;
|
float snr_min = Q_SNR_MIN_BASE-(int)radio_details[interface_page].sf*Q_SNR_STEP;
|
||||||
float snr_span = (Q_SNR_MAX-snr_min);
|
float snr_span = (Q_SNR_MAX-snr_min);
|
||||||
float snr = ((int)snr_int) * 0.25;
|
float snr = ((int)snr_int) * 0.25;
|
||||||
float quality = ((snr-snr_min)/(snr_span))*100;
|
float quality = ((snr-snr_min)/(snr_span))*100;
|
||||||
@ -641,7 +641,8 @@ void draw_signal_bars(int px, int py) {
|
|||||||
#define WF_PIXEL_WIDTH 22
|
#define WF_PIXEL_WIDTH 22
|
||||||
#endif
|
#endif
|
||||||
void draw_waterfall(int px, int py) {
|
void draw_waterfall(int px, int py) {
|
||||||
int rssi_val = interface_obj[interface_page]->currentRssi();
|
// \todo, this may not work, check
|
||||||
|
int rssi_val = interface_obj[interface_page]->getRSSI();
|
||||||
if (rssi_val < WF_RSSI_MIN) rssi_val = WF_RSSI_MIN;
|
if (rssi_val < WF_RSSI_MIN) rssi_val = WF_RSSI_MIN;
|
||||||
if (rssi_val > WF_RSSI_MAX) rssi_val = WF_RSSI_MAX;
|
if (rssi_val > WF_RSSI_MAX) rssi_val = WF_RSSI_MAX;
|
||||||
int rssi_normalised = ((rssi_val - WF_RSSI_MIN)*(1.0/WF_RSSI_SPAN))*WF_PIXEL_WIDTH;
|
int rssi_normalised = ((rssi_val - WF_RSSI_MIN)*(1.0/WF_RSSI_SPAN))*WF_PIXEL_WIDTH;
|
||||||
@ -681,9 +682,9 @@ void draw_stat_area() {
|
|||||||
if (millis()-last_interface_page_flip >= page_interval) {
|
if (millis()-last_interface_page_flip >= page_interval) {
|
||||||
int online_interfaces_check = 0;
|
int online_interfaces_check = 0;
|
||||||
|
|
||||||
// todo, is there a more efficient way of doing this?
|
// \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 (radio_details[i].radio_online) {
|
||||||
online_interfaces_check++;
|
online_interfaces_check++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -701,7 +702,7 @@ void draw_stat_area() {
|
|||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
|
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
if (interface_obj[i]->getRadioOnline()) {
|
if (radio_details[i].radio_online) {
|
||||||
online_interface_list[index] = i;
|
online_interface_list[index] = i;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@ -716,27 +717,27 @@ void draw_stat_area() {
|
|||||||
#if DISPLAY == OLED
|
#if DISPLAY == OLED
|
||||||
draw_cable_icon(3, 8);
|
draw_cable_icon(3, 8);
|
||||||
draw_bt_icon(3, 30);
|
draw_bt_icon(3, 30);
|
||||||
draw_lora_icon(interface_obj[0], 45, 8);
|
draw_lora_icon(0, 45, 8);
|
||||||
|
|
||||||
// todo, expand support to show more than two interfaces on screen
|
// todo, expand support to show more than two interfaces on screen
|
||||||
if (INTERFACE_COUNT > 1) {
|
if (INTERFACE_COUNT > 1) {
|
||||||
draw_lora_icon(interface_obj[1], 45, 30);
|
draw_lora_icon(1, 45, 30);
|
||||||
}
|
}
|
||||||
draw_battery_bars(4, 58);
|
draw_battery_bars(4, 58);
|
||||||
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
|
||||||
draw_cable_icon(6, 18);
|
draw_cable_icon(6, 18);
|
||||||
draw_bt_icon(6, 60);
|
draw_bt_icon(6, 60);
|
||||||
draw_lora_icon(interface_obj[0], 86, 18);
|
draw_lora_icon(0, 86, 18);
|
||||||
|
|
||||||
// todo, expand support to show more than two interfaces on screen
|
// todo, expand support to show more than two interfaces on screen
|
||||||
if (INTERFACE_COUNT > 1) {
|
if (INTERFACE_COUNT > 1) {
|
||||||
draw_lora_icon(interface_obj[1], 86, 60);
|
draw_lora_icon(1, 86, 60);
|
||||||
}
|
}
|
||||||
draw_battery_bars(8, 113);
|
draw_battery_bars(8, 113);
|
||||||
#endif
|
#endif
|
||||||
radio_online = false;
|
radio_online = false;
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
if (interface_obj[i]->getRadioOnline()) {
|
if (radio_details[i].radio_online) {
|
||||||
radio_online = true;
|
radio_online = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -876,7 +877,6 @@ 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[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
|
||||||
@ -886,25 +886,25 @@ void draw_disp_area() {
|
|||||||
disp_area.setCursor(14*2, 22);
|
disp_area.setCursor(14*2, 22);
|
||||||
disp_area.print("@");
|
disp_area.print("@");
|
||||||
disp_area.setCursor(21*2, 22);
|
disp_area.setCursor(21*2, 22);
|
||||||
disp_area.printf("%.1fKbps", (float)(selected_radio->getBitrate())/1000.0);
|
disp_area.printf("%.1fKbps", (float)(radio_details[online_interface_list[interface_page]].bitrate)/1000.0);
|
||||||
|
|
||||||
disp_area.setCursor(2, 36);
|
disp_area.setCursor(2, 36);
|
||||||
disp_area.print("Airtime:");
|
disp_area.print("Airtime:");
|
||||||
|
|
||||||
disp_area.setCursor(7+12, 53);
|
disp_area.setCursor(7+12, 53);
|
||||||
if (selected_radio->getTotalChannelUtil() < 0.099) {
|
if (radio_details[online_interface_list[interface_page]].total_channel_util < 0.099) {
|
||||||
disp_area.printf("%.1f%%", selected_radio->getAirtime()*100.0);
|
disp_area.printf("%.1f%%", radio_details[online_interface_list[interface_page]].airtime*100.0);
|
||||||
} else {
|
} else {
|
||||||
disp_area.printf("%.0f%%", selected_radio->getAirtime()*100.0);
|
disp_area.printf("%.0f%%", radio_details[online_interface_list[interface_page]].airtime*100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
disp_area.drawBitmap(2, 41, bm_hg_low, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
|
disp_area.drawBitmap(2, 41, bm_hg_low, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
|
||||||
|
|
||||||
disp_area.setCursor(64+17, 53);
|
disp_area.setCursor(64+17, 53);
|
||||||
if (selected_radio->getLongtermChannelUtil() < 0.099) {
|
if (radio_details[online_interface_list[interface_page]].longterm_channel_util < 0.099) {
|
||||||
disp_area.printf("%.1f%%", selected_radio->getLongtermAirtime()*100.0);
|
disp_area.printf("%.1f%%", radio_details[online_interface_list[interface_page]].longterm_airtime*100.0);
|
||||||
} else {
|
} else {
|
||||||
disp_area.printf("%.0f%%", selected_radio->getLongtermAirtime()*100.0);
|
disp_area.printf("%.0f%%", radio_details[online_interface_list[interface_page]].longterm_airtime*100.0);
|
||||||
}
|
}
|
||||||
disp_area.drawBitmap(64, 41, bm_hg_high, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
|
disp_area.drawBitmap(64, 41, bm_hg_high, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
|
||||||
|
|
||||||
@ -916,18 +916,18 @@ void draw_disp_area() {
|
|||||||
disp_area.print("Load:");
|
disp_area.print("Load:");
|
||||||
|
|
||||||
disp_area.setCursor(7+12, 110);
|
disp_area.setCursor(7+12, 110);
|
||||||
if (selected_radio->getTotalChannelUtil() < 0.099) {
|
if (radio_details[online_interface_list[interface_page]].total_channel_util < 0.099) {
|
||||||
disp_area.printf("%.1f%%", selected_radio->getTotalChannelUtil()*100.0);
|
disp_area.printf("%.1f%%", radio_details[online_interface_list[interface_page]].total_channel_util*100.0);
|
||||||
} else {
|
} else {
|
||||||
disp_area.printf("%.0f%%", selected_radio->getTotalChannelUtil()*100.0);
|
disp_area.printf("%.0f%%", radio_details[online_interface_list[interface_page]].total_channel_util*100.0);
|
||||||
}
|
}
|
||||||
disp_area.drawBitmap(2, 98, bm_hg_low, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
|
disp_area.drawBitmap(2, 98, bm_hg_low, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
|
||||||
|
|
||||||
disp_area.setCursor(64+17, 110);
|
disp_area.setCursor(64+17, 110);
|
||||||
if (selected_radio->getLongtermChannelUtil() < 0.099) {
|
if (radio_details[online_interface_list[interface_page]].longterm_channel_util < 0.099) {
|
||||||
disp_area.printf("%.1f%%", selected_radio->getLongtermChannelUtil()*100.0);
|
disp_area.printf("%.1f%%", radio_details[online_interface_list[interface_page]].longterm_channel_util*100.0);
|
||||||
} else {
|
} else {
|
||||||
disp_area.printf("%.0f%%", selected_radio->getLongtermChannelUtil()*100.0);
|
disp_area.printf("%.0f%%", radio_details[online_interface_list[interface_page]].longterm_channel_util*100.0);
|
||||||
}
|
}
|
||||||
disp_area.drawBitmap(64, 98, bm_hg_high, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
|
disp_area.drawBitmap(64, 98, bm_hg_high, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#ifndef FRAMING_H
|
#ifndef FRAMING_H
|
||||||
#define FRAMING_H
|
#define FRAMING_H
|
||||||
|
#define CMD_DEBUG 0xFD
|
||||||
#define FEND 0xC0
|
#define FEND 0xC0
|
||||||
#define FESC 0xDB
|
#define FESC 0xDB
|
||||||
#define TFEND 0xDC
|
#define TFEND 0xDC
|
||||||
@ -80,7 +80,7 @@
|
|||||||
#define CMD_INT1_DATA 0x10
|
#define CMD_INT1_DATA 0x10
|
||||||
#define CMD_INT2_DATA 0x20
|
#define CMD_INT2_DATA 0x20
|
||||||
#define CMD_INT3_DATA 0x70
|
#define CMD_INT3_DATA 0x70
|
||||||
#define CMD_INT4_DATA 0x80
|
#define CMD_INT4_DATA 0x75
|
||||||
#define CMD_INT5_DATA 0x90
|
#define CMD_INT5_DATA 0x90
|
||||||
#define CMD_INT6_DATA 0xA0
|
#define CMD_INT6_DATA 0xA0
|
||||||
#define CMD_INT7_DATA 0xB0
|
#define CMD_INT7_DATA 0xB0
|
||||||
@ -92,8 +92,8 @@
|
|||||||
#define CMD_SEL_INT0 0x1E
|
#define CMD_SEL_INT0 0x1E
|
||||||
#define CMD_SEL_INT1 0x1F
|
#define CMD_SEL_INT1 0x1F
|
||||||
#define CMD_SEL_INT2 0x2F
|
#define CMD_SEL_INT2 0x2F
|
||||||
#define CMD_SEL_INT3 0x7F
|
#define CMD_SEL_INT3 0x74
|
||||||
#define CMD_SEL_INT4 0x8F
|
#define CMD_SEL_INT4 0x7F
|
||||||
#define CMD_SEL_INT5 0x9F
|
#define CMD_SEL_INT5 0x9F
|
||||||
#define CMD_SEL_INT6 0xAF
|
#define CMD_SEL_INT6 0xAF
|
||||||
#define CMD_SEL_INT7 0xBF
|
#define CMD_SEL_INT7 0xBF
|
||||||
|
14
Interfaces.h
14
Interfaces.h
@ -1,7 +1,7 @@
|
|||||||
#define SX127X 0x00
|
#define INT_SX127X 0x00
|
||||||
#define SX1276 0x01
|
#define INT_SX1276 0x01
|
||||||
#define SX1278 0x02
|
#define INT_SX1278 0x02
|
||||||
#define SX126X 0x10
|
#define INT_SX126X 0x10
|
||||||
#define SX1262 0x11
|
#define INT_SX1262 0x11
|
||||||
#define SX128X 0x20
|
#define INT_SX128X 0x20
|
||||||
#define SX1280 0x21
|
#define INT_SX1280 0x21
|
||||||
|
@ -16,6 +16,16 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include "Utilities.h"
|
#include "Utilities.h"
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
#if PLATFORM == PLATFORM_ESP32
|
||||||
|
#if defined(ESP32) and !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
#include "soc/rtc_wdt.h"
|
||||||
|
#endif
|
||||||
|
#define ISR_VECT IRAM_ATTR
|
||||||
|
#else
|
||||||
|
#define ISR_VECT
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_NRF52
|
#if MCU_VARIANT == MCU_NRF52
|
||||||
#define INTERFACE_SPI
|
#define INTERFACE_SPI
|
||||||
@ -127,12 +137,12 @@ void setup() {
|
|||||||
pinMode(pin_led_tx, OUTPUT);
|
pinMode(pin_led_tx, OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
// for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
if (interface_pins[i][9] != -1) {
|
// if (interface_pins[i][9] != -1) {
|
||||||
pinMode(interface_pins[i][9], OUTPUT);
|
// pinMode(interface_pins[i][9], OUTPUT);
|
||||||
digitalWrite(interface_pins[i][9], HIGH);
|
// digitalWrite(interface_pins[i][9], HIGH);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Initialise buffers
|
// Initialise buffers
|
||||||
memset(pbuf, 0, sizeof(pbuf));
|
memset(pbuf, 0, sizeof(pbuf));
|
||||||
@ -147,75 +157,206 @@ void setup() {
|
|||||||
packet_queue[i] = (uint8_t*)malloc(getQueueSize(i)+1);
|
packet_queue[i] = (uint8_t*)malloc(getQueueSize(i)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(packet_rdy_interfaces_buf, 0, sizeof(packet_rdy_interfaces_buf));
|
|
||||||
|
|
||||||
fifo_init(&packet_rdy_interfaces, packet_rdy_interfaces_buf, MAX_INTERFACES);
|
|
||||||
|
|
||||||
// Create and configure interface objects
|
// Create and configure interface objects
|
||||||
|
int16_t status;
|
||||||
for (uint8_t i = 0; i < INTERFACE_COUNT; i++) {
|
for (uint8_t i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
switch (interfaces[i]) {
|
switch (interfaces[i]) {
|
||||||
case SX126X:
|
//case SX126X:
|
||||||
case SX1262:
|
case INT_SX1262:
|
||||||
{
|
{
|
||||||
sx126x* obj;
|
SX1262* radio;
|
||||||
// if default spi enabled
|
|
||||||
|
// If default SPI
|
||||||
if (interface_cfg[i][0]) {
|
if (interface_cfg[i][0]) {
|
||||||
obj = new sx126x(i, &SPI, interface_cfg[i][1],
|
radio = new SX1262(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], interface_pins[i][4]));
|
||||||
interface_cfg[i][2], interface_pins[i][0], interface_pins[i][1],
|
} else {
|
||||||
interface_pins[i][2], interface_pins[i][3], interface_pins[i][6],
|
interface_spi[0].begin();
|
||||||
interface_pins[i][5], interface_pins[i][4], interface_pins[i][8]);
|
radio = new SX1262(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], interface_pins[i][4], interface_spi[0]));
|
||||||
}
|
}
|
||||||
else {
|
if (interface_pins[i][8] != -1) {
|
||||||
obj = new sx126x(i, &interface_spi[i], interface_cfg[i][1],
|
// Enable antenna power
|
||||||
interface_cfg[i][2], interface_pins[i][0], interface_pins[i][1],
|
pinMode(interface_pins[i][8], OUTPUT);
|
||||||
interface_pins[i][2], interface_pins[i][3], interface_pins[i][6],
|
digitalWrite(interface_pins[i][8], HIGH);
|
||||||
interface_pins[i][5], interface_pins[i][4], interface_pins[i][8]);
|
}
|
||||||
|
interface_obj[i] = (PhysicalLayer*)radio;
|
||||||
|
interface_obj_sorted[i] = (PhysicalLayer*)radio;
|
||||||
|
struct radio_vars* config = &radio_details[i];
|
||||||
|
|
||||||
|
// Init default modulation parameters
|
||||||
|
config->freq = 434.0;
|
||||||
|
config->sf = 5;
|
||||||
|
config->cr = 5;
|
||||||
|
config->bw = 125.0;
|
||||||
|
|
||||||
|
status = radio->begin(config->freq, config->bw, config->sf, config->cr, 0x14, config->txp);
|
||||||
|
radio->setDio1Action(packet_received);
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->explicitHeader();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->setCRC(2);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->sleep();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
modems_installed = true;
|
||||||
}
|
}
|
||||||
interface_obj[i] = obj;
|
|
||||||
interface_obj_sorted[i] = obj;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SX127X:
|
// \todo CURRENTLY NOT SUPPORTED DUE TO REQUIREMENT FOR DIO1 pin in RadioLib, should be fixed soon...
|
||||||
case SX1276:
|
/*case INT_SX1272:
|
||||||
case SX1278:
|
|
||||||
{
|
{
|
||||||
sx127x* obj;
|
SX1272* radio;
|
||||||
// if default spi enabled
|
|
||||||
if (interface_cfg[i][0]) {
|
if (interface_cfg[i][0]) {
|
||||||
obj = new sx127x(i, &SPI, interface_pins[i][0],
|
radio = new SX1272(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC));
|
||||||
interface_pins[i][1], interface_pins[i][2], interface_pins[i][3],
|
} else {
|
||||||
interface_pins[i][6], interface_pins[i][5], interface_pins[i][4]);
|
interface_spi[0].begin();
|
||||||
}
|
radio = new SX1272(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC, interface_spi[0]));
|
||||||
else {
|
|
||||||
obj = new sx127x(i, &interface_spi[i], interface_pins[i][0],
|
|
||||||
interface_pins[i][1], interface_pins[i][2], interface_pins[i][3],
|
|
||||||
interface_pins[i][6], interface_pins[i][5], interface_pins[i][4]);
|
|
||||||
}
|
|
||||||
interface_obj[i] = obj;
|
|
||||||
interface_obj_sorted[i] = obj;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case SX128X:
|
interface_obj[i] = (PhysicalLayer*)radio;
|
||||||
case SX1280:
|
interface_obj_sorted[i] = (PhysicalLayer*)radio;
|
||||||
|
struct radio_vars* config = &radio_details[i];
|
||||||
|
|
||||||
|
// Init default modulation parameters
|
||||||
|
config->freq = 915.0;
|
||||||
|
config->sf = 7;
|
||||||
|
config->cr = 7;
|
||||||
|
config->bw = 125.0;
|
||||||
|
|
||||||
|
status = radio->begin(config->freq, config->bw, config->sf, config->cr, 0x12, config->txp);
|
||||||
|
radio->setDio1Action(packet_received);
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->explicitHeader();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->setCRC(2);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->sleep();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
modems_installed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INT_SX1276:
|
||||||
{
|
{
|
||||||
sx128x* obj;
|
SX1276* radio;
|
||||||
// if default spi enabled
|
|
||||||
if (interface_cfg[i][0]) {
|
if (interface_cfg[i][0]) {
|
||||||
obj = new sx128x(i, &SPI, interface_cfg[i][1],
|
radio = new SX1276(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC));
|
||||||
interface_pins[i][0], interface_pins[i][1], interface_pins[i][2],
|
} else {
|
||||||
interface_pins[i][3], interface_pins[i][6], interface_pins[i][5],
|
interface_spi[0].begin();
|
||||||
interface_pins[i][4], interface_pins[i][8], interface_pins[i][7]);
|
}radio = new SX1276(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC, interface_spi[0]));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
obj = new sx128x(i, &interface_spi[i], interface_cfg[i][1],
|
interface_obj[i] = (PhysicalLayer*)radio;
|
||||||
interface_pins[i][0], interface_pins[i][1], interface_pins[i][2],
|
interface_obj_sorted[i] = (PhysicalLayer*)radio;
|
||||||
interface_pins[i][3], interface_pins[i][6], interface_pins[i][5],
|
struct radio_vars* config = &radio_details[i];
|
||||||
interface_pins[i][4], interface_pins[i][8], interface_pins[i][7]);
|
|
||||||
|
// Init default modulation parameters
|
||||||
|
config->freq = 434.0;
|
||||||
|
config->sf = 7;
|
||||||
|
config->cr = 7;
|
||||||
|
config->bw = 125.0;
|
||||||
|
|
||||||
|
status = radio->begin(config->freq, config->bw, config->sf, config->cr, 0x12, config->txp);
|
||||||
|
radio->setDio1Action(packet_received);
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->explicitHeader();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->setCRC(2);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->sleep();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
modems_installed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INT_SX1278:
|
||||||
|
{
|
||||||
|
SX1278* radio;
|
||||||
|
if (interface_cfg[i][0]) {
|
||||||
|
radio = new SX1278(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC));
|
||||||
|
} else {
|
||||||
|
interface_spi[0].begin();
|
||||||
|
radio = new SX1278(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], RADIOLIB_NC, interface_spi[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
interface_obj[i] = (PhysicalLayer*)radio;
|
||||||
|
interface_obj_sorted[i] = (PhysicalLayer*)radio;
|
||||||
|
struct radio_vars* config = &radio_details[i];
|
||||||
|
|
||||||
|
// Init default modulation parameters
|
||||||
|
config->freq = 434.0;
|
||||||
|
config->sf = 7;
|
||||||
|
config->cr = 7;
|
||||||
|
config->bw = 125.0;
|
||||||
|
|
||||||
|
status = radio->begin(config->freq, config->bw, config->sf, config->cr, 0x12, config->txp);
|
||||||
|
radio->setDio1Action(packet_received);
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->explicitHeader();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->setCRC(2);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->sleep();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
modems_installed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
case INT_SX1280:
|
||||||
|
{
|
||||||
|
|
||||||
|
SX1280* radio;
|
||||||
|
|
||||||
|
// If default SPI
|
||||||
|
if (interface_cfg[i][0]) {
|
||||||
|
radio = new SX1280(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], interface_pins[i][4]));
|
||||||
|
} else {
|
||||||
|
interface_spi[0].begin();
|
||||||
|
radio = new SX1280(new Module(interface_pins[i][0], interface_pins[i][5], interface_pins[i][6], interface_pins[i][4], interface_spi[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If TXEN and RXEN pins set
|
||||||
|
if (interface_pins[i][8] != -1 && interface_pins[i][7] != -1) {
|
||||||
|
radio->setRfSwitchPins(interface_pins[i][8], interface_pins[i][7]);
|
||||||
|
}
|
||||||
|
interface_obj[i] = (PhysicalLayer*)radio;
|
||||||
|
interface_obj_sorted[i] = (PhysicalLayer*)radio;
|
||||||
|
struct radio_vars* config = &radio_details[i];
|
||||||
|
|
||||||
|
// Init default modulation parameters
|
||||||
|
config->freq = 2401.0;
|
||||||
|
config->sf = 5;
|
||||||
|
config->cr = 5;
|
||||||
|
config->bw = 203.125;
|
||||||
|
|
||||||
|
status = radio->begin(config->freq, config->bw, config->sf, config->cr, 0x14, config->txp);
|
||||||
|
radio->setDio1Action(packet_received);
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->explicitHeader();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->setCRC(2);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
status = radio->sleep();
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
modems_installed = true;
|
||||||
}
|
}
|
||||||
interface_obj[i] = obj;
|
|
||||||
interface_obj_sorted[i] = obj;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,45 +367,51 @@ void setup() {
|
|||||||
|
|
||||||
// Check installed transceiver chip(s) and probe boot parameters. If any of
|
// Check installed transceiver chip(s) and probe boot parameters. If any of
|
||||||
// the configured modems cannot be initialised, do not boot
|
// the configured modems cannot be initialised, do not boot
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
/*for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
|
int16_t status = 0;
|
||||||
switch (interfaces[i]) {
|
switch (interfaces[i]) {
|
||||||
case SX126X:
|
case SX126X:
|
||||||
case SX1262:
|
case SX1262:
|
||||||
|
// \todo
|
||||||
|
break;
|
||||||
case SX127X:
|
case SX127X:
|
||||||
case SX1276:
|
case SX1276:
|
||||||
case SX1278:
|
case SX1278:
|
||||||
|
// \todo
|
||||||
|
break;
|
||||||
case SX128X:
|
case SX128X:
|
||||||
case SX1280:
|
case SX1280:
|
||||||
selected_radio = interface_obj[i];
|
status = interface_obj[i]->begin();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
modems_installed = false;
|
modems_installed = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (selected_radio->preInit()) {
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
modems_installed = true;
|
modems_installed = true;*/
|
||||||
uint32_t lfr = selected_radio->getFrequency();
|
// \todo, fixme
|
||||||
if (lfr == 0) {
|
//uint32_t lfr = selected_radio->getFrequency();
|
||||||
// Normal boot
|
//if (lfr == 0) {
|
||||||
} else if (lfr == M_FRQ_R) {
|
// // Normal boot
|
||||||
// Quick reboot
|
//} else if (lfr == M_FRQ_R) {
|
||||||
#if HAS_CONSOLE
|
// // Quick reboot
|
||||||
if (rtc_get_reset_reason(0) == POWERON_RESET) {
|
// #if HAS_CONSOLE
|
||||||
console_active = true;
|
// if (rtc_get_reset_reason(0) == POWERON_RESET) {
|
||||||
}
|
// console_active = true;
|
||||||
#endif
|
// }
|
||||||
} else {
|
// #endif
|
||||||
// Unknown boot
|
//} else {
|
||||||
}
|
// // Unknown boot
|
||||||
selected_radio->setFrequency(M_FRQ_S);
|
//}
|
||||||
} else {
|
// } else {
|
||||||
modems_installed = false;
|
// modems_installed = false;
|
||||||
}
|
// }
|
||||||
if (!modems_installed) {
|
// if (!modems_installed) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//modems_installed = true;
|
||||||
|
|
||||||
#if HAS_DISPLAY
|
#if HAS_DISPLAY
|
||||||
#if HAS_EEPROM
|
#if HAS_EEPROM
|
||||||
@ -307,11 +454,16 @@ void setup() {
|
|||||||
validate_status();
|
validate_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lora_receive(RadioInterface* radio) {
|
void ISR_VECT packet_received() {
|
||||||
if (!implicit) {
|
if (!tx_flag) {
|
||||||
radio->receive();
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
|
if (digitalRead(interface_pins[i][5])) {
|
||||||
|
receive_callback(interface_obj[i], i, interface_obj[i]->getPacketLength());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
radio->receive(implicit_l);
|
tx_flag = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,15 +487,16 @@ inline void kiss_write_packet(int index) {
|
|||||||
packet_ready = false;
|
packet_ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void getPacketData(RadioInterface* radio, uint16_t len) {
|
inline void getPacketData(uint8_t* data, uint16_t len) {
|
||||||
while (len-- && read_len < MTU) {
|
memcpy(pbuf+read_len, data, len);
|
||||||
pbuf[read_len++] = radio->read();
|
read_len += len;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void receive_callback(uint8_t index, int packet_size) {
|
|
||||||
|
void receive_callback(PhysicalLayer* radio, uint8_t index, int packet_size) {
|
||||||
selected_radio = interface_obj[index];
|
selected_radio = interface_obj[index];
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
|
uint8_t tempbuf[MAX_PKT_LENGTH];
|
||||||
if (!promisc) {
|
if (!promisc) {
|
||||||
// The standard operating mode allows large
|
// The standard operating mode allows large
|
||||||
// packets with a payload up to 500 bytes,
|
// packets with a payload up to 500 bytes,
|
||||||
@ -351,7 +504,11 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
// We read the 1-byte header and extract
|
// We read the 1-byte header and extract
|
||||||
// packet sequence number and split flags
|
// packet sequence number and split flags
|
||||||
|
|
||||||
uint8_t header = selected_radio->read(); packet_size--;
|
radio->readData(tempbuf, packet_size);
|
||||||
|
|
||||||
|
uint8_t header = tempbuf[0]; packet_size--;
|
||||||
|
uint8_t* tempbufp = tempbuf;
|
||||||
|
tempbufp++;
|
||||||
uint8_t sequence = packetSequence(header);
|
uint8_t sequence = packetSequence(header);
|
||||||
|
|
||||||
if (isSplitPacket(header) && seq == SEQ_UNSET) {
|
if (isSplitPacket(header) && seq == SEQ_UNSET) {
|
||||||
@ -361,14 +518,14 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
read_len = 0;
|
read_len = 0;
|
||||||
seq = sequence;
|
seq = sequence;
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(tempbufp, packet_size);
|
||||||
|
|
||||||
} else if (isSplitPacket(header) && seq == sequence) {
|
} else if (isSplitPacket(header) && seq == sequence) {
|
||||||
// This is the second part of a split
|
// This is the second part of a split
|
||||||
// packet, so we add it to the buffer
|
// packet, so we add it to the buffer
|
||||||
// and set the ready flag.
|
// and set the ready flag.
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(tempbufp, packet_size);
|
||||||
|
|
||||||
seq = SEQ_UNSET;
|
seq = SEQ_UNSET;
|
||||||
packet_interface = index;
|
packet_interface = index;
|
||||||
@ -382,7 +539,7 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
read_len = 0;
|
read_len = 0;
|
||||||
seq = sequence;
|
seq = sequence;
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(tempbufp, packet_size);
|
||||||
|
|
||||||
} else if (!isSplitPacket(header)) {
|
} else if (!isSplitPacket(header)) {
|
||||||
// This is not a split packet, so we
|
// This is not a split packet, so we
|
||||||
@ -396,7 +553,7 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
seq = SEQ_UNSET;
|
seq = SEQ_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(tempbufp, packet_size);
|
||||||
|
|
||||||
packet_interface = index;
|
packet_interface = index;
|
||||||
packet_ready = true;
|
packet_ready = true;
|
||||||
@ -405,22 +562,57 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
// In promiscuous mode, raw packets are
|
// In promiscuous mode, raw packets are
|
||||||
// output directly to the host
|
// output directly to the host
|
||||||
read_len = 0;
|
read_len = 0;
|
||||||
|
radio->readData(tempbuf, packet_size);
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(tempbuf, packet_size);
|
||||||
|
|
||||||
packet_interface = index;
|
packet_interface = index;
|
||||||
packet_ready = true;
|
packet_ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
radio->startReceive();
|
||||||
|
|
||||||
last_rx = millis();
|
last_rx = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startRadio(RadioInterface* radio) {
|
bool startRadio(PhysicalLayer* radio, uint8_t index) {
|
||||||
update_radio_lock(radio);
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
//update_radio_lock(radio);
|
||||||
|
|
||||||
if (modems_installed && !console_active) {
|
//if (modems_installed && !console_active) {
|
||||||
if (!radio->getRadioLock() && hw_ready) {
|
//if (!radio->getRadioLock() && hw_ready) {
|
||||||
if (!radio->begin()) {
|
|
||||||
|
int16_t status = 0;
|
||||||
|
switch (interfaces[index]) {
|
||||||
|
case INT_SX1262:
|
||||||
|
// wake up module
|
||||||
|
digitalWrite(interface_pins[index][0], LOW);
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(interface_pins[index][0], HIGH);
|
||||||
|
status = radio->standby();
|
||||||
|
update_radio_params(radio, config);
|
||||||
|
radio->setFrequency(config->freq);
|
||||||
|
break;
|
||||||
|
case INT_SX1276:
|
||||||
|
case INT_SX1278:
|
||||||
|
// \todo
|
||||||
|
break;
|
||||||
|
case INT_SX1280:
|
||||||
|
// wake up module
|
||||||
|
digitalWrite(interface_pins[index][0], LOW);
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(interface_pins[index][0], HIGH);
|
||||||
|
status = radio->standby();
|
||||||
|
update_radio_params(radio, config);
|
||||||
|
radio->setFrequency(config->freq);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
modems_installed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != RADIOLIB_ERR_NONE) {
|
||||||
// The radio could not be started.
|
// The radio could not be started.
|
||||||
// Indicate this failure over both the
|
// Indicate this failure over both the
|
||||||
// serial port and with the onboard LEDs
|
// serial port and with the onboard LEDs
|
||||||
@ -428,64 +620,72 @@ bool startRadio(RadioInterface* radio) {
|
|||||||
led_indicate_error(0);
|
led_indicate_error(0);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
radio->enableCrc();
|
status = radio->startReceive();
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
radio->onReceive(receive_callback);
|
config->radio_online = true;
|
||||||
|
update_bitrate(radio, index);
|
||||||
radio->updateBitrate();
|
kiss_indicate_phy_stats(index);
|
||||||
sort_interfaces();
|
}
|
||||||
kiss_indicate_phy_stats(radio);
|
else {
|
||||||
|
// RX failed
|
||||||
lora_receive(radio);
|
kiss_indicate_error(ERROR_INITRADIO);
|
||||||
|
led_indicate_error(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// \todo enable again
|
||||||
|
//sort_interfaces();
|
||||||
|
|
||||||
// Flash an info pattern to indicate
|
// Flash an info pattern to indicate
|
||||||
// that the radio is now on
|
// that the radio is now on
|
||||||
kiss_indicate_radiostate(radio);
|
kiss_indicate_radiostate(index);
|
||||||
led_indicate_info(3);
|
led_indicate_info(3);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
//} else {
|
||||||
// Flash a warning pattern to indicate
|
// // Flash a warning pattern to indicate
|
||||||
// that the radio was locked, and thus
|
// // that the radio was locked, and thus
|
||||||
// not started
|
// // not started
|
||||||
kiss_indicate_radiostate(radio);
|
// kiss_indicate_radiostate(radio);
|
||||||
led_indicate_warning(3);
|
// led_indicate_warning(3);
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
} else {
|
//} else {
|
||||||
// If radio is already on, we silently
|
// // If radio is already on, we silently
|
||||||
// ignore the request.
|
// // ignore the request.
|
||||||
kiss_indicate_radiostate(radio);
|
// kiss_indicate_radiostate(radio);
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopRadio(RadioInterface* radio) {
|
void stopRadio(PhysicalLayer* radio, uint8_t index) {
|
||||||
radio->end();
|
struct radio_vars* config = &radio_details[index];
|
||||||
sort_interfaces();
|
radio->sleep();
|
||||||
kiss_indicate_radiostate(radio);
|
config->radio_online = false;
|
||||||
|
// \todo finish
|
||||||
|
//sort_interfaces();
|
||||||
|
//kiss_indicate_radiostate(radio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_radio_lock(RadioInterface* radio) {
|
void update_radio_lock(PhysicalLayer* radio, uint8_t index) {
|
||||||
if (radio->getFrequency() != 0 && radio->getSignalBandwidth() != 0 && radio->getTxPower() != 0xFF && radio->getSpreadingFactor() != 0) {
|
// \todo finish
|
||||||
radio->setRadioLock(false);
|
//if (radio->getFrequency() != 0 && radio->getSignalBandwidth() != 0 && radio->getTxPower() != 0xFF && radio->getSpreadingFactorVal() != 0) {
|
||||||
} else {
|
radio_details[index].radio_locked = false;
|
||||||
radio->setRadioLock(true);
|
//} else {
|
||||||
}
|
// radio->setRadioLock(true);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(uint8_t index) {
|
||||||
return (queue_height[radio->getIndex()] >= (CONFIG_QUEUE_MAX_LENGTH) || queued_bytes[radio->getIndex()] >= (getQueueSize(radio->getIndex())));
|
return (queue_height[index] >= (CONFIG_QUEUE_MAX_LENGTH) || queued_bytes[index] >= (getQueueSize(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile bool queue_flushing = false;
|
volatile bool queue_flushing = false;
|
||||||
|
|
||||||
// Flushes all packets for the interface
|
// Flushes all packets for the interface
|
||||||
void flushQueue(RadioInterface* radio) {
|
void flushQueue(PhysicalLayer* radio, uint8_t index) {
|
||||||
uint8_t index = radio->getIndex();
|
|
||||||
if (!queue_flushing) {
|
if (!queue_flushing) {
|
||||||
queue_flushing = true;
|
queue_flushing = true;
|
||||||
|
|
||||||
@ -502,51 +702,64 @@ void flushQueue(RadioInterface* radio) {
|
|||||||
uint16_t pos = (start+i)%(getQueueSize(index));
|
uint16_t pos = (start+i)%(getQueueSize(index));
|
||||||
tbuf[i] = packet_queue[index][pos];
|
tbuf[i] = packet_queue[index][pos];
|
||||||
}
|
}
|
||||||
transmit(radio, length);
|
transmit(radio, index, length);
|
||||||
processed++;
|
processed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lora_receive(radio);
|
radio->startReceive();
|
||||||
led_tx_off();
|
led_tx_off();
|
||||||
|
|
||||||
radio->setPostTxYieldTimeout(millis()+(lora_post_tx_yield_slots*selected_radio->getCSMASlotMS()));
|
radio_details[index].post_tx_yield_timeout = millis()+(lora_post_tx_yield_slots*(radio_details[index].csma_slot_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_height[index] = 0;
|
queue_height[index] = 0;
|
||||||
queued_bytes[index] = 0;
|
queued_bytes[index] = 0;
|
||||||
selected_radio->updateAirtime();
|
update_airtime(index);
|
||||||
queue_flushing = false;
|
queue_flushing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transmit(RadioInterface* radio, uint16_t size) {
|
void transmit(PhysicalLayer* radio, uint8_t index, uint16_t size) {
|
||||||
if (radio->getRadioOnline()) {
|
if (radio_details[index].radio_online) {
|
||||||
|
int16_t status;
|
||||||
if (!promisc) {
|
if (!promisc) {
|
||||||
uint16_t written = 0;
|
uint16_t written = 0;
|
||||||
uint8_t header = random(256) & 0xF0;
|
uint8_t header = random(256) & 0xF0;
|
||||||
|
uint8_t txbuf[SINGLE_MTU] = {0};
|
||||||
|
|
||||||
if (size > SINGLE_MTU - HEADER_L) {
|
if (size > SINGLE_MTU - HEADER_L) {
|
||||||
header = header | FLAG_SPLIT;
|
header = header | FLAG_SPLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txbuf[0] = header; written++;
|
||||||
radio->beginPacket();
|
|
||||||
radio->write(header); written++;
|
|
||||||
|
|
||||||
for (uint16_t i=0; i < size; i++) {
|
for (uint16_t i=0; i < size; i++) {
|
||||||
radio->write(tbuf[i]);
|
txbuf[written] = tbuf[i];
|
||||||
|
|
||||||
written++;
|
written++;
|
||||||
|
|
||||||
if (written == 255) {
|
if (written == 255) {
|
||||||
radio->endPacket(); radio->addAirtime(written);
|
tx_flag = true;
|
||||||
radio->beginPacket();
|
status = radio->transmit(txbuf, written); add_airtime(index, written);
|
||||||
radio->write(header);
|
if (status != RADIOLIB_ERR_NONE) {
|
||||||
|
serial_write(status);
|
||||||
|
kiss_indicate_error(ERROR_TXFAILED);
|
||||||
|
led_indicate_error(5);
|
||||||
|
}
|
||||||
|
txbuf[0] = header;
|
||||||
written = 1;
|
written = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
radio->endPacket(); radio->addAirtime(written);
|
tx_flag = true;
|
||||||
|
status = radio->transmit(txbuf, written); add_airtime(index, written);
|
||||||
|
|
||||||
|
if (status != RADIOLIB_ERR_NONE) {
|
||||||
|
serial_write(status >> 8);
|
||||||
|
serial_write(status & 0x00FF);
|
||||||
|
kiss_indicate_error(ERROR_TXFAILED);
|
||||||
|
led_indicate_error(5);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// In promiscuous mode, we only send out
|
// In promiscuous mode, we only send out
|
||||||
// plain raw LoRa packets with a maximum
|
// plain raw LoRa packets with a maximum
|
||||||
@ -559,20 +772,16 @@ void transmit(RadioInterface* radio, uint16_t size) {
|
|||||||
size = SINGLE_MTU;
|
size = SINGLE_MTU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// \todo check this with radiolib
|
||||||
// If implicit header mode has been set,
|
// If implicit header mode has been set,
|
||||||
// set packet length to payload data length
|
// set packet length to payload data length
|
||||||
if (!implicit) {
|
//if (!implicit) {
|
||||||
radio->beginPacket();
|
// radio->beginPacket();
|
||||||
} else {
|
//} else {
|
||||||
radio->beginPacket(size);
|
// radio->beginPacket(size);
|
||||||
}
|
//}
|
||||||
|
|
||||||
for (uint16_t i=0; i < size; i++) {
|
radio->transmit(tbuf, size); add_airtime(index, written);
|
||||||
radio->write(tbuf[i]);
|
|
||||||
|
|
||||||
written++;
|
|
||||||
}
|
|
||||||
radio->endPacket(); radio->addAirtime(written);
|
|
||||||
}
|
}
|
||||||
last_tx = millis();
|
last_tx = millis();
|
||||||
} else {
|
} else {
|
||||||
@ -696,10 +905,17 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
|
|
||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
if (freq == 0) {
|
if (freq == 0) {
|
||||||
kiss_indicate_frequency(selected_radio);
|
kiss_indicate_frequency(interface);
|
||||||
} else {
|
} else {
|
||||||
if (op_mode == MODE_HOST) selected_radio->setFrequency(freq);
|
int16_t status = RADIOLIB_ERR_NONE;
|
||||||
kiss_indicate_frequency(selected_radio);
|
float freq_f = freq / 1000000.0;
|
||||||
|
if (radio_details[interface].radio_online) {
|
||||||
|
if (op_mode == MODE_HOST) status = selected_radio->setFrequency(freq_f);
|
||||||
|
}
|
||||||
|
if (status == RADIOLIB_ERR_NONE) {
|
||||||
|
radio_details[interface].freq = freq_f;
|
||||||
|
}
|
||||||
|
kiss_indicate_frequency(interface);
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
}
|
}
|
||||||
@ -721,13 +937,18 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
|
|
||||||
if (bw == 0) {
|
if (bw == 0) {
|
||||||
kiss_indicate_bandwidth(selected_radio);
|
kiss_indicate_bandwidth(interface);
|
||||||
} else {
|
} else {
|
||||||
if (op_mode == MODE_HOST) selected_radio->setSignalBandwidth(bw);
|
float bw_f = bw / 1000.0;
|
||||||
selected_radio->updateBitrate();
|
if (radio_details[interface].radio_online) {
|
||||||
|
if (op_mode == MODE_HOST) set_bandwidth(selected_radio, interface, bw_f);
|
||||||
|
update_bitrate(selected_radio, interface);
|
||||||
|
kiss_indicate_phy_stats(interface);
|
||||||
|
} else {
|
||||||
|
radio_details[interface].bw = bw_f;
|
||||||
|
}
|
||||||
sort_interfaces();
|
sort_interfaces();
|
||||||
kiss_indicate_bandwidth(selected_radio);
|
kiss_indicate_bandwidth(interface);
|
||||||
kiss_indicate_phy_stats(selected_radio);
|
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
}
|
}
|
||||||
@ -735,45 +956,57 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
|
|
||||||
if (sbyte == 0xFF) {
|
if (sbyte == 0xFF) {
|
||||||
kiss_indicate_txpower(selected_radio);
|
kiss_indicate_txpower(interface);
|
||||||
} else {
|
} else {
|
||||||
int8_t txp = (int8_t)sbyte;
|
int8_t txp = (int8_t)sbyte;
|
||||||
|
|
||||||
if (op_mode == MODE_HOST) setTXPower(selected_radio, txp);
|
if (radio_details[interface].radio_online) {
|
||||||
kiss_indicate_txpower(selected_radio);
|
if (op_mode == MODE_HOST) setTXPower(selected_radio, interface, txp);
|
||||||
|
} else {
|
||||||
|
radio_details[interface].txp = txp;
|
||||||
|
}
|
||||||
|
kiss_indicate_txpower(interface);
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_SF) {
|
} else if (command == CMD_SF) {
|
||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
|
|
||||||
if (sbyte == 0xFF) {
|
if (sbyte == 0xFF) {
|
||||||
kiss_indicate_spreadingfactor(selected_radio);
|
kiss_indicate_spreadingfactor(interface);
|
||||||
} else {
|
} else {
|
||||||
int sf = sbyte;
|
int sf = sbyte;
|
||||||
if (sf < 5) sf = 5;
|
if (sf < 5) sf = 5;
|
||||||
if (sf > 12) sf = 12;
|
if (sf > 12) sf = 12;
|
||||||
|
|
||||||
if (op_mode == MODE_HOST) selected_radio->setSpreadingFactor(sf);
|
if (radio_details[interface].radio_online) {
|
||||||
selected_radio->updateBitrate();
|
if (op_mode == MODE_HOST) set_spreading_factor(selected_radio, interface, sf);
|
||||||
|
update_bitrate(selected_radio, interface);
|
||||||
|
kiss_indicate_phy_stats(interface);
|
||||||
|
} else {
|
||||||
|
radio_details[interface].sf = sf;
|
||||||
|
}
|
||||||
sort_interfaces();
|
sort_interfaces();
|
||||||
kiss_indicate_spreadingfactor(selected_radio);
|
kiss_indicate_spreadingfactor(interface);
|
||||||
kiss_indicate_phy_stats(selected_radio);
|
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_CR) {
|
} else if (command == CMD_CR) {
|
||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
if (sbyte == 0xFF) {
|
if (sbyte == 0xFF) {
|
||||||
kiss_indicate_codingrate(selected_radio);
|
kiss_indicate_codingrate(interface);
|
||||||
} else {
|
} else {
|
||||||
int cr = sbyte;
|
int cr = sbyte;
|
||||||
if (cr < 5) cr = 5;
|
if (cr < 5) cr = 5;
|
||||||
if (cr > 8) cr = 8;
|
if (cr > 8) cr = 8;
|
||||||
|
|
||||||
if (op_mode == MODE_HOST) selected_radio->setCodingRate4(cr);
|
if (radio_details[interface].radio_online) {
|
||||||
selected_radio->updateBitrate();
|
if (op_mode == MODE_HOST) set_coding_rate(selected_radio, interface, cr);
|
||||||
|
update_bitrate(selected_radio, interface);
|
||||||
|
kiss_indicate_phy_stats(interface);
|
||||||
|
} else {
|
||||||
|
radio_details[interface].cr = cr;
|
||||||
|
}
|
||||||
sort_interfaces();
|
sort_interfaces();
|
||||||
kiss_indicate_codingrate(selected_radio);
|
kiss_indicate_codingrate(interface);
|
||||||
kiss_indicate_phy_stats(selected_radio);
|
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_IMPLICIT) {
|
} else if (command == CMD_IMPLICIT) {
|
||||||
@ -791,11 +1024,11 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
if (bt_state != BT_STATE_CONNECTED) cable_state = CABLE_STATE_CONNECTED;
|
if (bt_state != BT_STATE_CONNECTED) cable_state = CABLE_STATE_CONNECTED;
|
||||||
if (sbyte == 0xFF) {
|
if (sbyte == 0xFF) {
|
||||||
kiss_indicate_radiostate(selected_radio);
|
kiss_indicate_radiostate(interface);
|
||||||
} else if (sbyte == 0x00) {
|
} else if (sbyte == 0x00) {
|
||||||
stopRadio(selected_radio);
|
stopRadio(selected_radio, interface);
|
||||||
} else if (sbyte == 0x01) {
|
} else if (sbyte == 0x01) {
|
||||||
startRadio(selected_radio);
|
startRadio(selected_radio, interface);
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_ST_ALOCK) {
|
} else if (command == CMD_ST_ALOCK) {
|
||||||
@ -815,13 +1048,13 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
|
uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
|
||||||
|
|
||||||
if (at == 0) {
|
if (at == 0) {
|
||||||
selected_radio->setSTALock(0.0);
|
radio_details[interface].st_airtime_limit = 0.0;
|
||||||
} else {
|
} else {
|
||||||
int st_airtime_limit = (float)at/(100.0*100.0);
|
int st_airtime_limit = (float)at/(100.0*100.0);
|
||||||
if (st_airtime_limit >= 1.0) { st_airtime_limit = 0.0; }
|
if (st_airtime_limit >= 1.0) { st_airtime_limit = 0.0; }
|
||||||
selected_radio->setSTALock(st_airtime_limit);
|
radio_details[interface].st_airtime_limit = st_airtime_limit;
|
||||||
}
|
}
|
||||||
kiss_indicate_st_alock(selected_radio);
|
kiss_indicate_st_alock(interface);
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_LT_ALOCK) {
|
} else if (command == CMD_LT_ALOCK) {
|
||||||
@ -841,13 +1074,13 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
|
uint16_t at = (uint16_t)cmdbuf[0] << 8 | (uint16_t)cmdbuf[1];
|
||||||
|
|
||||||
if (at == 0) {
|
if (at == 0) {
|
||||||
selected_radio->setLTALock(0.0);
|
radio_details[interface].lt_airtime_limit = 0.0;
|
||||||
} else {
|
} else {
|
||||||
int lt_airtime_limit = (float)at/(100.0*100.0);
|
int lt_airtime_limit = (float)at/(100.0*100.0);
|
||||||
if (lt_airtime_limit >= 1.0) { lt_airtime_limit = 0.0; }
|
if (lt_airtime_limit >= 1.0) { lt_airtime_limit = 0.0; }
|
||||||
selected_radio->setLTALock(lt_airtime_limit);
|
radio_details[interface].lt_airtime_limit = lt_airtime_limit;
|
||||||
}
|
}
|
||||||
kiss_indicate_lt_alock(selected_radio);
|
kiss_indicate_lt_alock(interface);
|
||||||
}
|
}
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_STAT_RX) {
|
} else if (command == CMD_STAT_RX) {
|
||||||
@ -858,8 +1091,8 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
kiss_indicate_stat_rssi();
|
kiss_indicate_stat_rssi();
|
||||||
} else if (command == CMD_RADIO_LOCK) {
|
} else if (command == CMD_RADIO_LOCK) {
|
||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
update_radio_lock(selected_radio);
|
update_radio_lock(selected_radio, interface);
|
||||||
kiss_indicate_radio_lock(selected_radio);
|
kiss_indicate_radio_lock(interface);
|
||||||
interface = 0;
|
interface = 0;
|
||||||
} else if (command == CMD_BLINK) {
|
} else if (command == CMD_BLINK) {
|
||||||
led_indicate_info(sbyte);
|
led_indicate_info(sbyte);
|
||||||
@ -883,7 +1116,7 @@ void serialCallback(uint8_t sbyte) {
|
|||||||
kiss_indicate_promisc();
|
kiss_indicate_promisc();
|
||||||
} else if (command == CMD_READY) {
|
} else if (command == CMD_READY) {
|
||||||
selected_radio = interface_obj[interface];
|
selected_radio = interface_obj[interface];
|
||||||
if (!queueFull(selected_radio)) {
|
if (!queueFull(interface)) {
|
||||||
kiss_indicate_ready();
|
kiss_indicate_ready();
|
||||||
} else {
|
} else {
|
||||||
kiss_indicate_not_ready();
|
kiss_indicate_not_ready();
|
||||||
@ -1175,8 +1408,8 @@ void loop() {
|
|||||||
#elif MCU_VARIANT == MCU_NRF52
|
#elif MCU_VARIANT == MCU_NRF52
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
#endif
|
#endif
|
||||||
last_rssi = selected_radio->packetRssi();
|
last_rssi = selected_radio->getRSSI();
|
||||||
last_snr_raw = selected_radio->packetSnrRaw();
|
last_snr_raw = selected_radio->getSNR(); // \todo, this is not the raw value, a conversion will be required to get this value correct!!
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
portEXIT_CRITICAL(&update_lock);
|
portEXIT_CRITICAL(&update_lock);
|
||||||
#elif MCU_VARIANT == MCU_NRF52
|
#elif MCU_VARIANT == MCU_NRF52
|
||||||
@ -1189,9 +1422,9 @@ void loop() {
|
|||||||
|
|
||||||
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];
|
struct radio_vars* config = &radio_details[i];
|
||||||
if (selected_radio->getRadioOnline()) {
|
if (config->radio_online) {
|
||||||
selected_radio->checkModemStatus();
|
check_modem_status(interface_obj[i], i);
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1200,44 +1433,32 @@ void loop() {
|
|||||||
// 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) {
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
selected_radio = interface_obj_sorted[i];
|
struct radio_vars* config = &radio_details[i];
|
||||||
|
selected_radio = interface_obj[i];//_sorted[i];
|
||||||
|
|
||||||
if (selected_radio->calculateALock() || !selected_radio->getRadioOnline()) {
|
if (calculate_alock(config) || !config->radio_online) {
|
||||||
// skip this interface
|
// skip this interface
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a higher data rate interface has received a packet after its
|
if (queue_height[i] > 0) {
|
||||||
// loop, it still needs to be the first to transmit, so check if this
|
|
||||||
// is the case.
|
|
||||||
for (int j = 0; j < INTERFACE_COUNT; j++) {
|
|
||||||
if (!interface_obj_sorted[j]->calculateALock() && interface_obj_sorted[j]->getRadioOnline()) {
|
|
||||||
if (interface_obj_sorted[j]->getBitrate() > selected_radio->getBitrate()) {
|
|
||||||
if (queue_height[interface_obj_sorted[j]->getIndex()] > 0) {
|
|
||||||
selected_radio = interface_obj_sorted[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queue_height[selected_radio->getIndex()] > 0) {
|
|
||||||
uint32_t check_time = millis();
|
uint32_t check_time = millis();
|
||||||
if (check_time > selected_radio->getPostTxYieldTimeout()) {
|
if (check_time > config->post_tx_yield_timeout) {
|
||||||
if (selected_radio->getDCDWaiting() && (check_time >= selected_radio->getDCDWaitUntil())) { selected_radio->setDCDWaiting(false); }
|
if (config->dcd_waiting && (check_time >= config->dcd_wait_until)) { config->dcd_waiting = false; }
|
||||||
if (!selected_radio->getDCDWaiting()) {
|
if (!config->dcd_waiting) {
|
||||||
// todo, will the delay here slow down transmission with
|
// todo, will the delay here slow down transmission with
|
||||||
// multiple interfaces? needs investigation
|
// multiple interfaces? needs investigation
|
||||||
for (uint8_t dcd_i = 0; dcd_i < DCD_THRESHOLD*2; dcd_i++) {
|
for (uint8_t dcd_i = 0; dcd_i < DCD_THRESHOLD*2; dcd_i++) {
|
||||||
delay(STATUS_INTERVAL_MS); selected_radio->updateModemStatus();
|
delay(STATUS_INTERVAL_MS); update_modem_status(selected_radio, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selected_radio->getDCD()) {
|
if (!config->dcd) {
|
||||||
uint8_t csma_r = (uint8_t)random(256);
|
uint8_t csma_r = (uint8_t)random(256);
|
||||||
if (selected_radio->getCSMAp() >= csma_r) {
|
if (config->csma_p >= csma_r) {
|
||||||
flushQueue(selected_radio);
|
flushQueue(selected_radio, i);
|
||||||
} else {
|
} else {
|
||||||
selected_radio->setDCDWaiting(true);
|
config->dcd_waiting = true;
|
||||||
selected_radio->setDCDWaitUntil(millis()+selected_radio->getCSMASlotMS());
|
config->dcd_wait_until = millis()+config->csma_slot_ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1258,7 +1479,7 @@ void loop() {
|
|||||||
led_indicate_not_ready();
|
led_indicate_not_ready();
|
||||||
// shut down all radio interfaces
|
// shut down all radio interfaces
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
stopRadio(interface_obj[i]);
|
stopRadio(interface_obj[i], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
607
Radio.hpp
607
Radio.hpp
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <RadioLib.h>
|
||||||
#include "Interfaces.h"
|
#include "Interfaces.h"
|
||||||
#include "Boards.h"
|
#include "Boards.h"
|
||||||
#include "src/misc/FIFOBuffer.h"
|
#include "src/misc/FIFOBuffer.h"
|
||||||
@ -59,610 +60,4 @@ void led_indicate_airtime_lock();
|
|||||||
// get update_lock for ESP32
|
// get update_lock for ESP32
|
||||||
extern portMUX_TYPE update_lock;
|
extern portMUX_TYPE update_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class RadioInterface : public Stream {
|
|
||||||
public:
|
|
||||||
// todo: in the future define _spiModem and _spiSettings from here for inheritence by child classes
|
|
||||||
RadioInterface(uint8_t index) : _index(index), _radio_locked(false),
|
|
||||||
_radio_online(false), _st_airtime_limit(0.0), _lt_airtime_limit(0.0),
|
|
||||||
_airtime_lock(false), _airtime(0.0), _longterm_airtime(0.0),
|
|
||||||
_local_channel_util(0.0), _total_channel_util(0.0),
|
|
||||||
_longterm_channel_util(0.0), _last_status_update(0),
|
|
||||||
_stat_signal_detected(false), _stat_signal_synced(false),_stat_rx_ongoing(false), _last_dcd(0),
|
|
||||||
_dcd_count(0), _dcd(false), _dcd_led(false),
|
|
||||||
_dcd_waiting(false), _dcd_wait_until(0), _dcd_sample(0),
|
|
||||||
_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),
|
|
||||||
_lora_symbol_rate(0.0), _lora_us_per_byte(0.0), _bitrate(0),
|
|
||||||
_packet{0}, _onReceive(NULL) {};
|
|
||||||
virtual int begin() = 0;
|
|
||||||
virtual void end() = 0;
|
|
||||||
|
|
||||||
virtual int beginPacket(int implicitHeader = false) = 0;
|
|
||||||
virtual int endPacket() = 0;
|
|
||||||
|
|
||||||
virtual int packetRssi() = 0;
|
|
||||||
virtual int currentRssi() = 0;
|
|
||||||
virtual uint8_t packetRssiRaw() = 0;
|
|
||||||
virtual uint8_t currentRssiRaw() = 0;
|
|
||||||
virtual uint8_t packetSnrRaw() = 0;
|
|
||||||
virtual float packetSnr() = 0;
|
|
||||||
virtual long packetFrequencyError() = 0;
|
|
||||||
|
|
||||||
// from Print
|
|
||||||
virtual size_t write(uint8_t byte) = 0;
|
|
||||||
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
|
|
||||||
|
|
||||||
// from Stream
|
|
||||||
virtual int available() = 0;
|
|
||||||
virtual int read() = 0;
|
|
||||||
virtual int peek() = 0;
|
|
||||||
virtual void flush() = 0;
|
|
||||||
|
|
||||||
virtual void onReceive(void(*callback)(uint8_t, int)) = 0;
|
|
||||||
|
|
||||||
virtual void receive(int size = 0) = 0;
|
|
||||||
virtual void standby() = 0;
|
|
||||||
virtual void sleep() = 0;
|
|
||||||
|
|
||||||
virtual bool preInit() = 0;
|
|
||||||
virtual uint8_t getTxPower() = 0;
|
|
||||||
virtual void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN) = 0;
|
|
||||||
virtual uint32_t getFrequency() = 0;
|
|
||||||
virtual void setFrequency(uint32_t frequency) = 0;
|
|
||||||
virtual void setSpreadingFactor(int sf) = 0;
|
|
||||||
virtual uint8_t getSpreadingFactor() = 0;
|
|
||||||
virtual uint32_t getSignalBandwidth() = 0;
|
|
||||||
virtual void setSignalBandwidth(uint32_t sbw) = 0;
|
|
||||||
virtual void setCodingRate4(int denominator) = 0;
|
|
||||||
virtual uint8_t getCodingRate4() = 0;
|
|
||||||
virtual void setPreambleLength(long length) = 0;
|
|
||||||
virtual uint8_t modemStatus() = 0;
|
|
||||||
virtual void enableCrc() = 0;
|
|
||||||
virtual void disableCrc() = 0;
|
|
||||||
virtual void enableTCXO() = 0;
|
|
||||||
virtual void disableTCXO() = 0;
|
|
||||||
|
|
||||||
virtual byte random() = 0;
|
|
||||||
|
|
||||||
virtual void setSPIFrequency(uint32_t frequency) = 0;
|
|
||||||
|
|
||||||
virtual void updateBitrate() = 0;
|
|
||||||
virtual void handleDio0Rise() = 0;
|
|
||||||
virtual bool getPacketValidity() = 0;
|
|
||||||
uint32_t getBitrate() { return _bitrate; };
|
|
||||||
uint8_t getIndex() { return _index; };
|
|
||||||
void setRadioLock(bool lock) { _radio_locked = lock; };
|
|
||||||
bool getRadioLock() { return _radio_locked; };
|
|
||||||
void setRadioOnline(bool online) { _radio_online = online; };
|
|
||||||
bool getRadioOnline() { return _radio_online; };
|
|
||||||
void setSTALock(float at) { _st_airtime_limit = at; };
|
|
||||||
float getSTALock() { return _st_airtime_limit; };
|
|
||||||
void setLTALock(float at) { _lt_airtime_limit = at; };
|
|
||||||
float getLTALock() { return _lt_airtime_limit; };
|
|
||||||
bool calculateALock() {
|
|
||||||
_airtime_lock = false;
|
|
||||||
if (_st_airtime_limit != 0.0 && _airtime >= _st_airtime_limit) {
|
|
||||||
_airtime_lock = true;
|
|
||||||
}
|
|
||||||
if (_lt_airtime_limit != 0.0 && _longterm_airtime >= _lt_airtime_limit) {
|
|
||||||
_airtime_lock = true;
|
|
||||||
}
|
|
||||||
return _airtime_lock;
|
|
||||||
};
|
|
||||||
void updateAirtime() {
|
|
||||||
uint16_t cb = current_airtime_bin();
|
|
||||||
uint16_t pb = cb-1; if (cb-1 < 0) { pb = AIRTIME_BINS-1; }
|
|
||||||
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
|
||||||
_airtime_bins[nb] = 0;
|
|
||||||
_airtime = (float)(_airtime_bins[cb]+_airtime_bins[pb])/(2.0*AIRTIME_BINLEN_MS);
|
|
||||||
|
|
||||||
uint32_t longterm_airtime_sum = 0;
|
|
||||||
for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) {
|
|
||||||
longterm_airtime_sum += _airtime_bins[bin];
|
|
||||||
}
|
|
||||||
_longterm_airtime = (float)longterm_airtime_sum/(float)AIRTIME_LONGTERM_MS;
|
|
||||||
|
|
||||||
float longterm_channel_util_sum = 0.0;
|
|
||||||
for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) {
|
|
||||||
longterm_channel_util_sum += _longterm_bins[bin];
|
|
||||||
}
|
|
||||||
_longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS;
|
|
||||||
|
|
||||||
updateCSMAp();
|
|
||||||
|
|
||||||
//kiss_indicate_channel_stats(); // todo: enable me!
|
|
||||||
};
|
|
||||||
void addAirtime(uint16_t written) {
|
|
||||||
float packet_cost_ms = 0.0;
|
|
||||||
float payload_cost_ms = ((float)written * _lora_us_per_byte)/1000.0;
|
|
||||||
packet_cost_ms += payload_cost_ms;
|
|
||||||
packet_cost_ms += (_preambleLength+4.25)*_lora_symbol_time_ms;
|
|
||||||
packet_cost_ms += PHY_HEADER_LORA_SYMBOLS * _lora_symbol_time_ms;
|
|
||||||
uint16_t cb = current_airtime_bin();
|
|
||||||
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
|
||||||
_airtime_bins[cb] += packet_cost_ms;
|
|
||||||
_airtime_bins[nb] = 0;
|
|
||||||
};
|
|
||||||
void checkModemStatus() {
|
|
||||||
if (millis()-_last_status_update >= STATUS_INTERVAL_MS) {
|
|
||||||
updateModemStatus();
|
|
||||||
|
|
||||||
_util_samples[_dcd_sample] = _dcd;
|
|
||||||
_dcd_sample = (_dcd_sample+1)%DCD_SAMPLES;
|
|
||||||
if (_dcd_sample % UTIL_UPDATE_INTERVAL == 0) {
|
|
||||||
int util_count = 0;
|
|
||||||
for (int ui = 0; ui < DCD_SAMPLES; ui++) {
|
|
||||||
if (_util_samples[ui]) util_count++;
|
|
||||||
}
|
|
||||||
_local_channel_util = (float)util_count / (float)DCD_SAMPLES;
|
|
||||||
_total_channel_util = _local_channel_util + _airtime;
|
|
||||||
if (_total_channel_util > 1.0) _total_channel_util = 1.0;
|
|
||||||
|
|
||||||
int16_t cb = current_airtime_bin();
|
|
||||||
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
|
||||||
if (_total_channel_util > _longterm_bins[cb]) _longterm_bins[cb] = _total_channel_util;
|
|
||||||
_longterm_bins[nb] = 0.0;
|
|
||||||
|
|
||||||
updateAirtime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
void updateModemStatus() {
|
|
||||||
#if PLATFORM == PLATFORM_ESP32
|
|
||||||
portENTER_CRITICAL(&update_lock);
|
|
||||||
#elif PLATFORM == PLATFORM_NRF52
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t status = modemStatus();
|
|
||||||
|
|
||||||
_last_status_update = millis();
|
|
||||||
|
|
||||||
#if PLATFORM == PLATFORM_ESP32
|
|
||||||
portEXIT_CRITICAL(&update_lock);
|
|
||||||
#elif PLATFORM == PLATFORM_NRF52
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((status & SIG_DETECT) == SIG_DETECT) { _stat_signal_detected = true; } else { _stat_signal_detected = false; }
|
|
||||||
if ((status & SIG_SYNCED) == SIG_SYNCED) { _stat_signal_synced = true; } else { _stat_signal_synced = false; }
|
|
||||||
if ((status & RX_ONGOING) == RX_ONGOING) { _stat_rx_ongoing = true; } else { _stat_rx_ongoing = false; }
|
|
||||||
|
|
||||||
// if (stat_signal_detected || stat_signal_synced || stat_rx_ongoing) {
|
|
||||||
if (_stat_signal_detected || _stat_signal_synced) {
|
|
||||||
if (_stat_rx_ongoing) {
|
|
||||||
if (_dcd_count < DCD_THRESHOLD) {
|
|
||||||
_dcd_count++;
|
|
||||||
} else {
|
|
||||||
_last_dcd = _last_status_update;
|
|
||||||
_dcd_led = true;
|
|
||||||
_dcd = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_dcd_count == 0) {
|
|
||||||
_dcd_led = false;
|
|
||||||
} else if (_dcd_count > DCD_LED_STEP_D) {
|
|
||||||
_dcd_count -= DCD_LED_STEP_D;
|
|
||||||
} else {
|
|
||||||
_dcd_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_last_status_update > _last_dcd+_csma_slot_ms) {
|
|
||||||
_dcd = false;
|
|
||||||
_dcd_led = false;
|
|
||||||
_dcd_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (_dcd_led) {
|
|
||||||
led_rx_on();
|
|
||||||
} else {
|
|
||||||
if (_airtime_lock) {
|
|
||||||
led_indicate_airtime_lock();
|
|
||||||
} else {
|
|
||||||
led_rx_off();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
void setPostTxYieldTimeout(uint32_t timeout) { _post_tx_yield_timeout = timeout; };
|
|
||||||
uint32_t getPostTxYieldTimeout() { return _post_tx_yield_timeout; };
|
|
||||||
void setDCD(bool dcd) { _dcd = dcd; };
|
|
||||||
bool getDCD() { return _dcd; };
|
|
||||||
void setDCDWaiting(bool dcd_waiting) { _dcd_waiting = dcd_waiting; };
|
|
||||||
bool getDCDWaiting() { return _dcd_waiting; };
|
|
||||||
void setDCDWaitUntil(uint32_t dcd_wait_until) { _dcd_wait_until = dcd_wait_until; };
|
|
||||||
bool getDCDWaitUntil() { return _dcd_wait_until; };
|
|
||||||
float getAirtime() { return _airtime; };
|
|
||||||
float getLongtermAirtime() { return _longterm_airtime; };
|
|
||||||
float getTotalChannelUtil() { return _total_channel_util; };
|
|
||||||
float getLongtermChannelUtil() { return _longterm_channel_util; };
|
|
||||||
float CSMASlope(float u) { return (pow(_e,_S*u-_S/2.0))/(pow(_e,_S*u-_S/2.0)+1.0); };
|
|
||||||
void updateCSMAp() {
|
|
||||||
_csma_p = (uint8_t)((1.0-(_csma_p_min+(_csma_p_max-_csma_p_min)*CSMASlope(_airtime)))*255.0);
|
|
||||||
};
|
|
||||||
uint8_t getCSMAp() { return _csma_p; };
|
|
||||||
void setCSMASlotMS(int slot_size) { _csma_slot_ms = slot_size; };
|
|
||||||
int getCSMASlotMS() { return _csma_slot_ms; };
|
|
||||||
float getSymbolTime() { return _lora_symbol_time_ms; };
|
|
||||||
float getSymbolRate() { return _lora_symbol_rate; };
|
|
||||||
long getPreambleLength() { return _preambleLength; };
|
|
||||||
protected:
|
|
||||||
virtual void explicitHeaderMode() = 0;
|
|
||||||
virtual void implicitHeaderMode() = 0;
|
|
||||||
|
|
||||||
uint8_t _index;
|
|
||||||
bool _radio_locked;
|
|
||||||
bool _radio_online;
|
|
||||||
float _st_airtime_limit;
|
|
||||||
float _lt_airtime_limit;
|
|
||||||
bool _airtime_lock;
|
|
||||||
uint16_t _airtime_bins[AIRTIME_BINS] = {0};
|
|
||||||
uint16_t _longterm_bins[AIRTIME_BINS] = {0};
|
|
||||||
float _airtime;
|
|
||||||
float _longterm_airtime;
|
|
||||||
float _local_channel_util;
|
|
||||||
float _total_channel_util;
|
|
||||||
float _longterm_channel_util;
|
|
||||||
uint32_t _last_status_update;
|
|
||||||
bool _stat_signal_detected;
|
|
||||||
bool _stat_signal_synced;
|
|
||||||
bool _stat_rx_ongoing;
|
|
||||||
uint32_t _last_dcd;
|
|
||||||
uint16_t _dcd_count;
|
|
||||||
bool _dcd;
|
|
||||||
bool _dcd_led;
|
|
||||||
bool _dcd_waiting;
|
|
||||||
long _dcd_wait_until;
|
|
||||||
bool _util_samples[DCD_SAMPLES] = {false};
|
|
||||||
int _dcd_sample;
|
|
||||||
uint32_t _post_tx_yield_timeout;
|
|
||||||
uint8_t _csma_p;
|
|
||||||
int _csma_slot_ms;
|
|
||||||
float _csma_p_min;
|
|
||||||
float _csma_p_max;
|
|
||||||
long _preambleLength;
|
|
||||||
float _lora_symbol_time_ms;
|
|
||||||
float _lora_symbol_rate;
|
|
||||||
float _lora_us_per_byte;
|
|
||||||
uint32_t _bitrate;
|
|
||||||
uint8_t _packet[255];
|
|
||||||
void (*_onReceive)(uint8_t, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
class sx126x : public RadioInterface {
|
|
||||||
public:
|
|
||||||
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);
|
|
||||||
|
|
||||||
int begin();
|
|
||||||
void end();
|
|
||||||
|
|
||||||
int beginPacket(int implicitHeader = false);
|
|
||||||
int endPacket();
|
|
||||||
|
|
||||||
int packetRssi();
|
|
||||||
int currentRssi();
|
|
||||||
uint8_t packetRssiRaw();
|
|
||||||
uint8_t currentRssiRaw();
|
|
||||||
uint8_t packetSnrRaw();
|
|
||||||
float packetSnr();
|
|
||||||
long packetFrequencyError();
|
|
||||||
|
|
||||||
// from Print
|
|
||||||
size_t write(uint8_t byte);
|
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
|
||||||
|
|
||||||
// from Stream
|
|
||||||
int available();
|
|
||||||
int read();
|
|
||||||
int peek();
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
void onReceive(void(*callback)(uint8_t, int));
|
|
||||||
|
|
||||||
void receive(int size = 0);
|
|
||||||
void standby();
|
|
||||||
void sleep();
|
|
||||||
|
|
||||||
bool preInit();
|
|
||||||
uint8_t getTxPower();
|
|
||||||
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
|
|
||||||
uint32_t getFrequency();
|
|
||||||
void setFrequency(uint32_t frequency);
|
|
||||||
void setSpreadingFactor(int sf);
|
|
||||||
uint8_t getSpreadingFactor();
|
|
||||||
uint32_t getSignalBandwidth();
|
|
||||||
void setSignalBandwidth(uint32_t sbw);
|
|
||||||
void setCodingRate4(int denominator);
|
|
||||||
uint8_t getCodingRate4();
|
|
||||||
void setPreambleLength(long length);
|
|
||||||
uint8_t modemStatus();
|
|
||||||
void enableCrc();
|
|
||||||
void disableCrc();
|
|
||||||
void enableTCXO();
|
|
||||||
void disableTCXO();
|
|
||||||
|
|
||||||
|
|
||||||
byte random();
|
|
||||||
|
|
||||||
void setSPIFrequency(uint32_t frequency);
|
|
||||||
|
|
||||||
void dumpRegisters(Stream& out);
|
|
||||||
|
|
||||||
void updateBitrate();
|
|
||||||
|
|
||||||
void handleDio0Rise();
|
|
||||||
private:
|
|
||||||
void writeBuffer(const uint8_t* buffer, size_t size);
|
|
||||||
void readBuffer(uint8_t* buffer, size_t size);
|
|
||||||
void loraMode();
|
|
||||||
void rxAntEnable();
|
|
||||||
void setPacketParams(uint32_t preamble, uint8_t headermode, uint8_t length, uint8_t crc);
|
|
||||||
void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro);
|
|
||||||
void setSyncWord(uint16_t sw);
|
|
||||||
void waitOnBusy();
|
|
||||||
void executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size);
|
|
||||||
void executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size);
|
|
||||||
void explicitHeaderMode();
|
|
||||||
void implicitHeaderMode();
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t readRegister(uint16_t address);
|
|
||||||
void writeRegister(uint16_t address, uint8_t value);
|
|
||||||
uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
|
|
||||||
|
|
||||||
static void onDio0Rise();
|
|
||||||
|
|
||||||
void handleLowDataRate();
|
|
||||||
void optimizeModemSensitivity();
|
|
||||||
|
|
||||||
void reset(void);
|
|
||||||
void calibrate(void);
|
|
||||||
void calibrate_image(uint32_t frequency);
|
|
||||||
bool getPacketValidity();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SPISettings _spiSettings;
|
|
||||||
SPIClass* _spiModem;
|
|
||||||
int _ss;
|
|
||||||
int _sclk;
|
|
||||||
int _mosi;
|
|
||||||
int _miso;
|
|
||||||
int _reset;
|
|
||||||
int _dio0;
|
|
||||||
int _rxen;
|
|
||||||
int _busy;
|
|
||||||
uint32_t _frequency;
|
|
||||||
int _txp;
|
|
||||||
uint8_t _sf;
|
|
||||||
uint8_t _bw;
|
|
||||||
uint8_t _cr;
|
|
||||||
uint8_t _ldro;
|
|
||||||
int _packetIndex;
|
|
||||||
int _implicitHeaderMode;
|
|
||||||
int _payloadLength;
|
|
||||||
int _crcMode;
|
|
||||||
int _fifo_tx_addr_ptr;
|
|
||||||
int _fifo_rx_addr_ptr;
|
|
||||||
bool _preinit_done;
|
|
||||||
uint8_t _index;
|
|
||||||
bool _tcxo;
|
|
||||||
bool _dio2_as_rf_switch;
|
|
||||||
};
|
|
||||||
|
|
||||||
class sx127x : public RadioInterface {
|
|
||||||
public:
|
|
||||||
sx127x(uint8_t index, SPIClass* spi, int ss, int sclk, int mosi, int miso, int reset, int dio0, int busy);
|
|
||||||
|
|
||||||
int begin();
|
|
||||||
void end();
|
|
||||||
|
|
||||||
int beginPacket(int implicitHeader = false);
|
|
||||||
int endPacket();
|
|
||||||
|
|
||||||
int packetRssi();
|
|
||||||
int currentRssi();
|
|
||||||
uint8_t packetRssiRaw();
|
|
||||||
uint8_t currentRssiRaw();
|
|
||||||
uint8_t packetSnrRaw();
|
|
||||||
float packetSnr();
|
|
||||||
long packetFrequencyError();
|
|
||||||
|
|
||||||
// from Print
|
|
||||||
size_t write(uint8_t byte);
|
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
|
||||||
|
|
||||||
// from Stream
|
|
||||||
int available();
|
|
||||||
int read();
|
|
||||||
int peek();
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
void onReceive(void(*callback)(uint8_t, int));
|
|
||||||
|
|
||||||
void receive(int size = 0);
|
|
||||||
void standby();
|
|
||||||
void sleep();
|
|
||||||
|
|
||||||
bool preInit();
|
|
||||||
uint8_t getTxPower();
|
|
||||||
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
|
|
||||||
uint32_t getFrequency();
|
|
||||||
void setFrequency(uint32_t frequency);
|
|
||||||
void setSpreadingFactor(int sf);
|
|
||||||
uint8_t getSpreadingFactor();
|
|
||||||
uint32_t getSignalBandwidth();
|
|
||||||
void setSignalBandwidth(uint32_t sbw);
|
|
||||||
void setCodingRate4(int denominator);
|
|
||||||
uint8_t getCodingRate4();
|
|
||||||
void setPreambleLength(long length);
|
|
||||||
uint8_t modemStatus();
|
|
||||||
void enableCrc();
|
|
||||||
void disableCrc();
|
|
||||||
void enableTCXO();
|
|
||||||
void disableTCXO();
|
|
||||||
|
|
||||||
byte random();
|
|
||||||
|
|
||||||
void setSPIFrequency(uint32_t frequency);
|
|
||||||
|
|
||||||
void updateBitrate();
|
|
||||||
|
|
||||||
void handleDio0Rise();
|
|
||||||
bool getPacketValidity();
|
|
||||||
private:
|
|
||||||
void setSyncWord(uint8_t sw);
|
|
||||||
void explicitHeaderMode();
|
|
||||||
void implicitHeaderMode();
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t readRegister(uint8_t address);
|
|
||||||
void writeRegister(uint8_t address, uint8_t value);
|
|
||||||
uint8_t singleTransfer(uint8_t address, uint8_t value);
|
|
||||||
|
|
||||||
static void onDio0Rise();
|
|
||||||
|
|
||||||
void handleLowDataRate();
|
|
||||||
void optimizeModemSensitivity();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SPISettings _spiSettings;
|
|
||||||
SPIClass* _spiModem;
|
|
||||||
int _ss;
|
|
||||||
int _sclk;
|
|
||||||
int _mosi;
|
|
||||||
int _miso;
|
|
||||||
int _reset;
|
|
||||||
int _dio0;
|
|
||||||
int _busy;
|
|
||||||
uint32_t _frequency;
|
|
||||||
int _packetIndex;
|
|
||||||
int _implicitHeaderMode;
|
|
||||||
bool _preinit_done;
|
|
||||||
uint8_t _index;
|
|
||||||
uint8_t _sf;
|
|
||||||
uint8_t _cr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class sx128x : public RadioInterface {
|
|
||||||
public:
|
|
||||||
sx128x(uint8_t index, SPIClass* spi, bool tcxo, int ss, int sclk, int mosi, int miso, int reset, int dio0, int busy, int rxen, int txen);
|
|
||||||
|
|
||||||
int begin();
|
|
||||||
void end();
|
|
||||||
|
|
||||||
int beginPacket(int implicitHeader = false);
|
|
||||||
int endPacket();
|
|
||||||
|
|
||||||
int packetRssi();
|
|
||||||
int currentRssi();
|
|
||||||
uint8_t packetRssiRaw();
|
|
||||||
uint8_t currentRssiRaw();
|
|
||||||
uint8_t packetSnrRaw();
|
|
||||||
float packetSnr();
|
|
||||||
long packetFrequencyError();
|
|
||||||
|
|
||||||
// from Print
|
|
||||||
size_t write(uint8_t byte);
|
|
||||||
size_t write(const uint8_t *buffer, size_t size);
|
|
||||||
|
|
||||||
// from Stream
|
|
||||||
int available();
|
|
||||||
int read();
|
|
||||||
int peek();
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
void onReceive(void(*callback)(uint8_t, int));
|
|
||||||
|
|
||||||
void receive(int size = 0);
|
|
||||||
void standby();
|
|
||||||
void sleep();
|
|
||||||
|
|
||||||
bool preInit();
|
|
||||||
uint8_t getTxPower();
|
|
||||||
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
|
|
||||||
uint32_t getFrequency();
|
|
||||||
void setFrequency(uint32_t frequency);
|
|
||||||
void setSpreadingFactor(int sf);
|
|
||||||
uint8_t getSpreadingFactor();
|
|
||||||
uint32_t getSignalBandwidth();
|
|
||||||
void setSignalBandwidth(uint32_t sbw);
|
|
||||||
void setCodingRate4(int denominator);
|
|
||||||
uint8_t getCodingRate4();
|
|
||||||
void setPreambleLength(long length);
|
|
||||||
uint8_t modemStatus();
|
|
||||||
void enableCrc();
|
|
||||||
void disableCrc();
|
|
||||||
void enableTCXO();
|
|
||||||
void disableTCXO();
|
|
||||||
|
|
||||||
byte random();
|
|
||||||
|
|
||||||
void setSPIFrequency(uint32_t frequency);
|
|
||||||
|
|
||||||
void dumpRegisters(Stream& out);
|
|
||||||
|
|
||||||
void updateBitrate();
|
|
||||||
|
|
||||||
void handleDio0Rise();
|
|
||||||
|
|
||||||
bool getPacketValidity();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void writeBuffer(const uint8_t* buffer, size_t size);
|
|
||||||
void readBuffer(uint8_t* buffer, size_t size);
|
|
||||||
void txAntEnable();
|
|
||||||
void rxAntEnable();
|
|
||||||
void loraMode();
|
|
||||||
void waitOnBusy();
|
|
||||||
void executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size);
|
|
||||||
void executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size);
|
|
||||||
void setPacketParams(uint32_t preamble, uint8_t headermode, uint8_t length, uint8_t crc);
|
|
||||||
void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr);
|
|
||||||
void setSyncWord(int sw);
|
|
||||||
void explicitHeaderMode();
|
|
||||||
void implicitHeaderMode();
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t readRegister(uint16_t address);
|
|
||||||
void writeRegister(uint16_t address, uint8_t value);
|
|
||||||
uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
|
|
||||||
|
|
||||||
static void onDio0Rise();
|
|
||||||
|
|
||||||
void handleLowDataRate();
|
|
||||||
void optimizeModemSensitivity();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SPISettings _spiSettings;
|
|
||||||
SPIClass* _spiModem;
|
|
||||||
int _ss;
|
|
||||||
int _sclk;
|
|
||||||
int _mosi;
|
|
||||||
int _miso;
|
|
||||||
int _reset;
|
|
||||||
int _dio0;
|
|
||||||
int _rxen;
|
|
||||||
int _txen;
|
|
||||||
int _busy;
|
|
||||||
int _modem;
|
|
||||||
uint32_t _frequency;
|
|
||||||
int _txp;
|
|
||||||
uint8_t _sf;
|
|
||||||
uint8_t _bw;
|
|
||||||
uint8_t _cr;
|
|
||||||
int _packetIndex;
|
|
||||||
int _implicitHeaderMode;
|
|
||||||
int _payloadLength;
|
|
||||||
int _crcMode;
|
|
||||||
int _fifo_tx_addr_ptr;
|
|
||||||
int _fifo_rx_addr_ptr;
|
|
||||||
bool _preinit_done;
|
|
||||||
int _rxPacketLength;
|
|
||||||
uint8_t _index;
|
|
||||||
bool _tcxo;
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
458
Utilities.h
458
Utilities.h
@ -20,6 +20,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
// For CSMA
|
||||||
|
#define _e 2.71828183
|
||||||
|
#define _S 10.0
|
||||||
|
|
||||||
#if HAS_EEPROM
|
#if HAS_EEPROM
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#elif PLATFORM == PLATFORM_NRF52
|
#elif PLATFORM == PLATFORM_NRF52
|
||||||
@ -565,16 +569,9 @@ int8_t led_standby_direction = 0;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool interface_bitrate_cmp(RadioInterface* p, RadioInterface* q) {
|
|
||||||
long p_bitrate = p->getBitrate();
|
|
||||||
long q_bitrate = q->getBitrate();
|
|
||||||
return p_bitrate > q_bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort interfaces in descending order according to bitrate.
|
// Sort interfaces in descending order according to bitrate.
|
||||||
void sort_interfaces() {
|
void sort_interfaces() {
|
||||||
std::sort(std::begin(interface_obj_sorted), std::end(interface_obj_sorted), interface_bitrate_cmp);
|
//std::sort(std::begin(interface_obj_sorted), std::end(interface_obj_sorted), interface_bitrate_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_write(uint8_t byte) {
|
void serial_write(uint8_t byte) {
|
||||||
@ -621,10 +618,10 @@ void kiss_indicate_error(uint8_t error_code) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_radiostate(RadioInterface* radio) {
|
void kiss_indicate_radiostate(uint8_t index) {
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_RADIO_STATE);
|
serial_write(CMD_RADIO_STATE);
|
||||||
serial_write(radio->getRadioOnline());
|
serial_write(radio_details[index].radio_online);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,24 +662,25 @@ void kiss_indicate_stat_snr() {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_radio_lock(RadioInterface* radio) {
|
void kiss_indicate_radio_lock(uint8_t index) {
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_RADIO_LOCK);
|
serial_write(CMD_RADIO_LOCK);
|
||||||
serial_write(radio->getRadioLock());
|
serial_write(radio_details[index].radio_locked);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_spreadingfactor(RadioInterface* radio) {
|
void kiss_indicate_spreadingfactor(uint8_t index) {
|
||||||
|
// \todo, add ability to choose FSK when multiple modem mode support added
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_SF);
|
serial_write(CMD_SF);
|
||||||
serial_write(radio->getSpreadingFactor());
|
serial_write(radio_details[index].sf);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_codingrate(RadioInterface* radio) {
|
void kiss_indicate_codingrate(uint8_t index) {
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_CR);
|
serial_write(CMD_CR);
|
||||||
serial_write(radio->getCodingRate4());
|
serial_write(radio_details[index].cr);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,16 +691,16 @@ void kiss_indicate_implicit_length() {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_txpower(RadioInterface* radio) {
|
void kiss_indicate_txpower(uint8_t index) {
|
||||||
int8_t txp = radio->getTxPower();
|
int8_t txp = radio_details[index].txp;
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_TXPOWER);
|
serial_write(CMD_TXPOWER);
|
||||||
serial_write(txp);
|
serial_write(txp);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_bandwidth(RadioInterface* radio) {
|
void kiss_indicate_bandwidth(uint8_t index) {
|
||||||
uint32_t bw = radio->getSignalBandwidth();
|
uint32_t bw = radio_details[index].bw * 1000;
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_BANDWIDTH);
|
serial_write(CMD_BANDWIDTH);
|
||||||
escaped_serial_write(bw>>24);
|
escaped_serial_write(bw>>24);
|
||||||
@ -712,8 +710,8 @@ void kiss_indicate_bandwidth(RadioInterface* radio) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_frequency(RadioInterface* radio) {
|
void kiss_indicate_frequency(uint8_t index) {
|
||||||
uint32_t freq = radio->getFrequency();
|
uint32_t freq = uint32_t(radio_details[index].freq * 1000000);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_FREQUENCY);
|
serial_write(CMD_FREQUENCY);
|
||||||
escaped_serial_write(freq>>24);
|
escaped_serial_write(freq>>24);
|
||||||
@ -732,8 +730,8 @@ void kiss_indicate_interface(int index) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_st_alock(RadioInterface* radio) {
|
void kiss_indicate_st_alock(uint8_t index) {
|
||||||
uint16_t at = (uint16_t)(radio->getSTALock()*100*100);
|
uint16_t at = (uint16_t)(radio_details[index].st_airtime_limit*100*100);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_ST_ALOCK);
|
serial_write(CMD_ST_ALOCK);
|
||||||
escaped_serial_write(at>>8);
|
escaped_serial_write(at>>8);
|
||||||
@ -741,8 +739,8 @@ void kiss_indicate_st_alock(RadioInterface* radio) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_lt_alock(RadioInterface* radio) {
|
void kiss_indicate_lt_alock(uint8_t index) {
|
||||||
uint16_t at = (uint16_t)(radio->getLTALock()*100*100);
|
uint16_t at = (uint16_t)(radio_details[index].lt_airtime_limit*100*100);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_LT_ALOCK);
|
serial_write(CMD_LT_ALOCK);
|
||||||
escaped_serial_write(at>>8);
|
escaped_serial_write(at>>8);
|
||||||
@ -750,11 +748,11 @@ void kiss_indicate_lt_alock(RadioInterface* radio) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_channel_stats(RadioInterface* radio) {
|
void kiss_indicate_channel_stats(uint8_t index) {
|
||||||
uint16_t ats = (uint16_t)(radio->getAirtime()*100*100);
|
uint16_t ats = (uint16_t)(radio_details[index].airtime*100*100);
|
||||||
uint16_t atl = (uint16_t)(radio->getLongtermAirtime()*100*100);
|
uint16_t atl = (uint16_t)(radio_details[index].longterm_airtime*100*100);
|
||||||
uint16_t cls = (uint16_t)(radio->getTotalChannelUtil()*100*100);
|
uint16_t cls = (uint16_t)(radio_details[index].total_channel_util*100*100);
|
||||||
uint16_t cll = (uint16_t)(radio->getLongtermChannelUtil()*100*100);
|
uint16_t cll = (uint16_t)(radio_details[index].longterm_channel_util*100*100);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_STAT_CHTM);
|
serial_write(CMD_STAT_CHTM);
|
||||||
escaped_serial_write(ats>>8);
|
escaped_serial_write(ats>>8);
|
||||||
@ -768,12 +766,12 @@ void kiss_indicate_channel_stats(RadioInterface* radio) {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kiss_indicate_phy_stats(RadioInterface* radio) {
|
void kiss_indicate_phy_stats(uint8_t index) {
|
||||||
uint16_t lst = (uint16_t)(radio->getSymbolTime()*1000);
|
uint16_t lst = (uint16_t)(radio_details[index].lora_symbol_time_ms*1000);
|
||||||
uint16_t lsr = (uint16_t)(radio->getSymbolRate());
|
uint16_t lsr = (uint16_t)(radio_details[index].lora_symbol_rate);
|
||||||
uint16_t prs = (uint16_t)(radio->getPreambleLength()+4);
|
uint16_t prs = (uint16_t)(radio_details[index].preamble_length+4);
|
||||||
uint16_t prt = (uint16_t)((radio->getPreambleLength()+4)*radio->getSymbolTime());
|
uint16_t prt = (uint16_t)((radio_details[index].preamble_length+4)*radio_details[index].lora_symbol_time_ms);
|
||||||
uint16_t cst = (uint16_t)(radio->getCSMASlotMS());
|
uint16_t cst = (uint16_t)(radio_details[index].csma_slot_ms);
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
serial_write(CMD_STAT_PHYPRM);
|
serial_write(CMD_STAT_PHYPRM);
|
||||||
escaped_serial_write(lst>>8);
|
escaped_serial_write(lst>>8);
|
||||||
@ -964,6 +962,203 @@ void kiss_indicate_mcu() {
|
|||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_radio_params(PhysicalLayer* radio, struct radio_vars* config) {
|
||||||
|
DataRate_t params;
|
||||||
|
params.lora.spreadingFactor = config->sf;
|
||||||
|
params.lora.codingRate = config->cr;
|
||||||
|
params.lora.bandwidth = config->bw;
|
||||||
|
int16_t status = radio->setDataRate(params);
|
||||||
|
if (status != RADIOLIB_ERR_NONE) {
|
||||||
|
kiss_indicate_error(ERROR_INITRADIO);
|
||||||
|
led_indicate_error(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t set_spreading_factor(PhysicalLayer* radio, uint8_t index, uint8_t sf) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
config->sf = sf;
|
||||||
|
update_radio_params(radio, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t set_coding_rate(PhysicalLayer* radio, uint8_t index, uint8_t cr) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
config->cr = cr;
|
||||||
|
update_radio_params(radio, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t set_bandwidth(PhysicalLayer* radio, uint8_t index, float bw) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
config->bw = bw;
|
||||||
|
update_radio_params(radio, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_modem_status(PhysicalLayer* radio, uint8_t index) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
#if PLATFORM == PLATFORM_ESP32
|
||||||
|
portENTER_CRITICAL(&update_lock);
|
||||||
|
#elif PLATFORM == PLATFORM_NRF52
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// \todo implement again
|
||||||
|
uint8_t status = 0;//modemStatus();
|
||||||
|
|
||||||
|
config->last_status_update = millis();
|
||||||
|
|
||||||
|
#if PLATFORM == PLATFORM_ESP32
|
||||||
|
portEXIT_CRITICAL(&update_lock);
|
||||||
|
#elif PLATFORM == PLATFORM_NRF52
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((status & SIG_DETECT) == SIG_DETECT) { config->stat_signal_detected = true; } else { config->stat_signal_detected = false; }
|
||||||
|
if ((status & SIG_SYNCED) == SIG_SYNCED) { config->stat_signal_synced = true; } else { config->stat_signal_synced = false; }
|
||||||
|
if ((status & RX_ONGOING) == RX_ONGOING) { config->stat_rx_ongoing = true; } else { config->stat_rx_ongoing = false; }
|
||||||
|
|
||||||
|
if (config->stat_signal_detected || config->stat_signal_synced) {
|
||||||
|
if (config->stat_rx_ongoing) {
|
||||||
|
if (config->dcd_count < DCD_THRESHOLD) {
|
||||||
|
config->dcd_count++;
|
||||||
|
} else {
|
||||||
|
config->last_dcd = config->last_status_update;
|
||||||
|
config->dcd_led = true;
|
||||||
|
config->dcd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (config->dcd_count == 0) {
|
||||||
|
config->dcd_led = false;
|
||||||
|
} else if (config->dcd_count > DCD_LED_STEP_D) {
|
||||||
|
config->dcd_count -= DCD_LED_STEP_D;
|
||||||
|
} else {
|
||||||
|
config->dcd_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->last_status_update > config->last_dcd+config->csma_slot_ms) {
|
||||||
|
config->dcd = false;
|
||||||
|
config->dcd_led = false;
|
||||||
|
config->dcd_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (config->dcd_led) {
|
||||||
|
led_rx_on();
|
||||||
|
} else {
|
||||||
|
if (config->airtime_lock) {
|
||||||
|
led_indicate_airtime_lock();
|
||||||
|
} else {
|
||||||
|
led_rx_off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
float csma_slope(float u) { return (pow(_e,_S*u-_S/2.0))/(pow(_e,_S*u-_S/2.0)+1.0); };
|
||||||
|
void update_csma_p(struct radio_vars* config) {
|
||||||
|
config->csma_p = (uint8_t)((1.0-(config->csma_p_min+(config->csma_p_max-config->csma_p_min)*csma_slope(config->airtime)))*255.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool calculate_alock(struct radio_vars* config) {
|
||||||
|
bool airtime_lock = false;
|
||||||
|
if (config->st_airtime_limit != 0.0 && config->airtime >= config->st_airtime_limit) {
|
||||||
|
airtime_lock = true;
|
||||||
|
config->airtime_lock = true;
|
||||||
|
}
|
||||||
|
if (config->lt_airtime_limit != 0.0 && config->longterm_airtime >= config->lt_airtime_limit) {
|
||||||
|
airtime_lock = true;
|
||||||
|
config->airtime_lock = true;
|
||||||
|
}
|
||||||
|
return airtime_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
void add_airtime(uint8_t index, uint16_t written) {
|
||||||
|
// \todo is referencing it this was actually necessary? Could I not just do it without the pointer?
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
float packet_cost_ms = 0.0;
|
||||||
|
float payload_cost_ms = ((float)written * config->lora_us_per_byte)/1000.0;
|
||||||
|
packet_cost_ms += payload_cost_ms;
|
||||||
|
packet_cost_ms += (config->preamble_length+4.25)*config->lora_symbol_time_ms;
|
||||||
|
packet_cost_ms += PHY_HEADER_LORA_SYMBOLS * config->lora_symbol_time_ms;
|
||||||
|
uint16_t cb = current_airtime_bin();
|
||||||
|
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
||||||
|
config->airtime_bins[cb] += packet_cost_ms;
|
||||||
|
config->airtime_bins[nb] = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void update_airtime(uint8_t index) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
uint16_t cb = current_airtime_bin();
|
||||||
|
uint16_t pb = cb-1; if (cb-1 < 0) { pb = AIRTIME_BINS-1; }
|
||||||
|
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
||||||
|
config->airtime_bins[nb] = 0;
|
||||||
|
config->airtime = (float)(config->airtime_bins[cb]+config->airtime_bins[pb])/(2.0*AIRTIME_BINLEN_MS);
|
||||||
|
|
||||||
|
uint32_t longterm_airtime_sum = 0;
|
||||||
|
for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) {
|
||||||
|
longterm_airtime_sum += config->airtime_bins[bin];
|
||||||
|
}
|
||||||
|
config->longterm_airtime = (float)longterm_airtime_sum/(float)AIRTIME_LONGTERM_MS;
|
||||||
|
|
||||||
|
float longterm_channel_util_sum = 0.0;
|
||||||
|
for (uint16_t bin = 0; bin < AIRTIME_BINS; bin++) {
|
||||||
|
longterm_channel_util_sum += config->longterm_bins[bin];
|
||||||
|
}
|
||||||
|
config->longterm_channel_util = (float)longterm_channel_util_sum/(float)AIRTIME_BINS;
|
||||||
|
|
||||||
|
update_csma_p(config);
|
||||||
|
|
||||||
|
//kiss_indicate_channel_stats(); // todo: enable me!
|
||||||
|
};
|
||||||
|
|
||||||
|
void check_modem_status(PhysicalLayer* radio, uint8_t index) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
if (millis()-(config->last_status_update) >= STATUS_INTERVAL_MS) {
|
||||||
|
update_modem_status(radio, index);
|
||||||
|
|
||||||
|
config->util_samples[config->dcd_sample] = config->dcd;
|
||||||
|
config->dcd_sample = (config->dcd_sample+1)%DCD_SAMPLES;
|
||||||
|
if (config->dcd_sample % UTIL_UPDATE_INTERVAL == 0) {
|
||||||
|
int util_count = 0;
|
||||||
|
for (int ui = 0; ui < DCD_SAMPLES; ui++) {
|
||||||
|
if (config->util_samples[ui]) util_count++;
|
||||||
|
}
|
||||||
|
config->local_channel_util = (float)util_count / (float)DCD_SAMPLES;
|
||||||
|
config->total_channel_util = config->local_channel_util + config->airtime;
|
||||||
|
if (config->total_channel_util > 1.0) config->total_channel_util = 1.0;
|
||||||
|
|
||||||
|
int16_t cb = current_airtime_bin();
|
||||||
|
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
|
||||||
|
if (config->total_channel_util > config->longterm_bins[cb]) config->longterm_bins[cb] = config->total_channel_util;
|
||||||
|
config->longterm_bins[nb] = 0.0;
|
||||||
|
|
||||||
|
update_airtime(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void update_bitrate(PhysicalLayer* radio, uint8_t index) {
|
||||||
|
struct radio_vars* config = &radio_details[index];
|
||||||
|
if (config->radio_online) {
|
||||||
|
config->lora_symbol_rate = (config->bw*1000)/(float)(pow(2, config->sf));
|
||||||
|
config->lora_symbol_time_ms = (1.0/config->lora_symbol_rate)*1000.0;
|
||||||
|
config->bitrate = (uint32_t)(config->sf * ( (4.0/(float)(config->cr+4)) / ((float)(pow(2, config->sf))/config->bw) ) * 1000.0);
|
||||||
|
config->lora_us_per_byte = 1000000.0/((float)config->bitrate/8.0);
|
||||||
|
//_csma_slot_ms = _lora_symbol_time_ms*10;
|
||||||
|
float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/config->lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
|
||||||
|
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
|
||||||
|
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
|
||||||
|
} else {
|
||||||
|
target_preamble_symbols = ceil(target_preamble_symbols);
|
||||||
|
}
|
||||||
|
// \todo actually update this on the radio
|
||||||
|
config->preamble_length = target_preamble_symbols;
|
||||||
|
radio->setPreambleLength(target_preamble_symbols);
|
||||||
|
} else {
|
||||||
|
config->bitrate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool isSplitPacket(uint8_t header) {
|
inline bool isSplitPacket(uint8_t header) {
|
||||||
return (header & FLAG_SPLIT);
|
return (header & FLAG_SPLIT);
|
||||||
}
|
}
|
||||||
@ -981,66 +1176,69 @@ void set_implicit_length(uint8_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTXPower(RadioInterface* radio, int txp) {
|
void setTXPower(PhysicalLayer* radio, uint8_t index, int txp) {
|
||||||
// Todo, revamp this function. The current parameters for setTxPower are
|
// Todo, revamp this function. The current parameters for setTxPower are
|
||||||
// suboptimal, as some chips have power amplifiers which means that the max
|
// suboptimal, as some chips have power amplifiers which means that the max
|
||||||
// dBm is not always the same.
|
// dBm is not always the same.
|
||||||
if (model == MODEL_11) {
|
int8_t set_pwr;
|
||||||
if (interfaces[radio->getIndex()] == SX128X) {
|
radio->checkOutputPower(txp, &set_pwr);
|
||||||
radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
radio_details[index].txp = set_pwr;
|
||||||
} else {
|
//if (model == MODEL_11) {
|
||||||
radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
// if (interfaces[radio->getIndex()] == SX128X) {
|
||||||
}
|
// radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
}
|
// } else {
|
||||||
if (model == MODEL_12) {
|
// radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
if (interfaces[radio->getIndex()] == SX128X) {
|
// }
|
||||||
radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//}
|
||||||
} else {
|
//if (model == MODEL_12) {
|
||||||
radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
// if (interfaces[radio->getIndex()] == SX128X) {
|
||||||
}
|
// radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
}
|
// } else {
|
||||||
|
// radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if (model == MODEL_21) {
|
//if (model == MODEL_21) {
|
||||||
if (interfaces[radio->getIndex()] == SX128X) {
|
// if (interfaces[radio->getIndex()] == SX128X) {
|
||||||
radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
// radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
} else {
|
// } else {
|
||||||
radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
// radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (model == MODEL_A1) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A1) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_A2) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A2) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_A3) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
//if (model == MODEL_A3) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
if (model == MODEL_A4) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
//if (model == MODEL_A4) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
if (model == MODEL_A5) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
//if (model == MODEL_A5) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
if (model == MODEL_A6) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A6) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_A7) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A7) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_A8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_A9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_A9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
|
|
||||||
if (model == MODEL_B3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_B3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_B4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_B4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_B8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_B8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_B9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_B9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
|
|
||||||
if (model == MODEL_C4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_C4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_C9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_C9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
|
|
||||||
if (model == MODEL_E4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_E4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_E9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_E9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_E3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_E3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_E8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_E8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
|
|
||||||
if (model == MODEL_FE) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
//if (model == MODEL_FE) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
|
||||||
if (model == MODEL_FF) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
//if (model == MODEL_FF) radio->setTxPower(txp, PA_OUTPUT_RFO_PIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getRandom(RadioInterface* radio) {
|
uint8_t getRandom(PhysicalLayer* radio) {
|
||||||
if (radio->getRadioOnline()) {
|
//if (radio->getRadioOnline()) {
|
||||||
return radio->random();
|
// return radio->random();
|
||||||
} else {
|
//} else {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getInterfaceIndex(uint8_t byte) {
|
uint8_t getInterfaceIndex(uint8_t byte) {
|
||||||
@ -1475,57 +1673,59 @@ bool eeprom_have_conf() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom_conf_load(RadioInterface* radio) {
|
void eeprom_conf_load(PhysicalLayer* radio) {
|
||||||
if (eeprom_have_conf()) {
|
// \todo remove, or will attermann need it?
|
||||||
if (!(radio->getRadioOnline())) {
|
//if (eeprom_have_conf()) {
|
||||||
#if HAS_EEPROM
|
// if (!(radio->getRadioOnline())) {
|
||||||
uint8_t sf = EEPROM.read(eeprom_addr(ADDR_CONF_SF));
|
// #if HAS_EEPROM
|
||||||
uint8_t cr = EEPROM.read(eeprom_addr(ADDR_CONF_CR));
|
// uint8_t sf = EEPROM.read(eeprom_addr(ADDR_CONF_SF));
|
||||||
uint8_t txp = EEPROM.read(eeprom_addr(ADDR_CONF_TXP));
|
// uint8_t cr = EEPROM.read(eeprom_addr(ADDR_CONF_CR));
|
||||||
uint32_t freq = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x03);
|
// uint8_t txp = EEPROM.read(eeprom_addr(ADDR_CONF_TXP));
|
||||||
uint32_t bw = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x03);
|
// uint32_t freq = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x03);
|
||||||
#elif MCU_VARIANT == MCU_NRF52
|
// uint32_t bw = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x03);
|
||||||
uint8_t sf = eeprom_read(eeprom_addr(ADDR_CONF_SF));
|
// #elif MCU_VARIANT == MCU_NRF52
|
||||||
uint8_t cr = eeprom_read(eeprom_addr(ADDR_CONF_CR));
|
// uint8_t sf = eeprom_read(eeprom_addr(ADDR_CONF_SF));
|
||||||
uint8_t txp = eeprom_read(eeprom_addr(ADDR_CONF_TXP));
|
// uint8_t cr = eeprom_read(eeprom_addr(ADDR_CONF_CR));
|
||||||
uint32_t freq = (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x03);
|
// uint8_t txp = eeprom_read(eeprom_addr(ADDR_CONF_TXP));
|
||||||
uint32_t bw = (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x03);
|
// uint32_t freq = (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_FREQ)+0x03);
|
||||||
#endif
|
// uint32_t bw = (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)eeprom_read(eeprom_addr(ADDR_CONF_BW)+0x03);
|
||||||
radio->setSpreadingFactor(sf);
|
// #endif
|
||||||
radio->setCodingRate4(cr);
|
// radio->setSpreadingFactor(sf);
|
||||||
setTXPower(radio, txp);
|
// radio->setCodingRate(cr);
|
||||||
radio->setFrequency(freq);
|
// setTXPower(radio, txp);
|
||||||
radio->setSignalBandwidth(bw);
|
// radio->setFrequency(freq);
|
||||||
radio->updateBitrate();
|
// radio->setBandwidth(bw);
|
||||||
}
|
// radio->updateBitrate();
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom_conf_save(RadioInterface* radio) {
|
void eeprom_conf_save(PhysicalLayer* radio) {
|
||||||
if (hw_ready && radio->getRadioOnline()) {
|
// \todo fixme
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_SF), radio->getSpreadingFactor());
|
//if (hw_ready && radio->getRadioOnline()) {
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_CR), radio->getCodingRate4());
|
// eeprom_update(eeprom_addr(ADDR_CONF_SF), radio->getSpreadingFactorVal());
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_TXP), radio->getTxPower());
|
// eeprom_update(eeprom_addr(ADDR_CONF_CR), radio->getCodingRateVal());
|
||||||
|
// eeprom_update(eeprom_addr(ADDR_CONF_TXP), radio->getTXPowerVal());
|
||||||
|
|
||||||
uint32_t bw = radio->getSignalBandwidth();
|
// uint32_t bw = radio->getBandwidthVal() * 1000;
|
||||||
|
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x00, bw>>24);
|
// eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x00, bw>>24);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x01, bw>>16);
|
// eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x01, bw>>16);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x02, bw>>8);
|
// eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x02, bw>>8);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x03, bw);
|
// eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x03, bw);
|
||||||
|
|
||||||
uint32_t freq = radio->getFrequency();
|
// uint32_t freq = radio->getFrequencyVal() * 1000;
|
||||||
|
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x00, freq>>24);
|
// eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x00, freq>>24);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x01, freq>>16);
|
// eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x01, freq>>16);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x02, freq>>8);
|
// eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x02, freq>>8);
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x03, freq);
|
// eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x03, freq);
|
||||||
|
|
||||||
eeprom_update(eeprom_addr(ADDR_CONF_OK), CONF_OK_BYTE);
|
// eeprom_update(eeprom_addr(ADDR_CONF_OK), CONF_OK_BYTE);
|
||||||
led_indicate_info(10);
|
// led_indicate_info(10);
|
||||||
} else {
|
//} else {
|
||||||
led_indicate_warning(10);
|
// led_indicate_warning(10);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom_conf_delete() {
|
void eeprom_conf_delete() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user