Embed:
(wiki syntax)
Show/hide line numbers
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 00191 00192 // 5. Receiver Control Command 00193 writeCmd( 00194 RFM_RX_CONTROL_P20_VDI | 00195 RFM_RX_CONTROL_VDI_FAST | 00196 //RFM_RX_CONTROL_BW(RFM_BAUD_RATE) | 00197 RFM_RX_CONTROL_BW_134 | // CHANGE THIS TO 67 TO IMPROVE RANGE! (though the bitrate must then be below 8kbaud, and fsk modulation changed) 00198 RFM_RX_CONTROL_GAIN_0 | 00199 RFM_RX_CONTROL_RSSI_103 // Might need adjustment. Datasheet says around 10^-5 bit error rate at this level and baudrate. 00200 ); 00201 00202 // 6. Data Filter Command 00203 writeCmd( 00204 RFM_DATA_FILTER_AL | 00205 RFM_DATA_FILTER_ML | 00206 RFM_DATA_FILTER_DIG //| 00207 //RFM_DATA_FILTER_DQD(4) 00208 ); 00209 00210 // 7. FIFO and Reset Mode Command 00211 writeCmd( 00212 RFM_FIFO_IT(8) | 00213 RFM_FIFO_DR | 00214 0x8 //turn on 16bit sync word 00215 ); 00216 00217 // 8. FIFO Syncword 00218 // Leave as default: 0xD4 00219 00220 // 9. Receiver FIFO Read 00221 // when the interupt goes high, (and if we can assume that it was a fifo fill interrupt) we can read a byte using: 00222 // result = RFM_READ_FIFO(); 00223 00224 // 10. AFC Command 00225 writeCmd( 00226 //RFM_AFC_AUTO_VDI | //Note this might be changed to improve range. Refer to datasheet. 00227 RFM_AFC_AUTO_INDEPENDENT | 00228 RFM_AFC_RANGE_LIMIT_7_8 | 00229 RFM_AFC_EN | 00230 RFM_AFC_OE | 00231 RFM_AFC_FI 00232 ); 00233 00234 // 11. TX Configuration Control Command 00235 writeCmd( 00236 RFM_TX_CONTROL_MOD_60 | 00237 RFM_TX_CONTROL_POW_0 00238 ); 00239 00240 00241 // 12. PLL Setting Command 00242 writeCmd( 00243 0xCC77 & ~0x01 // Setting the PLL bandwith, less noise, but max bitrate capped at 86.2 00244 // I think this will slow down the pll's reaction time. Not sure, check with someone! 00245 ); 00246 00247 changeMode(RX); 00248 resetRX(); 00249 status(); 00250 } 00251 00252 /* Write a command to the RF Module */ 00253 unsigned int RF12B::writeCmd(unsigned int cmd) { 00254 NCS = 0; 00255 unsigned int recv = spi.write(cmd); 00256 NCS = 1; 00257 return recv; 00258 } 00259 00260 /* Sends a byte of data across RF */ 00261 void RF12B::send(unsigned char data) { 00262 while (NIRQ); 00263 writeCmd(0xB800 + data); 00264 } 00265 00266 /* Change the mode of the RF module to Transmitting or Receiving */ 00267 void RF12B::changeMode(rfmode_t _mode) { 00268 mode = _mode; 00269 if (_mode == TX) { 00270 writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC 00271 } else { /* mode == RX */ 00272 writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC 00273 } 00274 } 00275 00276 // Interrupt routine for data reception */ 00277 void RF12B::rxISR() { 00278 00279 unsigned int data = 0; 00280 static int i = -2; 00281 static unsigned char packet_length = 0; 00282 static unsigned char crc = 0; 00283 static unsigned char temp; 00284 00285 //Loop while interrupt is asserted 00286 while (!NIRQ_in && mode == RX) { 00287 00288 // Grab the packet's length byte 00289 if (i == -2) { 00290 data = writeCmd(0x0000); 00291 if ( (data&0x8000) ) { 00292 data = writeCmd(0xB000); 00293 packet_length = (data&0x00FF); 00294 crc = crc8(crc, packet_length); 00295 i++; 00296 } 00297 } 00298 00299 //If we exhaust the interrupt, exit 00300 if (NIRQ_in) 00301 break; 00302 00303 // Check that packet length was correct 00304 if (i == -1) { 00305 data = writeCmd(0x0000); 00306 if ( (data&0x8000) ) { 00307 data = writeCmd(0xB000); 00308 unsigned char crcofsize = (data&0x00FF); 00309 if (crcofsize != crc) { 00310 //It was wrong, start over 00311 i = -2; 00312 packet_length = 0; 00313 crc = 0; 00314 //temp = queue<unsigned char>(); 00315 resetRX(); 00316 } else { 00317 crc = crc8(crc, crcofsize); 00318 i++; 00319 } 00320 } 00321 } 00322 00323 //If we exhaust the interrupt, exit 00324 if (NIRQ_in) 00325 break; 00326 00327 // Grab the packet's data 00328 if (i >= 0 && i < packet_length) { 00329 data = writeCmd(0x0000); 00330 if ( (data&0x8000) ) { 00331 data = writeCmd(0xB000); 00332 temp = data&0x00FF; 00333 //temp.push(data&0x00FF); 00334 crc = crc8(crc, (unsigned char)(data&0x00FF)); 00335 i++; 00336 } 00337 } 00338 00339 //If we exhaust the interrupt, exit 00340 if (NIRQ_in) 00341 break; 00342 00343 if (i >= packet_length) { 00344 data = writeCmd(0x0000); 00345 if ( (data&0x8000) ) { 00346 data = writeCmd(0xB000); 00347 if ((unsigned char)(data & 0x00FF) == crc) { 00348 //If the checksum is correct, add our data to the end of the output buffer 00349 //while (!temp.empty()) { 00350 //fifo.push(temp); 00351 // temp.pop(); 00352 #ifdef ROBOT_SECONDARY 00353 if (callbackfunc) 00354 (*callbackfunc)(temp); 00355 00356 if (callbackobj && mcallbackfunc) 00357 (callbackobj->*mcallbackfunc)(temp); 00358 #endif 00359 // } 00360 } 00361 00362 // Tell RF Module we are finished, and clean up 00363 i = -2; 00364 packet_length = 0; 00365 crc = 0; 00366 //temp = queue<unsigned char>(); 00367 resetRX(); 00368 } 00369 } 00370 } 00371 00372 } 00373 00374 unsigned int RF12B::status() { 00375 return writeCmd(0x0000); 00376 } 00377 00378 // Tell the RF Module this packet is received and wait for the next */ 00379 void RF12B::resetRX() { 00380 writeCmd(0xCA81); 00381 writeCmd(0xCA83); 00382 }; 00383 00384 // Calculate CRC8 */ 00385 unsigned char RF12B::crc8(unsigned char crc, unsigned char data) { 00386 crc = crc ^ data; 00387 for (int i = 0; i < 8; i++) { 00388 if (crc & 0x01) { 00389 crc = (crc >> 1) ^ 0x8C; 00390 } else { 00391 crc >>= 1; 00392 } 00393 } 00394 return crc; 00395 }
Generated on Fri Jul 15 2022 01:40:26 by
1.7.2