Library for HopeRF RFM22 / RFM22B transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/
Dependents: RF22_MAX_test_Send Geofence_receiver Geofence_sender Geofence_sender ... more
More Info about RFM22-modules like connecting and a demo-program see RF22-Notebook
Diff: RF22.cpp
- Revision:
- 8:d9e2ca137f2e
- Parent:
- 7:b86825b9d74b
- Child:
- 9:4002a2c117cc
diff -r b86825b9d74b -r d9e2ca137f2e RF22.cpp --- a/RF22.cpp Wed Mar 13 20:37:19 2013 +0000 +++ b/RF22.cpp Sun Apr 07 11:42:36 2013 +0000 @@ -16,11 +16,10 @@ //RF22* RF22::_RF22ForInterrupt[2] = {0, 0}; // These are indexed by the values of ModemConfigChoice -// Canned modem configurations generated with +// Canned modem configurations generated with // http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls // Stored in flash (program) memory to save SRAM -/*PROGMEM */ static const RF22::ModemConfig MODEM_CONFIG_TABLE[] = -{ +/*PROGMEM */ static const RF22::ModemConfig MODEM_CONFIG_TABLE[] = { { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5 @@ -59,7 +58,7 @@ }; RF22::RF22(PinName slaveSelectPin, PinName mosi, PinName miso, PinName sclk, PinName interrupt) - : _slaveSelectPin(slaveSelectPin), _spi(mosi, miso, sclk), _interrupt(interrupt), led1(LED1), led2(LED2), led3(LED3), led4(LED4) + : _slaveSelectPin(slaveSelectPin), _spi(mosi, miso, sclk), _interrupt(interrupt), led1(LED1), led2(LED2), led3(LED3), led4(LED4) { @@ -68,8 +67,8 @@ _rxGood = 0; _rxBad = 0; _txGood = 0; - - + + } boolean RF22::init() @@ -82,9 +81,9 @@ //pinMode(_slaveSelectPin, OUTPUT); //digitalWrite(_slaveSelectPin, HIGH); _slaveSelectPin = 1; - + wait_ms(100); - + // start the SPI library: // Note the RF22 wants mode 0, MSB first and default to 1 Mbps /*SPI.begin(); @@ -105,27 +104,27 @@ // 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; + && _deviceType != RF22_DEVICE_TYPE_TX) + return false; // Set up interrupt handler // if (_interrupt == 0) // { //_RF22ForInterrupt[0] = this; - //attachInterrupt(0, RF22::isr0, LOW); + //attachInterrupt(0, RF22::isr0, LOW); _interrupt.fall(this, &RF22::isr0); -/* } - else if (_interrupt == 1) - { - _RF22ForInterrupt[1] = this; - attachInterrupt(1, RF22::isr1, LOW); - } - else - return false; -*/ + /* } + 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); @@ -149,7 +148,7 @@ setPreambleLength(8); uint8_t syncwords[] = { 0x2d, 0xd4 }; setSyncWords(syncwords, sizeof(syncwords)); - setPromiscuous(false); + 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 @@ -165,9 +164,15 @@ 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); + // this is original from arduion, which crashes on mbed after some hours + //see https://groups.google.com/forum/?fromgroups#!topic/rf22-arduino/Ezkw256yQI8 + //spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR); + //without RF22_ENFFERR it works - Charly + spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM |RF22_ENRXFFAFULL | RF22_ENPKSENT |RF22_ENPKVALID| RF22_ENCRCERROR); + 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); @@ -178,10 +183,7 @@ setTxPower(RF22_TXPOW_8DBM); // setTxPower(RF22_TXPOW_17DBM); -// Set the AFC for receiver to max. 0,1MHz -// Other AFC-Registers have PowerOnValues which enable AFC -// RF22_AFC_LIMIT 0x50 =0,1MHz -// spiWrite(RF22_REG_2A_AFC_LIMITER, RF22_AFC_LIMIT); // POR=0x00 = OFF + return true; } @@ -190,9 +192,9 @@ void RF22::handleInterrupt() { uint8_t _lastInterruptFlags[2]; - -led1 = 1; - + + led1 = 1; + // Read the interrupt flags which clears the interrupt spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); @@ -203,110 +205,126 @@ Serial.print(" "); Serial.println(_lastInterruptFlags[1], HEX); if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0) - Serial.println("FUNNY: no interrupt!"); + 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; + 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_IFFERROR) { +// Serial.println("IFFERROR"); + led4 = !led4; + resetFifos(); // Clears the interrupt + if (_mode == RF22_MODE_TX) + restartTransmit(); + else if (_mode == RF22_MODE_RX){ + clearRxBuf(); + //stop and start Rx + setModeIdle(); + setModeRx(); + } + // stop handling the remaining interruppts as something went wrong here + return; } - 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"); + + // 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 + //led2 = !led2; + sendNextFragment(); +// Serial.println("ITXFFAEM"); } - 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_IRXFFAFULL) { + // Caution, any delay here may cause a FF overflow + // Read some data from the Rx FIFO + //led4 = !led4; + readNextFragment(); +// Serial.println("IRXFFAFULL"); + } + if (_lastInterruptFlags[0] & RF22_IEXT) { + // This is not enabled by the base code, but users may want to enable it + //led2 = !led2; + handleExternalInterrupt(); +// Serial.println("IEXT"); } - if (_lastInterruptFlags[0] & RF22_IPKSENT) - { -// Serial.println("IPKSENT"); - _txGood++; - led4 = !led4; - // Transmission does not automatically clear the tx buffer. - // Could retransmit if we wanted - // RF22 transitions automatically to Idle - _mode = RF22_MODE_IDLE; + if (_lastInterruptFlags[1] & RF22_IWUT) { + // This is not enabled by the base code, but users may want to enable it + //led2 = !led2; + handleWakeupTimerInterrupt(); +// Serial.println("IWUT"); + } + if (_lastInterruptFlags[0] & RF22_IPKSENT) { +// Serial.println("IPKSENT"); + _txGood++; + //led4 = !led4; + // 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); + + 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++; + // 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++; + led2 = !led2; + _mode = RF22_MODE_IDLE; + clearRxBuf(); + return; // Hmmm receiver buffer overflow. + } + + spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); + //__disable_irq(); // Disable Interrupts + _rxGood++; + _bufLen = len; _mode = RF22_MODE_IDLE; - clearRxBuf(); - return; // Hmmm receiver buffer overflow. - } + _rxBufValid = true; + // reset the fifo for next packet?? + //resetRxFifo(); + //__enable_irq(); // Enable Interrupts - spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); - __disable_irq(); // Disable Interrupts - _rxGood++; - _bufLen = len; - _mode = RF22_MODE_IDLE; - _rxBufValid = true; - __enable_irq(); // Enable Interrupts - - led3 = !led3; + led3 = !led3; } - if (_lastInterruptFlags[0] & RF22_ICRCERROR) - { -// Serial.println("ICRCERR"); - _rxBad++; - led2 = !led2; - clearRxBuf(); - resetRxFifo(); - _mode = RF22_MODE_IDLE; - setModeRx(); // Keep trying + + if (_lastInterruptFlags[0] & RF22_ICRCERROR) { +// Serial.println("ICRCERR"); + _rxBad++; + led2 = !led2; + clearRxBuf(); + resetRxFifo(); + _mode = RF22_MODE_IDLE; + setModeRx(); // Keep trying } - if (_lastInterruptFlags[1] & RF22_IPREAVAL) - { -// Serial.println("IPREAVAL"); - _lastRssi = spiRead(RF22_REG_26_RSSI); - clearRxBuf(); + + if (_lastInterruptFlags[1] & RF22_IPREAVAL) { +// Serial.println("IPREAVAL"); + + _lastRssi = spiRead(RF22_REG_26_RSSI); + + + // why clear the rx-buf here? charly + clearRxBuf(); + + } led1 = 0; } @@ -367,7 +385,7 @@ _slaveSelectPin = 0; _spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the start address with the write mask off while (len--) - *dest++ = _spi.write(0); + *dest++ = _spi.write(0); //digitalWrite(_slaveSelectPin, HIGH); _slaveSelectPin = 1; } @@ -378,7 +396,7 @@ _slaveSelectPin = 0; _spi.write(reg | RF22_SPI_WRITE_MASK); // Send the start address with the write mask on while (len--) - _spi.write(*src++); + _spi.write(*src++); //digitalWrite(_slaveSelectPin, HIGH); _slaveSelectPin = 1; } @@ -390,7 +408,7 @@ uint8_t RF22::adcRead(uint8_t adcsel, uint8_t adcref , - uint8_t adcgain, + uint8_t adcgain, uint8_t adcoffs) { uint8_t configuration = adcsel | adcref | (adcgain & RF22_ADCGAIN); @@ -400,8 +418,8 @@ // Conversion time is nominally 305usec // Wait for the DONE bit while (!(spiRead(RF22_REG_0F_ADC_CONFIGURATION) & RF22_ADCDONE)) - ; - // Return the value + ; + // Return the value return spiRead(RF22_REG_11_ADC_VALUE); } @@ -409,7 +427,7 @@ { spiWrite(RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RF22_ENTSOFFS); spiWrite(RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs); - return adcRead(RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RF22_ADCREF_BANDGAP_VOLTAGE); + return adcRead(RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RF22_ADCREF_BANDGAP_VOLTAGE); } uint16_t RF22::wutRead() @@ -438,20 +456,17 @@ uint8_t fbsel = RF22_SBSEL; uint8_t afclimiter; if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon - return false; - if (centre >= 480.0) - { - if (afcPullInRange < 0.0 || afcPullInRange > 0.318750) return false; - centre /= 2; - fbsel |= RF22_HBSEL; - afclimiter = afcPullInRange * 1000000.0 / 1250.0; - } - else - { - if (afcPullInRange < 0.0 || afcPullInRange > 0.159375) - return false; - afclimiter = afcPullInRange * 1000000.0 / 625.0; + if (centre >= 480.0) { + if (afcPullInRange < 0.0 || afcPullInRange > 0.318750) + return false; + centre /= 2; + fbsel |= RF22_HBSEL; + afclimiter = afcPullInRange * 1000000.0 / 1250.0; + } else { + if (afcPullInRange < 0.0 || afcPullInRange > 0.159375) + return false; + afclimiter = afcPullInRange * 1000000.0 / 625.0; } centre /= 10.0; float integerPart = floor(centre); @@ -502,35 +517,32 @@ void RF22::setModeIdle() { - if (_mode != RF22_MODE_IDLE) - { - setMode(_idleMode); - _mode = RF22_MODE_IDLE; + if (_mode != RF22_MODE_IDLE) { + setMode(_idleMode); + _mode = RF22_MODE_IDLE; } } void RF22::setModeRx() { - if (_mode != RF22_MODE_RX) - { - setMode(_idleMode | RF22_RXON); - _mode = RF22_MODE_RX; + if (_mode != RF22_MODE_RX) { + setMode(_idleMode | RF22_RXON); + _mode = RF22_MODE_RX; } } 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(); + 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(); } - } +} uint8_t RF22::mode() { @@ -591,7 +603,7 @@ boolean RF22::available() { if (!_rxBufValid) - setModeRx(); // Make sure we are receiving + setModeRx(); // Make sure we are receiving return _rxBufValid; } @@ -599,7 +611,7 @@ void RF22::waitAvailable() { while (!available()) - ; + ; } // Blocks until a valid message is received or timeout expires @@ -610,15 +622,15 @@ t.start(); unsigned long endtime = t.read_ms() + timeout; while (t.read_ms() < endtime) - if (available()) - return true; + if (available()) + return true; return false; } void RF22::waitPacketSent() { while (_mode == RF22_MODE_TX) - ; // Wait for any previous transmit to finish + ; // Wait for any previous transmit to finish } // Diagnostic help @@ -628,15 +640,13 @@ uint8_t i; Serial.println(prompt); - for (i = 0; i < len; i++) - { - if (i % 16 == 15) - Serial.println(buf[i], HEX); - else - { - Serial.print(buf[i], HEX); - Serial.print(' '); - } + for (i = 0; i < len; i++) { + if (i % 16 == 15) + Serial.println(buf[i], HEX); + else { + Serial.print(buf[i], HEX); + Serial.print(' '); + } } Serial.println(' '); #endif @@ -645,11 +655,13 @@ boolean RF22::recv(uint8_t* buf, uint8_t* len) { if (!available()) - return false; + return false; + __disable_irq(); // Disable Interrupts if (*len > _bufLen) - *len = _bufLen; + *len = _bufLen; memcpy(buf, _buf, *len); clearRxBuf(); + __enable_irq(); // Enable Interrupts // printBuffer("recv:", buf, *len); // } return true; @@ -685,9 +697,9 @@ waitPacketSent(); // ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - if (!fillTxBuf(data, len)) - return false; - startTransmit(); + if (!fillTxBuf(data, len)) + return false; + startTransmit(); } // printBuffer("send:", data, len); return true; @@ -697,17 +709,19 @@ { clearTxBuf(); if (!len) - return false; + return false; return appendTxBuf(data, len); } boolean RF22::appendTxBuf(const uint8_t* data, uint8_t len) { if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN) - return false; + return false; + __disable_irq(); // Disable Interrupts memcpy(_buf + _bufLen, data, len); _bufLen += len; - + __enable_irq(); // Enable Interrupts + // printBuffer("txbuf:", _buf, _bufLen); return true; } @@ -715,15 +729,14 @@ // Assumption: there is currently <= RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO void RF22::sendNextFragment() { - if (_txBufSentIndex < _bufLen) - { - // Some left to send? - uint8_t len = _bufLen - _txBufSentIndex; - // But dont send too much - if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1)) - len = (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1); - spiBurstWrite(RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len); - _txBufSentIndex += len; + if (_txBufSentIndex < _bufLen) { + // Some left to send? + uint8_t len = _bufLen - _txBufSentIndex; + // But dont send too much + if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1)) + len = (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1); + spiBurstWrite(RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len); + _txBufSentIndex += len; } } @@ -732,7 +745,7 @@ void RF22::readNextFragment() { if (((uint16_t)_bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN) - return; // Hmmm receiver overflow. Should never occur + 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);