[CC1101] Correctly wait for packet end on blocking receive.
When using a blocking receive, I was getting non-sensical packet length and garbage data, whereas IRQ mode was working fine. This was happening despite what looked like a workaround for this in the code which would read the length twice. I tracked it down to the receive function trying to read the data too early, before the packet had even been received. The receive function would wait for the GDO0 pin to become low, then assume the packet was ready and read off the data. However, the GD0 pin is set by the `startReceive` as inverted and, according to the datasheet, in a mode which "asserts when sync word has been received, and de-asserts at the end of the packet". In other words, taking into account the inversion, GDO0 becomes low at the start of the packet and high at the end of it. Therefore the receive function would actually try to read the packet data as soon as the packet had started, rather than wait until the end, explaining the garbage data. I suspect that with a slow MCU and a fast transmission rate, the previous workaround of reading the length field twice may have delayed the data read just enough to allow the packet to be fully received, but this does not work in the general case. This commit updates the logic by first waiting for a low signal, followed by a high one. This is actually the exact same logic used in the blocking transmit implementation, but inverted to account for the INV flag set on GDO0. The commit also removes the past workaround, since it should not be necessary anymore.
This commit is contained in:
parent
cb0218009d
commit
ab41bcac00
1 changed files with 11 additions and 6 deletions
|
@ -139,7 +139,7 @@ int16_t CC1101::receive(uint8_t* data, size_t len) {
|
||||||
int16_t state = startReceive();
|
int16_t state = startReceive();
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// wait for packet or timeout
|
// wait for packet start or timeout
|
||||||
uint32_t start = this->mod->hal->micros();
|
uint32_t start = this->mod->hal->micros();
|
||||||
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
|
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||||
this->mod->hal->yield();
|
this->mod->hal->yield();
|
||||||
|
@ -151,11 +151,16 @@ int16_t CC1101::receive(uint8_t* data, size_t len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for some reason, blocking receive will sometimes return impossible packet lengths
|
// wait for packet end or timeout
|
||||||
// reading packet length again in readData seems to resolve this
|
start = this->mod->hal->micros();
|
||||||
size_t length = getPacketLength();
|
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||||
if((length == 0) || (length > RADIOLIB_CC1101_MAX_PACKET_LENGTH)) {
|
this->mod->hal->yield();
|
||||||
this->packetLengthQueried = false;
|
|
||||||
|
if(this->mod->hal->micros() - start > timeout) {
|
||||||
|
standby();
|
||||||
|
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||||
|
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read packet data
|
// read packet data
|
||||||
|
|
Loading…
Add table
Reference in a new issue