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