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