Shuto Naruse
/
eurobot_2011_main
Embed:
(wiki syntax)
Show/hide line numbers
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