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:
hajesusrodrigues
Date:
Thu May 30 22:11:42 2013 +0000
Revision:
7:19d9da22271a
Parent:
6:52322349ee10
Child:
8:7d282360721a
Code Format

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hajesusrodrigues 6:52322349ee10 1 /*
hajesusrodrigues 6:52322349ee10 2 RFM12B Library. Based on work done by JeeLabs.org ported to mBed by SK Pang.
hajesusrodrigues 6:52322349ee10 3 http://jeelabs.net/projects/cafe/wiki/RF12
pangsk 0:66fdbf2cc578 4
hajesusrodrigues 6:52322349ee10 5 http://opensource.org/licenses/mit-license.php
pangsk 0:66fdbf2cc578 6
hajesusrodrigues 6:52322349ee10 7 Jan 2012 skpang.co.uk
pangsk 0:66fdbf2cc578 8
hajesusrodrigues 6:52322349ee10 9 Modified by Hugo Rodrigues (May 2013)
pangsk 0:66fdbf2cc578 10
hajesusrodrigues 6:52322349ee10 11 Permission is hereby granted, free of charge, to any person obtaining a copy
hajesusrodrigues 6:52322349ee10 12 of this software and associated documentation files (the "Software"), to deal
hajesusrodrigues 6:52322349ee10 13 in the Software without restriction, including without limitation the rights
hajesusrodrigues 6:52322349ee10 14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
hajesusrodrigues 6:52322349ee10 15 copies of the Software, and to permit persons to whom the Software is
hajesusrodrigues 6:52322349ee10 16 furnished to do so, subject to the following conditions:
pangsk 0:66fdbf2cc578 17
hajesusrodrigues 6:52322349ee10 18 The above copyright notice and this permission notice shall be included in
hajesusrodrigues 6:52322349ee10 19 all copies or substantial portions of the Software.
pangsk 0:66fdbf2cc578 20
hajesusrodrigues 6:52322349ee10 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
hajesusrodrigues 6:52322349ee10 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
hajesusrodrigues 6:52322349ee10 23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
hajesusrodrigues 6:52322349ee10 24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
hajesusrodrigues 6:52322349ee10 25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
hajesusrodrigues 6:52322349ee10 26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
hajesusrodrigues 6:52322349ee10 27 THE SOFTWARE.
hajesusrodrigues 6:52322349ee10 28 */
pangsk 0:66fdbf2cc578 29
hajesusrodrigues 6:52322349ee10 30 #include "RFM12B.h"
hajesusrodrigues 6:52322349ee10 31
hajesusrodrigues 6:52322349ee10 32 RFM12B::RFM12B(PinName _SDI, PinName _SDO, PinName _SCK, PinName _NCS, PinName _NIRQ, PinName _NIRQ_LED) :
hajesusrodrigues 7:19d9da22271a 33 spi(_SDI, _SDO, _SCK), NCS(_NCS), NIRQ(_NIRQ), NIRQ_in(_NIRQ), NIRQ_LED(_NIRQ_LED)
hajesusrodrigues 7:19d9da22271a 34 {
pangsk 0:66fdbf2cc578 35
hajesusrodrigues 6:52322349ee10 36 useEncryption = false;
hajesusrodrigues 6:52322349ee10 37
hajesusrodrigues 6:52322349ee10 38 /* SPI frequency, 8 bit word length, polarity and phase */
hajesusrodrigues 6:52322349ee10 39 spi.format(8, 0);
pangsk 0:66fdbf2cc578 40 spi.frequency(2000000);
pangsk 0:66fdbf2cc578 41
pangsk 0:66fdbf2cc578 42 /* Set ~CS high */
pangsk 0:66fdbf2cc578 43 NCS = 1;
pangsk 0:66fdbf2cc578 44
pangsk 0:66fdbf2cc578 45 /* Setup interrupt to happen on falling edge of NIRQ */
hajesusrodrigues 6:52322349ee10 46 NIRQ.fall(this, &RFM12B::InterruptHandler);
pangsk 0:66fdbf2cc578 47 }
pangsk 0:66fdbf2cc578 48
hajesusrodrigues 7:19d9da22271a 49 int RFM12B::writeCmd(int cmd)
hajesusrodrigues 7:19d9da22271a 50 {
pangsk 0:66fdbf2cc578 51 NCS = 0;
hajesusrodrigues 6:52322349ee10 52 int recv = spi.write(cmd >> 8);
pangsk 0:66fdbf2cc578 53 recv = spi.write(cmd);
pangsk 0:66fdbf2cc578 54 NCS = 1;
pangsk 0:66fdbf2cc578 55 return recv;
pangsk 0:66fdbf2cc578 56 }
pangsk 0:66fdbf2cc578 57
hajesusrodrigues 7:19d9da22271a 58 uint16_t RFM12B::crc16_update(uint16_t crc, uint8_t data)
hajesusrodrigues 7:19d9da22271a 59 {
pangsk 0:66fdbf2cc578 60 int i;
pangsk 0:66fdbf2cc578 61
pangsk 0:66fdbf2cc578 62 crc ^= data;
hajesusrodrigues 6:52322349ee10 63 for (i = 0; i < 8; ++i) {
pangsk 0:66fdbf2cc578 64 if (crc & 1)
hajesusrodrigues 6:52322349ee10 65 crc = (crc >> 1) ^ 0xA001;
pangsk 0:66fdbf2cc578 66 else
hajesusrodrigues 6:52322349ee10 67 crc = (crc >> 1);
pangsk 0:66fdbf2cc578 68 }
pangsk 0:66fdbf2cc578 69
pangsk 0:66fdbf2cc578 70 return crc;
pangsk 0:66fdbf2cc578 71 }
pangsk 0:66fdbf2cc578 72
hajesusrodrigues 7:19d9da22271a 73 uint8_t RFM12B::byte(uint8_t out)
hajesusrodrigues 7:19d9da22271a 74 {
hajesusrodrigues 6:52322349ee10 75 return spi.write(out);
hajesusrodrigues 6:52322349ee10 76 }
pangsk 0:66fdbf2cc578 77
hajesusrodrigues 7:19d9da22271a 78 uint16_t RFM12B::xfer(uint16_t cmd)
hajesusrodrigues 7:19d9da22271a 79 {
hajesusrodrigues 6:52322349ee10 80 NCS = 0;
hajesusrodrigues 6:52322349ee10 81 uint16_t reply = byte(cmd >> 8) << 8;
hajesusrodrigues 6:52322349ee10 82 reply |= byte(cmd);
hajesusrodrigues 6:52322349ee10 83 NCS = 1;
hajesusrodrigues 6:52322349ee10 84 return reply;
hajesusrodrigues 6:52322349ee10 85 }
hajesusrodrigues 6:52322349ee10 86
hajesusrodrigues 6:52322349ee10 87 // Call this once with params:
hajesusrodrigues 6:52322349ee10 88 // - node ID (0-31)
hajesusrodrigues 6:52322349ee10 89 // - frequency band (RF12_433MHZ, RF12_868MHZ, RF12_915MHZ)
hajesusrodrigues 6:52322349ee10 90 // - networkid [optional - default = 170] (0-255 for RF12B, only 212 allowed for RF12)
hajesusrodrigues 6:52322349ee10 91 // - txPower [optional - default = 0 (max)] (7 is min value)
hajesusrodrigues 6:52322349ee10 92 // - airKbps [optional - default = 38.31Kbps]
hajesusrodrigues 7:19d9da22271a 93 void RFM12B::Initialize(uint8_t nodeid, uint8_t freqBand, uint8_t groupid, uint8_t txPower, uint8_t airKbps)
hajesusrodrigues 7:19d9da22271a 94 {
hajesusrodrigues 6:52322349ee10 95
hajesusrodrigues 6:52322349ee10 96 nodeID = nodeid;
hajesusrodrigues 6:52322349ee10 97 networkID = groupid;
hajesusrodrigues 6:52322349ee10 98 rf12_grp= groupid;
hajesusrodrigues 6:52322349ee10 99
hajesusrodrigues 6:52322349ee10 100 writeCmd(0x0000); // initial SPI transfer added to avoid power-up problem
hajesusrodrigues 6:52322349ee10 101 writeCmd(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd
hajesusrodrigues 6:52322349ee10 102
hajesusrodrigues 6:52322349ee10 103 // wait until RFM12B is out of power-up reset, this takes several *seconds*
hajesusrodrigues 6:52322349ee10 104 writeCmd(RF_TXREG_WRITE); // in case we're still in OOK mode
hajesusrodrigues 6:52322349ee10 105
hajesusrodrigues 6:52322349ee10 106 while (NIRQ == 0)
hajesusrodrigues 6:52322349ee10 107 writeCmd(0x0000);
hajesusrodrigues 6:52322349ee10 108
hajesusrodrigues 6:52322349ee10 109 writeCmd(0x80C7 | (freqBand << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF
hajesusrodrigues 6:52322349ee10 110 writeCmd(0xA640); // Frequency is exactly 434/868/915MHz (whatever freqBand is)
hajesusrodrigues 6:52322349ee10 111 writeCmd(0xC600 + airKbps); //Air transmission baud rate: 0x08= ~38.31Kbps
hajesusrodrigues 6:52322349ee10 112 writeCmd(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm
hajesusrodrigues 6:52322349ee10 113 writeCmd(0xC2AC); // AL,!ml,DIG,DQD4
hajesusrodrigues 6:52322349ee10 114 if (networkID != 0) {
hajesusrodrigues 6:52322349ee10 115 writeCmd(0xCA83); // FIFO8,2-SYNC,!ff,DR
hajesusrodrigues 6:52322349ee10 116 writeCmd(0xCE00 | networkID); // SYNC=2DXX
hajesusrodrigues 6:52322349ee10 117 } else {
hajesusrodrigues 6:52322349ee10 118 writeCmd(0xCA8B); // FIFO8,1-SYNC,!ff,DR
hajesusrodrigues 6:52322349ee10 119 writeCmd(0xCE2D); // SYNC=2D
hajesusrodrigues 6:52322349ee10 120 }
hajesusrodrigues 6:52322349ee10 121
hajesusrodrigues 6:52322349ee10 122 writeCmd(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN
hajesusrodrigues 6:52322349ee10 123 writeCmd(0x9850 | (txPower > 7 ? 7 : txPower)); // !mp,90kHz,MAX OUT
hajesusrodrigues 6:52322349ee10 124 writeCmd(0xCC77); // OB1, OB0, LPX, ddy, DDIT, BW0
hajesusrodrigues 6:52322349ee10 125 writeCmd(0xE000); // NOT USE
hajesusrodrigues 6:52322349ee10 126 writeCmd(0xC800); // NOT USE
hajesusrodrigues 6:52322349ee10 127 writeCmd(0xC049); // 1.66MHz,3.1V
hajesusrodrigues 6:52322349ee10 128
hajesusrodrigues 6:52322349ee10 129 rxstate = TXIDLE;
hajesusrodrigues 6:52322349ee10 130 }
hajesusrodrigues 6:52322349ee10 131
hajesusrodrigues 7:19d9da22271a 132 void RFM12B::InterruptHandler()
hajesusrodrigues 7:19d9da22271a 133 {
hajesusrodrigues 6:52322349ee10 134
hajesusrodrigues 6:52322349ee10 135 NIRQ_LED = 1;
hajesusrodrigues 6:52322349ee10 136
hajesusrodrigues 6:52322349ee10 137 // a transfer of 2x 16 bits @ 2 MHz over SPI takes 2x 8 us inside this ISR
hajesusrodrigues 6:52322349ee10 138 writeCmd(0x0000);
hajesusrodrigues 6:52322349ee10 139
hajesusrodrigues 6:52322349ee10 140 if (rxstate == TXRECV) {
hajesusrodrigues 6:52322349ee10 141 uint8_t in = xfer(RF_RX_FIFO_READ);
hajesusrodrigues 6:52322349ee10 142
hajesusrodrigues 6:52322349ee10 143 if (rxfill == 0 && networkID != 0)
hajesusrodrigues 6:52322349ee10 144 rf12_buf[rxfill++] = networkID;
hajesusrodrigues 6:52322349ee10 145
hajesusrodrigues 6:52322349ee10 146 rf12_buf[rxfill++] = in;
hajesusrodrigues 6:52322349ee10 147 rf12_crc = crc16_update(rf12_crc, in);
pangsk 0:66fdbf2cc578 148
hajesusrodrigues 6:52322349ee10 149 if (rxfill >= rf12_len+ 6 || rxfill >= RF_MAX)
hajesusrodrigues 6:52322349ee10 150 xfer(RF_IDLE_MODE);
hajesusrodrigues 6:52322349ee10 151 } else {
hajesusrodrigues 6:52322349ee10 152 uint8_t out;
pangsk 0:66fdbf2cc578 153
hajesusrodrigues 6:52322349ee10 154 if (rxstate < 0) {
hajesusrodrigues 6:52322349ee10 155 uint8_t pos = 4 + rf12_len + rxstate++;
hajesusrodrigues 6:52322349ee10 156 out = rf12_buf[pos];
hajesusrodrigues 6:52322349ee10 157 rf12_crc = crc16_update(rf12_crc, out);
hajesusrodrigues 6:52322349ee10 158 } else {
hajesusrodrigues 6:52322349ee10 159 switch (rxstate++) {
hajesusrodrigues 7:19d9da22271a 160 case TXSYN1:
hajesusrodrigues 7:19d9da22271a 161 out = 0x2D;
hajesusrodrigues 7:19d9da22271a 162 break;
hajesusrodrigues 7:19d9da22271a 163 case TXSYN2:
hajesusrodrigues 7:19d9da22271a 164 out = rf12_grp;
hajesusrodrigues 7:19d9da22271a 165 rxstate = - (3 + rf12_len);
hajesusrodrigues 7:19d9da22271a 166 break;
hajesusrodrigues 7:19d9da22271a 167 case TXCRC1:
hajesusrodrigues 7:19d9da22271a 168 out = rf12_crc;
hajesusrodrigues 7:19d9da22271a 169 break;
hajesusrodrigues 7:19d9da22271a 170 case TXCRC2:
hajesusrodrigues 7:19d9da22271a 171 out = rf12_crc >> 8;
hajesusrodrigues 7:19d9da22271a 172 break;
hajesusrodrigues 7:19d9da22271a 173 case TXDONE:
hajesusrodrigues 7:19d9da22271a 174 xfer(RF_IDLE_MODE); // fall through
hajesusrodrigues 7:19d9da22271a 175 out = 0xAA;
hajesusrodrigues 7:19d9da22271a 176 break;
hajesusrodrigues 7:19d9da22271a 177 default:
hajesusrodrigues 7:19d9da22271a 178 out = 0xAA;
hajesusrodrigues 6:52322349ee10 179 }
hajesusrodrigues 6:52322349ee10 180 }
hajesusrodrigues 6:52322349ee10 181 xfer(RF_TXREG_WRITE + out);
hajesusrodrigues 6:52322349ee10 182 }
hajesusrodrigues 6:52322349ee10 183 NIRQ_LED = 0;
hajesusrodrigues 6:52322349ee10 184 }
pangsk 0:66fdbf2cc578 185
hajesusrodrigues 7:19d9da22271a 186 void RFM12B::ReceiveStart(void)
hajesusrodrigues 7:19d9da22271a 187 {
hajesusrodrigues 6:52322349ee10 188 rxfill = rf12_len= 0;
hajesusrodrigues 6:52322349ee10 189 rf12_crc = ~0;
hajesusrodrigues 6:52322349ee10 190
hajesusrodrigues 6:52322349ee10 191 if (networkID != 0)
hajesusrodrigues 6:52322349ee10 192 rf12_crc = crc16_update(~0, networkID);
hajesusrodrigues 6:52322349ee10 193
hajesusrodrigues 6:52322349ee10 194 rxstate = TXRECV;
hajesusrodrigues 6:52322349ee10 195 xfer(RF_RECEIVER_ON);
hajesusrodrigues 6:52322349ee10 196 }
hajesusrodrigues 6:52322349ee10 197
hajesusrodrigues 7:19d9da22271a 198 bool RFM12B::ReceiveComplete(void)
hajesusrodrigues 7:19d9da22271a 199 {
hajesusrodrigues 6:52322349ee10 200 if (rxstate == TXRECV && (rxfill >= rf12_len+ 6 || rxfill >= RF_MAX)) {
hajesusrodrigues 6:52322349ee10 201 rxstate = TXIDLE;
hajesusrodrigues 6:52322349ee10 202
hajesusrodrigues 6:52322349ee10 203 if (rf12_len > RF12_MAXDATA) {
hajesusrodrigues 6:52322349ee10 204 rf12_crc = 1; // force bad crc if packet length is invalid
hajesusrodrigues 6:52322349ee10 205 }
hajesusrodrigues 6:52322349ee10 206 if (RF12_DESTID == 0 || RF12_DESTID == nodeID) {
hajesusrodrigues 6:52322349ee10 207
hajesusrodrigues 6:52322349ee10 208 if (rf12_crc == 0 && useEncryption)
hajesusrodrigues 6:52322349ee10 209 Encryption(false);
hajesusrodrigues 6:52322349ee10 210 else
hajesusrodrigues 6:52322349ee10 211 rf12_seq = -1;
hajesusrodrigues 6:52322349ee10 212
hajesusrodrigues 6:52322349ee10 213 #ifdef DEBUG
hajesusrodrigues 6:52322349ee10 214 printf("\nReceived message from [%d]; crc:%x, len: %d, message: ", RF12_SOURCEID, rf12_crc, rf12_len);
hajesusrodrigues 6:52322349ee10 215 for (int i=0; i<rf12_len; i++) {
hajesusrodrigues 6:52322349ee10 216 printf("%c", rf12_data[i]);
hajesusrodrigues 6:52322349ee10 217 }
hajesusrodrigues 6:52322349ee10 218 printf("\n");
hajesusrodrigues 6:52322349ee10 219 #endif
hajesusrodrigues 6:52322349ee10 220
hajesusrodrigues 6:52322349ee10 221 return true; // it's a broadcast packet or it's addressed to this node
hajesusrodrigues 6:52322349ee10 222 }
hajesusrodrigues 6:52322349ee10 223 }
hajesusrodrigues 6:52322349ee10 224 if (rxstate == TXIDLE)
hajesusrodrigues 6:52322349ee10 225 ReceiveStart();
hajesusrodrigues 6:52322349ee10 226
hajesusrodrigues 6:52322349ee10 227 return false;
hajesusrodrigues 6:52322349ee10 228 }
pangsk 0:66fdbf2cc578 229
hajesusrodrigues 7:19d9da22271a 230 bool RFM12B::CanSend()
hajesusrodrigues 7:19d9da22271a 231 {
hajesusrodrigues 6:52322349ee10 232 // no need to test with interrupts disabled: state TXRECV is only reached
hajesusrodrigues 6:52322349ee10 233 // outside of ISR and we don't care if rxfill jumps from 0 to 1 here
hajesusrodrigues 6:52322349ee10 234 if (rxstate == TXRECV && rxfill == 0 && (byte(0x00) & (RF_RSSI_BIT >> 8)) == 0) {
hajesusrodrigues 6:52322349ee10 235 xfer(RF_IDLE_MODE); // stop receiver
hajesusrodrigues 6:52322349ee10 236 rxstate = TXIDLE;
hajesusrodrigues 6:52322349ee10 237 return true;
hajesusrodrigues 6:52322349ee10 238 }
hajesusrodrigues 6:52322349ee10 239 return false;
hajesusrodrigues 6:52322349ee10 240 }
pangsk 0:66fdbf2cc578 241
hajesusrodrigues 7:19d9da22271a 242 void RFM12B::SendStart(uint8_t toNodeID, bool requestACK, bool sendACK)
hajesusrodrigues 7:19d9da22271a 243 {
hajesusrodrigues 6:52322349ee10 244
hajesusrodrigues 6:52322349ee10 245 rf12_hdr1= toNodeID | (sendACK ? RF12_HDR_ACKCTLMASK : 0);
hajesusrodrigues 6:52322349ee10 246 rf12_hdr2= nodeID | (requestACK ? RF12_HDR_ACKCTLMASK : 0);
hajesusrodrigues 6:52322349ee10 247
hajesusrodrigues 6:52322349ee10 248 #ifdef DEBUG
hajesusrodrigues 6:52322349ee10 249 printf("SendStart to Node [%d], from Node [%d] \n", toNodeID, nodeID);
hajesusrodrigues 6:52322349ee10 250 #endif
hajesusrodrigues 6:52322349ee10 251
hajesusrodrigues 6:52322349ee10 252 if (useEncryption)
hajesusrodrigues 6:52322349ee10 253 Encryption(true);
hajesusrodrigues 6:52322349ee10 254
hajesusrodrigues 6:52322349ee10 255 rf12_crc = ~0;
hajesusrodrigues 6:52322349ee10 256 rf12_crc = crc16_update(rf12_crc, rf12_grp);
hajesusrodrigues 6:52322349ee10 257 rxstate = TXPRE1;
hajesusrodrigues 6:52322349ee10 258
hajesusrodrigues 6:52322349ee10 259 xfer(RF_XMITTER_ON); // bytes will be fed via interrupts
hajesusrodrigues 6:52322349ee10 260 }
hajesusrodrigues 6:52322349ee10 261
hajesusrodrigues 7:19d9da22271a 262 void RFM12B::SendStart(uint8_t toNodeID, const void* sendBuf, uint8_t sendLen, bool requestACK, bool sendACK)
hajesusrodrigues 7:19d9da22271a 263 {
hajesusrodrigues 7:19d9da22271a 264
hajesusrodrigues 6:52322349ee10 265 rf12_len = sendLen;
hajesusrodrigues 6:52322349ee10 266 memcpy((void*) rf12_data, sendBuf, sendLen);
hajesusrodrigues 7:19d9da22271a 267
hajesusrodrigues 6:52322349ee10 268 #ifdef DEBUG
hajesusrodrigues 7:19d9da22271a 269 printf("\nSending message from [%d]; crc:%x, len: %d, message: ", nodeID, rf12_crc, rf12_len);
hajesusrodrigues 7:19d9da22271a 270 for (int i=0; i<rf12_len; i++) {
hajesusrodrigues 7:19d9da22271a 271 printf("%c", rf12_data[i]);
hajesusrodrigues 7:19d9da22271a 272 }
hajesusrodrigues 6:52322349ee10 273 #endif
hajesusrodrigues 7:19d9da22271a 274
hajesusrodrigues 6:52322349ee10 275
hajesusrodrigues 6:52322349ee10 276 SendStart(toNodeID, requestACK, sendACK);
hajesusrodrigues 6:52322349ee10 277 }
hajesusrodrigues 6:52322349ee10 278
hajesusrodrigues 6:52322349ee10 279 /// Should be called immediately after reception in case sender wants ACK
hajesusrodrigues 7:19d9da22271a 280 void RFM12B::SendACK(const void* sendBuf, uint8_t sendLen)
hajesusrodrigues 7:19d9da22271a 281 {
hajesusrodrigues 6:52322349ee10 282 while (!CanSend())
hajesusrodrigues 6:52322349ee10 283 ReceiveComplete();
hajesusrodrigues 6:52322349ee10 284 SendStart(RF12_SOURCEID, sendBuf, (sendLen > 0) ? sendLen: strlen((const char*)sendBuf), false, true);
hajesusrodrigues 6:52322349ee10 285 }
hajesusrodrigues 6:52322349ee10 286
hajesusrodrigues 7:19d9da22271a 287 void RFM12B::Send(uint8_t toNodeID, const void* sendBuf, uint8_t sendLen, bool requestACK)
hajesusrodrigues 7:19d9da22271a 288 {
hajesusrodrigues 6:52322349ee10 289 while (!CanSend())
hajesusrodrigues 6:52322349ee10 290 ReceiveComplete();
hajesusrodrigues 6:52322349ee10 291 SendStart(toNodeID, sendBuf, (sendLen > 0) ? sendLen: strlen((const char*)sendBuf) , requestACK, false);
hajesusrodrigues 6:52322349ee10 292 }
hajesusrodrigues 6:52322349ee10 293
hajesusrodrigues 7:19d9da22271a 294 uint8_t RFM12B::GetSender(void)
hajesusrodrigues 7:19d9da22271a 295 {
hajesusrodrigues 6:52322349ee10 296 return RF12_SOURCEID;
hajesusrodrigues 6:52322349ee10 297 }
hajesusrodrigues 6:52322349ee10 298
hajesusrodrigues 7:19d9da22271a 299 volatile uint8_t * RFM12B::GetData(void)
hajesusrodrigues 7:19d9da22271a 300 {
hajesusrodrigues 6:52322349ee10 301
hajesusrodrigues 6:52322349ee10 302 return (uint8_t*) rf12_data;
hajesusrodrigues 6:52322349ee10 303 }
hajesusrodrigues 6:52322349ee10 304
hajesusrodrigues 7:19d9da22271a 305 uint8_t RFM12B::GetDataLen(void)
hajesusrodrigues 7:19d9da22271a 306 {
hajesusrodrigues 6:52322349ee10 307 return rf12_len;
hajesusrodrigues 6:52322349ee10 308 }
hajesusrodrigues 6:52322349ee10 309
hajesusrodrigues 7:19d9da22271a 310 bool RFM12B::ACKRequested()
hajesusrodrigues 7:19d9da22271a 311 {
hajesusrodrigues 6:52322349ee10 312 return RF12_WANTS_ACK;
hajesusrodrigues 6:52322349ee10 313 }
pangsk 0:66fdbf2cc578 314
hajesusrodrigues 6:52322349ee10 315 /// Should be polled immediately after sending a packet with ACK request
hajesusrodrigues 7:19d9da22271a 316 bool RFM12B::ACKReceived(uint8_t fromNodeID)
hajesusrodrigues 7:19d9da22271a 317 {
hajesusrodrigues 6:52322349ee10 318 if (ReceiveComplete())
hajesusrodrigues 6:52322349ee10 319 return CRC_Pass() && RF12_DESTID == nodeID && (RF12_SOURCEID == fromNodeID || fromNodeID == 0) && (rf12_hdr1&RF12_HDR_ACKCTLMASK) &&
hajesusrodrigues 7:19d9da22271a 320 !(rf12_hdr2 & RF12_HDR_ACKCTLMASK);
hajesusrodrigues 6:52322349ee10 321 return false;
hajesusrodrigues 6:52322349ee10 322 }
pangsk 0:66fdbf2cc578 323
hajesusrodrigues 7:19d9da22271a 324 bool RFM12B::CRC_Pass(void)
hajesusrodrigues 7:19d9da22271a 325 {
hajesusrodrigues 6:52322349ee10 326 return (rf12_crc == 0);
hajesusrodrigues 6:52322349ee10 327 }
pangsk 0:66fdbf2cc578 328
hajesusrodrigues 6:52322349ee10 329 // XXTEA by David Wheeler, adapted from http://en.wikipedia.org/wiki/XXTEA
hajesusrodrigues 6:52322349ee10 330 #define DELTA 0x9E3779B9
hajesusrodrigues 6:52322349ee10 331 #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (cryptKey[(uint8_t)((p&3)^e)] ^ z)))
hajesusrodrigues 7:19d9da22271a 332 void RFM12B::Encryption(bool encrypt)
hajesusrodrigues 7:19d9da22271a 333 {
hajesusrodrigues 6:52322349ee10 334
hajesusrodrigues 6:52322349ee10 335 uint32_t y, z, sum, *v = (uint32_t*) rf12_data;
hajesusrodrigues 6:52322349ee10 336 uint8_t p, e, rounds = 6;
hajesusrodrigues 6:52322349ee10 337
hajesusrodrigues 6:52322349ee10 338 if (encrypt) {
hajesusrodrigues 6:52322349ee10 339 // pad with 1..4-byte sequence number
hajesusrodrigues 6:52322349ee10 340 *(uint32_t*) (rf12_data + rf12_len) = ++seqNum;
hajesusrodrigues 6:52322349ee10 341 uint8_t pad = 3 - (rf12_len & 3);
hajesusrodrigues 6:52322349ee10 342 rf12_len += pad;
hajesusrodrigues 6:52322349ee10 343 rf12_data[rf12_len] &= 0x3F;
hajesusrodrigues 6:52322349ee10 344 rf12_data[rf12_len] |= pad << 6;
hajesusrodrigues 6:52322349ee10 345 ++rf12_len;
hajesusrodrigues 6:52322349ee10 346 // actual encoding
hajesusrodrigues 6:52322349ee10 347 char n = rf12_len / 4;
hajesusrodrigues 6:52322349ee10 348 if (n > 1) {
hajesusrodrigues 6:52322349ee10 349 sum = 0;
hajesusrodrigues 6:52322349ee10 350 z = v[n-1];
hajesusrodrigues 6:52322349ee10 351 do {
hajesusrodrigues 6:52322349ee10 352 sum += DELTA;
hajesusrodrigues 6:52322349ee10 353 e = (sum >> 2) & 3;
hajesusrodrigues 6:52322349ee10 354 for (p=0; p<n-1; p++)
hajesusrodrigues 6:52322349ee10 355 y = v[p+1], z = v[p] += MX;
hajesusrodrigues 6:52322349ee10 356 y = v[0];
hajesusrodrigues 6:52322349ee10 357 z = v[n-1] += MX;
hajesusrodrigues 7:19d9da22271a 358 } while (--rounds);
hajesusrodrigues 6:52322349ee10 359 }
hajesusrodrigues 6:52322349ee10 360 } else if (rf12_crc == 0) {
hajesusrodrigues 6:52322349ee10 361 // actual decoding
hajesusrodrigues 6:52322349ee10 362 char n = rf12_len / 4;
hajesusrodrigues 6:52322349ee10 363 if (n > 1) {
hajesusrodrigues 6:52322349ee10 364 sum = rounds*DELTA;
hajesusrodrigues 6:52322349ee10 365 y = v[0];
hajesusrodrigues 6:52322349ee10 366 do {
hajesusrodrigues 6:52322349ee10 367 e = (sum >> 2) & 3;
hajesusrodrigues 6:52322349ee10 368 for (p=n-1; p>0; p--)
hajesusrodrigues 6:52322349ee10 369 z = v[p-1], y = v[p] -= MX;
hajesusrodrigues 6:52322349ee10 370 z = v[n-1];
hajesusrodrigues 6:52322349ee10 371 y = v[0] -= MX;
hajesusrodrigues 7:19d9da22271a 372 } while ((sum -= DELTA) != 0);
hajesusrodrigues 6:52322349ee10 373 }
hajesusrodrigues 6:52322349ee10 374 // strip sequence number from the end again
hajesusrodrigues 6:52322349ee10 375 if (n > 0) {
hajesusrodrigues 6:52322349ee10 376 uint8_t pad = rf12_data[--rf12_len] >> 6;
hajesusrodrigues 6:52322349ee10 377 rf12_seq = rf12_data[rf12_len] & 0x3F;
hajesusrodrigues 6:52322349ee10 378 while (pad-- > 0)
hajesusrodrigues 6:52322349ee10 379 rf12_seq = (rf12_seq << 8) | rf12_data[--rf12_len];
hajesusrodrigues 6:52322349ee10 380 }
hajesusrodrigues 6:52322349ee10 381 }
hajesusrodrigues 6:52322349ee10 382
hajesusrodrigues 6:52322349ee10 383 }
hajesusrodrigues 6:52322349ee10 384
hajesusrodrigues 7:19d9da22271a 385 void RFM12B::SetEncryptionKey(const uint8_t* key)
hajesusrodrigues 7:19d9da22271a 386 {
hajesusrodrigues 6:52322349ee10 387 if (key != 0) {
hajesusrodrigues 6:52322349ee10 388 for (uint8_t i = 0; i < sizeof cryptKey; ++i)
hajesusrodrigues 6:52322349ee10 389 ((uint8_t*) cryptKey)[i] = key[i];
hajesusrodrigues 6:52322349ee10 390
hajesusrodrigues 6:52322349ee10 391 useEncryption = true;
hajesusrodrigues 6:52322349ee10 392 } else
hajesusrodrigues 6:52322349ee10 393 useEncryption = false;
hajesusrodrigues 6:52322349ee10 394 }