I am developing simple LoRA board (sx1276) with Atmega328PB but I ended up wiring DIO0 pin on lora module to pin D8. I’m using watteroot bootloader on Arduino framework. According to Arduino documentation (PcInt, PinChangeInt) I should be able to use PCINT interrupt instead of external interrupt INT0 and INT1.
As far as I can see I could do this in couple of ways.
-
Attach interrupt to pin 8 with method attachInterrupt(interruptPinNumber, isr_funct, RISING) and monitor for RISING signal. Then in loop() make a call when send()/recv() returnstrue/false .
-
Detach interrupt from pin 2 (PD2) and attach interrupt to pin 8. But how do I pass interrupt pin to rf95 object instance:
RH_RF5 rf = rf(CS_PIN, INTERRUPT_PIN);
The only way I see doing (2) would be to modify RadioHead RH_RF95.cpp code posted below to handle other interrupts other than external ones.
init()
_deviceForInterrupt[_myInterruptIndex] = this;
if (_myInterruptIndex == 0)
attachInterrupt(interruptNumber, isr0, RISING);
else if (_myInterruptIndex == 1)
attachInterrupt(interruptNumber, isr1, RISING);
else if (_myInterruptIndex == 2)
attachInterrupt(interruptNumber, isr2, RISING);
else
return false; // Too many devices,not enough interrupt vectors
isr0()
void RH_INTERRUPT_ATTR RH_RF95::isr0()
{
if (_deviceForInterrupt[0])
_deviceForInterrupt[0]->handleInterrupt();
}
void RH_INTERRUPT_ATTR RH_RF95::isr1()
{
if (_deviceForInterrupt[1])
_deviceForInterrupt[1]->handleInterrupt();
}
void RH_INTERRUPT_ATTR RH_RF95::isr2()
{
if (_deviceForInterrupt[2])
_deviceForInterrupt[2]->handleInterrupt();
}
handleInterrupt()
void RH_RF95::handleInterrupt()
{
// Read the interrupt register
uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS);
// Read the RegHopChannel register to check if CRC presence is signalled
// in the header. If not it might be a stray (noise) packet.*
uint8_t crc_present = spiRead(RH_RF95_REG_1C_HOP_CHANNEL);
if (_mode == RHModeRx
&& ((irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR))
| !(crc_present & RH_RF95_RX_PAYLOAD_CRC_IS_ON)))
// if (_mode == RHModeRx && irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR))
{
_rxBad++;
}
else if (_mode == RHModeRx && irq_flags & RH_RF95_RX_DONE)
{
// Have received a packet
uint8_t len = spiRead(RH_RF95_REG_13_RX_NB_BYTES);
// Reset the fifo read ptr to the beginning of the packet
spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, spiRead(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR));
spiBurstRead(RH_RF95_REG_00_FIFO, _buf, len);
_bufLen = len;
spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
// Remember the last signal to noise ratio, LORA mode
// Per page 111, SX1276/77/78/79 datasheet
_lastSNR = (int8_t)spiRead(RH_RF95_REG_19_PKT_SNR_VALUE) / 4;
// Remember the RSSI of this packet, LORA mode
// this is according to the doc, but is it really correct?
// weakest receiveable signals are reported RSSI at about -66
_lastRssi = spiRead(RH_RF95_REG_1A_PKT_RSSI_VALUE);
// Adjust the RSSI, datasheet page 87
if (_lastSNR < 0)
_lastRssi = _lastRssi + _lastSNR;
else
_lastRssi = (int)_lastRssi * 16 / 15;
if (_usingHFport)
_lastRssi -= 157;
else
_lastRssi -= 164;
// We have received a message.
validateRxBuf();
if (_rxBufValid)
setModeIdle(); // Got one
}
else if (_mode == RHModeTx && irq_flags & RH_RF95_TX_DONE)
{
_txGood++;
setModeIdle();
}
else if (_mode == RHModeCad && irq_flags & RH_RF95_CAD_DONE)
{
_cad = irq_flags & RH_RF95_CAD_DETECTED;
setModeIdle();
}
// Sigh: on some processors, for some unknown reason, doing this only once does not actually
// clear the radio's interrupt flag. So we do it twice. Why?
spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
}