Library for HopeRF RFM22 transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/
Fork of RF22 by
Diff: RF22.cpp
- Revision:
- 5:0386600f3408
- Parent:
- 4:f0bf38bb0ff8
- Child:
- 7:b86825b9d74b
--- a/RF22.cpp Sun Feb 19 21:12:10 2012 +0000 +++ b/RF22.cpp Sat Mar 02 20:49:07 2013 +0000 @@ -1,7 +1,7 @@ // RF22.cpp // // Copyright (C) 2011 Mike McCauley -// $Id: RF22.cpp,v 1.13 2011/10/09 21:22:24 mikem Exp mikem $ +// $Id: RF22.cpp,v 1.17 2013/02/06 21:33:56 mikem Exp mikem $ // ported to mbed by Karl Zweimueller @@ -17,13 +17,14 @@ // These are indexed by the values of ModemConfigChoice // Canned modem configurations generated with -// 'http://www.hoperf.com/upfile/RF22B 23B 31B 42B 43B Register Settings_RevB1-v5.xls' +// 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[] = { { 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 + // All the following enable FIFO with reg 71 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5 @@ -167,9 +168,8 @@ 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 - setFrequency(868.0); -// setFrequency(434.0); + // 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); @@ -181,7 +181,7 @@ // 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 +// spiWrite(RF22_REG_2A_AFC_LIMITER, RF22_AFC_LIMIT); // POR=0x00 = OFF return true; } @@ -197,7 +197,8 @@ spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); #if 0 - pc.print("interrupt "); + // 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); @@ -205,7 +206,7 @@ Serial.println("FUNNY: no interrupt!"); #endif -/* +#if 0 // TESTING: fake an RF22_IFFERROR static int counter = 0; if (_lastInterruptFlags[0] & RF22_IPKSENT && counter++ == 10) @@ -213,7 +214,7 @@ _lastInterruptFlags[0] = RF22_IFFERROR; counter = 0; } -*/ +#endif if (_lastInterruptFlags[0] & RF22_IFFERROR) { @@ -229,7 +230,7 @@ { // See if more data has to be loaded into the Tx FIFO sendNextFragment(); -// Serial.println("TXFFAEM"); +// Serial.println("ITXFFAEM"); } if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) { @@ -252,28 +253,42 @@ } if (_lastInterruptFlags[0] & RF22_IPKSENT) { -// Serial.println("PKSENT"); +// Serial.println("IPKSENT"); _txGood++; led4 = !led4; // Transmission does not automatically clear the tx buffer. // Could retransmit if we wanted - _txPacketSent = true; // RF22 transitions automatically to Idle _mode = RF22_MODE_IDLE; } if (_lastInterruptFlags[0] & RF22_IPKVALID) { -// Serial.println("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 - len -= _bufLen; - spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len); + // 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++; - led3 = !led3; - _bufLen += len; + _bufLen = len; _mode = RF22_MODE_IDLE; _rxBufValid = true; + + led3 = !led3; + } if (_lastInterruptFlags[0] & RF22_ICRCERROR) { @@ -287,7 +302,7 @@ } if (_lastInterruptFlags[1] & RF22_IPREAVAL) { -// Serial.println("ENPREAVAL"); +// Serial.println("IPREAVAL"); _lastRssi = spiRead(RF22_REG_26_RSSI); clearRxBuf(); } @@ -350,7 +365,7 @@ _slaveSelectPin = 1; } -void RF22::spiBurstWrite(uint8_t reg, uint8_t* src, uint8_t len) +void RF22::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len) { //digitalWrite(_slaveSelectPin, LOW); _slaveSelectPin = 0; @@ -409,17 +424,27 @@ } // Returns true if centre + (fhch * fhs) is within limits -// Caution, different versions of the RF22 suport different max freq +// Caution, different versions of the RF22 support different max freq // so YMMV -boolean RF22::setFrequency(float centre) +boolean RF22::setFrequency(float centre, float afcPullInRange) { 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; } centre /= 10.0; float integerPart = floor(centre); @@ -433,6 +458,7 @@ spiWrite(RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel); spiWrite(RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8); spiWrite(RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff); + spiWrite(RF22_REG_2A_AFC_LIMITER, afclimiter); return !(statusRead() & RF22_FREQERR); } @@ -491,7 +517,17 @@ { 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() +{ + return _mode; } void RF22::setTxPower(uint8_t power) @@ -500,7 +536,7 @@ } // Sets registers from a canned modem configuration structure -void RF22::setModemRegisters(ModemConfig* config) +void RF22::setModemRegisters(const ModemConfig* config) { spiWrite(RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c); spiWrite(RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f); @@ -532,7 +568,7 @@ } // Caution doesnt set sync word len in Header Control 2 0x33 -void RF22::setSyncWords(uint8_t* syncWords, uint8_t len) +void RF22::setSyncWords(const uint8_t* syncWords, uint8_t len) { spiBurstWrite(RF22_REG_36_SYNC_WORD3, syncWords, len); } @@ -545,7 +581,8 @@ boolean RF22::available() { - setModeRx(); + if (!_rxBufValid) + setModeRx(); // Make sure we are receiving return _rxBufValid; } @@ -571,8 +608,29 @@ void RF22::waitPacketSent() { - while (!_txPacketSent) - ; + while (_mode == RF22_MODE_TX) + ; // Wait for any previous transmit to finish +} + +// Diagnostic help +void RF22::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len) +{ +#ifdef RF22_HAVE_SERIAL + 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(' '); + } + } + Serial.println(' '); +#endif } boolean RF22::recv(uint8_t* buf, uint8_t* len) @@ -583,6 +641,8 @@ *len = _bufLen; memcpy(buf, _buf, *len); clearRxBuf(); +// printBuffer("recv:", buf, *len); +// } return true; } @@ -600,36 +660,44 @@ setModeTx(); // Start the transmitter, turns off the receiver } -// Restart the trasnmission of a packet that had a problem +// Restart the transmission of a packet that had a problem void RF22::restartTransmit() { _mode = RF22_MODE_IDLE; _txBufSentIndex = 0; - _txPacketSent = false; // Serial.println("Restart"); startTransmit(); } -boolean RF22::send(uint8_t* data, uint8_t len) +boolean RF22::send(const uint8_t* data, uint8_t len) { - setModeIdle(); - fillTxBuf(data, len); + waitPacketSent(); +// ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!fillTxBuf(data, len)) + return false; startTransmit(); + } +// printBuffer("send:", data, len); return true; } -boolean RF22::fillTxBuf(uint8_t* data, uint8_t len) +boolean RF22::fillTxBuf(const uint8_t* data, uint8_t len) { clearTxBuf(); + if (!len) + return false; return appendTxBuf(data, len); } -boolean RF22::appendTxBuf(uint8_t* data, uint8_t len) +boolean RF22::appendTxBuf(const uint8_t* data, uint8_t len) { if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN) return false; memcpy(_buf + _bufLen, data, len); _bufLen += len; + +// printBuffer("txbuf:", _buf, _bufLen); return true; } @@ -638,7 +706,7 @@ { if (_txBufSentIndex < _bufLen) { - // Some left to send + // Some left to send? uint8_t len = _bufLen - _txBufSentIndex; // But dont send too much if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1)) @@ -649,14 +717,12 @@ } // Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO -// That means it should only be called after a RXAFULL interrupt +// 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) - { - // Hmmm receiver overflow. Should never occur - return; - } + 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;