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 Mar 13 10:21:46 2012 +0000
Revision:
5:12d8175359f2
Parent:
3:e926e54424cb
Added ACK macro for mbed.

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 5:12d8175359f2 212 uint8_t RF12B::get_hdr(void)
pangsk 5:12d8175359f2 213 {
pangsk 5:12d8175359f2 214 return rf12_hdr;
pangsk 5:12d8175359f2 215
pangsk 5:12d8175359f2 216 }
pangsk 0:66fdbf2cc578 217
pangsk 0:66fdbf2cc578 218
pangsk 0:66fdbf2cc578 219 uint8_t RF12B::rf12_recvDone (void) {
pangsk 0:66fdbf2cc578 220
pangsk 1:27a1606deace 221 if (rxstate == TXRECV && (rxfill >= rf12_len + 5 || rxfill >= RF_MAX)) {
pangsk 0:66fdbf2cc578 222 rxstate = TXIDLE;
pangsk 0:66fdbf2cc578 223
pangsk 0:66fdbf2cc578 224 if (rf12_len > RF12_MAXDATA)
pangsk 0:66fdbf2cc578 225 rf12_crc = 1; // force bad crc if packet length is invalid
pangsk 0:66fdbf2cc578 226 if (!(rf12_hdr & RF12_HDR_DST) || (nodeid & NODE_ID) == 31 ||
pangsk 0:66fdbf2cc578 227 (rf12_hdr & RF12_HDR_MASK) == (nodeid & NODE_ID)) {
pangsk 0:66fdbf2cc578 228 /*
pangsk 0:66fdbf2cc578 229 for(i=0;i<rf12_len+6;i++)
pangsk 0:66fdbf2cc578 230 {
pangsk 0:66fdbf2cc578 231 printf("%X ",rf12_buf[i]);
pangsk 0:66fdbf2cc578 232 }
pangsk 0:66fdbf2cc578 233 printf(" crc:%x",rf12_crc);
pangsk 0:66fdbf2cc578 234 */
pangsk 0:66fdbf2cc578 235 /*
pangsk 0:66fdbf2cc578 236 if (rf12_crc == 0 && crypter != 0)
pangsk 0:66fdbf2cc578 237 crypter(0);
pangsk 0:66fdbf2cc578 238 else
pangsk 0:66fdbf2cc578 239 rf12_seq = -1;
pangsk 0:66fdbf2cc578 240 */
pangsk 0:66fdbf2cc578 241 return 1; // it's a broadcast packet or it's addressed to this node
pangsk 0:66fdbf2cc578 242
pangsk 0:66fdbf2cc578 243 }
pangsk 0:66fdbf2cc578 244 }
pangsk 0:66fdbf2cc578 245 if (rxstate == TXIDLE)
pangsk 0:66fdbf2cc578 246 rf12_recvStart();
pangsk 0:66fdbf2cc578 247 return 0;
pangsk 0:66fdbf2cc578 248 }
pangsk 0:66fdbf2cc578 249
pangsk 0:66fdbf2cc578 250 uint8_t RF12B::rf12_byte(uint8_t out)
pangsk 0:66fdbf2cc578 251 {
pangsk 0:66fdbf2cc578 252 unsigned char recv = spi.write(out);
pangsk 0:66fdbf2cc578 253
pangsk 0:66fdbf2cc578 254 return recv;
pangsk 0:66fdbf2cc578 255 }
pangsk 0:66fdbf2cc578 256
pangsk 0:66fdbf2cc578 257 uint16_t RF12B::_crc16_update(uint16_t crc, uint8_t data) {
pangsk 0:66fdbf2cc578 258 int i;
pangsk 0:66fdbf2cc578 259
pangsk 0:66fdbf2cc578 260 crc ^= data;
pangsk 0:66fdbf2cc578 261 for (i = 0; i < 8; ++i)
pangsk 0:66fdbf2cc578 262 {
pangsk 0:66fdbf2cc578 263 if (crc & 1)
pangsk 0:66fdbf2cc578 264 crc = (crc >> 1) ^ 0xA001;
pangsk 0:66fdbf2cc578 265 else
pangsk 0:66fdbf2cc578 266 crc = (crc >> 1);
pangsk 0:66fdbf2cc578 267 }
pangsk 0:66fdbf2cc578 268
pangsk 0:66fdbf2cc578 269 return crc;
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
pangsk 0:66fdbf2cc578 279
pangsk 0:66fdbf2cc578 280