dl9sau
US1GHQ 2022-10-08 16:06:03 +03:00
parent 290838bd1d
commit 594b830bcd
5 changed files with 158 additions and 145 deletions

View File

@ -3,13 +3,13 @@
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <BG_RF95.h>
#include <RadioLib.h>
#include <esp_wifi.h>
#ifndef TASK_WEBSERVER
#define TASK_WEBSERVER
extern BG_RF95 rf95;
extern SX1278 rf95;
#ifdef KISS_PROTOCOL
extern WiFiServer tncServer;
#endif

10
include/version.h 100644
View File

@ -0,0 +1,10 @@
#ifndef BUILD_NUMBER
#define BUILD_NUMBER "57"
#endif
#ifndef VERSION
#define VERSION "v0.3.57-290838b - 2022-10-08 15:48:09.958900"
#endif
#ifndef VERSION_SHORT
#define VERSION_SHORT "v0.3.57-290838b"
#endif

View File

@ -384,7 +384,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
// set expected packet length for SF6
if(_sf == 6) {
state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len + RADIOLIB_SX127X_HEADER_LEN - 1);
}
// apply fixes to errata
@ -584,6 +584,9 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
packetLen = RADIOLIB_SX127X_FIFO_THRESH - 1;
_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_THRESH, RADIOLIB_SX127X_TX_START_FIFO_NOT_EMPTY, 7, 7);
}
_mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, '<');
_mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, 0xFF);
_mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, 0x01);
_mod->SPIwriteRegisterBurst(RADIOLIB_SX127X_REG_FIFO, data, packetLen);
// this is a hack, but it seems than in Stream mode, Rx FIFO level is getting triggered 1 byte before it should

View File

@ -15,6 +15,14 @@
#define RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK 64
#define RADIOLIB_SX127X_CRYSTAL_FREQ 32.0
#define RADIOLIB_SX127X_DIV_EXPONENT 19
#define RADIOLIB_SX127X_HEADER_LEN 4
// This is the maximum message length that can be supported by this driver.
// Can be pre-defined to a smaller size (to save SRAM) prior to including this header
// Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS
#ifndef RADIOLIB_SX127X_MAX_MESSAGE_LEN
#define RADIOLIB_SX127X_MAX_MESSAGE_LEN (RADIOLIB_SX127X_MAX_PACKET_LENGTH - RADIOLIB_SX127X_HEADER_LEN)
#endif
// SX127x series common LoRa registers
#define RADIOLIB_SX127X_REG_FIFO 0x00

View File

@ -8,7 +8,7 @@
//#include <TTGO_T-Beam_LoRa_APRS_config.h> // to config user parameters
#include <Arduino.h>
#include <SPI.h>
#include <BG_RF95.h> // library from OE1ACM
#include <RadioLib.h>
#include <math.h>
#include <driver/adc.h>
#include <Wire.h>
@ -45,10 +45,20 @@ String wifi_info; // saving wifi info (CLI|AP|dis) for Oled. If W
#define SSD1306_ADDRESS 0x3C
// SPI config
#define SPI_sck 5
#define SPI_miso 19
#define SPI_mosi 27
#define SPI_ss 18
#ifdef ESP32_DEV_V1
#define SPI_sck 18
#define SPI_miso 19
#define SPI_mosi 23
#define SPI_ss 5
#else
#define SPI_sck 5
#define SPI_miso 19
#define SPI_mosi 27
#define SPI_ss 18
#define DIO0 26
#define RESET 14
#define DIO1 35
#endif
// IO config
#ifdef T_BEAM_V1_0
@ -116,6 +126,18 @@ String wifi_info; // saving wifi info (CLI|AP|dis) for Oled. If W
double lora_freq = 433.775;
#endif
// flag to indicate transmission or reception state
bool transmit_flag = false;
// flag to indicate that a packet was received
volatile bool received_flag = false;
// disable interrupt when it's not needed
volatile bool enable_interrupt = true;
// flag to indicate that a packet was sent
volatile bool transmitted_flag = false;
ulong lora_speed_cross_digi = 1200;
double lora_freq_cross_digi = 433.900;
@ -402,7 +424,7 @@ uint32_t time_lora_automaic_cr_adoption_rx_measurement_window = 0L;
uint16_t lora_automaic_cr_adoption_rf_transmissions_heard_in_timeslot = 0;
uint16_t lora_packets_received_in_timeslot_on_main_freq = 0;
uint16_t lora_packets_received_in_timeslot_on_secondary_freq = 0;
char lora_TXBUFF_for_digipeating[BG_RF95_MAX_MESSAGE_LEN+1] = ""; // buffer for digipeating
char lora_TXBUFF_for_digipeating[RADIOLIB_SX127X_MAX_MESSAGE_LEN+1] = ""; // buffer for digipeating
time_t time_lora_TXBUFF_for_digipeating_was_filled = 0L;
boolean sendpacket_was_called_twice = false;
// bits for sendpacket()
@ -425,10 +447,12 @@ static const adc_unit_t unit = ADC_UNIT_1;
AXP20X_Class axp;
#endif
// Singleton instance of the radio driver
BG_RF95 rf95(18, 26); // TTGO T-Beam has NSS @ Pin 18 and Interrupt IO @ Pin26
#ifdef ESP32_DEV_V1
SX1278 rf95 = new Module(SPI_ss, DIO0, RESET, DIO1); // For custom ESP32 and LoRa module
#else
SX1278 rf95 = new Module(SPI_ss, DIO0, RESET, DIO1);
#endif
char blacklist_calls[256] = "";
@ -436,14 +460,6 @@ char blacklist_calls[256] = "";
#define OLED_RESET 16 // not used
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
#ifdef IF_SEMAS_WOULD_WORK
xSemaphoreHandle sema_lora_chip;
#else
volatile boolean sema_lora_chip = false;
#endif
// + FUNCTIONS-----------------------------------------------------------+//
void do_serial_println(const String &msg)
@ -674,23 +690,65 @@ void buzzer(int* melody, int array_size){
void lora_set_speed(ulong lora_speed) {
if(lora_speed==1200){
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf512);
if(lora_speed==21000){
rf95.begin(lora_freq, 250.0, 12, 6, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==6000){
rf95.begin(lora_freq, 125.0, 7, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==1200){
rf95.begin(lora_freq, 125.0, 9, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==610){
rf95.setModemConfig(BG_RF95::Bw125Cr48Sf1024);
rf95.begin(lora_freq, 125.0, 10, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==180){
rf95.setModemConfig(BG_RF95::Bw125Cr48Sf4096);
rf95.begin(lora_freq, 125.0, 12, 8, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==210){
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf4096);
rf95.begin(lora_freq, 125.0, 12, 7, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==240){
rf95.setModemConfig(BG_RF95::Bw125Cr46Sf4096);
rf95.begin(lora_freq, 125.0, 12, 6, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==1367){
rf95.begin(lora_freq, 31.25, 7, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else if(lora_speed==439){
rf95.begin(lora_freq, 31.25, 9, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
else {
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096);
rf95.begin(lora_freq, 125.0, 12, 5, 0x12, txPower);
rf95.setCRC(1);
rf95.setDio0Action(setFlag);
rf95.startReceive();
}
}
@ -739,78 +797,29 @@ void loraSend(byte lora_LTXPower, float lora_FREQ, ulong lora_SPEED, const Strin
if (!lora_tx_enabled)
return;
// kind of csma/cd. TODO: better approach: add to a tx-queue
// in SF12: preamble + lora header = 663.552 -> we wait 1300ms for check if lora-chip is in decoding
// See https://www.rfwireless-world.com/calculators/LoRaWAN-Airtime-calculator.html
// In detail: At our supported speed "names":
// SF7: 28.928ms
// SF8: 57.856ms
// SF9: 115.712ms 1200
// SF10: 231.424ms 610
// SF11: 331.776ms
// SF12: 663.552ms 300,240, 210, 180
uint32_t wait_for_signal = 700;
if (lora_speed == 610) wait_for_signal = 250;
else if (lora_speed == 1200) wait_for_signal = 125;
// sema lock for lora chip operations
#ifdef IF_SEMAS_WOULD_WORK
while (xSemaphoreTake(sema_lora_chip, 10) != pdTRUE)
esp_task_wdt_reset();
#else
for (n = 0; sema_lora_chip; n++) {
delay(10);
if (!(n % 100))
esp_task_wdt_reset();
}
sema_lora_chip = true;
#endif
randomSeed(millis());
for (n = 0; n < 30; n++) {
esp_task_wdt_reset();
delay(wait_for_signal);
if (rf95.SignalDetected()) {
continue;
}
delay(100);
if (!rf95.SignalDetected() && random(256) < 64) {
break;
}
}
esp_task_wdt_reset();
#ifdef T_BEAM_V1_0
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // switch LoRa chip on
#endif
//byte array
byte lora_TXBUFF[BG_RF95_MAX_MESSAGE_LEN]; //buffer for packet to send
byte lora_TXBUFF[RADIOLIB_SX127X_MAX_MESSAGE_LEN]; //buffer for packet to send
int messageSize = min(message.length(), sizeof(lora_TXBUFF) - 1);
message.toCharArray((char*)lora_TXBUFF, messageSize + 1, 0);
lora_set_speed(lora_SPEED);
rf95.setFrequency(lora_FREQ);
rf95.setTxPower(lora_LTXPower);
enable_interrupt = false;
rf95.transmit(lora_TXBUFF, message.length());
enable_interrupt = true;
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, LOW);
#endif
lastTX = millis();
rf95.sendAPRS(lora_TXBUFF, messageSize);
rf95.waitPacketSent();
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, HIGH);
#endif
// cross-digipeating may have altered our RX-frequency. Revert frequency change needed for this transmission.
if (lora_FREQ != lora_freq_rx_curr) {
rf95.setFrequency(lora_freq_rx_curr);
// flush cache. just to be sure, so that no cross-digi-qrg packet comes in the input-buffer of the main qrg.
// With no buffer / length called, recvAPRS directly calls clearRxBuf()
rf95.recvAPRS(0, 0);
}
if (lora_SPEED != lora_speed_rx_curr)
lora_set_speed(lora_speed_rx_curr);
rf95.startReceive();
#ifdef T_BEAM_V1_0
// if lora_rx is disabled, but ONLY if lora_digipeating_mode == 0 AND no SerialBT.hasClient is connected,
// we can savely go to sleep
@ -821,13 +830,6 @@ void loraSend(byte lora_LTXPower, float lora_FREQ, ulong lora_SPEED, const Strin
) )
axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // switch LoRa chip off
#endif
// release lock
#ifdef IF_SEMAS_WOULD_WORK
xSemaphoreGive(sema_lora_chip);
#else
sema_lora_chip = false;
#endif
}
@ -2169,12 +2171,6 @@ static boolean preferences_cfg_valid = false;
batt_read();
writedisplaytext("LoRa-APRS","","Init:","ADC OK!","BAT: "+String(BattVolts,2),"");
delay(500);
if (!rf95.init()) {
writedisplaytext("LoRa-APRS","","Init:","RF95 FAILED!",":-(","");
for(;;); // Don't proceed, loop forever
}
writedisplaytext("LoRa-APRS","","Init:","RF95 OK!","","");
// if we are fill-in or wide2 digi, we listen only on configured main frequency
@ -2184,22 +2180,12 @@ static boolean preferences_cfg_valid = false;
Serial.printf("LoRa Speed:\t%lu\r\n", lora_speed_rx_curr);
lora_freq_rx_curr = (rx_on_frequencies != 2 || lora_digipeating_mode > 1) ? lora_freq : lora_freq_cross_digi;
rf95.setFrequency(lora_freq_rx_curr);
//rf95.setFrequency(lora_freq_rx_curr);
Serial.printf("LoRa FREQ:\t%f\r\n", lora_freq_rx_curr);
// we tx on main and/or secondary frequency. For tx, loraSend is called (and always has desired txpower as argument)
rf95.setTxPower((lora_digipeating_mode < 2 || lora_cross_digipeating_mode < 1) ? txPower : txPower_cross_digi);
delay(500);
// Avoid concurrent access of processes to lora our chip
#ifdef IF_SEMAS_WOULD_WORK
sema_lora_chip = xSemaphoreCreateBinary();
#else
sema_lora_chip = false;
#endif
//rf95.setTxPower((lora_digipeating_mode < 2 || lora_cross_digipeating_mode < 1) ? txPower : txPower_cross_digi);
//delay(500);
// LORA32_21: bug in hardware. cannot run bluetooth and wifi concurrently.
// We wait for a bt-client connecting, up to 60s. If none connected,
@ -2365,6 +2351,16 @@ static boolean preferences_cfg_valid = false;
digitalWrite(TXLED, HIGH);
}
void setFlag(void) {
// check if the interrupt is enabled
if(!enable_interrupt) {
return;
}
// we got a packet, set the flag
received_flag = true;
}
void enableOled() {
if (!enabled_oled)
return;
@ -2528,11 +2524,11 @@ int bg_rf95snr_to_snr(uint8_t snr)
int bg_rf95rssi_to_rssi(int rssi)
{
// We use an old BG_RF95 library from 2001. RadioHead/RH_RF95.cpp implements _lastSNR and _lastRssi correctly accordingg to the specs
int _lastSNR = bg_rf95snr_to_snr(rf95.lastSNR());
int _lastSNR = bg_rf95snr_to_snr(rf95.getSNR());
boolean _usingHFport = (lora_freq >= 779.0);
// bg_rf95 library: _lastRssi = spiRead(BG_RF95_REG_1A_PKT_RSSI_VALUE) - 137. First, undo -137 operation
int _lastRssi = rf95.lastRssi() + 137;
int _lastRssi = rf95.getRSSI() + 137;
if (_lastSNR < 0)
_lastRssi = _lastRssi + _lastSNR;
@ -2554,8 +2550,8 @@ char *encode_snr_rssi_in_path()
// https://github.com/Lora-net/LoRaMac-node/issues/275
// https://github.com/mayeranalytics/pySX127x/blob/master/SX127x/LoRa.py
// rf95snr_to_snr returns values in range -32 to 31. The lowest two bits are RFU
int snr = bg_rf95snr_to_snr(rf95.lastSNR());
int rssi = bg_rf95rssi_to_rssi(rf95.lastRssi());
int snr = bg_rf95snr_to_snr(rf95.getSNR());
int rssi = bg_rf95rssi_to_rssi(rf95.getRSSI());
if (snr > 99) snr = 99; // snr will not go upper 31
else if (snr < -99) snr = -99; // snr will not go below -32
if (rssi > 0) rssi = 0; // rssi is always negative
@ -2581,7 +2577,7 @@ char *encode_snr_rssi_in_path()
char *add_element_to_path(const char *data, const char *element)
{
static char buf[BG_RF95_MAX_MESSAGE_LEN+1];
static char buf[RADIOLIB_SX127X_MAX_MESSAGE_LEN+1];
if (strlen(data) + 1 /* ',' */ + strlen(element) + 1 /* '*' */ > sizeof(buf)-1)
return 0;
char *p = strchr(data, '>');
@ -2630,7 +2626,7 @@ char *add_element_to_path(const char *data, const char *element)
// append element to path, regardless if it will exceed max digipeaters. It's for snr encoding for aprs-is. We don't use
// add_element_to_path, because we will append at the last position, and do not change digipeated bit.
char *append_element_to_path(const char *data, const char *element) {
static char buf[BG_RF95_MAX_MESSAGE_LEN+10+1];
static char buf[RADIOLIB_SX127X_MAX_MESSAGE_LEN+10+1];
if (strlen(data) + 1 /* ',' */ + strlen(element) > sizeof(buf)-1)
return 0;
char *p = strchr(data, '>');
@ -2666,7 +2662,7 @@ struct ax25_frame {
struct ax25_frame *tnc_format_to_ax25_frame(const char *s)
{
static char data[BG_RF95_MAX_MESSAGE_LEN+1];
static char data[RADIOLIB_SX127X_MAX_MESSAGE_LEN+1];
static struct ax25_frame frame;
char *p;
char *q;
@ -3822,14 +3818,17 @@ out:
}
#endif // KISS_PROTOCOL
// sema lock for lora chip operations
#ifdef IF_SEMAS_WOULD_WORK
if (xSemaphoreTake(sema_lora_chip, 100) == pdTRUE) {
#else
if (!sema_lora_chip) {
sema_lora_chip = true;
#endif
if (rf95.waitAvailableTimeout(100)) {
if(received_flag == true) {
// disable the interrupt service routine while
// processing the data
enable_interrupt = false;
// reset flag
received_flag = false;
//get current packet size
int packetSize = rf95.getPacketLength();
#ifdef T_BEAM_V1_0
#ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
@ -3842,16 +3841,11 @@ out:
// we need to read the received packt, even if rx is set to disable. else rf95.waitAvailableTimeout(100) will always show, data is available
//byte array
byte lora_RXBUFF[BG_RF95_MAX_MESSAGE_LEN]; //buffer for packet to send
uint8_t loraReceivedLength = sizeof(lora_RXBUFF); // (implicit ) reset max length before receiving!
boolean lora_rx_data_available = rf95.recvAPRS(lora_RXBUFF, &loraReceivedLength);
// release lock here. We read the data from the lora chip. And we may call later loraSend (which should not be blocked by ourself)
#ifdef IF_SEMAS_WOULD_WORK
xSemaphoreGive(sema_lora_chip);
#else
sema_lora_chip = false;
#endif
byte lora_RXBUFF[RADIOLIB_SX127X_MAX_MESSAGE_LEN]; //buffer for packet to send
//uint8_t loraReceivedLength = sizeof(lora_RXBUFF); // (implicit ) reset max length before receiving!
//boolean lora_rx_data_available = rf95.readData(lora_RXBUFF, loraReceivedLength);
const char *rssi_for_path = encode_snr_rssi_in_path();
// always needed (even if rx is disabled)
@ -3862,7 +3856,9 @@ out:
lora_packets_received_in_timeslot_on_secondary_freq++;
}
if (lora_rx_enabled && lora_rx_data_available) {
if (lora_rx_enabled) {
if (packetSize > 0) {
rf95.readData(lora_RXBUFF, packetSize);
String loraReceivedFrameString; //data on buff is copied to this string. raw
#if defined(ENABLE_SYSLOG)
String loraReceivedFrameString_for_syslog; //data on buff is copied to this string. Non-printable characters are shown as <0xnn>. Even valid EOL \r. Syslog is for analyzing.
@ -3870,7 +3866,7 @@ out:
String loraReceivedFrameString_for_weblist; //data on buff is copied to this string. Bad characters like \n and \0 are replaced by ' ' (also valid \r - aprs does not use two line messages ;); \r, \n or \0 at the end of the string are removed.
char *s = 0;
for (int i=0 ; i < loraReceivedLength ; i++) {
for (int i=3 ; i < packetSize ; i++) {
loraReceivedFrameString += (char) lora_RXBUFF[i];
#if defined(ENABLE_WIFI) // || defined(ENABLE_SYSLOG)
if (lora_RXBUFF[i] >= 0x20) {
@ -3968,11 +3964,11 @@ out:
writedisplaytext(" ((RX))", "", loraReceivedFrameString, "", "", "");
time_to_refresh = millis() + showRXTime;
#ifdef ENABLE_WIFI
sendToWebList(loraReceivedFrameString_for_weblist, bg_rf95rssi_to_rssi(rf95.lastRssi()), bg_rf95snr_to_snr(rf95.lastSNR()));
sendToWebList(loraReceivedFrameString_for_weblist, bg_rf95rssi_to_rssi(rf95.getRSSI()), bg_rf95snr_to_snr(rf95.getSNR()));
#endif
#endif
#if defined(ENABLE_SYSLOG) && defined(ENABLE_WIFI) // unfortunately, on this plattform we only have IP if we have WIFI
syslog_log(LOG_INFO, String("LoRa-RX: '") + loraReceivedFrameString_for_syslog + "', RSSI:" + bg_rf95rssi_to_rssi(rf95.lastRssi()) + ", SNR: " + bg_rf95snr_to_snr(rf95.lastSNR()));
syslog_log(LOG_INFO, String("LoRa-RX: '") + loraReceivedFrameString_for_syslog + "', RSSI:" + bg_rf95rssi_to_rssi(rf95.getRSSI()) + ", SNR: " + bg_rf95snr_to_snr(rf95.getSNR()));
#endif
#ifdef KISS_PROTOCOL
s = 0;
@ -4031,14 +4027,10 @@ invalid_packet:
#else
; // make compiler happy
#endif
} else {
#ifdef IF_SEMAS_WOULD_WORK
xSemaphoreGive(sema_lora_chip);
#else
sema_lora_chip = false;
#endif
}
rf95.startReceive();
enable_interrupt = true;
}
}
if (lora_rx_enabled && rx_on_frequencies == 3 && lora_digipeating_mode < 2) {
static uint8_t slot_table[9][10] = {
@ -4082,7 +4074,7 @@ invalid_packet:
// avoid calling rf95.setFrequency() and lora_set_speed() if previos *p_curr_slot_table was the same freq/speed
if (*p_curr_slot_table != ((p_curr_slot_table > curr_slot_table) ? p_curr_slot_table[-1] : curr_slot_table[9])) {
lora_freq_rx_curr = (*p_curr_slot_table) ? lora_freq_cross_digi : lora_freq;
rf95.setFrequency(lora_freq_rx_curr);
//rf95.setFrequency(lora_freq_rx_curr);
lora_speed_rx_curr = (*p_curr_slot_table) ? lora_speed_cross_digi : lora_speed;
lora_set_speed(lora_speed_rx_curr);
}