mBed RFM12B module library

Dependents:   _EXAMPLE_RFM12B

Fork of RF12B by Sukkin Pang

RFM12B Library

The main purpose of this library was to implement the RFM12B module in order to be able to establish communication with the Moteino (arduino clone that uses the RFM12B).

In order to achieve my goal I was highly inspired by RF12B library from pangsk https://mbed.org/users/pangsk/ and by RFM12B arduino library made by Felix Rusu (http://lowpowerlab.com/blog/2012/12/28/rfm12b-arduino-library/)

Who/What is Moteino? (http://lowpowerlab.com/moteino/)

Committer:
pangsk
Date:
Sun Jan 01 22:09:41 2012 +0000
Revision:
1:27a1606deace
Parent:
0:66fdbf2cc578
Child:
2:cfeb4c9cdbe3
Initial release.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pangsk 0:66fdbf2cc578 1 /* RF12B Library. Based on work done by JeeLabs.org ported to mbed by SK Pang.
pangsk 0:66fdbf2cc578 2 http://jeelabs.net/projects/cafe/wiki/RF12
pangsk 0:66fdbf2cc578 3
pangsk 0:66fdbf2cc578 4 http://opensource.org/licenses/mit-license.php
pangsk 0:66fdbf2cc578 5
pangsk 0:66fdbf2cc578 6 Jan 2012 skpang.co.uk
pangsk 0:66fdbf2cc578 7
pangsk 0:66fdbf2cc578 8 */
pangsk 0:66fdbf2cc578 9
pangsk 0:66fdbf2cc578 10 #include "RF12B.h"
pangsk 0:66fdbf2cc578 11
pangsk 0:66fdbf2cc578 12 // RF12 command codes
pangsk 0:66fdbf2cc578 13 #define RF_RECEIVER_ON 0x82DD
pangsk 0:66fdbf2cc578 14 #define RF_XMITTER_ON 0x823D
pangsk 0:66fdbf2cc578 15 #define RF_IDLE_MODE 0x820D
pangsk 0:66fdbf2cc578 16 #define RF_SLEEP_MODE 0x8205
pangsk 0:66fdbf2cc578 17 #define RF_WAKEUP_MODE 0x8207
pangsk 0:66fdbf2cc578 18 #define RF_TXREG_WRITE 0xB800
pangsk 0:66fdbf2cc578 19 #define RF_RX_FIFO_READ 0xB000
pangsk 0:66fdbf2cc578 20 #define RF_WAKEUP_TIMER 0xE000
pangsk 0:66fdbf2cc578 21
pangsk 0:66fdbf2cc578 22 // RF12 status bits
pangsk 0:66fdbf2cc578 23 #define RF_LBD_BIT 0x0400
pangsk 0:66fdbf2cc578 24 #define RF_RSSI_BIT 0x0100
pangsk 0:66fdbf2cc578 25
pangsk 0:66fdbf2cc578 26 // bits in the node id configuration byte
pangsk 0:66fdbf2cc578 27 #define NODE_BAND 0xC0 // frequency band
pangsk 0:66fdbf2cc578 28 #define NODE_ACKANY 0x20 // ack on broadcast packets if set
pangsk 0:66fdbf2cc578 29 #define NODE_ID 0x1F // id of this node, as A..Z or 1..31
pangsk 0:66fdbf2cc578 30
pangsk 0:66fdbf2cc578 31 // transceiver states, these determine what to do with each interrupt
pangsk 0:66fdbf2cc578 32 enum {
pangsk 0:66fdbf2cc578 33 TXCRC1, TXCRC2, TXTAIL, TXDONE, TXIDLE,
pangsk 0:66fdbf2cc578 34 TXRECV,
pangsk 0:66fdbf2cc578 35 TXPRE1, TXPRE2, TXPRE3, TXSYN1, TXSYN2,
pangsk 0:66fdbf2cc578 36 };
pangsk 0:66fdbf2cc578 37
pangsk 0:66fdbf2cc578 38 DigitalOut rfled(LED3);
pangsk 0:66fdbf2cc578 39 DigitalOut t1(p5);
pangsk 0:66fdbf2cc578 40 DigitalOut t2(p6);
pangsk 0:66fdbf2cc578 41
pangsk 0:66fdbf2cc578 42 RF12B::RF12B(PinName _SDI,
pangsk 0:66fdbf2cc578 43 PinName _SDO,
pangsk 0:66fdbf2cc578 44 PinName _SCK,
pangsk 0:66fdbf2cc578 45 PinName _NCS,
pangsk 0:66fdbf2cc578 46 PinName _NIRQ):spi(_SDI, _SDO, _SCK),
pangsk 0:66fdbf2cc578 47 NCS(_NCS), NIRQ(_NIRQ), NIRQ_in(_NIRQ), rfled(LED3),t1(p5),t2(p6) {
pangsk 0:66fdbf2cc578 48
pangsk 0:66fdbf2cc578 49 /* SPI frequency, word lenght, polarity and phase */
pangsk 0:66fdbf2cc578 50 spi.format(8,0);
pangsk 0:66fdbf2cc578 51 spi.frequency(2000000);
pangsk 0:66fdbf2cc578 52
pangsk 0:66fdbf2cc578 53 /* Set ~CS high */
pangsk 0:66fdbf2cc578 54 NCS = 1;
pangsk 0:66fdbf2cc578 55
pangsk 0:66fdbf2cc578 56 /* Setup interrupt to happen on falling edge of NIRQ */
pangsk 0:66fdbf2cc578 57 NIRQ.fall(this, &RF12B::rxISR);
pangsk 0:66fdbf2cc578 58 }
pangsk 0:66fdbf2cc578 59
pangsk 0:66fdbf2cc578 60
pangsk 0:66fdbf2cc578 61 /**********************************************************************
pangsk 0:66fdbf2cc578 62 * PRIVATE FUNCTIONS
pangsk 0:66fdbf2cc578 63 *********************************************************************/
pangsk 0:66fdbf2cc578 64
pangsk 0:66fdbf2cc578 65 /* Initialises the RF12B module */
pangsk 0:66fdbf2cc578 66 void RF12B::init(uint8_t id, uint8_t band, uint8_t g) {
pangsk 0:66fdbf2cc578 67
pangsk 0:66fdbf2cc578 68 nodeid = id;
pangsk 0:66fdbf2cc578 69 group = g;
pangsk 0:66fdbf2cc578 70 rf12_grp = g;
pangsk 0:66fdbf2cc578 71
pangsk 0:66fdbf2cc578 72 writeCmd(0x0000); // intitial SPI transfer added to avoid power-up problem
pangsk 0:66fdbf2cc578 73 writeCmd(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd
pangsk 0:66fdbf2cc578 74
pangsk 0:66fdbf2cc578 75 // wait until RFM12B is out of power-up reset, this takes several *seconds*
pangsk 0:66fdbf2cc578 76 writeCmd(RF_TXREG_WRITE); // in case we're still in OOK mode
pangsk 0:66fdbf2cc578 77
pangsk 0:66fdbf2cc578 78 while (NIRQ == 0) writeCmd(0x0000);
pangsk 0:66fdbf2cc578 79
pangsk 0:66fdbf2cc578 80 writeCmd(0x80C7 | (2 << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF
pangsk 0:66fdbf2cc578 81 writeCmd(0xA640); // 868MHz
pangsk 0:66fdbf2cc578 82 writeCmd(0xC606); // approx 49.2 Kbps, i.e. 10000/29/(1+6) Kbps
pangsk 0:66fdbf2cc578 83 writeCmd(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm
pangsk 0:66fdbf2cc578 84 writeCmd(0xC2AC); // AL,!ml,DIG,DQD4
pangsk 0:66fdbf2cc578 85
pangsk 0:66fdbf2cc578 86 writeCmd(0xCA83); // FIFO8,2-SYNC,!ff,DR
pangsk 0:66fdbf2cc578 87 writeCmd(0xCE00 | 1); // SYNC=2DXX&#65307;
pangsk 0:66fdbf2cc578 88
pangsk 0:66fdbf2cc578 89 writeCmd(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN
pangsk 0:66fdbf2cc578 90 writeCmd(0x9850); // !mp,90kHz,MAX OUT
pangsk 0:66fdbf2cc578 91 writeCmd(0xCC77); // OB1&#65292;OB0, LPX,&#65281;ddy&#65292;DDIT&#65292;BW0
pangsk 0:66fdbf2cc578 92 writeCmd(0xE000); // NOT USE
pangsk 0:66fdbf2cc578 93 writeCmd(0xC800); // NOT USE
pangsk 0:66fdbf2cc578 94 writeCmd(0xC049); // 1.66MHz,3.1V
pangsk 0:66fdbf2cc578 95
pangsk 0:66fdbf2cc578 96 rxstate = TXIDLE;
pangsk 0:66fdbf2cc578 97
pangsk 0:66fdbf2cc578 98 rfled = 0;
pangsk 0:66fdbf2cc578 99 }
pangsk 0:66fdbf2cc578 100
pangsk 0:66fdbf2cc578 101 /* Write a command to the RF Module */
pangsk 0:66fdbf2cc578 102 unsigned int RF12B::writeCmd(unsigned int cmd) {
pangsk 0:66fdbf2cc578 103 NCS = 0;
pangsk 0:66fdbf2cc578 104 unsigned int recv = spi.write(cmd >>8);
pangsk 0:66fdbf2cc578 105 recv = spi.write(cmd);
pangsk 0:66fdbf2cc578 106 NCS = 1;
pangsk 0:66fdbf2cc578 107 return recv;
pangsk 0:66fdbf2cc578 108 }
pangsk 0:66fdbf2cc578 109
pangsk 0:66fdbf2cc578 110 /* Sends a byte of data across RF */
pangsk 0:66fdbf2cc578 111 void RF12B::send(unsigned char data) {
pangsk 0:66fdbf2cc578 112 while (NIRQ);
pangsk 0:66fdbf2cc578 113 writeCmd(0xB800 + data);
pangsk 0:66fdbf2cc578 114 }
pangsk 0:66fdbf2cc578 115
pangsk 0:66fdbf2cc578 116
pangsk 0:66fdbf2cc578 117 /* Interrupt routine for data reception and Txing */
pangsk 0:66fdbf2cc578 118 void RF12B::rxISR() {
pangsk 0:66fdbf2cc578 119
pangsk 0:66fdbf2cc578 120 // a transfer of 2x 16 bits @ 2 MHz over SPI takes 2x 8 us inside this ISR
pangsk 0:66fdbf2cc578 121 writeCmd(0x0000);
pangsk 0:66fdbf2cc578 122
pangsk 0:66fdbf2cc578 123 if (rxstate == TXRECV) {
pangsk 0:66fdbf2cc578 124 uint8_t in = rf12_xfer(RF_RX_FIFO_READ);
pangsk 0:66fdbf2cc578 125
pangsk 0:66fdbf2cc578 126 if (rxfill == 0 && group != 0)
pangsk 0:66fdbf2cc578 127 rf12_buf[rxfill++] = group;
pangsk 0:66fdbf2cc578 128
pangsk 0:66fdbf2cc578 129 rf12_buf[rxfill++] = in;
pangsk 0:66fdbf2cc578 130 rf12_crc = _crc16_update(rf12_crc, in);
pangsk 0:66fdbf2cc578 131
pangsk 0:66fdbf2cc578 132 if (rxfill >= rf12_len + 5 || rxfill >= RF_MAX)
pangsk 0:66fdbf2cc578 133 rf12_xfer(RF_IDLE_MODE);
pangsk 0:66fdbf2cc578 134 } else {
pangsk 0:66fdbf2cc578 135 uint8_t out;
pangsk 0:66fdbf2cc578 136
pangsk 0:66fdbf2cc578 137 if (rxstate < 0) {
pangsk 0:66fdbf2cc578 138 uint8_t pos = 3 + rf12_len + rxstate++;
pangsk 0:66fdbf2cc578 139 out = rf12_buf[pos];
pangsk 0:66fdbf2cc578 140 rf12_crc = _crc16_update(rf12_crc, out);
pangsk 0:66fdbf2cc578 141 } else
pangsk 0:66fdbf2cc578 142 switch (rxstate++) {
pangsk 0:66fdbf2cc578 143 case TXSYN1: out = 0x2D; break;
pangsk 0:66fdbf2cc578 144 case TXSYN2: out = rf12_grp; rxstate = - (2 + rf12_len); break;
pangsk 0:66fdbf2cc578 145 case TXCRC1: out = rf12_crc; break;
pangsk 0:66fdbf2cc578 146 case TXCRC2: out = rf12_crc >> 8; break;
pangsk 0:66fdbf2cc578 147 case TXDONE: rf12_xfer(RF_IDLE_MODE); // fall through
pangsk 0:66fdbf2cc578 148 default: out = 0xAA;
pangsk 0:66fdbf2cc578 149 }
pangsk 0:66fdbf2cc578 150
pangsk 0:66fdbf2cc578 151 rf12_xfer(RF_TXREG_WRITE + out);
pangsk 0:66fdbf2cc578 152 }
pangsk 0:66fdbf2cc578 153 }
pangsk 0:66fdbf2cc578 154
pangsk 0:66fdbf2cc578 155
pangsk 0:66fdbf2cc578 156 void RF12B::rf12_sendStart (uint8_t hdr, const void* ptr, uint8_t len)
pangsk 0:66fdbf2cc578 157 {
pangsk 0:66fdbf2cc578 158 rf12_len = len;
pangsk 0:66fdbf2cc578 159 memcpy((void*) rf12_data, ptr, len);
pangsk 0:66fdbf2cc578 160
pangsk 0:66fdbf2cc578 161 rf12_sendStart2(hdr);
pangsk 0:66fdbf2cc578 162
pangsk 0:66fdbf2cc578 163 }
pangsk 0:66fdbf2cc578 164 void RF12B::rf12_sendStart2 (uint8_t hdr) {
pangsk 0:66fdbf2cc578 165 rf12_hdr = hdr & RF12_HDR_DST ? hdr :
pangsk 0:66fdbf2cc578 166 (hdr & ~RF12_HDR_MASK) + (nodeid & NODE_ID);
pangsk 0:66fdbf2cc578 167
pangsk 0:66fdbf2cc578 168 /* if (crypter != 0)
pangsk 0:66fdbf2cc578 169 crypter(1);
pangsk 0:66fdbf2cc578 170 */
pangsk 0:66fdbf2cc578 171 rf12_crc = ~0;
pangsk 0:66fdbf2cc578 172
pangsk 0:66fdbf2cc578 173 rf12_crc = _crc16_update(rf12_crc, rf12_grp);
pangsk 0:66fdbf2cc578 174 rxstate = TXPRE1;
pangsk 0:66fdbf2cc578 175
pangsk 0:66fdbf2cc578 176 rf12_xfer(RF_XMITTER_ON); // bytes will be fed via interrupts
pangsk 0:66fdbf2cc578 177 }
pangsk 0:66fdbf2cc578 178
pangsk 0:66fdbf2cc578 179
pangsk 0:66fdbf2cc578 180 uint16_t RF12B::rf12_xfer (uint16_t cmd) {
pangsk 0:66fdbf2cc578 181 NCS = 0;
pangsk 0:66fdbf2cc578 182 uint16_t reply = rf12_byte(cmd >> 8) << 8;
pangsk 0:66fdbf2cc578 183 reply |= rf12_byte(cmd);
pangsk 0:66fdbf2cc578 184 NCS = 1;
pangsk 0:66fdbf2cc578 185 return reply;
pangsk 0:66fdbf2cc578 186 }
pangsk 0:66fdbf2cc578 187
pangsk 0:66fdbf2cc578 188 void RF12B::rf12_recvStart (void) {
pangsk 0:66fdbf2cc578 189 rxfill = rf12_len = 0;
pangsk 0:66fdbf2cc578 190 rf12_crc = ~0;
pangsk 0:66fdbf2cc578 191
pangsk 0:66fdbf2cc578 192 if (group != 0)
pangsk 0:66fdbf2cc578 193 rf12_crc = _crc16_update(~0, group);
pangsk 0:66fdbf2cc578 194
pangsk 0:66fdbf2cc578 195 rxstate = TXRECV;
pangsk 0:66fdbf2cc578 196 rf12_xfer(RF_RECEIVER_ON);
pangsk 0:66fdbf2cc578 197 }
pangsk 0:66fdbf2cc578 198 uint16_t RF12B::check_crc(void)
pangsk 0:66fdbf2cc578 199 {
pangsk 0:66fdbf2cc578 200
pangsk 0:66fdbf2cc578 201 return rf12_crc;
pangsk 0:66fdbf2cc578 202 }
pangsk 0:66fdbf2cc578 203 uint8_t RF12B::length(void)
pangsk 0:66fdbf2cc578 204 {
pangsk 0:66fdbf2cc578 205
pangsk 0:66fdbf2cc578 206 return rf12_len;
pangsk 0:66fdbf2cc578 207 }
pangsk 0:66fdbf2cc578 208 uint8_t* RF12B::get_data(void)
pangsk 0:66fdbf2cc578 209 {
pangsk 0:66fdbf2cc578 210 return (uint8_t*)rf12_data;
pangsk 0:66fdbf2cc578 211
pangsk 0:66fdbf2cc578 212 }
pangsk 0:66fdbf2cc578 213
pangsk 0:66fdbf2cc578 214
pangsk 0:66fdbf2cc578 215 uint8_t RF12B::rf12_recvDone (void) {
pangsk 0:66fdbf2cc578 216
pangsk 1:27a1606deace 217 if (rxstate == TXRECV && (rxfill >= rf12_len + 5 || rxfill >= RF_MAX)) {
pangsk 0:66fdbf2cc578 218 rxstate = TXIDLE;
pangsk 0:66fdbf2cc578 219
pangsk 0:66fdbf2cc578 220 if (rf12_len > RF12_MAXDATA)
pangsk 0:66fdbf2cc578 221 rf12_crc = 1; // force bad crc if packet length is invalid
pangsk 0:66fdbf2cc578 222 if (!(rf12_hdr & RF12_HDR_DST) || (nodeid & NODE_ID) == 31 ||
pangsk 0:66fdbf2cc578 223 (rf12_hdr & RF12_HDR_MASK) == (nodeid & NODE_ID)) {
pangsk 0:66fdbf2cc578 224 /*
pangsk 0:66fdbf2cc578 225 for(i=0;i<rf12_len+6;i++)
pangsk 0:66fdbf2cc578 226 {
pangsk 0:66fdbf2cc578 227 printf("%X ",rf12_buf[i]);
pangsk 0:66fdbf2cc578 228 }
pangsk 0:66fdbf2cc578 229 printf(" crc:%x",rf12_crc);
pangsk 0:66fdbf2cc578 230 */
pangsk 0:66fdbf2cc578 231 /*
pangsk 0:66fdbf2cc578 232 if (rf12_crc == 0 && crypter != 0)
pangsk 0:66fdbf2cc578 233 crypter(0);
pangsk 0:66fdbf2cc578 234 else
pangsk 0:66fdbf2cc578 235 rf12_seq = -1;
pangsk 0:66fdbf2cc578 236 */
pangsk 0:66fdbf2cc578 237 return 1; // it's a broadcast packet or it's addressed to this node
pangsk 0:66fdbf2cc578 238
pangsk 0:66fdbf2cc578 239 }
pangsk 0:66fdbf2cc578 240 }
pangsk 0:66fdbf2cc578 241 if (rxstate == TXIDLE)
pangsk 0:66fdbf2cc578 242 rf12_recvStart();
pangsk 0:66fdbf2cc578 243 return 0;
pangsk 0:66fdbf2cc578 244 }
pangsk 0:66fdbf2cc578 245
pangsk 0:66fdbf2cc578 246 uint8_t RF12B::rf12_byte(uint8_t out)
pangsk 0:66fdbf2cc578 247 {
pangsk 0:66fdbf2cc578 248 unsigned char recv = spi.write(out);
pangsk 0:66fdbf2cc578 249
pangsk 0:66fdbf2cc578 250 return recv;
pangsk 0:66fdbf2cc578 251 }
pangsk 0:66fdbf2cc578 252
pangsk 0:66fdbf2cc578 253 uint16_t RF12B::_crc16_update(uint16_t crc, uint8_t data) {
pangsk 0:66fdbf2cc578 254 int i;
pangsk 0:66fdbf2cc578 255
pangsk 0:66fdbf2cc578 256 crc ^= data;
pangsk 0:66fdbf2cc578 257 for (i = 0; i < 8; ++i)
pangsk 0:66fdbf2cc578 258 {
pangsk 0:66fdbf2cc578 259 if (crc & 1)
pangsk 0:66fdbf2cc578 260 crc = (crc >> 1) ^ 0xA001;
pangsk 0:66fdbf2cc578 261 else
pangsk 0:66fdbf2cc578 262 crc = (crc >> 1);
pangsk 0:66fdbf2cc578 263 }
pangsk 0:66fdbf2cc578 264
pangsk 0:66fdbf2cc578 265 return crc;
pangsk 0:66fdbf2cc578 266 }
pangsk 0:66fdbf2cc578 267
pangsk 0:66fdbf2cc578 268
pangsk 0:66fdbf2cc578 269
pangsk 0:66fdbf2cc578 270
pangsk 0:66fdbf2cc578 271
pangsk 0:66fdbf2cc578 272
pangsk 0:66fdbf2cc578 273
pangsk 0:66fdbf2cc578 274
pangsk 0:66fdbf2cc578 275
pangsk 0:66fdbf2cc578 276