File content as of revision 0:7583de124698:
#include "RF12B.h"
#include "RF_defs.h"
#include <algorithm>
//#include "globals.h"
//DigitalOut DBG2(LED2);
//DigitalOut DBG3(LED3);
//DigitalOut DBG4(LED4);
RF12B::RF12B(PinName _SDI,
PinName _SDO,
PinName _SCK,
PinName _NCS,
PinName _NIRQ):spi(_SDI, _SDO, _SCK),
NCS(_NCS), NIRQ(_NIRQ), NIRQ_in(_NIRQ){// rfled(LED3) {
/* SPI frequency, word lenght, polarity and phase */
spi.format(16,0);
spi.frequency(2000000);
/* Set ~CS high */
NCS = 1;
/* Initialise RF Module */
init();
/* Setup interrupt to happen on falling edge of NIRQ */
NIRQ.fall(this, &RF12B::rxISR);
}
/* Returns the packet length if data is available in the receive buffer, 0 otherwise*/
unsigned int RF12B::available() {
return fifo.size();
}
/* Reads a packet of data, with length "size" Returns false if read failed. TODO: make a metafifo to isolate packets*/
bool RF12B::read(unsigned char* data, unsigned int size) {
if (fifo.size() == 0) {
return false;
} else {
unsigned int i = 0;
while (fifo.size() > 0 && i < size) {
data[i++] = fifo.front();
fifo.pop();
}
return true;
}
}
/* Reads a byte of data from the receive buffer */
unsigned char RF12B::read() {
if (available()) {
unsigned char data = fifo.front();
fifo.pop();
return data;
} else {
return 0xFF; // Error val although could also be data...
}
}
/* Sends a packet of data to the RF module for transmission TODO: Make asych*/
void RF12B::write(unsigned char *data, unsigned char length) {
unsigned char crc = 0;
/* Transmitter mode */
changeMode(TX);
writeCmd(0x0000);
send(0xAA); // PREAMBLE
send(0xAA);
send(0xAA);
send(0x2D); // SYNC
send(0xD4);
/* Packet Length */
send(length);
crc = crc8(crc, length);
send(crc);
crc = crc8(crc, crc);
/* 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);
/* Back to receiver mode */
changeMode(RX);
status();
}
/* Transmit a 1-byte data packet */
void RF12B::write(unsigned char data) {
write(&data, 1);
}
void RF12B::write(queue<char> &data, int length) {
char crc = 0;
char length_byte = 0;
/* -1 means try to transmit everything in the queue */
if(length == -1) {
length = data.size();
}
/* max length of packet is 255 */
length_byte = min(length, 255);
/* Transmitter mode */
changeMode(TX);
writeCmd(0x0000);
send(0xAA); // PREAMBLE
send(0xAA);
send(0xAA);
send(0x2D); // SYNC
send(0xD4);
/* Packet Length */
send(length_byte);
crc = crc8(crc, length_byte);
send(crc);
crc = crc8(crc, crc);
/* Packet Data */
for (char i=0; i<length_byte; i++) {
send(data.front());
crc = crc8(crc, data.front());
data.pop();
}
send(crc);
send(0xAA); // DUMMY BYTES
send(0xAA);
send(0xAA);
/* Back to receiver mode */
changeMode(RX);
status();
}
/**********************************************************************
* PRIVATE FUNCTIONS
*********************************************************************/
/* 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(
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 pll's reaction time. Not sure, check with someone!
);
changeMode(RX);
resetRX();
status();
}
/* Write a command to the RF Module */
unsigned int RF12B::writeCmd(unsigned int cmd) {
NCS = 0;
unsigned int recv = spi.write(cmd);
NCS = 1;
return recv;
}
/* Sends a byte of data across RF */
void RF12B::send(unsigned char data) {
while (NIRQ);
writeCmd(0xB800 + data);
}
/* Change the mode of the RF module to Transmitting or Receiving */
void RF12B::changeMode(rfmode_t _mode) {
mode = _mode;
if (_mode == TX) {
writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
} else { /* mode == RX */
writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC
}
}
/* Interrupt routine for data reception */
void RF12B::rxISR() {
//static int cnt = 0;
//printf("%d hits\r\n", cnt);
//cnt++;
//DBG2 = !(cnt%3);
//DBG3 = !((cnt+1)%3);
//DBG4 = !((cnt+2)%3);
unsigned int data = 0;
static int i = -2;
static unsigned char packet_length = 0;
static unsigned char crc = 0;
//Loop while interrupt is asserted
while (!NIRQ_in && mode == RX) {
// Grab the packet's length byte
if (i == -2) {
data = writeCmd(0x0000);
if ( (data&0x8000) ) {
data = writeCmd(0xB000);
packet_length = (data&0x00FF);
crc = crc8(crc, packet_length);
i++;
}
}
//If we exhaust the interrupt, exit
if (NIRQ_in)
break;
// Check that packet length was correct
if (i == -1) {
data = writeCmd(0x0000);
if ( (data&0x8000) ) {
data = writeCmd(0xB000);
unsigned char crcofsize = (data&0x00FF);
if (crcofsize != crc) {
//It was wrong, start over
i = -2;
packet_length = 0;
crc = 0;
//temp = queue<unsigned char>();
resetRX();
} else {
crc = crc8(crc, crcofsize);
i++;
}
}
}
//If we exhaust the interrupt, exit
if (NIRQ_in)
break;
// Grab the packet's data
if (i >= 0 && i < packet_length) {
data = writeCmd(0x0000);
if ( (data&0x8000) ) {
data = writeCmd(0xB000);
//temp.push(data&0x00FF);
crc = crc8(crc, (unsigned char)(data&0x00FF));
i++;
}
}
//If we exhaust the interrupt, exit
if (NIRQ_in)
break;
if (i >= packet_length) {
data = writeCmd(0x0000);
if ( (data&0x8000) ) {
data = writeCmd(0xB000);
if ((unsigned char)(data & 0x00FF) == crc) {
//If the checksum is correct, add our data to the end of the output buffer
//while (!temp.empty()) {
// fifo.push(temp.front());
// temp.pop();
//}
}
// Tell RF Module we are finished, and clean up
i = -2;
packet_length = 0;
crc = 0;
//temp = queue<unsigned char>();
resetRX();
}
}
}
}
unsigned int RF12B::status() {
return writeCmd(0x0000);
}
/* Tell the RF Module this packet is received and wait for the next */
void RF12B::resetRX() {
writeCmd(0xCA81);
writeCmd(0xCA83);
};
/* 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;
}