Closed beegee-tokyo closed 5 years ago
That's not a bad idea. The reason it was done with two interrupt pins previously was that on SX127x series, DIO configurability is limited (specific interrupt sources only trigger specific DIO pins). Since that's no longer the case on SX126x, there's no reason to sacrifice additional pin.
There's going to be some changes to the examples, so I'm going to add this myself, you don't have to open PR. Thanks for the suggestion!
:thumbsup::thumbsup::thumbsup::thumbsup::thumbsup:
But (there is always a but :wink:)
Not sure if it is my ESP32 that I use for testing, but in
uint16_t SX126x::getIrqStatus() {
uint8_t data[2];
SPIreadCommand(SX126X_CMD_GET_IRQ_STATUS, data, 2);
return(((uint16_t)(data[1]) << 8) | data[0]);
}
the return value gives me Highbyte and Lowbyte reversed. The IRQ params (masks?) in SX126x.h does not match the returned values. I get 0x8000 and 0x8001 for CAD_DONE and CAD_DETECTED/_DONE instead of 0x0080 and 0x0180. If I change
return(((uint16_t)(data[1]) << 8) | data[0]);
into
return(((uint16_t)(data[0]) << 8) | data[1]);
the returned values match the masks
Here is the final version I am testing right now, using a flag: scanChannel()
int16_t SX126x::scanChannel()
{
// check active modem
if (getPacketType() != SX126X_PACKET_TYPE_LORA)
{
return (ERR_WRONG_MODEM);
}
bool useDIO2 = true;
if (_dio2RfSwitch)
{
// If DIO2 is used as RF switch this function does not work
// return(ERR_CAD_UNAVAILABLE);
// Set a flag that CAD needs to be done with DIO1 only
useDIO2 = false;
}
// set mode to standby
int16_t state = standby();
if (state != ERR_NONE)
{
return (state);
}
// set DIO pin mapping
if (useDIO2)
{
state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED);
}
else
{
state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE | SX126X_IRQ_CAD_DETECTED);
}
if (state != ERR_NONE)
{
return (state);
}
// clear interrupt flags
state = clearIrqStatus();
if (state != ERR_NONE)
{
return (state);
}
// set mode to CAD
state = setCad();
if (state != ERR_NONE)
{
return (state);
}
// wait for channel activity detected or timeout
while (!digitalRead(_mod->getInt0()))
{
// If DIO2 was available, check status of DIO2
if (useDIO2)
{
if (digitalRead(_mod->getInt1()))
{
clearIrqStatus();
return (LORA_DETECTED);
}
else
{
clearIrqStatus();
return (CHANNEL_FREE);
}
}
}
// We arrive here only if DIO2 was not available
uint16_t cadResult = getIrqStatus();
if (cadResult == (SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE)) // Check why high and low byte are switched
{
clearIrqStatus();
return (LORA_DETECTED);
}
// clear interrupt flags
clearIrqStatus();
return (CHANNEL_FREE);
}
and getIrqStatus()
uint16_t SX126x::getIrqStatus()
{
uint8_t data[2];
SPIreadCommand(SX126X_CMD_GET_IRQ_STATUS, data, 2);
return (((uint16_t)(data[0]) << 8) | data[1]);
}
When comparing to SX126x::getPacketStatus()
, it looks like the bytes are actually swapped. I'll fix that as well.
I think we can just remove the DIO2 flag completely, I see no benefit of DIO1/DIO2 CAD when compared to DIO1 only. Like I said, the second pin is just a remnant from the older LoRa series.
Added in eddf96bbb2c31734141f93401fe814b68eddc88b, thanks for the suggestion!
As on some modules DIO2 is not available because it is used to switch the RF antenna between RX and TX.
This means
scanChannel()
function cannot be used.As simple workaround could be to change
scanChannel()
to use only DIO1 as IRQ input. Example code how it works (tested on eByte E22 module which uses DIO2 as RF antenna switch):