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:05:50 2013 +0000
Revision:
6:52322349ee10
Parent:
RF12B.cpp@5:12d8175359f2
Child:
7:19d9da22271a
Moteino Comunication Protocol Implementation

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