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:
Tue Feb 28 10:40:30 2012 +0000
Revision:
3:e926e54424cb
Parent:
2:cfeb4c9cdbe3
Child:
5:12d8175359f2
Remove debugs

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