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