// 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(); } }
// C++ level interrupt handler for this instance void RH_RF24::handleInterrupt() { uint8_t status[8]; command(RH_RF24_CMD_GET_INT_STATUS, NULL, 0, status, sizeof(status)); // Decode and handle the interrupt bits we are interested in // if (status[0] & RH_RF24_INT_STATUS_CHIP_INT_STATUS) if (status[0] & RH_RF24_INT_STATUS_MODEM_INT_STATUS) { // if (status[4] & RH_RF24_INT_STATUS_INVALID_PREAMBLE) if (status[4] & RH_RF24_INT_STATUS_INVALID_SYNC) { // After INVALID_SYNC, sometimes the radio gets into a silly state and subsequently reports it for every packet // Need to reset the radio and clear the RX FIFO, cause sometimes theres junk there too _mode = RHModeIdle; clearRxFifo(); clearBuffer(); } } if (status[0] & RH_RF24_INT_STATUS_PH_INT_STATUS) { if (status[2] & RH_RF24_INT_STATUS_CRC_ERROR) { // CRC Error // Radio automatically went to _idleMode _mode = RHModeIdle; _rxBad++; clearRxFifo(); clearBuffer(); } if (status[2] & RH_RF24_INT_STATUS_PACKET_SENT) { _txGood++; // Transmission does not automatically clear the tx buffer. // Could retransmit if we wanted // RH_RF24 configured to transition automatically to Idle after packet sent _mode = RHModeIdle; clearBuffer(); } if (status[2] & RH_RF24_INT_STATUS_PACKET_RX) { // A complete message has been received with good CRC // Get the RSSI, configured to latch at sync detect in radio_config uint8_t modem_status[6]; command(RH_RF24_CMD_GET_MODEM_STATUS, NULL, 0, modem_status, sizeof(modem_status)); _lastRssi = modem_status[3]; _lastPreambleTime = millis(); // Save it in our buffer readNextFragment(); // And see if we have a valid message validateRxBuf(); // Radio will have transitioned automatically to the _idleMode _mode = RHModeIdle; } if (status[2] & RH_RF24_INT_STATUS_TX_FIFO_ALMOST_EMPTY) { // TX FIFO almost empty, maybe send another chunk, if there is one sendNextFragment(); } if (status[2] & RH_RF24_INT_STATUS_RX_FIFO_ALMOST_FULL) { // Some more data to read, get it readNextFragment(); } } }
// 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(); } }