diff --git a/src/shared/radio/SX1278/SX1278Fsk.cpp b/src/shared/radio/SX1278/SX1278Fsk.cpp index 58dcca41b8cc0bc5b4ffb394f1e199f5d218d0da..5051e6b7e5cc06095d48f3114cb53a08819dff5f 100644 --- a/src/shared/radio/SX1278/SX1278Fsk.cpp +++ b/src/shared/radio/SX1278/SX1278Fsk.cpp @@ -240,11 +240,19 @@ ssize_t SX1278Fsk::receive(uint8_t *pkt, size_t max_len) // TODO: Maybe flush stuff? uint8_t len = 0; - bool crc_ok = false; + bool length_ok; + bool crc_ok; do { + length_ok = false; + crc_ok = false; + + // Current FIFO read progress uint8_t cur_len = 0; + // Have we received payload ready yet? (aka the whole packet is in the + // FIFO) + bool payload_ready = false; // Special wait for fifo level/payload ready, release the lock at this // stage @@ -254,48 +262,67 @@ ssize_t SX1278Fsk::receive(uint8_t *pkt, size_t max_len) RegIrqFlags::PAYLOAD_READY) != 0 && crc_enabled) { - crc_ok = checkForIrqAndReset(RegIrqFlags::CRC_OK, 0) != 0; + payload_ready = true; + crc_ok = checkForIrqAndReset(RegIrqFlags::CRC_OK, 0) != 0; } + // Record RSSI here, it's where it is the most accurate last_rx_rssi = getRssi(); - // Now first packet bit + // Now read packet length { SPITransaction spi(getSpiSlave()); len = spi.readRegister(REG_FIFO); + } + + while (cur_len < len) + { + // Calculate next read_size, remember, the FIFO will be at least + // FIFO_LEN / 2 filled at this point! + int read_size = std::min((int)(len - cur_len), FIFO_LEN / 2); - int read_size = std::min((int)len, FIFO_LEN / 2); - // Skip 0 sized read - if (read_size != 0) + // Read the packet chunk + { + SPITransaction spi(getSpiSlave()); spi.readRegisters(REG_FIFO, &tmp_pkt[cur_len], read_size); + } + // Advance the read pointer cur_len += read_size; - } - // Then read the other chunks - while (cur_len < len) - { + // If the payload went from high to low, this means we have read the + // whole packet + if (payload_ready && + checkForIrqAndReset(0, RegIrqFlags::PAYLOAD_READY) != 0) + { + // Check if we have read the correct amount of data + length_ok = cur_len == len; + break; + } + else if (cur_len == len) + { + // We have read the whole packet, but PAYLOAD_READY did not + // trigger, something went wrong! + length_ok = false; + break; + } + + // Ok there is still more data, wait for it if ((waitForIrq( guard_mode, RegIrqFlags::FIFO_LEVEL | RegIrqFlags::PAYLOAD_READY, 0) & RegIrqFlags::PAYLOAD_READY) != 0 && crc_enabled) { + payload_ready = true; crc_ok = checkForIrqAndReset(RegIrqFlags::CRC_OK, 0) != 0; } - - SPITransaction spi(getSpiSlave()); - - int read_size = std::min((int)(len - cur_len), FIFO_LEN / 2); - spi.readRegisters(REG_FIFO, &tmp_pkt[cur_len], read_size); - - cur_len += read_size; } // For some reason this sometimes happen? } while (len == 0); - if (len > max_len || (!crc_ok && crc_enabled)) + if (len > max_len || (!crc_ok && crc_enabled) || !length_ok) return -1; // Finally copy the packet to the destination