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