jgromes / RadioLib

Universal wireless communication library for embedded devices
https://jgromes.github.io/RadioLib/
MIT License
1.57k stars 393 forks source link

[SX1278] Stream receive mode works incorrect #602

Closed notsleep196 closed 1 year ago

notsleep196 commented 2 years ago

Hello! I already tried to use SX1278 and Radiolib to receive long packets in FSK #399 and i'm glad to see the implementation of "Stream mode" in it. I tried to use your example and watch how fifoGet() functionality works. This functionality works unexpectedly. To simplify I sent messages of 60 bytes payload (+1 byte packet length) from another SX1278 module in variableLengthPacketMode. I think it is valid scenario to check how FIFO threshold functionality works, because default FIFO threshold now is 31. I used example for stream receive (with small changes, see below):

void IRAM_ATTR fifoGet() {
    // check if the interrupt is enabled
    if(!enableInterrupt) {
        return;
    }

    // set the flag when we receive the full packet
    receivedFlag = radioRx.fifoGet(rxBuffer, totalLength, &receivedLength);
    interruptTriggeredFlag = true;
}

The last thing: this two strings in fifoGet() method:

// dump the padding byte
  _mod->SPIreadRegister(RADIOLIB_SX127X_REG_FIFO);

I saw this hack with padding byte for TX, but for RX it looks strange, as you can see above, one value from initial byte sequence (1E hex, 30 decimal) was missed on RX side. So i think this "dump padding byte" is also a mistake. If i comment this, i see valid byte sequence as i sent.

jgromes commented 2 years ago

Hmm, I'm not actually sure whether I tested with transmission of less than 256 bytes (since that was the original use case). I will try to reproduce this and let you know.

jgromes commented 2 years ago

I spent a little while thinking about this, before I realized it doesn't actually make sense - the stream mode is entered only if the packet length is higher than the SX1278 internal FSK buffer size (64 bytes). So if the packet is shorter than this threshold, it will use the normal packet transfer. The problem is that there's now also an interrupt service tied to the DIO lines, which attempts to handle FIFO on its own. This limitation probably should be documented somewhere.

A qcuick test with Arduino Uno and SX1278 confirms the behavior that was reported.

Could you please try if the problem persists for messages longer than 64 bytes?

notsleep196 commented 1 year ago

Thank you for reply! Yes, i'll try with messages longer than 64 bytes later this or next week.

notsleep196 commented 1 year ago

Hello! I changed totalLength value to 208 Buffer to send (208 bytes): CF 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF

So the result is completely the same. FIFO threshold interrupt triggers only once every time i send packet.

jgromes commented 1 year ago

Could you please provide the exact code you are using now?

notsleep196 commented 1 year ago

Hello! Thank you for reply.

My code ```cpp /* RadioLib Stream Receive Example This example shows how to receive data in "Stream" mode. In this mode, arbitrary length of data may be sent, up to "infinite" continuous transmission between two devices. Caveats: - CRC of the payload is not supported - the length of the payload must be known in advance Modules that can be used for Stream are: - SX127x/RFM9x (FSK mode only) - RF69 - SX1231 For default module settings, see the wiki page https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---lora-modem For full API reference, see the GitHub Pages https://jgromes.github.io/RadioLib/ */ // include the library #include #include // SX1278 has the following connections: // NSS pin: 10 // DIO0 pin: 2 // RESET pin: 9 // DIO1 pin: 3 SX1278 radioRx = new Module(GPIO_NUM_4, GPIO_NUM_34, GPIO_NUM_27, GPIO_NUM_25); // or using RadioShield // https://github.com/jgromes/RadioShield //SX1278 radioRx = RadioShield.ModuleA; // flag to indicate that a packet was received volatile bool receivedFlag = false; volatile bool interruptTriggeredFlag = false; // disable interrupt when it's not needed volatile bool enableInterrupt = true; // how many bytes are there in total const int totalLength = 207; // counter to keep track of how many bytes have been received so far volatile int receivedLength = 0; // buffer to save the received data into volatile uint8_t rxBuffer[totalLength + 1]; // this function is called when the radioRx receive buffer // is full and ready to be read // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! void IRAM_ATTR fifoGet() { // check if the interrupt is enabled if(!enableInterrupt) { return; } // set the flag when we receive the full packet receivedFlag = radioRx.fifoGet(rxBuffer, totalLength, &receivedLength); interruptTriggeredFlag = true; } void setup() { Serial.begin(115200); // initialize SX1278 with default settings Serial.print(F("[SX1278] Initializing Rx... ")); int state = radioRx.beginFSK(436.7, 9.6, 4.8, 10.4); if (state == RADIOLIB_ERR_NONE) { state = radioRx.setDataShaping(RADIOLIB_SHAPING_1_0); } if (state == RADIOLIB_ERR_NONE) { state = radioRx.setPreambleLength(24); } if (state == RADIOLIB_ERR_NONE) { //syncword uint8_t syncWord[6] = {0x4e,0x53,0x55,0x4e,0x45,0x54}; state = radioRx.setSyncWord(syncWord, 6); } if (state == RADIOLIB_ERR_NONE) { state = radioRx.setEncoding(RADIOLIB_ENCODING_WHITENING); } if (state == RADIOLIB_ERR_NONE) { //For SX1278 we just enable/disable CRC. We can add crc mode switch in future state = radioRx.setCRC(true); } // when using one of the non-LoRa modules for Stream transmit // (RF69, CC1101, Si4432 etc.), use the basic begin() method // int state = radioRx.begin(); if (state == RADIOLIB_ERR_NONE) { Serial.println(F("success!")); } else { Serial.print(F("failed, code ")); Serial.println(state); while (true); } // set the function that will be called // when receive buffer is full radioRx.setFifoFullAction(fifoGet); // fixed packet length mode is required radioRx.fixedPacketLengthMode(0); // start listening for packets Serial.print(F("[SX1278] Starting to listen ... ")); state = radioRx.startReceive(); if (state == RADIOLIB_ERR_NONE) { Serial.println(F("success!")); } else { Serial.print(F("failed, code ")); Serial.println(state); while (true); } // if needed, 'listen' mode can be disabled by calling // any of the following methods: // // radioRx.standby() // radioRx.sleep() // radioRx.transmit(); // radioRx.receive(); // radioRx.readData(); // radioRx.scanChannel(); } void loop() { if (interruptTriggeredFlag) { Serial.println("FifoThresh interrupt triggered"); Serial.print("ReceivedLength: "); Serial.println(receivedLength); interruptTriggeredFlag = false; } // check if the flag is set if(receivedFlag) { // disable the interrupt service routine while // processing the data enableInterrupt = false; // packet was successfully received Serial.println(F("[SX1278] Received packet!")); // print data of the packet Serial.print(F("[SX1278] Data: ")); for (auto i = 0; i < totalLength; i++) { Serial.print(rxBuffer[i]); Serial.print(' '); } Serial.println(); // reset flag receivedFlag = false; receivedLength = 0; // put module back to listen mode radioRx.startReceive(); // we're ready to receive more packets, // enable interrupt service routine enableInterrupt = true; } } ```
jgromes commented 1 year ago

Resolved by merging #651.