// Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO // That means it should only be called after a RXFFAFULL interrupt void RF22::readNextFragment() { if (((uint16_t) _bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN) return; // Hmmm receiver overflow. Should never occur // Read the RF22_RXFFAFULL_THRESHOLD octets that should be there spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RF22_RXFFAFULL_THRESHOLD); _bufLen += RF22_RXFFAFULL_THRESHOLD; }
// C++ level interrupt handler for this instance // LORA is unusual in that it has several interrupt lines, and not a single, combined one. // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly // connnected to the processor. // We use this to get RxDone and TxDone interrupts void RH_RF95::handleInterrupt() { // Read the interrupt register uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS); 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 }
uint8_t RFM69_checkRx() { // Check IRQ register for payloadready flag (indicates RXed packet waiting in FIFO) if(spiRead(RFM69_REG_28_IRQ_FLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) { // Get packet length from first byte of FIFO _bufLen = spiRead(RFM69_REG_00_FIFO)+1; // Read FIFO into our Buffer spiBurstRead(RFM69_REG_00_FIFO, _buf, RFM69_FIFO_SIZE); // Read RSSI register (should be of the packet? - TEST THIS) _lastRssi = -(spiRead(RFM69_REG_24_RSSI_VALUE)/2); // Clear the radio FIFO (found in HopeRF demo code) RFM69_clearFifo(); return 1; } return 0; }
// C++ level interrupt handler for this instance // LORA is unusual in that it has several interrupt lines, and not a single, combined one. // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly // connnected to the processor. // We use this to get RxDone and TxDone interrupts void RH_RF95::handleInterrupt() { // Read the interrupt register uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS); if (_mode == RHModeRx) { if (irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR)) { _rxBad++; // Stay in RX mode } else if (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 RSSI of this packet // 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) - 137; // We have received a message. validateRxBuf(); if (_rxBufValid) setModeIdle(); // Got one // else stay in RX mode } } else if (_mode == RHModeTx && (irq_flags & RH_RF95_TX_DONE)) { _txGood++; setModeIdle(); } spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xFF); // Clear all IRQ flags }
// C++ level interrupt handler for this instance // LORA is unusual in that it has several interrupt lines, and not a single, combined one. // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly // connnected to the processor. // We use this to get RxDone and TxDone interrupts void RH_RF95::handleInterrupt() { // Read the interrupt register // Serial.println("debug|Interrupt from RFM!"); uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS); if (_mode == RHModeRx && irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR)) { // Serial.print("debug|Bad packet received - irq_flags: "); // Serial.println(irq_flags, BIN); _rxBad++; spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags return; // after this point, we know that the data in the FIFO is corrupted } if (_mode == RHModeRx && irq_flags & RH_RF95_RX_DONE) { // Have received a packet uint8_t len = spiRead(RH_RF95_REG_13_RX_NB_BYTES); // Serial.println("debug|RX interrupt - we got some data!"); // 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; // Remember the RSSI of this packet // this is according to the doc, but is it really correct? // weakest receiveable signals are reported RSSI at about -94 _lastRssi = -137 + (uint8_t) spiRead(RH_RF95_REG_1A_PKT_RSSI_VALUE); byte snr; snr = spiRead(0x19); if( snr & 0x80 ) { // The SNR sign bit is True // 2's complement -> Invert and divide by 4 snr = ( ( ~snr + 1 ) & 0xFF ) >> 2; _lastSnr = -snr; } else {
// C++ level interrupt handler for this instance void RF22::handleInterrupt() { uint8_t _lastInterruptFlags[2]; // Read the interrupt flags which clears the interrupt spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); #if 0 // Caution: Serial printing in this interrupt routine can cause mysterious crashes Serial.print("interrupt "); Serial.print(_lastInterruptFlags[0], HEX); Serial.print(" "); Serial.println(_lastInterruptFlags[1], HEX); if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0) Serial.println("FUNNY: no interrupt!"); #endif #if 0 // TESTING: fake an RF22_IFFERROR static int counter = 0; if (_lastInterruptFlags[0] & RF22_IPKSENT && counter++ == 10) { _lastInterruptFlags[0] = RF22_IFFERROR; counter = 0; } #endif if (_lastInterruptFlags[0] & RF22_IFFERROR) { // Serial.println("IFFERROR"); resetFifos(); // Clears the interrupt if (_mode == RF22_MODE_TX) restartTransmit(); else if (_mode == RF22_MODE_RX) clearRxBuf(); } // Caution, any delay here may cause a FF underflow or overflow if (_lastInterruptFlags[0] & RF22_ITXFFAEM) { // See if more data has to be loaded into the Tx FIFO sendNextFragment(); // Serial.println("ITXFFAEM"); } if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) { // Caution, any delay here may cause a FF overflow // Read some data from the Rx FIFO readNextFragment(); // Serial.println("IRXFFAFULL"); } if (_lastInterruptFlags[0] & RF22_IEXT) { // This is not enabled by the base code, but users may want to enable it handleExternalInterrupt(); // Serial.println("IEXT"); } if (_lastInterruptFlags[1] & RF22_IWUT) { // This is not enabled by the base code, but users may want to enable it handleWakeupTimerInterrupt(); // Serial.println("IWUT"); } if (_lastInterruptFlags[0] & RF22_IPKSENT) { // Serial.println("IPKSENT"); _txGood++; // Transmission does not automatically clear the tx buffer. // Could retransmit if we wanted // RF22 transitions automatically to Idle _mode = RF22_MODE_IDLE; } if (_lastInterruptFlags[0] & RF22_IPKVALID) { uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH); // Serial.println("IPKVALID"); // Serial.println(len); // Serial.println(_bufLen); // May have already read one or more fragments // Get any remaining unread octets, based on the expected length // First make sure we dont overflow the buffer in the case of a stupid length // or partial bad receives if ( len > RF22_MAX_MESSAGE_LEN || len < _bufLen) { _rxBad++; _mode = RF22_MODE_IDLE; clearRxBuf(); return; // Hmmm receiver buffer overflow. } spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); _rxGood++; _bufLen = len; _mode = RF22_MODE_IDLE; _rxBufValid = true; } if (_lastInterruptFlags[0] & RF22_ICRCERROR) { // Serial.println("ICRCERR"); _rxBad++; clearRxBuf(); resetRxFifo(); _mode = RF22_MODE_IDLE; setModeRx(); // Keep trying } if (_lastInterruptFlags[1] & RF22_IPREAVAL) { // Serial.println("IPREAVAL"); _lastRssi = spiRead(RF22_REG_26_RSSI); clearRxBuf(); } }
//------------------------------------------------------------------------ uint16_t RF22_wutRead() { uint8_t buf[2]; spiBurstRead(RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2); return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order }
//------------------------------------------------------------------------ // C level interrupt handler for this instance void RF22_handleInterrupt() { uint8_t _lastInterruptFlags[2]; // Read the interrupt flags which clears the interrupt spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); if (_lastInterruptFlags[0] & RF22_IFFERROR) { RF22_resetFifos(); // Clears the interrupt if (_mode == RF22_MODE_TX) { RF22_restartTransmit(); } else if (_mode == RF22_MODE_RX) { RF22_clearRxBuf(); //stop and start Rx RF22_setModeIdle(); RF22_setModeRx(); } // stop handling the remaining interruppts as something went wrong here return; } // Caution, any delay here may cause a FF underflow or overflow if (_lastInterruptFlags[0] & RF22_ITXFFAEM) { RF22_sendNextFragment(); } if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) { RF22_readNextFragment(); } if (_lastInterruptFlags[0] & RF22_IEXT) { RF22_handleExternalInterrupt(); } if (_lastInterruptFlags[1] & RF22_IWUT) { RF22_handleWakeupTimerInterrupt(); } if (_lastInterruptFlags[0] & RF22_IPKSENT) { _txGood++; _mode = RF22_MODE_IDLE; } if (_lastInterruptFlags[0] & RF22_IPKVALID) { uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH); // May have already read one or more fragments // Get any remaining unread octets, based on the expected length // First make sure we dont overflow the buffer in the case of a stupid length // or partial bad receives if (len > RF22_MAX_MESSAGE_LEN || len < _bufLen) { _rxBad++; _mode = RF22_MODE_IDLE; RF22_clearRxBuf(); return; // Hmmm receiver buffer overflow. } spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); DISABLE_ALL_INTERRUPTS(); // Disable Interrupts _rxGood++; _bufLen = len; _mode = RF22_MODE_IDLE; _rxBufValid = true; // reset the fifo for next packet?? //resetRxFifo(); ENABLE_ALL_INTERRUPTS(); // Enable Interrupts } if (_lastInterruptFlags[0] & RF22_ICRCERROR) { _rxBad++; RF22_clearRxBuf(); RF22_resetRxFifo(); _mode = RF22_MODE_IDLE; RF22_setModeRx(); // Keep trying } if (_lastInterruptFlags[1] & RF22_IPREAVAL) { _lastRssi = spiRead(RF22_REG_26_RSSI); RF22_clearRxBuf(); } }
uint8_t RF22::spiRead(uint8_t reg) { uint8_t data; spiBurstRead (reg, &data, 1); return data; }
// C++ level interrupt handler for this instance void RF22::handleInterrupt() { uint8_t _lastInterruptFlags[2]; // Read the interrupt flags which clears the interrupt spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); if (_lastInterruptFlags[0] & RF22_IFFERROR) { // cout << "RFM22 handleInterrupt(): IFFERROR\n"; resetFifos(); // Clears the interrupt if (_mode == RF22_MODE_TX) { restartTransmit(); } else if (_mode == RF22_MODE_RX) { clearRxBuf(); setModeIdle(); setModeRx(); } } // Caution, any delay here may cause a FF underflow or overflow if (_lastInterruptFlags[0] & RF22_ITXFFAEM) { // See if more data has to be loaded into the Tx FIFO sendNextFragment(); //cout << "RFM22 handleInterrupt(): ITXFFAEM\n"; } if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) { // Caution, any delay here may cause a FF overflow // Read some data from the Rx FIFO readNextFragment(); cout << "RFM22 handleInterrupt(): IRXFFAFULL\n"; } if (_lastInterruptFlags[0] & RF22_IEXT) { // This is not enabled by the base code, but users may want to enable it handleExternalInterrupt(); cout << "RFM22 handleInterrupt(): IEXT\n"; } if (_lastInterruptFlags[1] & RF22_IWUT) { // This is not enabled by the base code, but users may want to enable it handleWakeupTimerInterrupt(); } if (_lastInterruptFlags[0] & RF22_IPKSENT) { _txGood++; // Transmission does not automatically clear the tx buffer. // Could retransmit if we wanted // RF22 transitions automatically to Idle _mode = RF22_MODE_IDLE; } if (_lastInterruptFlags[0] & RF22_IPKVALID) { // cout << "RFM22 handleInterrupt(): IPKVALID\n"; fflush(stdout); uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH); // May have already read one or more fragments // Get any remaining unread octets, based on the expected length // First make sure we dont overflow the buffer in the case of a stupid length // or partial bad receives if (len > RF22_MAX_MESSAGE_LEN || len < _bufLen) { _rxBad++; _mode = RF22_MODE_IDLE; clearRxBuf(); return; // Hmmm receiver buffer overflow. } spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf, 64); resetRxFifo(); setModeIdle(); setModeRx(); // spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); _rxGood++; _bufLen = len; _mode = RF22_MODE_IDLE; _rxBufValid = true; //notify registered dispatcherModule dispatcher->receiveMessage(this); } if (_lastInterruptFlags[0] & RF22_ICRCERROR) { cout << "RFM22 handleInterrupt(): ICRCERR\n"; _rxBad++; clearRxBuf(); resetRxFifo(); _mode = RF22_MODE_IDLE; setModeRx(); // Keep trying } if (_lastInterruptFlags[1] & RF22_IPREAVAL) { // cout << "RFM22 handleInterrupt(): IPREAVAL\n"; _lastRssi = spiRead(RF22_REG_26_RSSI); // clearRxBuf(); } }