SpaceTeddy / CC1101

driver library for Ti CC1100 / CC1101. For Arduino and Raspberry Pi
MIT License
271 stars 92 forks source link

uint8_t CC1100::packet_available() failing with unexpected MARCSTATE #12

Closed mrcodetastic closed 3 years ago

mrcodetastic commented 7 years ago

Hi,

Thank you again for the code/libraries to get the CC1100/CC1101 module up and running on the Raspberry Pi.

I was testing a modified version of the RX_Demo and whilst it worked, after some period of time the CC1101 would fail to receive any further packets, and the only way to get it to work again was to stop the script and restart the device.

When using a variable length packets (PKTLEN of 0xFF) this issue would happen often. After a bit of analysing the MARCSTATE to see what was going on, I believe it is to do with either the bug in the CC1101 transceiver and/or the fact that the code can't handle RX or TX overflows/underflows, or any other weird MARCSTATE:

https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/t/372505 https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/t/17006

For my problem, it was specific to MARCSTATE values of 0x16 and 0x11.

To get around this, I put the following code at the top of packet_available() to flush the CC1101's buffers when MARCSTATE of 0x16 or 0x11 occurs. I suggest you include something similar.

//--------------------------[check if Packet is received]----------------------
uint8_t CC1100::packet_available()
{
     //printf("Checking if packet is available: ");

     uint8_t marcstate;

     marcstate = (spi_read_register(MARCSTATE) & 0x1F);//read out state of

      if (cc1100_debug == 1) 
      {
            printf("marcstate_rx (in packet check): 0x%02X\n", marcstate);
      }

     if (marcstate == 0x16  || marcstate == 0x11)
     {
            // We have a underflow or overflow condition, need to flush
            printf("========================= MARCSTATE ERROR ========================= ");
            sidle();
            spi_write_strobe(SFTX); delayMicroseconds(100); //flush the TX_fifo content
            spi_write_strobe(SFRX); delayMicroseconds(100); //flush the RX_fifo content
            receive();
     }

marcstate

SpaceTeddy commented 7 years ago

well, basically the library is not designed for package lengths > CC1101 FIFO size (64 bytes). If you want to use larger packages, you have to always monitor how many bytes are in the RXFIFO buffer. If the buffer reaches a critical threshold you must read it out before an overflow occurs. Please check this for details. Because it is more complex I prefer it to send more packages with less package size. This helps also for longer distances. A short package can be better received then a longer package. To tell the trues, I'm not sure if I want to implement it in the library, but as you suggested, a over or underflow check should be implemented. I will check that.

Thank you very much for testing and giving feedback

mrcodetastic commented 7 years ago

Hi SpaceTeddy. That is fair enough, the only reason I mention this is I was getting these MARCSTATE values even when using fixed length packets - perhaps an issue with my chip. Either way, it would be good to handle TX and RX overflows, as when the CC110x gets into this state, it's as good as dead unless the buffers are flushed and it's set back to receive or transmit mode forcefully.

flashman21 commented 6 years ago

hi, I made some investigation. Tested with two transmitterts. Several times successfully received both packets, but when they go over, receive stuck. I thing it's something wrong with reception of number of bytes in buffer, or something else. I was trayed to read num of bytes several times with delay in code, but it's not fix it. I read something about bit hazard in single read of state machine register. Any idea how to debug?

flashman21 commented 6 years ago

I don't know, what is exacly wrong, after some time of receiving CC1101 go into idle mode (marcstate=0x01). To fix it I added some additional code for testing marcstate in packet_available procedure. Now it seems to work. `uint8_t CC1100::packet_available() { //printf("Checking if packet is available: "); uint8_t marcstate=spi_read_register(MARCSTATE) & 0x1F;

if(digitalRead(GDO2) == TRUE)                           //if RF package received
{
    if(spi_read_register(IOCFG2) == 0x06)               //if sync word detect mode is used
    {
        while(digitalRead(GDO2) == TRUE){               //wait till sync word is fully received
            printf("!\r\n");
            printf("packet available \r\n");
        }                                                  //for sync word receive
    }

    if(debug_level > 0){
         //printf("Pkt->:\r\n");
    }

    return TRUE;
}else if (marcstate==0x01)
{
printf("reset to receive \r\n");
receive();    
}  
//printf("no packet\r\n");
return FALSE;

}`

SpaceTeddy commented 6 years ago

thank you for your feedback. I've seen this behavior as well, but only if I use the WOR mode. In permanent RX mode, I've never seen this. Basically it is not my recommendation to put this kind of check into packet_available(), because this function is placed in the main loop and is executed very often. You will produce a lot more spi traffic to the cc1101. For this kind of bugfix you can use a timer which checks every x seconds the marcstate of the cc1101.

chris

flashman21 commented 6 years ago

Hi, you absolutely right with testing this in main loop. I will use some counter. Maybe I made some sensitive changes in register settings. So after all day testing receive packets results in 42000 packed received 270 reset from ilde mode Thank you for your work, I was sent you some change for beer :-) Lukas

SpaceTeddy commented 6 years ago

Hi Lukas, i'm happy that you have fun with the software. You are the first who has sent me a beer! thanks a lot buddy.

cheers!