Sukkin Pang / Mbed 2 deprecated rf12b_pachube

Dependencies:   EthernetNetIf mbed

Committer:
pangsk
Date:
Mon Jan 02 20:03:01 2012 +0000
Revision:
0:7f301f08b68f
Initial release.

Who changed what in which revision?

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