Hugo Rodrigues / RFM12B

Dependents:   _EXAMPLE_RFM12B

Fork of RF12B by Sukkin Pang

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 }