Exemplo n.º 1
0
boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
{
    // Assemble the message
    uint8_t thisSequenceNumber = ++_lastSequenceNumber;

    Timer t;

    uint8_t retries = 0;
    while (retries++ <= _retries)
    {
        setHeaderId(thisSequenceNumber);
        setHeaderFlags(0);
        sendto(buf, len, address);
        waitPacketSent(3000);

        // Never wait for ACKS to broadcasts:
        if (address == RF22_BROADCAST_ADDRESS)
            return true;

        if (retries > 1)
            _retransmissions++;
        t.start();
        unsigned long thisSendTime = t.read_ms(); // Timeout does not include original transmit time


        // Compute a new timeout, random between _timeout and _timeout*2
    // This is to prevent collisions on every retransmit
        // if 2 nodes try to transmit at the same time
        uint16_t timeout = _timeout + (_timeout * (rand() % 100) / 100);
        while (t.read_ms() < (thisSendTime + timeout)) 
        {
            if (available()) {
                clearRxBuf(); // Not using recv, so clear it ourselves
                uint8_t from = headerFrom();
                uint8_t to = headerTo();
                uint8_t id = headerId();
                uint8_t flags = headerFlags();
                // Now have a message: is it our ACK?
                if (   from == address
                        && to == _thisAddress
                        && (flags & RF22_FLAGS_ACK)
            && (id == thisSequenceNumber))
        {
                    // Its the ACK we are waiting for
                    return true;
        }
        else if (   !(flags & RF22_FLAGS_ACK)
             && (id == _seenIds[from]))
        {
                    // This is a request we have already received. ACK it again
                    acknowledge(id, from);
                }
                // Else discard it
            }
            // Not the one we are waiting for, maybe keep waiting until timeout exhausted
        }
        // Timeout exhausted, maybe retry
    }
    return false;
}
Exemplo n.º 2
0
uint8_t RF22::recv(uint8_t* buf, uint8_t* len)
{
    if (!available())
		return false;

	if (*len > _bufLen)
	    *len = _bufLen;
	memcpy(buf, _buf, *len);
	clearRxBuf();
    return true;
}
Exemplo n.º 3
0
void RF22::setModeTx() {
	if (_mode != RF22_MODE_TX) {
		setMode(_idleMode | RF22_TXON);
		_mode = RF22_MODE_TX;
		// Hmmm, if you dont clear the RX FIFO here, then it appears that going
		// to transmit mode in the middle of a receive can corrupt the
		// RX FIFO
		resetRxFifo();
		clearRxBuf();
	}
}
Exemplo n.º 4
0
bool RF22::recv(uint8_t* buf, uint8_t* len) {
	if (!available())
		return false;
//TODO check
	piLock(1);
	if (*len > _bufLen)
		*len = _bufLen;
	memcpy(buf, _buf, *len);
	clearRxBuf();
//    printBuffer("recv:", buf, *len);
	piUnlock(1);
	return true;
}
Exemplo n.º 5
0
bool RH_TCP::recv(uint8_t* buf, uint8_t* len)
{
    if (!available())
	return false;

    if (buf && len)
    {
	if (*len > _rxBufLen)
	    *len = _rxBufLen;
	memcpy(buf, _rxBuf, *len);
    }
    clearRxBuf();
    return true;
}
Exemplo n.º 6
0
bool RH_RF95::recv(uint8_t* buf, uint8_t* len)
{
    if (!available())
	return false;
    if (buf && len)
    {
	ATOMIC_BLOCK_START;
	// Skip the 4 headers that are at the beginning of the rxBuf
	if (*len > _bufLen-RH_RF95_HEADER_LEN)
	    *len = _bufLen-RH_RF95_HEADER_LEN;
	memcpy(buf, _buf+RH_RF95_HEADER_LEN, *len);
	ATOMIC_BLOCK_END;
    }
    clearRxBuf(); // This message accepted and cleared
    return true;
}
Exemplo n.º 7
0
bool RH_RF22::recv(uint8_t* buf, uint8_t* len)
{
    if (!available())
	return false;

    if (buf && len)
    {
	ATOMIC_BLOCK_START;
	if (*len > _bufLen)
	    *len = _bufLen;
	memcpy(buf, _buf, *len);
	ATOMIC_BLOCK_END;
    }
    clearRxBuf();
//    printBuffer("recv:", buf, *len);
    return true;
}
Exemplo n.º 8
0
Arquivo: RF22.cpp Projeto: Ygorf/RF22
boolean RF22::init()
{
    // Wait for RF22 POR (up to 16msec)
    delay(16);

    // Initialise the slave select pin
    pinMode(_slaveSelectPin, OUTPUT);
    digitalWrite(_slaveSelectPin, HIGH);

    // start the SPI library:
    // Note the RF22 wants mode 0, MSB first and default to 1 Mbps
    _spi->begin();
    _spi->setDataMode(SPI_MODE0);
    _spi->setBitOrder(MSBFIRST);
    _spi->setClockDivider(SPI_CLOCK_DIV16);  // (16 Mhz / 16) = 1 MHz
    delay(100);

    // Software reset the device
    reset();

    // Get the device type and check it
    // This also tests whether we are really connected to a device
    _deviceType = spiRead(RF22_REG_00_DEVICE_TYPE);
    if (   _deviceType != RF22_DEVICE_TYPE_RX_TRX
        && _deviceType != RF22_DEVICE_TYPE_TX)
	return false;

	// Set up interrupt handler
    if (_interrupt == 0)
    {
	_RF22ForInterrupt[0] = this;
	attachInterrupt(0, RF22::isr0, LOW);  
    }
    else if (_interrupt == 1)
    {
	_RF22ForInterrupt[1] = this;
	attachInterrupt(1, RF22::isr1, LOW);  
    }
    else
	return false;
 
    clearTxBuf();
    clearRxBuf();
  
    // Most of these are the POR default
    spiWrite(RF22_REG_7D_TX_FIFO_CONTROL2, RF22_TXFFAEM_THRESHOLD);
    spiWrite(RF22_REG_7E_RX_FIFO_CONTROL,  RF22_RXFFAFULL_THRESHOLD);
    spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_ENPACRX | RF22_ENPACTX | RF22_ENCRC | RF22_CRC_CRC_16_IBM);
    // Configure the message headers
    // Here we set up the standard packet format for use by the RF22 library
    // 8 nibbles preamble
    // 2 SYNC words 2d, d4
    // Header length 4 (to, from, id, flags)
    // 1 octet of data length (0 to 255)
    // 0 to 255 octets data
    // 2 CRC octets as CRC16(IBM), computed on the header, length and data
    // On reception the to address is check for validity against RF22_REG_3F_CHECK_HEADER3
    // or the broadcast address of 0xff
    // If no changes are made after this, the transmitted
    // to address will be 0xff, the from address will be 0xff
    // and all such messages will be accepted. This permits the out-of the box
    // RF22 config to act as an unaddresed, unreliable datagram service
    spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_HEADER3 | RF22_HDCH_HEADER3);
    spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_4 | RF22_SYNCLEN_2);
    setPreambleLength(8);
    uint8_t syncwords[] = { 0x2d, 0xd4 };
    setSyncWords(syncwords, sizeof(syncwords));
    setPromiscuous(false); 
    // Check the TO header against RF22_DEFAULT_NODE_ADDRESS
    spiWrite(RF22_REG_3F_CHECK_HEADER3, RF22_DEFAULT_NODE_ADDRESS);
    // Set the default transmit header values
    setHeaderTo(RF22_DEFAULT_NODE_ADDRESS);
    setHeaderFrom(RF22_DEFAULT_NODE_ADDRESS);
    setHeaderId(0);
    setHeaderFlags(0);

    // Ensure the antenna can be switched automatically according to transmit and receive
    // This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
    // This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive
    spiWrite (RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state
    spiWrite (RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state

    // Enable interrupts
    spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR);
    spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL);

    // Set some defaults. An innocuous ISM frequency, and reasonable pull-in
    setFrequency(434.0, 0.05);
//    setFrequency(900.0);
    // Some slow, reliable default speed and modulation
    setModemConfig(FSK_Rb2_4Fd36);
//    setModemConfig(FSK_Rb125Fd125);
    // Minimum power
    setTxPower(RF22_TXPOW_8DBM);
//    setTxPower(RF22_TXPOW_17DBM);

    return true;
}
Exemplo n.º 9
0
Arquivo: RF22.cpp Projeto: Ygorf/RF22
// 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();
    }
}
Exemplo n.º 10
0
bool RH_RF22::init()
{
    if (!RHSPIDriver::init())
	return false;

    // Determine the interrupt number that corresponds to the interruptPin
    int interruptNumber = digitalPinToInterrupt(_interruptPin);
    if (interruptNumber == NOT_AN_INTERRUPT)
	return false;

    // Software reset the device
    reset();

    // Get the device type and check it
    // This also tests whether we are really connected to a device
    _deviceType = spiRead(RH_RF22_REG_00_DEVICE_TYPE);
    if (   _deviceType != RH_RF22_DEVICE_TYPE_RX_TRX
        && _deviceType != RH_RF22_DEVICE_TYPE_TX)
    {
	return false;
    }

    // Add by Adrien van den Bossche <*****@*****.**> for Teensy
    // ARM M4 requires the below. else pin interrupt doesn't work properly.
    // On all other platforms, its innocuous, belt and braces
    pinMode(_interruptPin, INPUT); 

    // Enable interrupt output on the radio. Interrupt line will now go high until
    // an interrupt occurs
    spiWrite(RH_RF22_REG_05_INTERRUPT_ENABLE1, RH_RF22_ENTXFFAEM | RH_RF22_ENRXFFAFULL | RH_RF22_ENPKSENT | RH_RF22_ENPKVALID | RH_RF22_ENCRCERROR | RH_RF22_ENFFERR);
    spiWrite(RH_RF22_REG_06_INTERRUPT_ENABLE2, RH_RF22_ENPREAVAL);

    // Set up interrupt handler
    // Since there are a limited number of interrupt glue functions isr*() available,
    // we can only support a limited number of devices simultaneously
    // On some devices, notably most Arduinos, the interrupt pin passed in is actually the 
    // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
    // yourself based on knowledge of what Arduino board you are running on.
    _deviceForInterrupt[_interruptCount] = this;
    if (_interruptCount == 0)
	attachInterrupt(interruptNumber, isr0, FALLING);
    else if (_interruptCount == 1)
	attachInterrupt(interruptNumber, isr1, FALLING);
    else if (_interruptCount == 2)
	attachInterrupt(interruptNumber, isr2, FALLING);
    else
	return false; // Too many devices, not enough interrupt vectors
    _interruptCount++;

    setModeIdle();

    clearTxBuf();
    clearRxBuf();
  
    // Most of these are the POR default
    spiWrite(RH_RF22_REG_7D_TX_FIFO_CONTROL2, RH_RF22_TXFFAEM_THRESHOLD);
    spiWrite(RH_RF22_REG_7E_RX_FIFO_CONTROL,  RH_RF22_RXFFAFULL_THRESHOLD);
    spiWrite(RH_RF22_REG_30_DATA_ACCESS_CONTROL, RH_RF22_ENPACRX | RH_RF22_ENPACTX | RH_RF22_ENCRC | (_polynomial & RH_RF22_CRC));

    // Configure the message headers
    // Here we set up the standard packet format for use by the RH_RF22 library
    // 8 nibbles preamble
    // 2 SYNC words 2d, d4
    // Header length 4 (to, from, id, flags)
    // 1 octet of data length (0 to 255)
    // 0 to 255 octets data
    // 2 CRC octets as CRC16(IBM), computed on the header, length and data
    // On reception the to address is check for validity against RH_RF22_REG_3F_CHECK_HEADER3
    // or the broadcast address of 0xff
    // If no changes are made after this, the transmitted
    // to address will be 0xff, the from address will be 0xff
    // and all such messages will be accepted. This permits the out-of the box
    // RH_RF22 config to act as an unaddresed, unreliable datagram service
    spiWrite(RH_RF22_REG_32_HEADER_CONTROL1, RH_RF22_BCEN_HEADER3 | RH_RF22_HDCH_HEADER3);
    spiWrite(RH_RF22_REG_33_HEADER_CONTROL2, RH_RF22_HDLEN_4 | RH_RF22_SYNCLEN_2);

    setPreambleLength(8);
    uint8_t syncwords[] = { 0x2d, 0xd4 };
    setSyncWords(syncwords, sizeof(syncwords));
    setPromiscuous(false); 

    // Set some defaults. An innocuous ISM frequency, and reasonable pull-in
    setFrequency(434.0, 0.05);
//    setFrequency(900.0);
    // Some slow, reliable default speed and modulation
    setModemConfig(FSK_Rb2_4Fd36);
//    setModemConfig(FSK_Rb125Fd125);
    setGpioReversed(false);
    // Lowish power
    setTxPower(RH_RF22_TXPOW_8DBM);

    return true;
}
Exemplo n.º 11
0
bool RF22::init() {
	//TODO check.
	wiringPiSetup();

//	// Wait for RF22 POR (up to 16msec)
//	delay(16);

	if (wiringPiSPISetup(_slaveSelectPin, 1000000) == -1) {
		printf("Could not initialize SPI\n");
		return false;
	}

	delay(20);

	// Software reset the device
	reset();
	delay(1);

	// Get the device type and check it
	// This also tests whether we are really connected to a device
	_deviceType = spiRead(RF22_REG_00_DEVICE_TYPE);
	if (_deviceType != RF22_DEVICE_TYPE_RX_TRX && _deviceType != RF22_DEVICE_TYPE_TX)
		return false;

	// Set up interrupt handler
	if (_interrupt == 0) {
		_RF22ForInterrupt[0] = this;
		//attaching interrupt to gpio pins. see wiringPi.com -> gpio chart
		wiringPiISR(6, INT_EDGE_FALLING, RF22::isr0);
	} else if (_interrupt == 1) {
		_RF22ForInterrupt[1] = this;
		wiringPiISR(4, INT_EDGE_FALLING, RF22::isr1);
	} else
		return false;

	clearTxBuf();
	clearRxBuf();

	// Most of these are the POR default
	spiWrite(RF22_REG_7D_TX_FIFO_CONTROL2, RF22_TXFFAEM_THRESHOLD);
	spiWrite(RF22_REG_7E_RX_FIFO_CONTROL, RF22_RXFFAFULL_THRESHOLD);
	spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_ENPACRX | RF22_ENPACTX | RF22_ENCRC | RF22_CRC_CRC_16_IBM);
	// Configure the message headers
	// Here we set up the standard packet format for use by the RF22 library
	// 8 nibbles preamble
	// 2 SYNC words 2d, d4
	// Header length 4 (to, from, id, flags)
	// 1 octet of data length (0 to 255)
	// 0 to 255 octets data
	// 2 CRC octets as CRC16(IBM), computed on the header, length and data
	// On reception the to address is check for validity against RF22_REG_3F_CHECK_HEADER3
	// or the broadcast address of 0xff
	// If no changes are made after this, the transmitted
	// to address will be 0xff, the from address will be 0xff
	// and all such messages will be accepted. This permits the out-of the box
	// RF22 config to act as an unaddresed, unreliable datagram service
	spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_HEADER3 | RF22_HDCH_HEADER3);
	spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_4 | RF22_SYNCLEN_2 | 0x1);
	setPreambleLength(8);
	uint8_t syncwords[] = { 0x2d, 0xd4 };
	setSyncWords(syncwords, sizeof(syncwords));
	setPromiscuous(false);
	// Check the TO header against RF22_DEFAULT_NODE_ADDRESS
	spiWrite(RF22_REG_3F_CHECK_HEADER3, RF22_DEFAULT_NODE_ADDRESS);
	// Set the default transmit header values
	setHeaderTo(RF22_DEFAULT_NODE_ADDRESS);
	setHeaderFrom(RF22_DEFAULT_NODE_ADDRESS);
	setHeaderId(0);
	setHeaderFlags(0);

	// Ensure the antenna can be switched automatically according to transmit and receive
	// This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
	// This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive
	spiWrite(RF22_REG_0B_GPIO_CONFIGURATION0, 0x12); // TX state
	spiWrite(RF22_REG_0C_GPIO_CONFIGURATION1, 0x15); // RX state
	//spiWrite(RF22_REG_0D_GPIO_CONFIGURATION2, 0x14); //raw data to port 4 have to activate it later?
	//put into a mode where the interrupt frequency is not as high as the clock of the rfm22.
	//the raspberry is connected to that pin and would freeze if an isr is registered.
	spiWrite(RF22_REG_0D_GPIO_CONFIGURATION2, 0x13);
	// Enable interrupts
	spiWrite(RF22_REG_05_INTERRUPT_ENABLE1,
			RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR);
	spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL);

	// Set some defaults. An innocuous ISM frequency, and reasonable pull-in
	setFrequency(434.0, 0.05);
//    setFrequency(900.0);
	// Some slow, reliable default speed and modulation
	setModemConfig(FSK_Rb2_4Fd36);
//    setModemConfig(FSK_Rb125Fd125);
	// Minimum power
	setTxPower(RF22_TXPOW_8DBM);
//    setTxPower(RF22_TXPOW_17DBM);

	return true;
}
Exemplo n.º 12
0
// 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();
	}
}