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.
RF12B.cpp
00001 #include "RF12B.h" 00002 00003 #include "RF_defs.h" 00004 #include <algorithm> 00005 00006 00007 RF12B::RF12B(PinName _SDI, 00008 PinName _SDO, 00009 PinName _SCK, 00010 PinName _NCS, 00011 PinName _NIRQ):spi(_SDI, _SDO, _SCK), 00012 NCS(_NCS), NIRQ(_NIRQ), NIRQ_in(_NIRQ), rfled(LED3) { 00013 00014 /* SPI frequency, word lenght, polarity and phase */ 00015 spi.format(16,0); 00016 spi.frequency(2000000); 00017 00018 /* Set ~CS high */ 00019 NCS = 1; 00020 00021 /* Initialise RF Module */ 00022 init(); 00023 00024 /* Setup interrupt to happen on falling edge of NIRQ */ 00025 NIRQ.fall(this, &RF12B::rxISR); 00026 } 00027 00028 /* Returns the packet length if data is available in the receive buffer, 0 otherwise*/ 00029 unsigned int RF12B::available() { 00030 return fifo.size(); 00031 } 00032 00033 /* Reads a packet of data, with length "size" Returns false if read failed. TODO: make a metafifo to isolate packets*/ 00034 bool RF12B::read(unsigned char* data, unsigned int size) { 00035 if (fifo.size() == 0) { 00036 return false; 00037 } else { 00038 unsigned int i = 0; 00039 while (fifo.size() > 0 && i < size) { 00040 data[i++] = fifo.front(); 00041 fifo.pop(); 00042 } 00043 return true; 00044 } 00045 } 00046 00047 /* Reads a byte of data from the receive buffer */ 00048 unsigned char RF12B::read() { 00049 if (available()) { 00050 unsigned char data = fifo.front(); 00051 fifo.pop(); 00052 return data; 00053 } else { 00054 return 0xFF; // Error val although could also be data... 00055 } 00056 } 00057 00058 /* Sends a packet of data to the RF module for transmission TODO: Make asych*/ 00059 void RF12B::write(unsigned char *data, unsigned char length) { 00060 unsigned char crc = 0; 00061 00062 /* Transmitter mode */ 00063 changeMode(TX); 00064 00065 writeCmd(0x0000); 00066 send(0xAA); // PREAMBLE 00067 send(0xAA); 00068 send(0xAA); 00069 send(0x2D); // SYNC 00070 send(0xD4); 00071 /* Packet Length */ 00072 send(length); 00073 crc = crc8(crc, length); 00074 send(crc); 00075 crc = crc8(crc, crc); 00076 /* Packet Data */ 00077 for (unsigned char i=0; i<length; i++) { 00078 send(data[i]); 00079 crc = crc8(crc, data[i]); 00080 } 00081 send(crc); 00082 send(0xAA); // DUMMY BYTES 00083 send(0xAA); 00084 send(0xAA); 00085 00086 /* Back to receiver mode */ 00087 changeMode(RX); 00088 status(); 00089 00090 00091 } 00092 00093 /* Transmit a 1-byte data packet */ 00094 void RF12B::write(unsigned char data) { 00095 write(&data, 1); 00096 } 00097 00098 void RF12B::write(queue<char> &data, int length) { 00099 char crc = 0; 00100 char length_byte = 0; 00101 00102 /* -1 means try to transmit everything in the queue */ 00103 if(length == -1) { 00104 length = data.size(); 00105 } 00106 00107 /* max length of packet is 255 */ 00108 length_byte = min(length, 255); 00109 00110 /* Transmitter mode */ 00111 changeMode(TX); 00112 00113 writeCmd(0x0000); 00114 send(0xAA); // PREAMBLE 00115 send(0xAA); 00116 send(0xAA); 00117 send(0x2D); // SYNC 00118 send(0xD4); 00119 /* Packet Length */ 00120 send(length_byte); 00121 crc = crc8(crc, length_byte); 00122 send(crc); 00123 crc = crc8(crc, crc); 00124 /* Packet Data */ 00125 for (char i=0; i<length_byte; i++) { 00126 send(data.front()); 00127 crc = crc8(crc, data.front()); 00128 data.pop(); 00129 } 00130 send(crc); 00131 send(0xAA); // DUMMY BYTES 00132 send(0xAA); 00133 send(0xAA); 00134 00135 /* Back to receiver mode */ 00136 changeMode(RX); 00137 status(); 00138 } 00139 00140 /********************************************************************** 00141 * PRIVATE FUNCTIONS 00142 *********************************************************************/ 00143 00144 /* Initialises the RF12B module */ 00145 void RF12B::init() { 00146 /* writeCmd(0x80E7); //EL,EF,868band,12.0pF 00147 changeMode(RX); 00148 writeCmd(0xA640); //frequency select 00149 writeCmd(0xC647); //4.8kbps 00150 writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm 00151 writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 00152 writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR 00153 writeCmd(0xCED4); //SYNC=2DD4 00154 writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN 00155 writeCmd(0x9850); //!mp,90kHz,MAX OUT 00156 writeCmd(0xCC17); //OB1, COB0, LPX, Iddy, CDDIT�CBW0 00157 writeCmd(0xE000); //NOT USED 00158 writeCmd(0xC800); //NOT USED 00159 writeCmd(0xC040); //1.66MHz,2.2V */ 00160 00161 writeCmd( 00162 RFM_CONFIG_EL | 00163 RFM_CONFIG_EF | 00164 RFM_CONFIG_BAND_433 //| 00165 //RFM_CONFIG_X_11_0pf // meh, using default 00166 ); 00167 00168 // 2. Power Management Command 00169 // leave everything switched off for now 00170 /* 00171 writeCmd( 00172 RFM_POWER_MANAGEMENT // switch all off 00173 ); 00174 */ 00175 00176 // 3. Frequency Setting Command 00177 writeCmd( 00178 RFM_FREQUENCY | 00179 RFM_FREQ_433Band(435.7) //I totally made this value up... if someone knows where the sweetspots are in this band, tell me! 00180 ); 00181 00182 00183 // 4. Data Rate Command 00184 writeCmd(RFM_DATA_RATE_9600); 00185 00186 00187 // 5. Receiver Control Command 00188 writeCmd( 00189 RFM_RX_CONTROL_P20_VDI | 00190 RFM_RX_CONTROL_VDI_FAST | 00191 //RFM_RX_CONTROL_BW(RFM_BAUD_RATE) | 00192 RFM_RX_CONTROL_BW_134 | // CHANGE THIS TO 67 TO IMPROVE RANGE! (though the bitrate must then be below 8kbaud, and fsk modulation changed) 00193 RFM_RX_CONTROL_GAIN_0 | 00194 RFM_RX_CONTROL_RSSI_103 // Might need adjustment. Datasheet says around 10^-5 bit error rate at this level and baudrate. 00195 ); 00196 00197 // 6. Data Filter Command 00198 writeCmd( 00199 RFM_DATA_FILTER_AL | 00200 RFM_DATA_FILTER_ML | 00201 RFM_DATA_FILTER_DIG //| 00202 //RFM_DATA_FILTER_DQD(4) 00203 ); 00204 00205 // 7. FIFO and Reset Mode Command 00206 writeCmd( 00207 RFM_FIFO_IT(8) | 00208 RFM_FIFO_DR | 00209 0x8 //turn on 16bit sync word 00210 ); 00211 00212 // 8. FIFO Syncword 00213 // Leave as default: 0xD4 00214 00215 // 9. Receiver FIFO Read 00216 // when the interupt goes high, (and if we can assume that it was a fifo fill interrupt) we can read a byte using: 00217 // result = RFM_READ_FIFO(); 00218 00219 // 10. AFC Command 00220 writeCmd( 00221 //RFM_AFC_AUTO_VDI | //Note this might be changed to improve range. Refer to datasheet. 00222 RFM_AFC_AUTO_INDEPENDENT | 00223 RFM_AFC_RANGE_LIMIT_7_8 | 00224 RFM_AFC_EN | 00225 RFM_AFC_OE | 00226 RFM_AFC_FI 00227 ); 00228 00229 // 11. TX Configuration Control Command 00230 writeCmd( 00231 RFM_TX_CONTROL_MOD_60 | 00232 RFM_TX_CONTROL_POW_0 00233 ); 00234 00235 00236 // 12. PLL Setting Command 00237 writeCmd( 00238 0xCC77 & ~0x01 // Setting the PLL bandwith, less noise, but max bitrate capped at 86.2 00239 // I think this will slow down the pll's reaction time. Not sure, check with someone! 00240 ); 00241 00242 changeMode(RX); 00243 resetRX(); 00244 status(); 00245 } 00246 00247 /* Write a command to the RF Module */ 00248 unsigned int RF12B::writeCmd(unsigned int cmd) { 00249 NCS = 0; 00250 unsigned int recv = spi.write(cmd); 00251 NCS = 1; 00252 return recv; 00253 } 00254 00255 /* Sends a byte of data across RF */ 00256 void RF12B::send(unsigned char data) { 00257 while (NIRQ); 00258 writeCmd(0xB800 + data); 00259 } 00260 00261 /* Change the mode of the RF module to Transmitting or Receiving */ 00262 void RF12B::changeMode(rfmode_t _mode) { 00263 mode = _mode; 00264 if (_mode == TX) { 00265 writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC 00266 } else { /* mode == RX */ 00267 writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC 00268 } 00269 } 00270 00271 /* Interrupt routine for data reception */ 00272 void RF12B::rxISR() { 00273 unsigned int data = 0; 00274 static int i = -2; 00275 static unsigned char packet_length = 0; 00276 static unsigned char crc = 0; 00277 static queue<unsigned char> temp; 00278 00279 //Loop while interrupt is asserted 00280 while (!NIRQ_in && mode == RX) { 00281 00282 /* Grab the packet's length byte */ 00283 if (i == -2) { 00284 data = writeCmd(0x0000); 00285 if ( (data&0x8000) ) { 00286 data = writeCmd(0xB000); 00287 packet_length = (data&0x00FF); 00288 crc = crc8(crc, packet_length); 00289 i++; 00290 } 00291 } 00292 00293 //If we exhaust the interrupt, exit 00294 if (NIRQ_in) 00295 break; 00296 00297 // Check that packet length was correct 00298 if (i == -1) { 00299 data = writeCmd(0x0000); 00300 if ( (data&0x8000) ) { 00301 data = writeCmd(0xB000); 00302 unsigned char crcofsize = (data&0x00FF); 00303 if (crcofsize != crc) { 00304 //It was wrong, start over 00305 i = -2; 00306 packet_length = 0; 00307 crc = 0; 00308 temp = queue<unsigned char>(); 00309 resetRX(); 00310 } else { 00311 crc = crc8(crc, crcofsize); 00312 i++; 00313 } 00314 } 00315 } 00316 00317 //If we exhaust the interrupt, exit 00318 if (NIRQ_in) 00319 break; 00320 00321 /* Grab the packet's data */ 00322 if (i >= 0 && i < packet_length) { 00323 data = writeCmd(0x0000); 00324 if ( (data&0x8000) ) { 00325 data = writeCmd(0xB000); 00326 temp.push(data&0x00FF); 00327 crc = crc8(crc, (unsigned char)(data&0x00FF)); 00328 i++; 00329 } 00330 } 00331 00332 //If we exhaust the interrupt, exit 00333 if (NIRQ_in) 00334 break; 00335 00336 if (i >= packet_length) { 00337 data = writeCmd(0x0000); 00338 if ( (data&0x8000) ) { 00339 data = writeCmd(0xB000); 00340 if ((unsigned char)(data & 0x00FF) == crc) { 00341 //If the checksum is correct, add our data to the end of the output buffer 00342 while (!temp.empty()) { 00343 fifo.push(temp.front()); 00344 temp.pop(); 00345 } 00346 } 00347 00348 /* Tell RF Module we are finished, and clean up */ 00349 i = -2; 00350 packet_length = 0; 00351 crc = 0; 00352 temp = queue<unsigned char>(); 00353 resetRX(); 00354 } 00355 } 00356 } 00357 } 00358 00359 unsigned int RF12B::status() { 00360 return writeCmd(0x0000); 00361 } 00362 00363 /* Tell the RF Module this packet is received and wait for the next */ 00364 void RF12B::resetRX() { 00365 writeCmd(0xCA81); 00366 writeCmd(0xCA83); 00367 }; 00368 00369 /* Calculate CRC8 */ 00370 unsigned char RF12B::crc8(unsigned char crc, unsigned char data) { 00371 crc = crc ^ data; 00372 for (int i = 0; i < 8; i++) { 00373 if (crc & 0x01) { 00374 crc = (crc >> 1) ^ 0x8C; 00375 } else { 00376 crc >>= 1; 00377 } 00378 } 00379 return crc; 00380 }
Generated on Wed Jul 13 2022 18:14:02 by
1.7.2