Change interrupt layout and address SX1280 errata
This commit is contained in:
parent
7f787d5910
commit
c3c254cd96
@ -64,8 +64,6 @@ volatile bool serial_buffering = false;
|
|||||||
|
|
||||||
char sbuf[128];
|
char sbuf[128];
|
||||||
|
|
||||||
bool packet_ready = false;
|
|
||||||
|
|
||||||
uint8_t *packet_queue[INTERFACE_COUNT];
|
uint8_t *packet_queue[INTERFACE_COUNT];
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
@ -322,7 +320,6 @@ inline void kiss_write_packet(int index) {
|
|||||||
}
|
}
|
||||||
serial_write(FEND);
|
serial_write(FEND);
|
||||||
read_len = 0;
|
read_len = 0;
|
||||||
packet_ready = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void getPacketData(RadioInterface* radio, uint16_t len) {
|
inline void getPacketData(RadioInterface* radio, uint16_t len) {
|
||||||
@ -332,17 +329,17 @@ inline void getPacketData(RadioInterface* radio, uint16_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void receive_callback(uint8_t index, int packet_size) {
|
void receive_callback(uint8_t index, int packet_size) {
|
||||||
if (!promisc) {
|
|
||||||
selected_radio = interface_obj[index];
|
selected_radio = interface_obj[index];
|
||||||
|
bool ready = false;
|
||||||
|
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,
|
||||||
// by combining two raw LoRa packets.
|
// by combining two raw LoRa packets.
|
||||||
// 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--;
|
uint8_t header = selected_radio->read(); packet_size--;
|
||||||
uint8_t sequence = packetSequence(header);
|
uint8_t sequence = packetSequence(header);
|
||||||
bool ready = false;
|
|
||||||
|
|
||||||
if (isSplitPacket(header) && seq == SEQ_UNSET) {
|
if (isSplitPacket(header) && seq == SEQ_UNSET) {
|
||||||
// This is the first part of a split
|
// This is the first part of a split
|
||||||
@ -388,20 +385,16 @@ void receive_callback(uint8_t index, int packet_size) {
|
|||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(selected_radio, packet_size);
|
||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ready) {
|
|
||||||
packet_ready = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 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;
|
||||||
|
|
||||||
getPacketData(selected_radio, packet_size);
|
getPacketData(selected_radio, packet_size);
|
||||||
packet_ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet_ready) {
|
if (ready) {
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
portENTER_CRITICAL(&update_lock);
|
portENTER_CRITICAL(&update_lock);
|
||||||
#elif MCU_VARIANT == MCU_NRF52
|
#elif MCU_VARIANT == MCU_NRF52
|
||||||
@ -1329,13 +1322,12 @@ void packet_poll() {
|
|||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
#endif
|
#endif
|
||||||
uint8_t packet_int = fifo_pop(&packet_rdy_interfaces);
|
uint8_t packet_int = fifo_pop(&packet_rdy_interfaces);
|
||||||
selected_radio = interface_obj[packet_int];
|
|
||||||
#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
|
||||||
portEXIT_CRITICAL();
|
portEXIT_CRITICAL();
|
||||||
#endif
|
#endif
|
||||||
selected_radio->clearIRQStatus();
|
selected_radio = interface_obj[packet_int];
|
||||||
selected_radio->handleDio0Rise();
|
selected_radio->handleDio0Rise();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
123
Radio.cpp
123
Radio.cpp
@ -98,8 +98,18 @@ extern RadioInterface* interface_obj[];
|
|||||||
void ISR_VECT onDio0Rise() {
|
void ISR_VECT onDio0Rise() {
|
||||||
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
for (int i = 0; i < INTERFACE_COUNT; i++) {
|
||||||
if (digitalRead(interface_pins[i][5]) == HIGH) {
|
if (digitalRead(interface_pins[i][5]) == HIGH) {
|
||||||
|
if (interface_obj[i]->getPacketValidity()) {
|
||||||
fifo_push(&packet_rdy_interfaces, i);
|
fifo_push(&packet_rdy_interfaces, i);
|
||||||
}
|
}
|
||||||
|
if (interfaces[i] == SX128X) {
|
||||||
|
// On the SX1280, there is a bug which can cause the busy line
|
||||||
|
// to remain high if a high amount of packets are received when
|
||||||
|
// in continuous RX mode. This is documented as Errata 16.1 in
|
||||||
|
// the SX1280 datasheet v3.2 (page 149)
|
||||||
|
// Therefore, the modem is set into receive mode each time a packet is received.
|
||||||
|
interface_obj[i]->receive();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -962,16 +972,6 @@ void sx126x::implicitHeaderMode()
|
|||||||
|
|
||||||
void sx126x::handleDio0Rise()
|
void sx126x::handleDio0Rise()
|
||||||
{
|
{
|
||||||
uint8_t buf[2];
|
|
||||||
|
|
||||||
buf[0] = 0x00;
|
|
||||||
buf[1] = 0x00;
|
|
||||||
|
|
||||||
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
|
|
||||||
|
|
||||||
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2);
|
|
||||||
|
|
||||||
if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_6X) == 0) {
|
|
||||||
// received a packet
|
// received a packet
|
||||||
_packetIndex = 0;
|
_packetIndex = 0;
|
||||||
|
|
||||||
@ -983,12 +983,6 @@ void sx126x::handleDio0Rise()
|
|||||||
if (_onReceive) {
|
if (_onReceive) {
|
||||||
_onReceive(_index, packetLength);
|
_onReceive(_index, packetLength);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// else {
|
|
||||||
// Serial.println("CRCE");
|
|
||||||
// Serial.println(buf[0]);
|
|
||||||
// Serial.println(buf[1]);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx126x::updateBitrate() {
|
void sx126x::updateBitrate() {
|
||||||
@ -1011,7 +1005,7 @@ void sx126x::updateBitrate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx126x::clearIRQStatus() {
|
bool ISR_VECT sx126x::getPacketValidity() {
|
||||||
uint8_t buf[2];
|
uint8_t buf[2];
|
||||||
|
|
||||||
buf[0] = 0x00;
|
buf[0] = 0x00;
|
||||||
@ -1020,6 +1014,12 @@ void sx126x::clearIRQStatus() {
|
|||||||
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
|
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
|
||||||
|
|
||||||
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2);
|
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2);
|
||||||
|
|
||||||
|
if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_6X) == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// SX127x registers
|
// SX127x registers
|
||||||
#define REG_FIFO_7X 0x00
|
#define REG_FIFO_7X 0x00
|
||||||
@ -1512,11 +1512,6 @@ void sx127x::optimizeModemSensitivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sx127x::handleDio0Rise() {
|
void sx127x::handleDio0Rise() {
|
||||||
int irqFlags = readRegister(REG_IRQ_FLAGS_7X);
|
|
||||||
|
|
||||||
// Clear IRQs
|
|
||||||
writeRegister(REG_IRQ_FLAGS_7X, irqFlags);
|
|
||||||
if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK_7X) == 0) {
|
|
||||||
_packetIndex = 0;
|
_packetIndex = 0;
|
||||||
int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH_7X) : readRegister(REG_RX_NB_BYTES_7X);
|
int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH_7X) : readRegister(REG_RX_NB_BYTES_7X);
|
||||||
writeRegister(REG_FIFO_ADDR_PTR_7X, readRegister(REG_FIFO_RX_CURRENT_ADDR_7X));
|
writeRegister(REG_FIFO_ADDR_PTR_7X, readRegister(REG_FIFO_RX_CURRENT_ADDR_7X));
|
||||||
@ -1524,7 +1519,6 @@ void sx127x::handleDio0Rise() {
|
|||||||
_onReceive(_index, packetLength);
|
_onReceive(_index, packetLength);
|
||||||
}
|
}
|
||||||
writeRegister(REG_FIFO_ADDR_PTR_7X, 0);
|
writeRegister(REG_FIFO_ADDR_PTR_7X, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx127x::updateBitrate() {
|
void sx127x::updateBitrate() {
|
||||||
@ -1546,11 +1540,17 @@ void sx127x::updateBitrate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx127x::clearIRQStatus() {
|
bool ISR_VECT sx127x::getPacketValidity() {
|
||||||
int irqFlags = readRegister(REG_IRQ_FLAGS_7X);
|
int irqFlags = readRegister(REG_IRQ_FLAGS_7X);
|
||||||
|
|
||||||
// Clear IRQs
|
// Clear IRQs
|
||||||
writeRegister(REG_IRQ_FLAGS_7X, irqFlags);
|
writeRegister(REG_IRQ_FLAGS_7X, irqFlags);
|
||||||
|
|
||||||
|
if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK_7X) == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SX128x registers
|
// SX128x registers
|
||||||
@ -2040,7 +2040,7 @@ uint8_t ISR_VECT sx128x::packetSnrRaw() {
|
|||||||
|
|
||||||
float ISR_VECT sx128x::packetSnr() {
|
float ISR_VECT sx128x::packetSnr() {
|
||||||
uint8_t buf[5] = {0};
|
uint8_t buf[5] = {0};
|
||||||
executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 3);
|
executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
|
||||||
return float(buf[1]) * 0.25;
|
return float(buf[1]) * 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2080,6 +2080,27 @@ int ISR_VECT sx128x::read()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if received new packet
|
||||||
|
if (_packetIndex == 0) {
|
||||||
|
uint8_t rxbuf[2] = {0};
|
||||||
|
executeOpcodeRead(OP_RX_BUFFER_STATUS_8X, rxbuf, 2);
|
||||||
|
int size;
|
||||||
|
// If implicit header mode is enabled, read packet length as payload length instead.
|
||||||
|
// See SX1280 datasheet v3.2, page 92
|
||||||
|
if (_implicitHeaderMode == 0x80) {
|
||||||
|
size = _payloadLength;
|
||||||
|
} else {
|
||||||
|
size = rxbuf[0];
|
||||||
|
}
|
||||||
|
_fifo_rx_addr_ptr = rxbuf[1];
|
||||||
|
|
||||||
|
if (size > 255) {
|
||||||
|
size = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
readBuffer(_packet, size);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t byte = _packet[_packetIndex];
|
uint8_t byte = _packet[_packetIndex];
|
||||||
_packetIndex++;
|
_packetIndex++;
|
||||||
return byte;
|
return byte;
|
||||||
@ -2113,9 +2134,16 @@ void sx128x::onReceive(void(*callback)(uint8_t, int))
|
|||||||
buf[0] = 0xFF;
|
buf[0] = 0xFF;
|
||||||
buf[1] = 0xFF;
|
buf[1] = 0xFF;
|
||||||
|
|
||||||
|
// On the SX1280, no RxDone IRQ is generated if a packet is received with
|
||||||
|
// an invalid header, but the modem will be taken out of single RX mode.
|
||||||
|
// This can cause the modem to not receive packets until it is reset
|
||||||
|
// again. This is documented as Errata 16.2 in the SX1280 datasheet v3.2
|
||||||
|
// (page 150) Below, the header error IRQ is mapped to dio0 so that the
|
||||||
|
// modem can be set into RX mode again on reception of a corrupted
|
||||||
|
// header.
|
||||||
// set dio0 masks
|
// set dio0 masks
|
||||||
buf[2] = 0x00;
|
buf[2] = 0x00;
|
||||||
buf[3] = IRQ_RX_DONE_MASK_8X;
|
buf[3] = IRQ_RX_DONE_MASK_8X | IRQ_HEADER_ERROR_MASK_8X;
|
||||||
|
|
||||||
// set dio1 masks
|
// set dio1 masks
|
||||||
buf[4] = 0x00;
|
buf[4] = 0x00;
|
||||||
@ -2126,9 +2154,9 @@ void sx128x::onReceive(void(*callback)(uint8_t, int))
|
|||||||
buf[7] = 0x00;
|
buf[7] = 0x00;
|
||||||
|
|
||||||
executeOpcode(OP_SET_IRQ_FLAGS_8X, buf, 8);
|
executeOpcode(OP_SET_IRQ_FLAGS_8X, buf, 8);
|
||||||
//#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
||||||
// _spiModem->usingInterrupt(digitalPinToInterrupt(_dio0));
|
_spiModem->usingInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
// make function available
|
// make function available
|
||||||
extern void onDio0Rise();
|
extern void onDio0Rise();
|
||||||
@ -2136,9 +2164,9 @@ void sx128x::onReceive(void(*callback)(uint8_t, int))
|
|||||||
attachInterrupt(digitalPinToInterrupt(_dio0), onDio0Rise, RISING);
|
attachInterrupt(digitalPinToInterrupt(_dio0), onDio0Rise, RISING);
|
||||||
} else {
|
} else {
|
||||||
detachInterrupt(digitalPinToInterrupt(_dio0));
|
detachInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
//#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
||||||
// _spiModem->notUsingInterrupt(digitalPinToInterrupt(_dio0));
|
_spiModem->notUsingInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
//#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2157,7 +2185,12 @@ void sx128x::receive(int size)
|
|||||||
|
|
||||||
rxAntEnable();
|
rxAntEnable();
|
||||||
|
|
||||||
uint8_t mode[3] = {0xFF, 0xFF, 0xFF}; // continuous mode
|
// On the SX1280, there is a bug which can cause the busy line
|
||||||
|
// to remain high if a high amount of packets are received when
|
||||||
|
// in continuous RX mode. This is documented as Errata 16.1 in
|
||||||
|
// the SX1280 datasheet v3.2 (page 149)
|
||||||
|
// Therefore, the modem is set to single RX mode below instead.
|
||||||
|
uint8_t mode[3] = {0}; // single RX mode
|
||||||
executeOpcode(OP_RX_8X, mode, 3);
|
executeOpcode(OP_RX_8X, mode, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2561,16 +2594,6 @@ void sx128x::implicitHeaderMode()
|
|||||||
|
|
||||||
void sx128x::handleDio0Rise()
|
void sx128x::handleDio0Rise()
|
||||||
{
|
{
|
||||||
uint8_t buf[2];
|
|
||||||
|
|
||||||
buf[0] = 0x00;
|
|
||||||
buf[1] = 0x00;
|
|
||||||
|
|
||||||
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
|
|
||||||
|
|
||||||
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
|
|
||||||
|
|
||||||
if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_8X) == 0) {
|
|
||||||
// received a packet
|
// received a packet
|
||||||
_packetIndex = 0;
|
_packetIndex = 0;
|
||||||
|
|
||||||
@ -2585,15 +2608,9 @@ void sx128x::handleDio0Rise()
|
|||||||
_rxPacketLength = rxbuf[0];
|
_rxPacketLength = rxbuf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
_fifo_rx_addr_ptr = rxbuf[1];
|
|
||||||
|
|
||||||
readBuffer(_packet, _rxPacketLength);
|
|
||||||
|
|
||||||
if (_onReceive) {
|
if (_onReceive) {
|
||||||
_onReceive(_index, _rxPacketLength);
|
_onReceive(_index, _rxPacketLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx128x::updateBitrate() {
|
void sx128x::updateBitrate() {
|
||||||
@ -2622,7 +2639,7 @@ void sx128x::updateBitrate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sx128x::clearIRQStatus() {
|
bool ISR_VECT sx128x::getPacketValidity() {
|
||||||
uint8_t buf[2];
|
uint8_t buf[2];
|
||||||
|
|
||||||
buf[0] = 0x00;
|
buf[0] = 0x00;
|
||||||
@ -2631,4 +2648,10 @@ void sx128x::clearIRQStatus() {
|
|||||||
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
|
executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
|
||||||
|
|
||||||
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
|
executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
|
||||||
|
|
||||||
|
if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_8X) == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ public:
|
|||||||
|
|
||||||
virtual void updateBitrate() = 0;
|
virtual void updateBitrate() = 0;
|
||||||
virtual void handleDio0Rise() = 0;
|
virtual void handleDio0Rise() = 0;
|
||||||
virtual void clearIRQStatus() = 0;
|
virtual bool getPacketValidity() = 0;
|
||||||
uint32_t getBitrate() { return _bitrate; };
|
uint32_t getBitrate() { return _bitrate; };
|
||||||
uint8_t getIndex() { return _index; };
|
uint8_t getIndex() { return _index; };
|
||||||
void setRadioLock(bool lock) { _radio_locked = lock; };
|
void setRadioLock(bool lock) { _radio_locked = lock; };
|
||||||
@ -422,7 +422,7 @@ private:
|
|||||||
void reset(void);
|
void reset(void);
|
||||||
void calibrate(void);
|
void calibrate(void);
|
||||||
void calibrate_image(uint32_t frequency);
|
void calibrate_image(uint32_t frequency);
|
||||||
void clearIRQStatus();
|
bool getPacketValidity();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SPISettings _spiSettings;
|
SPISettings _spiSettings;
|
||||||
@ -512,7 +512,7 @@ public:
|
|||||||
void updateBitrate();
|
void updateBitrate();
|
||||||
|
|
||||||
void handleDio0Rise();
|
void handleDio0Rise();
|
||||||
void clearIRQStatus();
|
bool getPacketValidity();
|
||||||
private:
|
private:
|
||||||
void setSyncWord(uint8_t sw);
|
void setSyncWord(uint8_t sw);
|
||||||
void explicitHeaderMode();
|
void explicitHeaderMode();
|
||||||
@ -609,7 +609,8 @@ public:
|
|||||||
|
|
||||||
void handleDio0Rise();
|
void handleDio0Rise();
|
||||||
|
|
||||||
void clearIRQStatus();
|
bool getPacketValidity();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeBuffer(const uint8_t* buffer, size_t size);
|
void writeBuffer(const uint8_t* buffer, size_t size);
|
||||||
void readBuffer(uint8_t* buffer, size_t size);
|
void readBuffer(uint8_t* buffer, size_t size);
|
||||||
|
Loading…
Reference in New Issue
Block a user