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
RF12B.cpp@4:2a295db9ba1a, 2011-03-10 (annotated)
- Committer:
- harryeakins
- Date:
- Thu Mar 10 17:26:42 2011 +0000
- Revision:
- 4:2a295db9ba1a
- Parent:
- 3:e72ad65868ab
- Child:
- 5:a92c3f6d1711
Added variable length packets
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
harryeakins | 3:e72ad65868ab | 1 | #include "RF12B.h" |
harryeakins | 3:e72ad65868ab | 2 | |
harryeakins | 4:2a295db9ba1a | 3 | RF12B::RF12B(PinName _SDI, |
harryeakins | 4:2a295db9ba1a | 4 | PinName _SDO, |
harryeakins | 4:2a295db9ba1a | 5 | PinName _SCK, |
harryeakins | 4:2a295db9ba1a | 6 | PinName _NCS, |
harryeakins | 4:2a295db9ba1a | 7 | PinName _NIRQ):spi(_SDI, _SDO, _SCK), |
harryeakins | 4:2a295db9ba1a | 8 | NCS(_NCS), NIRQ(_NIRQ), NIRQ_in(_NIRQ) { |
harryeakins | 3:e72ad65868ab | 9 | |
harryeakins | 4:2a295db9ba1a | 10 | /* SPI frequency, word lenght, polarity and phase */ |
harryeakins | 4:2a295db9ba1a | 11 | spi.format(16,0); |
harryeakins | 4:2a295db9ba1a | 12 | spi.frequency(2000000); |
harryeakins | 4:2a295db9ba1a | 13 | |
harryeakins | 4:2a295db9ba1a | 14 | /* Set ~CS high */ |
harryeakins | 4:2a295db9ba1a | 15 | NCS = 1; |
harryeakins | 3:e72ad65868ab | 16 | |
harryeakins | 4:2a295db9ba1a | 17 | /* Initialise RF Module */ |
harryeakins | 3:e72ad65868ab | 18 | init(); |
harryeakins | 4:2a295db9ba1a | 19 | resetRX(); |
harryeakins | 4:2a295db9ba1a | 20 | |
harryeakins | 4:2a295db9ba1a | 21 | /* Setup interrupt to happen on falling edge of NIRQ */ |
harryeakins | 4:2a295db9ba1a | 22 | NIRQ.fall(this, &RF12B::rxISR); |
harryeakins | 3:e72ad65868ab | 23 | } |
harryeakins | 3:e72ad65868ab | 24 | |
harryeakins | 4:2a295db9ba1a | 25 | /* Returns true if receive buffer contains data */ |
harryeakins | 4:2a295db9ba1a | 26 | bool RF12B::available() { |
harryeakins | 4:2a295db9ba1a | 27 | return !fifo.empty(); |
harryeakins | 4:2a295db9ba1a | 28 | } |
harryeakins | 3:e72ad65868ab | 29 | |
harryeakins | 4:2a295db9ba1a | 30 | /* Reads a byte of data from the receive buffer */ |
harryeakins | 3:e72ad65868ab | 31 | unsigned char RF12B::read() { |
harryeakins | 4:2a295db9ba1a | 32 | if (available()) { |
harryeakins | 4:2a295db9ba1a | 33 | unsigned char data = fifo.front(); |
harryeakins | 4:2a295db9ba1a | 34 | fifo.pop(); |
harryeakins | 4:2a295db9ba1a | 35 | return data; |
harryeakins | 4:2a295db9ba1a | 36 | } else { |
harryeakins | 4:2a295db9ba1a | 37 | return 0xFF; // Error val although could also be data... |
harryeakins | 3:e72ad65868ab | 38 | } |
harryeakins | 3:e72ad65868ab | 39 | } |
harryeakins | 3:e72ad65868ab | 40 | |
harryeakins | 3:e72ad65868ab | 41 | /* Sends a byte of data to the RF module for transmission */ |
harryeakins | 4:2a295db9ba1a | 42 | void RF12B::write(unsigned char *data, unsigned char length) { |
harryeakins | 4:2a295db9ba1a | 43 | /* Transmitter mode */ |
harryeakins | 4:2a295db9ba1a | 44 | changeMode(TX); |
harryeakins | 4:2a295db9ba1a | 45 | |
harryeakins | 3:e72ad65868ab | 46 | writeCmd(0x0000); |
harryeakins | 3:e72ad65868ab | 47 | send(0xAA); // PREAMBLE |
harryeakins | 3:e72ad65868ab | 48 | send(0xAA); |
harryeakins | 3:e72ad65868ab | 49 | send(0xAA); |
harryeakins | 3:e72ad65868ab | 50 | send(0x2D); // SYNC |
harryeakins | 3:e72ad65868ab | 51 | send(0xD4); |
harryeakins | 4:2a295db9ba1a | 52 | /* Packet Length */ |
harryeakins | 4:2a295db9ba1a | 53 | send(length); |
harryeakins | 4:2a295db9ba1a | 54 | /* Packet Data */ |
harryeakins | 4:2a295db9ba1a | 55 | for (unsigned char i=0; i<length; i++) { |
harryeakins | 3:e72ad65868ab | 56 | send(data[i]); |
harryeakins | 3:e72ad65868ab | 57 | } |
harryeakins | 3:e72ad65868ab | 58 | send(0xAA); // DUMMY BYTES |
harryeakins | 3:e72ad65868ab | 59 | send(0xAA); |
harryeakins | 3:e72ad65868ab | 60 | send(0xAA); |
harryeakins | 3:e72ad65868ab | 61 | |
harryeakins | 4:2a295db9ba1a | 62 | /* Back to receiver mode */ |
harryeakins | 4:2a295db9ba1a | 63 | changeMode(RX); |
harryeakins | 3:e72ad65868ab | 64 | } |
harryeakins | 3:e72ad65868ab | 65 | |
harryeakins | 4:2a295db9ba1a | 66 | /* Transmit a 1-byte data packet */ |
harryeakins | 4:2a295db9ba1a | 67 | void RF12B::write(unsigned char data) { |
harryeakins | 4:2a295db9ba1a | 68 | write(&data, 1); |
harryeakins | 3:e72ad65868ab | 69 | } |
harryeakins | 3:e72ad65868ab | 70 | |
harryeakins | 4:2a295db9ba1a | 71 | /********************************************************************** |
harryeakins | 4:2a295db9ba1a | 72 | * PRIVATE FUNCTIONS |
harryeakins | 4:2a295db9ba1a | 73 | *********************************************************************/ |
harryeakins | 3:e72ad65868ab | 74 | |
harryeakins | 4:2a295db9ba1a | 75 | /* Initialises the RF12B module */ |
harryeakins | 3:e72ad65868ab | 76 | void RF12B::init() { |
harryeakins | 3:e72ad65868ab | 77 | writeCmd(0x80E7); //EL,EF,868band,12.0pF |
harryeakins | 4:2a295db9ba1a | 78 | changeMode(RX); |
harryeakins | 3:e72ad65868ab | 79 | writeCmd(0xA640); //frequency select |
harryeakins | 3:e72ad65868ab | 80 | writeCmd(0xC647); //4.8kbps |
harryeakins | 3:e72ad65868ab | 81 | writeCmd(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm |
harryeakins | 3:e72ad65868ab | 82 | writeCmd(0xC2AC); //AL,!ml,DIG,DQD4 |
harryeakins | 3:e72ad65868ab | 83 | writeCmd(0xCA81); //FIFO8,SYNC,!ff,DR |
harryeakins | 3:e72ad65868ab | 84 | writeCmd(0xCED4); //SYNC=2DD4 |
harryeakins | 3:e72ad65868ab | 85 | writeCmd(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN |
harryeakins | 3:e72ad65868ab | 86 | writeCmd(0x9850); //!mp,90kHz,MAX OUT |
harryeakins | 4:2a295db9ba1a | 87 | writeCmd(0xCC17); //OB1, COB0, LPX, Iddy, CDDIT�CBW0 |
harryeakins | 3:e72ad65868ab | 88 | writeCmd(0xE000); //NOT USED |
harryeakins | 3:e72ad65868ab | 89 | writeCmd(0xC800); //NOT USED |
harryeakins | 3:e72ad65868ab | 90 | writeCmd(0xC040); //1.66MHz,2.2V |
harryeakins | 4:2a295db9ba1a | 91 | } |
harryeakins | 3:e72ad65868ab | 92 | |
harryeakins | 4:2a295db9ba1a | 93 | /* Write a command to the RF Module */ |
harryeakins | 4:2a295db9ba1a | 94 | unsigned int RF12B::writeCmd(unsigned int cmd) { |
harryeakins | 4:2a295db9ba1a | 95 | NCS = 0; |
harryeakins | 4:2a295db9ba1a | 96 | unsigned int recv = spi.write(cmd); |
harryeakins | 4:2a295db9ba1a | 97 | NCS = 1; |
harryeakins | 4:2a295db9ba1a | 98 | return recv; |
harryeakins | 3:e72ad65868ab | 99 | } |
harryeakins | 3:e72ad65868ab | 100 | |
harryeakins | 4:2a295db9ba1a | 101 | /* Sends a byte of data across RF */ |
harryeakins | 4:2a295db9ba1a | 102 | void RF12B::send(unsigned char data) { |
harryeakins | 4:2a295db9ba1a | 103 | while (NIRQ); |
harryeakins | 4:2a295db9ba1a | 104 | writeCmd(0xB800 + data); |
harryeakins | 4:2a295db9ba1a | 105 | } |
harryeakins | 4:2a295db9ba1a | 106 | |
harryeakins | 4:2a295db9ba1a | 107 | /* Change the mode of the RF module to Transmitting or Receiving */ |
harryeakins | 4:2a295db9ba1a | 108 | void RF12B::changeMode(rfmode_t mode) { |
harryeakins | 4:2a295db9ba1a | 109 | if (mode == TX) { |
harryeakins | 3:e72ad65868ab | 110 | writeCmd(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC |
harryeakins | 4:2a295db9ba1a | 111 | } else { /* mode == RX */ |
harryeakins | 3:e72ad65868ab | 112 | writeCmd(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC |
harryeakins | 3:e72ad65868ab | 113 | } |
harryeakins | 3:e72ad65868ab | 114 | } |
harryeakins | 3:e72ad65868ab | 115 | |
harryeakins | 4:2a295db9ba1a | 116 | /* Interrupt routine for data reception */ |
harryeakins | 4:2a295db9ba1a | 117 | void RF12B::rxISR() { |
harryeakins | 4:2a295db9ba1a | 118 | unsigned int data = 0, i = 0; |
harryeakins | 4:2a295db9ba1a | 119 | unsigned char packet_length = 0; |
harryeakins | 4:2a295db9ba1a | 120 | |
harryeakins | 4:2a295db9ba1a | 121 | /* Grab the packet's length byte */ |
harryeakins | 4:2a295db9ba1a | 122 | data = writeCmd(0x0000); |
harryeakins | 4:2a295db9ba1a | 123 | if ( (data&0x8000) ) { |
harryeakins | 4:2a295db9ba1a | 124 | data = writeCmd(0xB000); |
harryeakins | 4:2a295db9ba1a | 125 | packet_length = (data&0x00FF); |
harryeakins | 4:2a295db9ba1a | 126 | } |
harryeakins | 4:2a295db9ba1a | 127 | |
harryeakins | 4:2a295db9ba1a | 128 | /* Grab the packet's data */ |
harryeakins | 4:2a295db9ba1a | 129 | while ((++i) < packet_length) { |
harryeakins | 4:2a295db9ba1a | 130 | data = writeCmd(0x0000); |
harryeakins | 4:2a295db9ba1a | 131 | if ( (data&0x8000) ) { |
harryeakins | 4:2a295db9ba1a | 132 | data = writeCmd(0xB000); |
harryeakins | 4:2a295db9ba1a | 133 | fifo.push(data&0x00FF); |
harryeakins | 4:2a295db9ba1a | 134 | } |
harryeakins | 4:2a295db9ba1a | 135 | } |
harryeakins | 4:2a295db9ba1a | 136 | /* Tell RF Module we are finished */ |
harryeakins | 4:2a295db9ba1a | 137 | resetRX(); |
harryeakins | 3:e72ad65868ab | 138 | } |
harryeakins | 4:2a295db9ba1a | 139 | |
harryeakins | 4:2a295db9ba1a | 140 | /* Tell the RF Module this packet is received and wait for the next */ |
harryeakins | 4:2a295db9ba1a | 141 | void RF12B::resetRX() { |
harryeakins | 4:2a295db9ba1a | 142 | writeCmd(0xCA81); |
harryeakins | 4:2a295db9ba1a | 143 | writeCmd(0xCA83); |
harryeakins | 4:2a295db9ba1a | 144 | }; |