Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RF22 by
RF22.cpp
00001 // RF22.cpp 00002 // 00003 // Copyright (C) 2011 Mike McCauley 00004 // $Id: RF22.cpp,v 1.17 2013/02/06 21:33:56 mikem Exp mikem $ 00005 // ported to mbed by Karl Zweimueller 00006 00007 00008 #include "mbed.h" 00009 #include "RF22.h" 00010 //#include <SPI.h> 00011 00012 00013 // Interrupt vectors for the 2 Arduino interrupt pins 00014 // Each interrupt can be handled by a different instance of RF22, allowing you to have 00015 // 2 RF22s per Arduino 00016 //RF22* RF22::_RF22ForInterrupt[2] = {0, 0}; 00017 00018 // These are indexed by the values of ModemConfigChoice 00019 // Canned modem configurations generated with 00020 // http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls 00021 // Stored in flash (program) memory to save SRAM 00022 /*PROGMEM */ static const RF22::ModemConfig MODEM_CONFIG_TABLE[] = { 00023 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier 00024 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5 00025 00026 // All the following enable FIFO with reg 71 00027 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72 00028 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm 00029 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5 00030 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36 00031 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45 00032 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45 00033 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6 00034 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6 00035 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8 00036 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125 00037 00038 // GFSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm 00039 // These differ from FSK only in register 71, for the modulation type 00040 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x23, 0x08 }, // 2, 5 00041 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x23, 0x3a }, // 2.4, 36 00042 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x23, 0x48 }, // 4.8, 45 00043 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x23, 0x48 }, // 9.6, 45 00044 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x23, 0x0f }, // 19.2, 9.6 00045 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x23, 0x1f }, // 38.4, 19.6 00046 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x23, 0x2e }, // 57.6. 28.8 00047 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x23, 0xc8 }, // 125, 125 00048 00049 // OOK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm 00050 { 0x51, 0x03, 0x68, 0x00, 0x3a, 0x93, 0x01, 0x3d, 0x2c, 0x11, 0x28, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x21, 0x08 }, // 1.2, 75 00051 { 0xc8, 0x03, 0x39, 0x20, 0x68, 0xdc, 0x00, 0x6b, 0x2a, 0x08, 0x2a, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x21, 0x08 }, // 2.4, 335 00052 { 0xc8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x29, 0x04, 0x29, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x21, 0x08 }, // 4.8, 335 00053 { 0xb8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x82, 0x29, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x21, 0x08 }, // 9.6, 335 00054 { 0xa8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x41, 0x29, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x21, 0x08 }, // 19.2, 335 00055 { 0x98, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x20, 0x29, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x21, 0x08 }, // 38.4, 335 00056 { 0x98, 0x03, 0x96, 0x00, 0xda, 0x74, 0x00, 0xdc, 0x28, 0x1f, 0x29, 0x80, 0x60, 0x0a, 0x3d, 0x0c, 0x21, 0x08 }, // 40, 335 00057 00058 }; 00059 00060 RF22::RF22(PinName slaveSelectPin, PinName mosi, PinName miso, PinName sclk, PinName interrupt) 00061 : _slaveSelectPin(slaveSelectPin), _spi(mosi, miso, sclk), _interrupt(interrupt), led1(LED4), led2(LED2), led3(LED3), led4(LED4) 00062 { 00063 00064 00065 _idleMode = RF22_XTON; // Default idle state is READY mode 00066 _mode = RF22_MODE_IDLE; // We start up in idle mode 00067 _rxGood = 0; 00068 _rxBad = 0; 00069 _txGood = 0; 00070 00071 00072 } 00073 00074 boolean RF22::init() 00075 { 00076 // Wait for RF22 POR (up to 16msec) 00077 //delay(16); 00078 wait_ms(16); 00079 00080 // Initialise the slave select pin 00081 //pinMode(_slaveSelectPin, OUTPUT); 00082 //digitalWrite(_slaveSelectPin, HIGH); 00083 _slaveSelectPin = 1; 00084 00085 wait_ms(100); 00086 00087 // start the SPI library: 00088 // Note the RF22 wants mode 0, MSB first and default to 1 Mbps 00089 /*SPI.begin(); 00090 SPI.setDataMode(SPI_MODE0); 00091 SPI.setBitOrder(MSBFIRST); 00092 SPI.setClockDivider(SPI_CLOCK_DIV16); // (16 Mhz / 16) = 1 MHz 00093 */ 00094 00095 // Setup the spi for 8 bit data : 1RW-bit 7 adressbit and 8 databit 00096 // second edge capture, with a 10MHz clock rate 00097 _spi.format(8,0); 00098 _spi.frequency(10000000); 00099 00100 // Software reset the device 00101 reset(); 00102 00103 // Get the device type and check it 00104 // This also tests whether we are really connected to a device 00105 _deviceType = spiRead(RF22_REG_00_DEVICE_TYPE); 00106 if ( _deviceType != RF22_DEVICE_TYPE_RX_TRX 00107 && _deviceType != RF22_DEVICE_TYPE_TX) 00108 return false; 00109 00110 // Set up interrupt handler 00111 // if (_interrupt == 0) 00112 // { 00113 //_RF22ForInterrupt[0] = this; 00114 //attachInterrupt(0, RF22::isr0, LOW); 00115 _interrupt.fall(this, &RF22::isr0); 00116 /* } 00117 else if (_interrupt == 1) 00118 { 00119 _RF22ForInterrupt[1] = this; 00120 attachInterrupt(1, RF22::isr1, LOW); 00121 } 00122 else 00123 return false; 00124 */ 00125 clearTxBuf(); 00126 clearRxBuf(); 00127 00128 // Most of these are the POR default 00129 spiWrite(RF22_REG_7D_TX_FIFO_CONTROL2, RF22_TXFFAEM_THRESHOLD); 00130 spiWrite(RF22_REG_7E_RX_FIFO_CONTROL, RF22_RXFFAFULL_THRESHOLD); 00131 spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_ENPACRX | RF22_ENPACTX | RF22_ENCRC | RF22_CRC_CRC_16_IBM); 00132 // Configure the message headers 00133 // Here we set up the standard packet format for use by the RF22 library 00134 // 8 nibbles preamble 00135 // 2 SYNC words 2d, d4 00136 // Header length 4 (to, from, id, flags) 00137 // 1 octet of data length (0 to 255) 00138 // 0 to 255 octets data 00139 // 2 CRC octets as CRC16(IBM), computed on the header, length and data 00140 // On reception the to address is check for validity against RF22_REG_3F_CHECK_HEADER3 00141 // or the broadcast address of 0xff 00142 // If no changes are made after this, the transmitted 00143 // to address will be 0xff, the from address will be 0xff 00144 // and all such messages will be accepted. This permits the out-of the box 00145 // RF22 config to act as an unaddresed, unreliable datagram service 00146 spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_HEADER3 | RF22_HDCH_HEADER3); 00147 spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_4 | RF22_SYNCLEN_2); 00148 setPreambleLength(8); 00149 uint8_t syncwords[] = { 0x2d, 0xd4 }; 00150 setSyncWords(syncwords, sizeof(syncwords)); 00151 setPromiscuous(false); 00152 // Check the TO header against RF22_DEFAULT_NODE_ADDRESS 00153 spiWrite(RF22_REG_3F_CHECK_HEADER3, RF22_DEFAULT_NODE_ADDRESS); 00154 // Set the default transmit header values 00155 setHeaderTo(RF22_DEFAULT_NODE_ADDRESS); 00156 setHeaderFrom(RF22_DEFAULT_NODE_ADDRESS); 00157 setHeaderId(0); 00158 setHeaderFlags(0); 00159 00160 // Ensure the antenna can be switched automatically according to transmit and receive 00161 // This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit 00162 // This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive 00163 spiWrite (RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state 00164 spiWrite (RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state 00165 00166 // Enable interrupts 00167 // this is original from arduion, which crashes on mbed after some hours 00168 //see https://groups.google.com/forum/?fromgroups#!topic/rf22-arduino/Ezkw256yQI8 00169 //spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR); 00170 //without RF22_ENFFERR it works - Charly 00171 spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM |RF22_ENRXFFAFULL | RF22_ENPKSENT |RF22_ENPKVALID| RF22_ENCRCERROR); 00172 00173 spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL); 00174 00175 00176 // Set some defaults. An innocuous ISM frequency, and reasonable pull-in 00177 setFrequency(434.0, 0.05); 00178 // setFrequency(900.0); 00179 // Some slow, reliable default speed and modulation 00180 setModemConfig(FSK_Rb2_4Fd36); 00181 // setModemConfig(FSK_Rb125Fd125); 00182 // Minimum power 00183 setTxPower(RF22_TXPOW_8DBM); 00184 // setTxPower(RF22_TXPOW_17DBM); 00185 00186 00187 00188 return true; 00189 } 00190 00191 // C++ level interrupt handler for this instance 00192 void RF22::handleInterrupt() 00193 { 00194 uint8_t _lastInterruptFlags[2]; 00195 00196 led1 = 1; 00197 00198 // Read the interrupt flags which clears the interrupt 00199 spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); 00200 00201 #if 0 00202 // Caution: Serial printing in this interrupt routine can cause mysterious crashes 00203 Serial.print("interrupt "); 00204 Serial.print(_lastInterruptFlags[0], HEX); 00205 Serial.print(" "); 00206 Serial.println(_lastInterruptFlags[1], HEX); 00207 if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0) 00208 Serial.println("FUNNY: no interrupt!"); 00209 #endif 00210 00211 #if 0 00212 // TESTING: fake an RF22_IFFERROR 00213 static int counter = 0; 00214 if (_lastInterruptFlags[0] & RF22_IPKSENT && counter++ == 10) { 00215 _lastInterruptFlags[0] = RF22_IFFERROR; 00216 counter = 0; 00217 } 00218 #endif 00219 00220 00221 if (_lastInterruptFlags[0] & RF22_IFFERROR) { 00222 // Serial.println("IFFERROR"); 00223 led4 = !led4; 00224 resetFifos(); // Clears the interrupt 00225 if (_mode == RF22_MODE_TX) 00226 restartTransmit(); 00227 else if (_mode == RF22_MODE_RX){ 00228 clearRxBuf(); 00229 //stop and start Rx 00230 setModeIdle(); 00231 setModeRx(); 00232 } 00233 // stop handling the remaining interruppts as something went wrong here 00234 return; 00235 } 00236 00237 // Caution, any delay here may cause a FF underflow or overflow 00238 if (_lastInterruptFlags[0] & RF22_ITXFFAEM) { 00239 // See if more data has to be loaded into the Tx FIFO 00240 //led2 = !led2; 00241 sendNextFragment(); 00242 // Serial.println("ITXFFAEM"); 00243 } 00244 00245 if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) { 00246 // Caution, any delay here may cause a FF overflow 00247 // Read some data from the Rx FIFO 00248 //led4 = !led4; 00249 readNextFragment(); 00250 // Serial.println("IRXFFAFULL"); 00251 } 00252 if (_lastInterruptFlags[0] & RF22_IEXT) { 00253 // This is not enabled by the base code, but users may want to enable it 00254 //led2 = !led2; 00255 handleExternalInterrupt(); 00256 // Serial.println("IEXT"); 00257 } 00258 if (_lastInterruptFlags[1] & RF22_IWUT) { 00259 // This is not enabled by the base code, but users may want to enable it 00260 //led2 = !led2; 00261 handleWakeupTimerInterrupt(); 00262 // Serial.println("IWUT"); 00263 } 00264 if (_lastInterruptFlags[0] & RF22_IPKSENT) { 00265 // Serial.println("IPKSENT"); 00266 _txGood++; 00267 //led4 = !led4; 00268 // Transmission does not automatically clear the tx buffer. 00269 // Could retransmit if we wanted 00270 // RF22 transitions automatically to Idle 00271 _mode = RF22_MODE_IDLE; 00272 } 00273 00274 if (_lastInterruptFlags[0] & RF22_IPKVALID) { 00275 uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH); 00276 // Serial.println("IPKVALID"); 00277 // Serial.println(len); 00278 // Serial.println(_bufLen); 00279 00280 // May have already read one or more fragments 00281 // Get any remaining unread octets, based on the expected length 00282 // First make sure we dont overflow the buffer in the case of a stupid length 00283 // or partial bad receives 00284 00285 if ( len > RF22_MAX_MESSAGE_LEN 00286 || len < _bufLen) { 00287 _rxBad++; 00288 led2 = !led2; 00289 _mode = RF22_MODE_IDLE; 00290 clearRxBuf(); 00291 return; // Hmmm receiver buffer overflow. 00292 } 00293 00294 spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); 00295 //__disable_irq(); // Disable Interrupts 00296 _rxGood++; 00297 _bufLen = len; 00298 _mode = RF22_MODE_IDLE; 00299 _rxBufValid = true; 00300 // reset the fifo for next packet?? 00301 //resetRxFifo(); 00302 //__enable_irq(); // Enable Interrupts 00303 00304 led3 = !led3; 00305 00306 } 00307 00308 if (_lastInterruptFlags[0] & RF22_ICRCERROR) { 00309 // Serial.println("ICRCERR"); 00310 _rxBad++; 00311 led2 = !led2; 00312 clearRxBuf(); 00313 resetRxFifo(); 00314 _mode = RF22_MODE_IDLE; 00315 setModeRx(); // Keep trying 00316 } 00317 00318 if (_lastInterruptFlags[1] & RF22_IPREAVAL) { 00319 // Serial.println("IPREAVAL"); 00320 00321 _lastRssi = spiRead(RF22_REG_26_RSSI); 00322 00323 00324 // why clear the rx-buf here? charly 00325 clearRxBuf(); 00326 00327 00328 } 00329 led1 = 0; 00330 } 00331 00332 // These are low level functions that call the interrupt handler for the correct 00333 // instance of RF22. 00334 // 2 interrupts allows us to have 2 different devices 00335 void RF22::isr0() 00336 { 00337 //if (_RF22ForInterrupt[0]) 00338 //_RF22ForInterrupt[0]->handleInterrupt(); 00339 handleInterrupt(); 00340 } 00341 /* 00342 void RF22::isr1() 00343 { 00344 if (_RF22ForInterrupt[1]) 00345 _RF22ForInterrupt[1]->handleInterrupt(); 00346 } 00347 */ 00348 void RF22::reset() 00349 { 00350 spiWrite(RF22_REG_07_OPERATING_MODE1, RF22_SWRES); 00351 // Wait for it to settle 00352 //delay(1); // SWReset time is nominally 100usec 00353 wait_ms(1); 00354 } 00355 00356 uint8_t RF22::spiRead(uint8_t reg) 00357 { 00358 __disable_irq(); // Disable Interrupts 00359 //digitalWrite(_slaveSelectPin, LOW); 00360 _slaveSelectPin=0; 00361 //_spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the address with the write mask off 00362 _spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the address with the write mask off 00363 uint8_t val = _spi.write(0); // The written value is ignored, reg value is read 00364 //digitalWrite(_slaveSelectPin, HIGH); 00365 _slaveSelectPin = 1; 00366 __enable_irq(); // Enable Interrupts 00367 return val; 00368 } 00369 00370 void RF22::spiWrite(uint8_t reg, uint8_t val) 00371 { 00372 __disable_irq(); // Disable Interrupts 00373 //digitalWrite(_slaveSelectPin, LOW); 00374 _slaveSelectPin = 0; 00375 _spi.write(reg | RF22_SPI_WRITE_MASK); // Send the address with the write mask on 00376 _spi.write(val); // New value follows 00377 //digitalWrite(_slaveSelectPin, HIGH); 00378 _slaveSelectPin = 1; 00379 __enable_irq(); // Enable Interrupts 00380 } 00381 00382 void RF22::spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len) 00383 { 00384 //digitalWrite(_slaveSelectPin, LOW); 00385 _slaveSelectPin = 0; 00386 _spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the start address with the write mask off 00387 while (len--) 00388 *dest++ = _spi.write(0); 00389 //digitalWrite(_slaveSelectPin, HIGH); 00390 _slaveSelectPin = 1; 00391 } 00392 00393 void RF22::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len) 00394 { 00395 //digitalWrite(_slaveSelectPin, LOW); 00396 _slaveSelectPin = 0; 00397 _spi.write(reg | RF22_SPI_WRITE_MASK); // Send the start address with the write mask on 00398 while (len--) 00399 _spi.write(*src++); 00400 //digitalWrite(_slaveSelectPin, HIGH); 00401 _slaveSelectPin = 1; 00402 } 00403 00404 uint8_t RF22::statusRead() 00405 { 00406 return spiRead(RF22_REG_02_DEVICE_STATUS); 00407 } 00408 00409 uint8_t RF22::adcRead(uint8_t adcsel, 00410 uint8_t adcref , 00411 uint8_t adcgain, 00412 uint8_t adcoffs) 00413 { 00414 uint8_t configuration = adcsel | adcref | (adcgain & RF22_ADCGAIN); 00415 spiWrite(RF22_REG_0F_ADC_CONFIGURATION, configuration | RF22_ADCSTART); 00416 spiWrite(RF22_REG_10_ADC_SENSOR_AMP_OFFSET, adcoffs); 00417 00418 // Conversion time is nominally 305usec 00419 // Wait for the DONE bit 00420 while (!(spiRead(RF22_REG_0F_ADC_CONFIGURATION) & RF22_ADCDONE)) 00421 ; 00422 // Return the value 00423 return spiRead(RF22_REG_11_ADC_VALUE); 00424 } 00425 00426 uint8_t RF22::temperatureRead(uint8_t tsrange, uint8_t tvoffs) 00427 { 00428 spiWrite(RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RF22_ENTSOFFS); 00429 spiWrite(RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs); 00430 return adcRead(RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RF22_ADCREF_BANDGAP_VOLTAGE); 00431 } 00432 00433 uint16_t RF22::wutRead() 00434 { 00435 uint8_t buf[2]; 00436 spiBurstRead(RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2); 00437 return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order 00438 } 00439 00440 // RFM-22 doc appears to be wrong: WUT for wtm = 10000, r, = 0, d = 0 is about 1 sec 00441 void RF22::setWutPeriod(uint16_t wtm, uint8_t wtr, uint8_t wtd) 00442 { 00443 uint8_t period[3]; 00444 00445 period[0] = ((wtr & 0xf) << 2) | (wtd & 0x3); 00446 period[1] = wtm >> 8; 00447 period[2] = wtm & 0xff; 00448 spiBurstWrite(RF22_REG_14_WAKEUP_TIMER_PERIOD1, period, sizeof(period)); 00449 } 00450 00451 // Returns true if centre + (fhch * fhs) is within limits 00452 // Caution, different versions of the RF22 support different max freq 00453 // so YMMV 00454 boolean RF22::setFrequency(float centre, float afcPullInRange) 00455 { 00456 uint8_t fbsel = RF22_SBSEL; 00457 uint8_t afclimiter; 00458 if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon 00459 return false; 00460 if (centre >= 480.0) { 00461 if (afcPullInRange < 0.0 || afcPullInRange > 0.318750) 00462 return false; 00463 centre /= 2; 00464 fbsel |= RF22_HBSEL; 00465 afclimiter = afcPullInRange * 1000000.0 / 1250.0; 00466 } else { 00467 if (afcPullInRange < 0.0 || afcPullInRange > 0.159375) 00468 return false; 00469 afclimiter = afcPullInRange * 1000000.0 / 625.0; 00470 } 00471 centre /= 10.0; 00472 float integerPart = floor(centre); 00473 float fractionalPart = centre - integerPart; 00474 00475 uint8_t fb = (uint8_t)integerPart - 24; // Range 0 to 23 00476 fbsel |= fb; 00477 uint16_t fc = fractionalPart * 64000; 00478 spiWrite(RF22_REG_73_FREQUENCY_OFFSET1, 0); // REVISIT 00479 spiWrite(RF22_REG_74_FREQUENCY_OFFSET2, 0); 00480 spiWrite(RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel); 00481 spiWrite(RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8); 00482 spiWrite(RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff); 00483 spiWrite(RF22_REG_2A_AFC_LIMITER, afclimiter); 00484 return !(statusRead() & RF22_FREQERR); 00485 } 00486 00487 // Step size in 10kHz increments 00488 // Returns true if centre + (fhch * fhs) is within limits 00489 boolean RF22::setFHStepSize(uint8_t fhs) 00490 { 00491 spiWrite(RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE, fhs); 00492 return !(statusRead() & RF22_FREQERR); 00493 } 00494 00495 // Adds fhch * fhs to centre frequency 00496 // Returns true if centre + (fhch * fhs) is within limits 00497 boolean RF22::setFHChannel(uint8_t fhch) 00498 { 00499 spiWrite(RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT, fhch); 00500 return !(statusRead() & RF22_FREQERR); 00501 } 00502 00503 uint8_t RF22::rssiRead() 00504 { 00505 return spiRead(RF22_REG_26_RSSI); 00506 } 00507 00508 uint8_t RF22::ezmacStatusRead() 00509 { 00510 return spiRead(RF22_REG_31_EZMAC_STATUS); 00511 } 00512 00513 void RF22::setMode(uint8_t mode) 00514 { 00515 spiWrite(RF22_REG_07_OPERATING_MODE1, mode); 00516 } 00517 00518 void RF22::setModeIdle() 00519 { 00520 if (_mode != RF22_MODE_IDLE) { 00521 setMode(_idleMode); 00522 _mode = RF22_MODE_IDLE; 00523 } 00524 } 00525 00526 void RF22::setModeRx() 00527 { 00528 if (_mode != RF22_MODE_RX) { 00529 setMode(_idleMode | RF22_RXON); 00530 _mode = RF22_MODE_RX; 00531 } 00532 } 00533 00534 void RF22::setModeTx() 00535 { 00536 if (_mode != RF22_MODE_TX) { 00537 setMode(_idleMode | RF22_TXON); 00538 _mode = RF22_MODE_TX; 00539 // Hmmm, if you dont clear the RX FIFO here, then it appears that going 00540 // to transmit mode in the middle of a receive can corrupt the 00541 // RX FIFO 00542 resetRxFifo(); 00543 // clearRxBuf(); 00544 } 00545 } 00546 00547 uint8_t RF22::mode() 00548 { 00549 return _mode; 00550 } 00551 00552 void RF22::setTxPower(uint8_t power) 00553 { 00554 spiWrite(RF22_REG_6D_TX_POWER, power); 00555 } 00556 00557 // Sets registers from a canned modem configuration structure 00558 void RF22::setModemRegisters(const ModemConfig* config) 00559 { 00560 spiWrite(RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c); 00561 spiWrite(RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f); 00562 spiBurstWrite(RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE, &config->reg_20, 6); 00563 spiBurstWrite(RF22_REG_2C_OOK_COUNTER_VALUE_1, &config->reg_2c, 3); 00564 spiWrite(RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING, config->reg_58); 00565 spiWrite(RF22_REG_69_AGC_OVERRIDE1, config->reg_69); 00566 spiBurstWrite(RF22_REG_6E_TX_DATA_RATE1, &config->reg_6e, 5); 00567 } 00568 00569 // Set one of the canned FSK Modem configs 00570 // Returns true if its a valid choice 00571 boolean RF22::setModemConfig(ModemConfigChoice index) 00572 { 00573 if (index > (sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig))) 00574 return false; 00575 00576 RF22::ModemConfig cfg; 00577 memcpy(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RF22::ModemConfig)); 00578 setModemRegisters(&cfg); 00579 00580 return true; 00581 } 00582 00583 // REVISIT: top bit is in Header Control 2 0x33 00584 void RF22::setPreambleLength(uint8_t nibbles) 00585 { 00586 spiWrite(RF22_REG_34_PREAMBLE_LENGTH, nibbles); 00587 } 00588 00589 // Caution doesnt set sync word len in Header Control 2 0x33 00590 void RF22::setSyncWords(const uint8_t* syncWords, uint8_t len) 00591 { 00592 spiBurstWrite(RF22_REG_36_SYNC_WORD3, syncWords, len); 00593 } 00594 00595 void RF22::clearRxBuf() 00596 { 00597 __disable_irq(); // Disable Interrupts 00598 _bufLen = 0; 00599 _rxBufValid = false; 00600 __enable_irq(); // Enable Interrupts 00601 } 00602 00603 boolean RF22::available() 00604 { 00605 if (!_rxBufValid) 00606 setModeRx(); // Make sure we are receiving 00607 return _rxBufValid; 00608 } 00609 00610 // Blocks until a valid message is received 00611 void RF22::waitAvailable() 00612 { 00613 while (!available()) 00614 ; 00615 } 00616 00617 // Blocks until a valid message is received or timeout expires 00618 // Return true if there is a message available 00619 bool RF22::waitAvailableTimeout(uint16_t timeout) 00620 { 00621 Timer t; 00622 t.start(); 00623 unsigned long endtime = t.read_ms() + timeout; 00624 while (t.read_ms() < endtime) 00625 if (available()) 00626 return true; 00627 return false; 00628 } 00629 00630 void RF22::waitPacketSent() 00631 { 00632 while (_mode == RF22_MODE_TX) 00633 ; // Wait for any previous transmit to finish 00634 } 00635 00636 // Diagnostic help 00637 void RF22::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len) 00638 { 00639 #ifdef RF22_HAVE_SERIAL 00640 uint8_t i; 00641 00642 Serial.println(prompt); 00643 for (i = 0; i < len; i++) { 00644 if (i % 16 == 15) 00645 Serial.println(buf[i], HEX); 00646 else { 00647 Serial.print(buf[i], HEX); 00648 Serial.print(' '); 00649 } 00650 } 00651 Serial.println(' '); 00652 #endif 00653 } 00654 00655 boolean RF22::recv(uint8_t* buf, uint8_t* len) 00656 { 00657 if (!available()) 00658 return false; 00659 __disable_irq(); // Disable Interrupts 00660 if (*len > _bufLen) 00661 *len = _bufLen; 00662 memcpy(buf, _buf, *len); 00663 clearRxBuf(); 00664 __enable_irq(); // Enable Interrupts 00665 // printBuffer("recv:", buf, *len); 00666 // } 00667 return true; 00668 } 00669 00670 void RF22::clearTxBuf() 00671 { 00672 __disable_irq(); // Disable Interrupts 00673 _bufLen = 0; 00674 _txBufSentIndex = 0; 00675 _txPacketSent = false; 00676 __enable_irq(); // Enable Interrupts 00677 } 00678 00679 void RF22::startTransmit() 00680 { 00681 sendNextFragment(); // Actually the first fragment 00682 spiWrite(RF22_REG_3E_PACKET_LENGTH, _bufLen); // Total length that will be sent 00683 setModeTx(); // Start the transmitter, turns off the receiver 00684 } 00685 00686 // Restart the transmission of a packet that had a problem 00687 void RF22::restartTransmit() 00688 { 00689 _mode = RF22_MODE_IDLE; 00690 _txBufSentIndex = 0; 00691 // Serial.println("Restart"); 00692 startTransmit(); 00693 } 00694 00695 boolean RF22::send(const uint8_t* data, uint8_t len) 00696 { 00697 waitPacketSent(); 00698 // ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00699 { 00700 if (!fillTxBuf(data, len)) 00701 return false; 00702 startTransmit(); 00703 } 00704 // printBuffer("send:", data, len); 00705 return true; 00706 } 00707 00708 boolean RF22::fillTxBuf(const uint8_t* data, uint8_t len) 00709 { 00710 clearTxBuf(); 00711 if (!len) 00712 return false; 00713 return appendTxBuf(data, len); 00714 } 00715 00716 boolean RF22::appendTxBuf(const uint8_t* data, uint8_t len) 00717 { 00718 if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN) 00719 return false; 00720 __disable_irq(); // Disable Interrupts 00721 memcpy(_buf + _bufLen, data, len); 00722 _bufLen += len; 00723 __enable_irq(); // Enable Interrupts 00724 00725 // printBuffer("txbuf:", _buf, _bufLen); 00726 return true; 00727 } 00728 00729 // Assumption: there is currently <= RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO 00730 void RF22::sendNextFragment() 00731 { 00732 if (_txBufSentIndex < _bufLen) { 00733 // Some left to send? 00734 uint8_t len = _bufLen - _txBufSentIndex; 00735 // But dont send too much 00736 if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1)) 00737 len = (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1); 00738 spiBurstWrite(RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len); 00739 _txBufSentIndex += len; 00740 } 00741 } 00742 00743 // Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO 00744 // That means it should only be called after a RXFFAFULL interrupt 00745 void RF22::readNextFragment() 00746 { 00747 if (((uint16_t)_bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN) 00748 return; // Hmmm receiver overflow. Should never occur 00749 00750 // Read the RF22_RXFFAFULL_THRESHOLD octets that should be there 00751 spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RF22_RXFFAFULL_THRESHOLD); 00752 _bufLen += RF22_RXFFAFULL_THRESHOLD; 00753 } 00754 00755 // Clear the FIFOs 00756 void RF22::resetFifos() 00757 { 00758 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX | RF22_FFCLRTX); 00759 spiWrite(RF22_REG_08_OPERATING_MODE2, 0); 00760 } 00761 00762 // Clear the Rx FIFO 00763 void RF22::resetRxFifo() 00764 { 00765 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX); 00766 spiWrite(RF22_REG_08_OPERATING_MODE2, 0); 00767 } 00768 00769 // CLear the TX FIFO 00770 void RF22::resetTxFifo() 00771 { 00772 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRTX); 00773 spiWrite(RF22_REG_08_OPERATING_MODE2, 0); 00774 } 00775 00776 // Default implmentation does nothing. Override if you wish 00777 void RF22::handleExternalInterrupt() 00778 { 00779 } 00780 00781 // Default implmentation does nothing. Override if you wish 00782 void RF22::handleWakeupTimerInterrupt() 00783 { 00784 } 00785 00786 void RF22::setHeaderTo(uint8_t to) 00787 { 00788 spiWrite(RF22_REG_3A_TRANSMIT_HEADER3, to); 00789 } 00790 00791 void RF22::setHeaderFrom(uint8_t from) 00792 { 00793 spiWrite(RF22_REG_3B_TRANSMIT_HEADER2, from); 00794 } 00795 00796 void RF22::setHeaderId(uint8_t id) 00797 { 00798 spiWrite(RF22_REG_3C_TRANSMIT_HEADER1, id); 00799 } 00800 00801 void RF22::setHeaderFlags(uint8_t flags) 00802 { 00803 spiWrite(RF22_REG_3D_TRANSMIT_HEADER0, flags); 00804 } 00805 00806 uint8_t RF22::headerTo() 00807 { 00808 return spiRead(RF22_REG_47_RECEIVED_HEADER3); 00809 } 00810 00811 uint8_t RF22::headerFrom() 00812 { 00813 return spiRead(RF22_REG_48_RECEIVED_HEADER2); 00814 } 00815 00816 uint8_t RF22::headerId() 00817 { 00818 return spiRead(RF22_REG_49_RECEIVED_HEADER1); 00819 } 00820 00821 uint8_t RF22::headerFlags() 00822 { 00823 return spiRead(RF22_REG_4A_RECEIVED_HEADER0); 00824 } 00825 00826 uint8_t RF22::lastRssi() 00827 { 00828 return _lastRssi; 00829 } 00830 00831 void RF22::setPromiscuous(boolean promiscuous) 00832 { 00833 spiWrite(RF22_REG_43_HEADER_ENABLE3, promiscuous ? 0x00 : 0xff); 00834 }
Generated on Wed Jul 13 2022 22:24:22 by
