Library to send and receive data using RF12B transceiver modules Big thanks to the tutorial at https://loee.jottit.com/rfm12b_and_avr_-_quick_start and madcowswe
Dependents: Measure_system Quadcopter_copy
Diff: RF12B.cpp
- Revision:
- 6:98da0571ec31
- Parent:
- 5:a92c3f6d1711
- Child:
- 7:9f9e2a63a8a2
--- a/RF12B.cpp Thu Mar 10 18:07:53 2011 +0000 +++ b/RF12B.cpp Fri Mar 11 15:47:06 2011 +0000 @@ -1,5 +1,7 @@ #include "RF12B.h" +#include "RF_defs.h" + DigitalOut rfled(LED3); RF12B::RF12B(PinName _SDI, @@ -41,6 +43,7 @@ /* Sends a packet of data to the RF module for transmission */ void RF12B::write(unsigned char *data, unsigned char length) { + unsigned char crc = 0; /* Transmitter mode */ changeMode(TX); @@ -52,10 +55,13 @@ send(0xD4); /* Packet Length */ send(length); + crc = crc8(crc, length); /* Packet Data */ for (unsigned char i=0; i<length; i++) { send(data[i]); + crc = crc8(crc, data[i]); } + send(crc); send(0xAA); // DUMMY BYTES send(0xAA); send(0xAA); @@ -76,20 +82,101 @@ /* Initialises the RF12B module */ void RF12B::init() { - writeCmd(0x80E7); //EL,EF,868band,12.0pF - changeMode(RX); - writeCmd(0xA640); //frequency select - writeCmd(0xC647); //4.8kbps - writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm - writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 - writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR - writeCmd(0xCED4); //SYNC=2DD4 - writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN - writeCmd(0x9850); //!mp,90kHz,MAX OUT - writeCmd(0xCC17); //OB1, COB0, LPX, Iddy, CDDIT�CBW0 - writeCmd(0xE000); //NOT USED - writeCmd(0xC800); //NOT USED - writeCmd(0xC040); //1.66MHz,2.2V + /* writeCmd(0x80E7); //EL,EF,868band,12.0pF + changeMode(RX); + writeCmd(0xA640); //frequency select + writeCmd(0xC647); //4.8kbps + writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm + writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 + writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR + writeCmd(0xCED4); //SYNC=2DD4 + writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN + writeCmd(0x9850); //!mp,90kHz,MAX OUT + writeCmd(0xCC17); //OB1, COB0, LPX, Iddy, CDDIT�CBW0 + writeCmd(0xE000); //NOT USED + writeCmd(0xC800); //NOT USED + writeCmd(0xC040); //1.66MHz,2.2V */ + + writeCmd( + RFM_CONFIG_EL | + RFM_CONFIG_EF | + RFM_CONFIG_BAND_433 //| + //RFM_CONFIG_X_11_0pf // meh, using default + ); + + // 2. Power Management Command + // leave everything switched off for now + /* + writeCmd( + RFM_POWER_MANAGEMENT // switch all off + ); + */ + + // 3. Frequency Setting Command + writeCmd( + RFM_FREQUENCY | + RFM_FREQ_433Band(435.7) //I totally made this value up... if someone knows where the sweetspots are in this band, tell me! + ); + + + // 4. Data Rate Command + writeCmd(RFM_DATA_RATE_9600); + + + // 5. Receiver Control Command + writeCmd( + RFM_RX_CONTROL_P20_VDI | + RFM_RX_CONTROL_VDI_FAST | + //RFM_RX_CONTROL_BW(RFM_BAUD_RATE) | + RFM_RX_CONTROL_BW_134 | // CHANGE THIS TO 67 TO IMPROVE RANGE! (though the bitrate must then be below 8kbaud, and fsk modulation changed) + RFM_RX_CONTROL_GAIN_0 | + RFM_RX_CONTROL_RSSI_103 // Might need adjustment. Datasheet says around 10^-5 bit error rate at this level and baudrate. + ); + + // 6. Data Filter Command + writeCmd( + RFM_DATA_FILTER_AL | + RFM_DATA_FILTER_ML | + RFM_DATA_FILTER_DIG //| + //RFM_DATA_FILTER_DQD(4) + ); + + // 7. FIFO and Reset Mode Command + writeCmd( + RFM_FIFO_IT(8) | + RFM_FIFO_DR | + 0x8 //turn on 16bit sync word + ); + + // 8. FIFO Syncword + // Leave as default: 0xD4 + + // 9. Receiver FIFO Read + // when the interupt goes high, (and if we can assume that it was a fifo fill interrupt) we can read a byte using: + // result = RFM_READ_FIFO(); + + // 10. AFC Command + writeCmd( + //RFM_AFC_AUTO_VDI | //Note this might be changed to improve range. Refer to datasheet. + RFM_AFC_AUTO_INDEPENDENT | + RFM_AFC_RANGE_LIMIT_7_8 | + RFM_AFC_EN | + RFM_AFC_OE | + RFM_AFC_FI + ); + + // 11. TX Configuration Control Command + writeCmd( + RFM_TX_CONTROL_MOD_60 | + RFM_TX_CONTROL_POW_0 + ); + + + // 12. PLL Setting Command + writeCmd( + 0xCC77 & ~0x01 // Setting the PLL bandwith, less noise, but max bitrate capped at 86.2 + // I think this will slow down the plls reaction time. Not sure, check with someone! + ); resetRX(); status(); @@ -122,12 +209,15 @@ void RF12B::rxISR() { unsigned int data = 0, i = 0; unsigned char packet_length = 0; + unsigned char crc = 0; + queue<unsigned char> temp; /* Grab the packet's length byte */ data = writeCmd(0x0000); if ( (data&0x8000) ) { data = writeCmd(0xB000); packet_length = (data&0x00FF); + crc = crc8(crc, packet_length); } /* Grab the packet's data */ @@ -136,11 +226,27 @@ data = writeCmd(0x0000); if ( (data&0x8000) ) { data = writeCmd(0xB000); - fifo.push(data&0x00FF); + temp.push(data&0x00FF); + crc = crc8(crc, (unsigned char)(data&0x00FF)); i++; } } } + while (1) { + if (!NIRQ_in) { + data = writeCmd(0x0000); + if ( (data&0x8000) ) { + data = writeCmd(0xB000); + if ((unsigned char)(data & 0x00FF) == crc) { + while (!temp.empty()) { + fifo.push(temp.front()); + temp.pop(); + } + } + break; + } + } + } /* Tell RF Module we are finished */ resetRX(); } @@ -153,4 +259,17 @@ void RF12B::resetRX() { writeCmd(0xCA81); writeCmd(0xCA83); -}; \ No newline at end of file +}; + +/* Calculate CRC8 */ +unsigned char RF12B::crc8(unsigned char crc, unsigned char data) { + crc = crc ^ data; + for (int i = 0; i < 8; i++) { + if (crc & 0x01) { + crc = (crc >> 1) ^ 0x8C; + } else { + crc >>= 1; + } + } + return crc; +} \ No newline at end of file