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 RadioHead-148 by
RH_RF22.cpp
00001 // RH_RF22.cpp 00002 // 00003 // Copyright (C) 2011 Mike McCauley 00004 // $Id: RH_RF22.cpp,v 1.24 2015/05/17 00:11:26 mikem Exp $ 00005 00006 #include <RH_RF22.h> 00007 00008 // Interrupt vectors for the 2 Arduino interrupt pins 00009 // Each interrupt can be handled by a different instance of RH_RF22, allowing you to have 00010 // 2 RH_RF22s per Arduino 00011 RH_RF22* RH_RF22::_deviceForInterrupt[RH_RF22_NUM_INTERRUPTS] = {0, 0, 0}; 00012 uint8_t RH_RF22::_interruptCount = 0; // Index into _deviceForInterrupt for next device 00013 00014 // These are indexed by the values of ModemConfigChoice 00015 // Canned modem configurations generated with 00016 // http://www.hoperf.com/upload/rf/RH_RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls 00017 // Stored in flash (program) memory to save SRAM 00018 PROGMEM static const RH_RF22::ModemConfig MODEM_CONFIG_TABLE[] = 00019 { 00020 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier 00021 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5 00022 00023 // All the following enable FIFO with reg 71 00024 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72 00025 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm 00026 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5 00027 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36 00028 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45 00029 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45 00030 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6 00031 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6 00032 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8 00033 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125 00034 00035 { 0x2b, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x09, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x04 }, // 512 baud, FSK, 2.5 Khz fd for POCSAG compatibility 00036 { 0x27, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x06, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x07 }, // 512 baud, FSK, 4.5 Khz fd for POCSAG compatibility 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 RH_RF22::RH_RF22(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi) 00060 : 00061 RHSPIDriver(slaveSelectPin, spi), 00062 _interruptPin(interruptPin) 00063 { 00064 _idleMode = RH_RF22_XTON; // Default idle state is READY mode 00065 _polynomial = CRC_16_IBM; // Historical 00066 _myInterruptIndex = 0xff; // Not allocated yet 00067 } 00068 00069 void RH_RF22::setIdleMode(uint8_t idleMode) 00070 { 00071 _idleMode = idleMode; 00072 } 00073 00074 bool RH_RF22::init() 00075 { 00076 if (!RHSPIDriver::init()) 00077 return false; 00078 00079 #if (RH_PLATFORM != RH_PLATFORM_MBED) 00080 // Determine the interrupt number that corresponds to the interruptPin 00081 int interruptNumber = digitalPinToInterrupt(_interruptPin); 00082 if (interruptNumber == NOT_AN_INTERRUPT) 00083 return false; 00084 #endif 00085 00086 // Software reset the device 00087 reset(); 00088 00089 // Get the device type and check it 00090 // This also tests whether we are really connected to a device 00091 _deviceType = spiRead(RH_RF22_REG_00_DEVICE_TYPE); 00092 if ( _deviceType != RH_RF22_DEVICE_TYPE_RX_TRX 00093 && _deviceType != RH_RF22_DEVICE_TYPE_TX) 00094 { 00095 return false; 00096 } 00097 00098 00099 #if (RH_PLATFORM != RH_PLATFORM_MBED) 00100 // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy 00101 // ARM M4 requires the below. else pin interrupt doesn't work properly. 00102 // On all other platforms, its innocuous, belt and braces 00103 pinMode(_interruptPin, INPUT); 00104 #endif 00105 00106 // Enable interrupt output on the radio. Interrupt line will now go high until 00107 // an interrupt occurs 00108 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); 00109 spiWrite(RH_RF22_REG_06_INTERRUPT_ENABLE2, RH_RF22_ENPREAVAL); 00110 00111 // Set up interrupt handler 00112 // Since there are a limited number of interrupt glue functions isr*() available, 00113 // we can only support a limited number of devices simultaneously 00114 // On some devices, notably most Arduinos, the interrupt pin passed in is actually the 00115 // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping 00116 // yourself based on knowledge of what Arduino board you are running on. 00117 if (_myInterruptIndex == 0xff) 00118 { 00119 // First run, no interrupt allocated yet 00120 if (_interruptCount <= RH_RF22_NUM_INTERRUPTS) 00121 _myInterruptIndex = _interruptCount++; 00122 else 00123 return false; // Too many devices, not enough interrupt vectors 00124 } 00125 _deviceForInterrupt[_myInterruptIndex] = this; 00126 00127 #if (RH_PLATFORM == RH_PLATFORM_MBED) 00128 if (_myInterruptIndex == 0) 00129 _interruptPin.fall(&isr0); 00130 else if (_myInterruptIndex == 1) 00131 _interruptPin.fall(&isr1); 00132 else if (_myInterruptIndex == 2) 00133 _interruptPin.fall(&isr2); 00134 else 00135 return false; // Too many devices, not enough interrupt vectors 00136 #else 00137 if (_myInterruptIndex == 0) 00138 attachInterrupt(interruptNumber, isr0, FALLING); 00139 else if (_myInterruptIndex == 1) 00140 attachInterrupt(interruptNumber, isr1, FALLING); 00141 else if (_myInterruptIndex == 2) 00142 attachInterrupt(interruptNumber, isr2, FALLING); 00143 else 00144 return false; // Too many devices, not enough interrupt vectors 00145 #endif 00146 00147 setModeIdle(); 00148 00149 clearTxBuf(); 00150 clearRxBuf(); 00151 00152 // Most of these are the POR default 00153 spiWrite(RH_RF22_REG_7D_TX_FIFO_CONTROL2, RH_RF22_TXFFAEM_THRESHOLD); 00154 spiWrite(RH_RF22_REG_7E_RX_FIFO_CONTROL, RH_RF22_RXFFAFULL_THRESHOLD); 00155 spiWrite(RH_RF22_REG_30_DATA_ACCESS_CONTROL, RH_RF22_ENPACRX | RH_RF22_ENPACTX | RH_RF22_ENCRC | (_polynomial & RH_RF22_CRC)); 00156 00157 // Configure the message headers 00158 // Here we set up the standard packet format for use by the RH_RF22 library 00159 // 8 nibbles preamble 00160 // 2 SYNC words 2d, d4 00161 // Header length 4 (to, from, id, flags) 00162 // 1 octet of data length (0 to 255) 00163 // 0 to 255 octets data 00164 // 2 CRC octets as CRC16(IBM), computed on the header, length and data 00165 // On reception the to address is check for validity against RH_RF22_REG_3F_CHECK_HEADER3 00166 // or the broadcast address of 0xff 00167 // If no changes are made after this, the transmitted 00168 // to address will be 0xff, the from address will be 0xff 00169 // and all such messages will be accepted. This permits the out-of the box 00170 // RH_RF22 config to act as an unaddresed, unreliable datagram service 00171 spiWrite(RH_RF22_REG_32_HEADER_CONTROL1, RH_RF22_BCEN_HEADER3 | RH_RF22_HDCH_HEADER3); 00172 spiWrite(RH_RF22_REG_33_HEADER_CONTROL2, RH_RF22_HDLEN_4 | RH_RF22_SYNCLEN_2); 00173 00174 setPreambleLength(8); 00175 uint8_t syncwords[] = { 0x2d, 0xd4 }; 00176 setSyncWords(syncwords, sizeof(syncwords)); 00177 setPromiscuous(false); 00178 00179 // Set some defaults. An innocuous ISM frequency, and reasonable pull-in 00180 setFrequency(434.0, 0.05); 00181 // setFrequency(900.0); 00182 // Some slow, reliable default speed and modulation 00183 setModemConfig(FSK_Rb2_4Fd36); 00184 // setModemConfig(FSK_Rb125Fd125); 00185 setGpioReversed(false); 00186 // Lowish power 00187 setTxPower(RH_RF22_TXPOW_8DBM); 00188 00189 return true; 00190 } 00191 00192 // C++ level interrupt handler for this instance 00193 void RH_RF22::handleInterrupt() 00194 { 00195 uint8_t _lastInterruptFlags[2]; 00196 // Read the interrupt flags which clears the interrupt 00197 spiBurstRead(RH_RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2); 00198 00199 #if 0 00200 // DEVELOPER TESTING ONLY 00201 // Caution: Serial printing in this interrupt routine can cause mysterious crashes 00202 Serial.print("interrupt "); 00203 Serial.print(_lastInterruptFlags[0], HEX); 00204 Serial.print(" "); 00205 Serial.println(_lastInterruptFlags[1], HEX); 00206 if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0) 00207 Serial.println("FUNNY: no interrupt!"); 00208 #endif 00209 00210 #if 0 00211 // DEVELOPER TESTING ONLY 00212 // TESTING: fake an RH_RF22_IFFERROR 00213 static int counter = 0; 00214 if (_lastInterruptFlags[0] & RH_RF22_IPKSENT && counter++ == 10) 00215 { 00216 _lastInterruptFlags[0] = RH_RF22_IFFERROR; 00217 counter = 0; 00218 } 00219 #endif 00220 00221 if (_lastInterruptFlags[0] & RH_RF22_IFFERROR) 00222 { 00223 resetFifos(); // Clears the interrupt 00224 if (_mode == RHModeTx) 00225 restartTransmit(); 00226 else if (_mode == RHModeRx) 00227 clearRxBuf(); 00228 // Serial.println("IFFERROR"); 00229 } 00230 // Caution, any delay here may cause a FF underflow or overflow 00231 if (_lastInterruptFlags[0] & RH_RF22_ITXFFAEM) 00232 { 00233 // See if more data has to be loaded into the Tx FIFO 00234 sendNextFragment(); 00235 // Serial.println("ITXFFAEM"); 00236 } 00237 if (_lastInterruptFlags[0] & RH_RF22_IRXFFAFULL) 00238 { 00239 // Caution, any delay here may cause a FF overflow 00240 // Read some data from the Rx FIFO 00241 readNextFragment(); 00242 // Serial.println("IRXFFAFULL"); 00243 } 00244 if (_lastInterruptFlags[0] & RH_RF22_IEXT) 00245 { 00246 // This is not enabled by the base code, but users may want to enable it 00247 handleExternalInterrupt(); 00248 // Serial.println("IEXT"); 00249 } 00250 if (_lastInterruptFlags[1] & RH_RF22_IWUT) 00251 { 00252 // This is not enabled by the base code, but users may want to enable it 00253 handleWakeupTimerInterrupt(); 00254 // Serial.println("IWUT"); 00255 } 00256 if (_lastInterruptFlags[0] & RH_RF22_IPKSENT) 00257 { 00258 // Serial.println("IPKSENT"); 00259 _txGood++; 00260 // Transmission does not automatically clear the tx buffer. 00261 // Could retransmit if we wanted 00262 // RH_RF22 transitions automatically to Idle 00263 _mode = RHModeIdle; 00264 } 00265 if (_lastInterruptFlags[0] & RH_RF22_IPKVALID) 00266 { 00267 uint8_t len = spiRead(RH_RF22_REG_4B_RECEIVED_PACKET_LENGTH); 00268 // Serial.println("IPKVALID"); 00269 00270 // May have already read one or more fragments 00271 // Get any remaining unread octets, based on the expected length 00272 // First make sure we dont overflow the buffer in the case of a stupid length 00273 // or partial bad receives 00274 if ( len > RH_RF22_MAX_MESSAGE_LEN 00275 || len < _bufLen) 00276 { 00277 _rxBad++; 00278 _mode = RHModeIdle; 00279 clearRxBuf(); 00280 return; // Hmmm receiver buffer overflow. 00281 } 00282 00283 spiBurstRead(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen); 00284 _rxHeaderTo = spiRead(RH_RF22_REG_47_RECEIVED_HEADER3); 00285 _rxHeaderFrom = spiRead(RH_RF22_REG_48_RECEIVED_HEADER2); 00286 _rxHeaderId = spiRead(RH_RF22_REG_49_RECEIVED_HEADER1); 00287 _rxHeaderFlags = spiRead(RH_RF22_REG_4A_RECEIVED_HEADER0); 00288 _rxGood++; 00289 _bufLen = len; 00290 _mode = RHModeIdle; 00291 _rxBufValid = true; 00292 } 00293 if (_lastInterruptFlags[0] & RH_RF22_ICRCERROR) 00294 { 00295 // Serial.println("ICRCERR"); 00296 _rxBad++; 00297 clearRxBuf(); 00298 resetRxFifo(); 00299 _mode = RHModeIdle; 00300 setModeRx(); // Keep trying 00301 } 00302 if (_lastInterruptFlags[1] & RH_RF22_IPREAVAL) 00303 { 00304 // Serial.println("IPREAVAL"); 00305 _lastRssi = (int8_t)(-120 + ((spiRead(RH_RF22_REG_26_RSSI) / 2))); 00306 _lastPreambleTime = millis(); 00307 resetRxFifo(); 00308 clearRxBuf(); 00309 } 00310 } 00311 00312 // These are low level functions that call the interrupt handler for the correct 00313 // instance of RH_RF22. 00314 // 3 interrupts allows us to have 3 different devices 00315 void RH_RF22::isr0() 00316 { 00317 if (_deviceForInterrupt[0]) 00318 _deviceForInterrupt[0]->handleInterrupt(); 00319 } 00320 void RH_RF22::isr1() 00321 { 00322 if (_deviceForInterrupt[1]) 00323 _deviceForInterrupt[1]->handleInterrupt(); 00324 } 00325 void RH_RF22::isr2() 00326 { 00327 if (_deviceForInterrupt[2]) 00328 _deviceForInterrupt[2]->handleInterrupt(); 00329 } 00330 00331 void RH_RF22::reset() 00332 { 00333 spiWrite(RH_RF22_REG_07_OPERATING_MODE1, RH_RF22_SWRES); 00334 // Wait for it to settle 00335 delay(1); // SWReset time is nominally 100usec 00336 } 00337 00338 uint8_t RH_RF22::statusRead() 00339 { 00340 return spiRead(RH_RF22_REG_02_DEVICE_STATUS); 00341 } 00342 00343 uint8_t RH_RF22::adcRead(uint8_t adcsel, 00344 uint8_t adcref , 00345 uint8_t adcgain, 00346 uint8_t adcoffs) 00347 { 00348 uint8_t configuration = adcsel | adcref | (adcgain & RH_RF22_ADCGAIN); 00349 spiWrite(RH_RF22_REG_0F_ADC_CONFIGURATION, configuration | RH_RF22_ADCSTART); 00350 spiWrite(RH_RF22_REG_10_ADC_SENSOR_AMP_OFFSET, adcoffs); 00351 00352 // Conversion time is nominally 305usec 00353 // Wait for the DONE bit 00354 while (!(spiRead(RH_RF22_REG_0F_ADC_CONFIGURATION) & RH_RF22_ADCDONE)) 00355 ; 00356 // Return the value 00357 return spiRead(RH_RF22_REG_11_ADC_VALUE); 00358 } 00359 00360 uint8_t RH_RF22::temperatureRead(uint8_t tsrange, uint8_t tvoffs) 00361 { 00362 spiWrite(RH_RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RH_RF22_ENTSOFFS); 00363 spiWrite(RH_RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs); 00364 return adcRead(RH_RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RH_RF22_ADCREF_BANDGAP_VOLTAGE); 00365 } 00366 00367 uint16_t RH_RF22::wutRead() 00368 { 00369 uint8_t buf[2]; 00370 spiBurstRead(RH_RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2); 00371 return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order 00372 } 00373 00374 // RFM-22 doc appears to be wrong: WUT for wtm = 10000, r, = 0, d = 0 is about 1 sec 00375 void RH_RF22::setWutPeriod(uint16_t wtm, uint8_t wtr, uint8_t wtd) 00376 { 00377 uint8_t period[3]; 00378 00379 period[0] = ((wtr & 0xf) << 2) | (wtd & 0x3); 00380 period[1] = wtm >> 8; 00381 period[2] = wtm & 0xff; 00382 spiBurstWrite(RH_RF22_REG_14_WAKEUP_TIMER_PERIOD1, period, sizeof(period)); 00383 } 00384 00385 // Returns true if centre + (fhch * fhs) is within limits 00386 // Caution, different versions of the RH_RF22 support different max freq 00387 // so YMMV 00388 bool RH_RF22::setFrequency(float centre, float afcPullInRange) 00389 { 00390 uint8_t fbsel = RH_RF22_SBSEL; 00391 uint8_t afclimiter; 00392 if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon 00393 return false; 00394 if (centre >= 480.0) 00395 { 00396 if (afcPullInRange < 0.0 || afcPullInRange > 0.318750) 00397 return false; 00398 centre /= 2; 00399 fbsel |= RH_RF22_HBSEL; 00400 afclimiter = afcPullInRange * 1000000.0 / 1250.0; 00401 } 00402 else 00403 { 00404 if (afcPullInRange < 0.0 || afcPullInRange > 0.159375) 00405 return false; 00406 afclimiter = afcPullInRange * 1000000.0 / 625.0; 00407 } 00408 centre /= 10.0; 00409 float integerPart = floor(centre); 00410 float fractionalPart = centre - integerPart; 00411 00412 uint8_t fb = (uint8_t)integerPart - 24; // Range 0 to 23 00413 fbsel |= fb; 00414 uint16_t fc = fractionalPart * 64000; 00415 spiWrite(RH_RF22_REG_73_FREQUENCY_OFFSET1, 0); // REVISIT 00416 spiWrite(RH_RF22_REG_74_FREQUENCY_OFFSET2, 0); 00417 spiWrite(RH_RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel); 00418 spiWrite(RH_RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8); 00419 spiWrite(RH_RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff); 00420 spiWrite(RH_RF22_REG_2A_AFC_LIMITER, afclimiter); 00421 return !(statusRead() & RH_RF22_FREQERR); 00422 } 00423 00424 // Step size in 10kHz increments 00425 // Returns true if centre + (fhch * fhs) is within limits 00426 bool RH_RF22::setFHStepSize(uint8_t fhs) 00427 { 00428 spiWrite(RH_RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE, fhs); 00429 return !(statusRead() & RH_RF22_FREQERR); 00430 } 00431 00432 // Adds fhch * fhs to centre frequency 00433 // Returns true if centre + (fhch * fhs) is within limits 00434 bool RH_RF22::setFHChannel(uint8_t fhch) 00435 { 00436 spiWrite(RH_RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT, fhch); 00437 return !(statusRead() & RH_RF22_FREQERR); 00438 } 00439 00440 uint8_t RH_RF22::rssiRead() 00441 { 00442 return spiRead(RH_RF22_REG_26_RSSI); 00443 } 00444 00445 uint8_t RH_RF22::ezmacStatusRead() 00446 { 00447 return spiRead(RH_RF22_REG_31_EZMAC_STATUS); 00448 } 00449 00450 void RH_RF22::setOpMode(uint8_t mode) 00451 { 00452 spiWrite(RH_RF22_REG_07_OPERATING_MODE1, mode); 00453 } 00454 00455 void RH_RF22::setModeIdle() 00456 { 00457 if (_mode != RHModeIdle) 00458 { 00459 setOpMode(_idleMode); 00460 _mode = RHModeIdle; 00461 } 00462 } 00463 00464 bool RH_RF22::sleep() 00465 { 00466 if (_mode != RHModeSleep) 00467 { 00468 setOpMode(0); 00469 _mode = RHModeSleep; 00470 } 00471 return true; 00472 } 00473 00474 void RH_RF22::setModeRx() 00475 { 00476 if (_mode != RHModeRx) 00477 { 00478 setOpMode(_idleMode | RH_RF22_RXON); 00479 _mode = RHModeRx; 00480 } 00481 } 00482 00483 void RH_RF22::setModeTx() 00484 { 00485 if (_mode != RHModeTx) 00486 { 00487 setOpMode(_idleMode | RH_RF22_TXON); 00488 // Hmmm, if you dont clear the RX FIFO here, then it appears that going 00489 // to transmit mode in the middle of a receive can corrupt the 00490 // RX FIFO 00491 resetRxFifo(); 00492 _mode = RHModeTx; 00493 } 00494 } 00495 00496 void RH_RF22::setTxPower(uint8_t power) 00497 { 00498 spiWrite(RH_RF22_REG_6D_TX_POWER, power | RH_RF22_LNA_SW); // On RF23, LNA_SW must be set. 00499 } 00500 00501 // Sets registers from a canned modem configuration structure 00502 void RH_RF22::setModemRegisters(const ModemConfig* config) 00503 { 00504 spiWrite(RH_RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c); 00505 spiWrite(RH_RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f); 00506 spiBurstWrite(RH_RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE, &config->reg_20, 6); 00507 spiBurstWrite(RH_RF22_REG_2C_OOK_COUNTER_VALUE_1, &config->reg_2c, 3); 00508 spiWrite(RH_RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING, config->reg_58); 00509 spiWrite(RH_RF22_REG_69_AGC_OVERRIDE1, config->reg_69); 00510 spiBurstWrite(RH_RF22_REG_6E_TX_DATA_RATE1, &config->reg_6e, 5); 00511 } 00512 00513 // Set one of the canned FSK Modem configs 00514 // Returns true if its a valid choice 00515 bool RH_RF22::setModemConfig(ModemConfigChoice index) 00516 { 00517 if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig))) 00518 return false; 00519 00520 RH_RF22::ModemConfig cfg; 00521 memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF22::ModemConfig)); 00522 setModemRegisters(&cfg); 00523 00524 return true; 00525 } 00526 00527 // REVISIT: top bit is in Header Control 2 0x33 00528 void RH_RF22::setPreambleLength(uint8_t nibbles) 00529 { 00530 spiWrite(RH_RF22_REG_34_PREAMBLE_LENGTH, nibbles); 00531 } 00532 00533 // Caution doesnt set sync word len in Header Control 2 0x33 00534 void RH_RF22::setSyncWords(const uint8_t* syncWords, uint8_t len) 00535 { 00536 spiBurstWrite(RH_RF22_REG_36_SYNC_WORD3, syncWords, len); 00537 } 00538 00539 void RH_RF22::clearRxBuf() 00540 { 00541 ATOMIC_BLOCK_START; 00542 _bufLen = 0; 00543 _rxBufValid = false; 00544 ATOMIC_BLOCK_END; 00545 } 00546 00547 bool RH_RF22::available() 00548 { 00549 if (!_rxBufValid) 00550 { 00551 if (_mode == RHModeTx) 00552 return false; 00553 setModeRx(); // Make sure we are receiving 00554 } 00555 return _rxBufValid; 00556 } 00557 00558 bool RH_RF22::recv(uint8_t* buf, uint8_t* len) 00559 { 00560 if (!available()) 00561 return false; 00562 00563 if (buf && len) 00564 { 00565 ATOMIC_BLOCK_START; 00566 if (*len > _bufLen) 00567 *len = _bufLen; 00568 memcpy(buf, _buf, *len); 00569 ATOMIC_BLOCK_END; 00570 } 00571 clearRxBuf(); 00572 // printBuffer("recv:", buf, *len); 00573 return true; 00574 } 00575 00576 void RH_RF22::clearTxBuf() 00577 { 00578 ATOMIC_BLOCK_START; 00579 _bufLen = 0; 00580 _txBufSentIndex = 0; 00581 ATOMIC_BLOCK_END; 00582 } 00583 00584 void RH_RF22::startTransmit() 00585 { 00586 sendNextFragment(); // Actually the first fragment 00587 spiWrite(RH_RF22_REG_3E_PACKET_LENGTH, _bufLen); // Total length that will be sent 00588 setModeTx(); // Start the transmitter, turns off the receiver 00589 } 00590 00591 // Restart the transmission of a packet that had a problem 00592 void RH_RF22::restartTransmit() 00593 { 00594 _mode = RHModeIdle; 00595 _txBufSentIndex = 0; 00596 // Serial.println("Restart"); 00597 startTransmit(); 00598 } 00599 00600 bool RH_RF22::send(const uint8_t* data, uint8_t len) 00601 { 00602 bool ret = true; 00603 waitPacketSent(); 00604 ATOMIC_BLOCK_START; 00605 spiWrite(RH_RF22_REG_3A_TRANSMIT_HEADER3, _txHeaderTo); 00606 spiWrite(RH_RF22_REG_3B_TRANSMIT_HEADER2, _txHeaderFrom); 00607 spiWrite(RH_RF22_REG_3C_TRANSMIT_HEADER1, _txHeaderId); 00608 spiWrite(RH_RF22_REG_3D_TRANSMIT_HEADER0, _txHeaderFlags); 00609 if (!fillTxBuf(data, len)) 00610 ret = false; 00611 else 00612 startTransmit(); 00613 ATOMIC_BLOCK_END; 00614 // printBuffer("send:", data, len); 00615 return ret; 00616 } 00617 00618 bool RH_RF22::fillTxBuf(const uint8_t* data, uint8_t len) 00619 { 00620 clearTxBuf(); 00621 if (!len) 00622 return false; 00623 return appendTxBuf(data, len); 00624 } 00625 00626 bool RH_RF22::appendTxBuf(const uint8_t* data, uint8_t len) 00627 { 00628 if (((uint16_t)_bufLen + len) > RH_RF22_MAX_MESSAGE_LEN) 00629 return false; 00630 ATOMIC_BLOCK_START; 00631 memcpy(_buf + _bufLen, data, len); 00632 _bufLen += len; 00633 ATOMIC_BLOCK_END; 00634 // printBuffer("txbuf:", _buf, _bufLen); 00635 return true; 00636 } 00637 00638 // Assumption: there is currently <= RH_RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO 00639 void RH_RF22::sendNextFragment() 00640 { 00641 if (_txBufSentIndex < _bufLen) 00642 { 00643 // Some left to send? 00644 uint8_t len = _bufLen - _txBufSentIndex; 00645 // But dont send too much 00646 if (len > (RH_RF22_FIFO_SIZE - RH_RF22_TXFFAEM_THRESHOLD - 1)) 00647 len = (RH_RF22_FIFO_SIZE - RH_RF22_TXFFAEM_THRESHOLD - 1); 00648 spiBurstWrite(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len); 00649 // printBuffer("frag:", _buf + _txBufSentIndex, len); 00650 _txBufSentIndex += len; 00651 } 00652 } 00653 00654 // Assumption: there are at least RH_RF22_RXFFAFULL_THRESHOLD in the RX FIFO 00655 // That means it should only be called after a RXFFAFULL interrupt 00656 void RH_RF22::readNextFragment() 00657 { 00658 if (((uint16_t)_bufLen + RH_RF22_RXFFAFULL_THRESHOLD) > RH_RF22_MAX_MESSAGE_LEN) 00659 return; // Hmmm receiver overflow. Should never occur 00660 00661 // Read the RH_RF22_RXFFAFULL_THRESHOLD octets that should be there 00662 spiBurstRead(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RH_RF22_RXFFAFULL_THRESHOLD); 00663 _bufLen += RH_RF22_RXFFAFULL_THRESHOLD; 00664 } 00665 00666 // Clear the FIFOs 00667 void RH_RF22::resetFifos() 00668 { 00669 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRRX | RH_RF22_FFCLRTX); 00670 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0); 00671 } 00672 00673 // Clear the Rx FIFO 00674 void RH_RF22::resetRxFifo() 00675 { 00676 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRRX); 00677 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0); 00678 } 00679 00680 // CLear the TX FIFO 00681 void RH_RF22::resetTxFifo() 00682 { 00683 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRTX); 00684 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0); 00685 } 00686 00687 // Default implmentation does nothing. Override if you wish 00688 void RH_RF22::handleExternalInterrupt() 00689 { 00690 } 00691 00692 // Default implmentation does nothing. Override if you wish 00693 void RH_RF22::handleWakeupTimerInterrupt() 00694 { 00695 } 00696 00697 void RH_RF22::setPromiscuous(bool promiscuous) 00698 { 00699 RHSPIDriver::setPromiscuous(promiscuous); 00700 spiWrite(RH_RF22_REG_43_HEADER_ENABLE3, promiscuous ? 0x00 : 0xff); 00701 } 00702 00703 bool RH_RF22::setCRCPolynomial(CRCPolynomial polynomial) 00704 { 00705 if (polynomial >= CRC_CCITT && 00706 polynomial <= CRC_Biacheva) 00707 { 00708 _polynomial = polynomial; 00709 return true; 00710 } 00711 else 00712 return false; 00713 } 00714 00715 uint8_t RH_RF22::maxMessageLength() 00716 { 00717 return RH_RF22_MAX_MESSAGE_LEN; 00718 } 00719 00720 void RH_RF22::setThisAddress(uint8_t thisAddress) 00721 { 00722 RHSPIDriver::setThisAddress(thisAddress); 00723 spiWrite(RH_RF22_REG_3F_CHECK_HEADER3, thisAddress); 00724 } 00725 00726 uint32_t RH_RF22::getLastPreambleTime() 00727 { 00728 return _lastPreambleTime; 00729 } 00730 00731 void RH_RF22::setGpioReversed(bool gpioReversed) 00732 { 00733 // Ensure the antenna can be switched automatically according to transmit and receive 00734 // This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit 00735 // This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive 00736 if (gpioReversed) 00737 { 00738 // Reversed for HAB-RFM22B-BOA HAB-RFM22B-BO, also Si4432 sold by Dorji.com via Tindie.com. 00739 spiWrite(RH_RF22_REG_0B_GPIO_CONFIGURATION0, 0x15) ; // RX state 00740 spiWrite(RH_RF22_REG_0C_GPIO_CONFIGURATION1, 0x12) ; // TX state 00741 } 00742 else 00743 { 00744 spiWrite(RH_RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state 00745 spiWrite(RH_RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state 00746 } 00747 } 00748
Generated on Tue Jul 12 2022 20:15:57 by
1.7.2
