|
|
@ -21,6 +21,14 @@ volatile bool serial_buffering = false; |
|
|
|
|
|
|
|
|
|
|
|
char sbuf[128]; |
|
|
|
char sbuf[128]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
|
|
|
|
#include "soc/rtc_wdt.h" |
|
|
|
|
|
|
|
#define ISR_VECT IRAM_ATTR |
|
|
|
|
|
|
|
bool packet_ready = false; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
#define ISR_VECT |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
void setup() { |
|
|
|
void setup() { |
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
delay(500); |
|
|
|
delay(500); |
|
|
@ -62,9 +70,14 @@ void setup() { |
|
|
|
LoRa.setPins(pin_cs, pin_reset, pin_dio); |
|
|
|
LoRa.setPins(pin_cs, pin_reset, pin_dio); |
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
radio_locked = true; |
|
|
|
// ESP32-specific initialisation
|
|
|
|
radio_online = false; |
|
|
|
// The WDT is disabled for now. This
|
|
|
|
hw_ready = false; |
|
|
|
// should be re-enabled as soon as any
|
|
|
|
|
|
|
|
// Core0-related features are used
|
|
|
|
|
|
|
|
rtc_wdt_protect_off(); |
|
|
|
|
|
|
|
rtc_wdt_disable(); |
|
|
|
|
|
|
|
// rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
|
|
|
|
|
|
|
|
// rtc_wdt_set_time(RTC_WDT_STAGE0, 25);
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// Validate board health, EEPROM and config
|
|
|
|
// Validate board health, EEPROM and config
|
|
|
@ -79,68 +92,23 @@ void lora_receive() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool startRadio() { |
|
|
|
inline void kiss_write_packet() { |
|
|
|
update_radio_lock(); |
|
|
|
Serial.write(FEND); |
|
|
|
if (!radio_online) { |
|
|
|
Serial.write(CMD_DATA); |
|
|
|
if (!radio_locked && hw_ready) { |
|
|
|
for (int i = 0; i < read_len; i++) { |
|
|
|
if (!LoRa.begin(lora_freq)) { |
|
|
|
uint8_t byte = pbuf[i]; |
|
|
|
// The radio could not be started.
|
|
|
|
if (byte == FEND) { Serial.write(FESC); byte = TFEND; } |
|
|
|
// Indicate this failure over both the
|
|
|
|
if (byte == FESC) { Serial.write(FESC); byte = TFESC; } |
|
|
|
// serial port and with the onboard LEDs
|
|
|
|
Serial.write(byte); |
|
|
|
kiss_indicate_error(ERROR_INITRADIO); |
|
|
|
|
|
|
|
led_indicate_error(0); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
radio_online = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTXPower(); |
|
|
|
|
|
|
|
setBandwidth(); |
|
|
|
|
|
|
|
setSpreadingFactor(); |
|
|
|
|
|
|
|
setCodingRate(); |
|
|
|
|
|
|
|
getFrequency(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LoRa.enableCrc(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
LoRa.onReceive(receive_callback); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lora_receive(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Flash an info pattern to indicate
|
|
|
|
|
|
|
|
// that the radio is now on
|
|
|
|
|
|
|
|
led_indicate_info(3); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Flash a warning pattern to indicate
|
|
|
|
|
|
|
|
// that the radio was locked, and thus
|
|
|
|
|
|
|
|
// not started
|
|
|
|
|
|
|
|
led_indicate_warning(3); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// If radio is already on, we silently
|
|
|
|
|
|
|
|
// ignore the request.
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void stopRadio() { |
|
|
|
|
|
|
|
LoRa.end(); |
|
|
|
|
|
|
|
radio_online = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void update_radio_lock() { |
|
|
|
|
|
|
|
if (lora_freq != 0 && lora_bw != 0 && lora_txp != 0xFF && lora_sf != 0) { |
|
|
|
|
|
|
|
radio_locked = false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
radio_locked = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Serial.write(FEND); |
|
|
|
|
|
|
|
read_len = 0; |
|
|
|
|
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
|
|
|
|
packet_ready = false; |
|
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void receive_callback(int packet_size) { |
|
|
|
void ISR_VECT receive_callback(int packet_size) { |
|
|
|
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,
|
|
|
@ -157,15 +125,23 @@ void receive_callback(int packet_size) { |
|
|
|
// and add the data to the buffer
|
|
|
|
// and add the data to the buffer
|
|
|
|
read_len = 0; |
|
|
|
read_len = 0; |
|
|
|
seq = sequence; |
|
|
|
seq = sequence; |
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
getPacketData(packet_size); |
|
|
|
getPacketData(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.
|
|
|
|
last_rssi = (last_rssi+LoRa.packetRssi())/2; |
|
|
|
|
|
|
|
last_snr_raw = (last_snr_raw+LoRa.packetSnrRaw())/2; |
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
last_rssi = (last_rssi+LoRa.packetRssi())/2; |
|
|
|
|
|
|
|
last_snr_raw = (last_snr_raw+LoRa.packetSnrRaw())/2; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
getPacketData(packet_size); |
|
|
|
getPacketData(packet_size); |
|
|
|
seq = SEQ_UNSET; |
|
|
|
seq = SEQ_UNSET; |
|
|
|
ready = true; |
|
|
|
ready = true; |
|
|
@ -176,8 +152,12 @@ void receive_callback(int packet_size) { |
|
|
|
// a new split packet.
|
|
|
|
// a new split packet.
|
|
|
|
read_len = 0; |
|
|
|
read_len = 0; |
|
|
|
seq = sequence; |
|
|
|
seq = sequence; |
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
getPacketData(packet_size); |
|
|
|
getPacketData(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
|
|
|
@ -191,54 +171,111 @@ void receive_callback(int packet_size) { |
|
|
|
seq = SEQ_UNSET; |
|
|
|
seq = SEQ_UNSET; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
getPacketData(packet_size); |
|
|
|
getPacketData(packet_size); |
|
|
|
ready = true; |
|
|
|
ready = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (ready) { |
|
|
|
if (ready) { |
|
|
|
|
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
// We first signal the RSSI of the
|
|
|
|
|
|
|
|
// recieved packet to the host.
|
|
|
|
|
|
|
|
kiss_indicate_stat_rssi(); |
|
|
|
|
|
|
|
kiss_indicate_stat_snr(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// And then write the entire packet
|
|
|
|
|
|
|
|
kiss_write_packet(); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
packet_ready = true; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
// In promiscuous mode, raw packets are
|
|
|
|
|
|
|
|
// output directly to the host
|
|
|
|
|
|
|
|
read_len = 0; |
|
|
|
|
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
|
|
|
|
getPacketData(packet_size); |
|
|
|
|
|
|
|
|
|
|
|
// We first signal the RSSI of the
|
|
|
|
// We first signal the RSSI of the
|
|
|
|
// recieved packet to the host.
|
|
|
|
// recieved packet to the host.
|
|
|
|
kiss_indicate_stat_rssi(); |
|
|
|
kiss_indicate_stat_rssi(); |
|
|
|
kiss_indicate_stat_snr(); |
|
|
|
kiss_indicate_stat_snr(); |
|
|
|
|
|
|
|
|
|
|
|
// And then write the entire packet
|
|
|
|
// And then write the entire packet
|
|
|
|
Serial.write(FEND); |
|
|
|
kiss_write_packet(); |
|
|
|
Serial.write(CMD_DATA); |
|
|
|
|
|
|
|
for (int i = 0; i < read_len; i++) { |
|
|
|
#else |
|
|
|
uint8_t byte = pbuf[i]; |
|
|
|
// Promiscous mode is not supported on ESP32 for now
|
|
|
|
if (byte == FEND) { Serial.write(FESC); byte = TFEND; } |
|
|
|
getPacketData(packet_size); |
|
|
|
if (byte == FESC) { Serial.write(FESC); byte = TFESC; } |
|
|
|
|
|
|
|
Serial.write(byte); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Serial.write(FEND); |
|
|
|
|
|
|
|
read_len = 0; |
|
|
|
read_len = 0; |
|
|
|
}
|
|
|
|
#endif |
|
|
|
} else { |
|
|
|
} |
|
|
|
// In promiscuous mode, raw packets are
|
|
|
|
} |
|
|
|
// output directly to the host
|
|
|
|
|
|
|
|
read_len = 0; |
|
|
|
|
|
|
|
last_rssi = LoRa.packetRssi(); |
|
|
|
|
|
|
|
last_snr_raw = LoRa.packetSnrRaw(); |
|
|
|
bool startRadio() { |
|
|
|
getPacketData(packet_size); |
|
|
|
update_radio_lock(); |
|
|
|
|
|
|
|
if (!radio_online) { |
|
|
|
// We first signal the RSSI of the
|
|
|
|
if (!radio_locked && hw_ready) { |
|
|
|
// recieved packet to the host.
|
|
|
|
if (!LoRa.begin(lora_freq)) { |
|
|
|
kiss_indicate_stat_rssi(); |
|
|
|
// The radio could not be started.
|
|
|
|
kiss_indicate_stat_snr(); |
|
|
|
// Indicate this failure over both the
|
|
|
|
|
|
|
|
// serial port and with the onboard LEDs
|
|
|
|
// And then write the entire packet
|
|
|
|
kiss_indicate_error(ERROR_INITRADIO); |
|
|
|
Serial.write(FEND); |
|
|
|
led_indicate_error(0); |
|
|
|
Serial.write(CMD_DATA); |
|
|
|
return false; |
|
|
|
for (int i = 0; i < read_len; i++) { |
|
|
|
} else { |
|
|
|
uint8_t byte = pbuf[i]; |
|
|
|
radio_online = true; |
|
|
|
if (byte == FEND) { Serial.write(FESC); byte = TFEND; } |
|
|
|
|
|
|
|
if (byte == FESC) { Serial.write(FESC); byte = TFESC; } |
|
|
|
setTXPower(); |
|
|
|
Serial.write(byte); |
|
|
|
setBandwidth(); |
|
|
|
|
|
|
|
setSpreadingFactor(); |
|
|
|
|
|
|
|
setCodingRate(); |
|
|
|
|
|
|
|
getFrequency(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LoRa.enableCrc(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LoRa.onReceive(receive_callback); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lora_receive(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Flash an info pattern to indicate
|
|
|
|
|
|
|
|
// that the radio is now on
|
|
|
|
|
|
|
|
led_indicate_info(3); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Flash a warning pattern to indicate
|
|
|
|
|
|
|
|
// that the radio was locked, and thus
|
|
|
|
|
|
|
|
// not started
|
|
|
|
|
|
|
|
led_indicate_warning(3); |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
Serial.write(FEND); |
|
|
|
} else { |
|
|
|
read_len = 0;
|
|
|
|
// If radio is already on, we silently
|
|
|
|
|
|
|
|
// ignore the request.
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void stopRadio() { |
|
|
|
|
|
|
|
LoRa.end(); |
|
|
|
|
|
|
|
radio_online = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void update_radio_lock() { |
|
|
|
|
|
|
|
if (lora_freq != 0 && lora_bw != 0 && lora_txp != 0xFF && lora_sf != 0) { |
|
|
|
|
|
|
|
radio_locked = false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
radio_locked = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -650,9 +687,8 @@ void loop() { |
|
|
|
checkModemStatus(); |
|
|
|
checkModemStatus(); |
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
int packet_size = LoRa.parsePacket(); |
|
|
|
if (packet_ready) { |
|
|
|
if (packet_size) { |
|
|
|
kiss_write_packet(); |
|
|
|
receive_callback(packet_size); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
@ -686,12 +722,9 @@ void loop() { |
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
#if MCU_VARIANT == MCU_ESP32 |
|
|
|
buffer_serial(); |
|
|
|
buffer_serial(); |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if MCU_VARIANT != MCU_ESP32 |
|
|
|
|
|
|
|
if (!fifo_isempty_locked(&serialFIFO)) serial_poll(); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
if (!fifo_isempty(&serialFIFO)) serial_poll(); |
|
|
|
if (!fifo_isempty(&serialFIFO)) serial_poll(); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
if (!fifo_isempty_locked(&serialFIFO)) serial_poll();
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|