SHOW:
|
|
- or go back to the newest paste.
| 1 | - | if defined(__AVR_ATmega32U4__) //Arduino Leonardo |
| 1 | + | /// @file |
| 2 | - | if (pin==10) cs_pin=6; // Dig10, PB6 |
| 2 | + | /// RFM12B driver implementation |
| 3 | - | if (pin==9) cs_pin=5; // Dig9, PB5 |
| 3 | + | // 2009-02-09 <[email protected]> http://opensource.org/licenses/mit-license.php |
| 4 | - | if (pin==8) cs_pin=4; // Dig8, PB4 |
| 4 | + | |
| 5 | #include "RF12.h" | |
| 6 | - | if (pin==10) cs_pin = 2; // Dig10, PB2 |
| 6 | + | #include <avr/io.h> |
| 7 | - | if (pin==9) cs_pin = 1; // Dig9, PB1 |
| 7 | + | #include <util/crc16.h> |
| 8 | - | if (pin==8) cs_pin = 0; // Dig8, PB0 |
| 8 | + | #include <avr/eeprom.h> |
| 9 | #include <avr/sleep.h> | |
| 10 | - | {
|
| 10 | + | #if ARDUINO >= 100 |
| 11 | - | cs_pin = 5; //PD5 |
| 11 | + | #include <Arduino.h> // Arduino 1.0 |
| 12 | - | #define SS_DDR DDRD |
| 12 | + | #else |
| 13 | - | #define SS_PORT PORTD |
| 13 | + | #include <WProgram.h> // Arduino 0022 |
| 14 | #endif | |
| 15 | ||
| 16 | // #define OPTIMIZE_SPI 1 // uncomment this to write to the RFM12B @ 8 Mhz | |
| 17 | ||
| 18 | // pin change interrupts are currently only supported on ATmega328's | |
| 19 | // #define PINCHG_IRQ 1 // uncomment this to use pin-change interrupts | |
| 20 | ||
| 21 | // maximum transmit / receive buffer: 3 header + data + 2 crc bytes | |
| 22 | #define RF_MAX (RF12_MAXDATA + 5) | |
| 23 | ||
| 24 | // pins used for the RFM12B interface - yes, there *is* logic in this madness: | |
| 25 | // | |
| 26 | // - leave RFM_IRQ set to the pin which corresponds with INT0, because the | |
| 27 | // current driver code will use attachInterrupt() to hook into that | |
| 28 | // - (new) you can now change RFM_IRQ, if you also enable PINCHG_IRQ - this | |
| 29 | // will switch to pin change interrupts instead of attach/detachInterrupt() | |
| 30 | // - use SS_DDR, SS_PORT, and SS_BIT to define the pin you will be using as | |
| 31 | // select pin for the RFM12B (you're free to set them to anything you like) | |
| 32 | // - please leave SPI_SS, SPI_MOSI, SPI_MISO, and SPI_SCK as is, i.e. pointing | |
| 33 | // to the hardware-supported SPI pins on the ATmega, *including* SPI_SS ! | |
| 34 | ||
| 35 | #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) | |
| 36 | ||
| 37 | #define RFM_IRQ 2 | |
| 38 | #define SS_DDR DDRB | |
| 39 | #define SS_PORT PORTB | |
| 40 | #define SS_BIT 0 | |
| 41 | ||
| 42 | #define SPI_SS 53 // PB0, pin 19 | |
| 43 | #define SPI_MOSI 51 // PB2, pin 21 | |
| 44 | #define SPI_MISO 50 // PB3, pin 22 | |
| 45 | #define SPI_SCK 52 // PB1, pin 20 | |
| 46 | ||
| 47 | #elif defined(__AVR_ATmega644P__) | |
| 48 | ||
| 49 | #define RFM_IRQ 10 | |
| 50 | #define SS_DDR DDRB | |
| 51 | #define SS_PORT PORTB | |
| 52 | #define SS_BIT 4 | |
| 53 | ||
| 54 | #define SPI_SS 4 | |
| 55 | #define SPI_MOSI 5 | |
| 56 | #define SPI_MISO 6 | |
| 57 | #define SPI_SCK 7 | |
| 58 | ||
| 59 | #elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny44__) | |
| 60 | ||
| 61 | #define RFM_IRQ 2 | |
| 62 | #define SS_DDR DDRB | |
| 63 | #define SS_PORT PORTB | |
| 64 | #define SS_BIT 1 | |
| 65 | ||
| 66 | #define SPI_SS 1 // PB1, pin 3 | |
| 67 | #define SPI_MISO 4 // PA6, pin 7 | |
| 68 | #define SPI_MOSI 5 // PA5, pin 8 | |
| 69 | #define SPI_SCK 6 // PA4, pin 9 | |
| 70 | ||
| 71 | #elif defined(__AVR_ATmega32U4__) //Arduino Leonardo | |
| 72 | ||
| 73 | #define RFM_IRQ 0 // PD0, INT0, Digital3 | |
| 74 | #define SS_DDR DDRB | |
| 75 | #define SS_PORT PORTB | |
| 76 | #define SS_BIT 6 // Dig10, PB6 | |
| 77 | ||
| 78 | #define SPI_SS 17 // PB0, pin 8, Digital17 | |
| 79 | #define SPI_MISO 14 // PB3, pin 11, Digital14 | |
| 80 | #define SPI_MOSI 16 // PB2, pin 10, Digital16 | |
| 81 | #define SPI_SCK 15 // PB1, pin 9, Digital15 | |
| 82 | ||
| 83 | #else | |
| 84 | ||
| 85 | // ATmega168, ATmega328, etc. | |
| 86 | #define RFM_IRQ 2 | |
| 87 | #define SS_DDR DDRB | |
| 88 | #define SS_PORT PORTB | |
| 89 | #define SS_BIT 2 // for PORTB: 2 = d.10, 1 = d.9, 0 = d.8 | |
| 90 | ||
| 91 | #define SPI_SS 10 // PB2, pin 16 | |
| 92 | #define SPI_MOSI 11 // PB3, pin 17 | |
| 93 | #define SPI_MISO 12 // PB4, pin 18 | |
| 94 | #define SPI_SCK 13 // PB5, pin 19 | |
| 95 | ||
| 96 | #endif | |
| 97 | ||
| 98 | // RF12 command codes | |
| 99 | #define RF_RECEIVER_ON 0x82DD | |
| 100 | #define RF_XMITTER_ON 0x823D | |
| 101 | #define RF_IDLE_MODE 0x820D | |
| 102 | #define RF_SLEEP_MODE 0x8205 | |
| 103 | #define RF_WAKEUP_MODE 0x8207 | |
| 104 | #define RF_TXREG_WRITE 0xB800 | |
| 105 | #define RF_RX_FIFO_READ 0xB000 | |
| 106 | #define RF_WAKEUP_TIMER 0xE000 | |
| 107 | ||
| 108 | // RF12 status bits | |
| 109 | #define RF_LBD_BIT 0x0400 | |
| 110 | #define RF_RSSI_BIT 0x0100 | |
| 111 | ||
| 112 | // bits in the node id configuration byte | |
| 113 | #define NODE_BAND 0xC0 // frequency band | |
| 114 | #define NODE_ACKANY 0x20 // ack on broadcast packets if set | |
| 115 | #define NODE_ID 0x1F // id of this node, as A..Z or 1..31 | |
| 116 | ||
| 117 | // transceiver states, these determine what to do with each interrupt | |
| 118 | enum {
| |
| 119 | TXCRC1, TXCRC2, TXTAIL, TXDONE, TXIDLE, | |
| 120 | TXRECV, | |
| 121 | TXPRE1, TXPRE2, TXPRE3, TXSYN1, TXSYN2, | |
| 122 | }; | |
| 123 | ||
| 124 | static uint8_t cs_pin = SS_BIT; // chip select pin | |
| 125 | ||
| 126 | static uint8_t nodeid; // address of this node | |
| 127 | static uint8_t group; // network group | |
| 128 | static volatile uint8_t rxfill; // number of data bytes in rf12_buf | |
| 129 | static volatile int8_t rxstate; // current transceiver state | |
| 130 | ||
| 131 | #define RETRIES 8 // stop retrying after 8 times | |
| 132 | #define RETRY_MS 1000 // resend packet every second until ack'ed | |
| 133 | ||
| 134 | static uint8_t ezInterval; // number of seconds between transmits | |
| 135 | static uint8_t ezSendBuf[RF12_MAXDATA]; // data to send | |
| 136 | static char ezSendLen; // number of bytes to send | |
| 137 | static uint8_t ezPending; // remaining number of retries | |
| 138 | static long ezNextSend[2]; // when was last retry [0] or data [1] sent | |
| 139 | ||
| 140 | volatile uint16_t rf12_crc; // running crc value | |
| 141 | volatile uint8_t rf12_buf[RF_MAX]; // recv/xmit buf, including hdr & crc bytes | |
| 142 | long rf12_seq; // seq number of encrypted packet (or -1) | |
| 143 | ||
| 144 | static uint32_t seqNum; // encrypted send sequence number | |
| 145 | static uint32_t cryptKey[4]; // encryption key to use | |
| 146 | void (*crypter)(uint8_t); // does en-/decryption (null if disabled) | |
| 147 | ||
| 148 | // function to set chip select pin from within sketch | |
| 149 | void rf12_set_cs(uint8_t pin) | |
| 150 | {
| |
| 151 | #if defined(__AVR_ATmega32U4__) //Arduino Leonardo | |
| 152 | if (pin==10) cs_pin=6; // Dig10, PB6 | |
| 153 | if (pin==9) cs_pin=5; // Dig9, PB5 | |
| 154 | if (pin==8) cs_pin=4; // Dig8, PB4 | |
| 155 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__) // ATmega168, ATmega328 | |
| 156 | if (pin==10) cs_pin = 2; // Dig10, PB2 | |
| 157 | if (pin==9) cs_pin = 1; // Dig9, PB1 | |
| 158 | if (pin==8) cs_pin = 0; // Dig8, PB0 | |
| 159 | if (pin==5) | |
| 160 | {
| |
| 161 | cs_pin = 5; //PD5 | |
| 162 | #define SS_DDR DDRD | |
| 163 | #define SS_PORT PORTD | |
| 164 | } | |
| 165 | ||
| 166 | #endif | |
| 167 | } | |
| 168 | ||
| 169 | ||
| 170 | void rf12_spiInit () {
| |
| 171 | bitSet(SS_PORT, cs_pin); | |
| 172 | bitSet(SS_DDR, cs_pin); | |
| 173 | digitalWrite(SPI_SS, 1); | |
| 174 | pinMode(SPI_SS, OUTPUT); | |
| 175 | pinMode(SPI_MOSI, OUTPUT); | |
| 176 | pinMode(SPI_MISO, INPUT); | |
| 177 | pinMode(SPI_SCK, OUTPUT); | |
| 178 | #ifdef SPCR | |
| 179 | SPCR = _BV(SPE) | _BV(MSTR); | |
| 180 | #if F_CPU > 10000000 | |
| 181 | // use clk/2 (2x 1/4th) for sending (and clk/8 for recv, see rf12_xferSlow) | |
| 182 | SPSR |= _BV(SPI2X); | |
| 183 | #endif | |
| 184 | #else | |
| 185 | // ATtiny | |
| 186 | USICR = bit(USIWM0); | |
| 187 | #endif | |
| 188 | pinMode(RFM_IRQ, INPUT); | |
| 189 | digitalWrite(RFM_IRQ, 1); // pull-up | |
| 190 | } | |
| 191 | ||
| 192 | static uint8_t rf12_byte (uint8_t out) {
| |
| 193 | #ifdef SPDR | |
| 194 | SPDR = out; | |
| 195 | // this loop spins 4 usec with a 2 MHz SPI clock | |
| 196 | while (!(SPSR & _BV(SPIF))) | |
| 197 | ; | |
| 198 | return SPDR; | |
| 199 | #else | |
| 200 | // ATtiny | |
| 201 | USIDR = out; | |
| 202 | byte v1 = bit(USIWM0) | bit(USITC); | |
| 203 | byte v2 = bit(USIWM0) | bit(USITC) | bit(USICLK); | |
| 204 | #if F_CPU <= 5000000 | |
| 205 | // only unroll if resulting clock stays under 2.5 MHz | |
| 206 | USICR = v1; USICR = v2; | |
| 207 | USICR = v1; USICR = v2; | |
| 208 | USICR = v1; USICR = v2; | |
| 209 | USICR = v1; USICR = v2; | |
| 210 | USICR = v1; USICR = v2; | |
| 211 | USICR = v1; USICR = v2; | |
| 212 | USICR = v1; USICR = v2; | |
| 213 | USICR = v1; USICR = v2; | |
| 214 | #else | |
| 215 | for (uint8_t i = 0; i < 8; ++i) {
| |
| 216 | USICR = v1; | |
| 217 | USICR = v2; | |
| 218 | } | |
| 219 | #endif | |
| 220 | return USIDR; | |
| 221 | #endif | |
| 222 | } | |
| 223 | ||
| 224 | static uint16_t rf12_xferSlow (uint16_t cmd) {
| |
| 225 | // slow down to under 2.5 MHz | |
| 226 | #if F_CPU > 10000000 | |
| 227 | bitSet(SPCR, SPR0); | |
| 228 | #endif | |
| 229 | bitClear(SS_PORT, cs_pin); | |
| 230 | uint16_t reply = rf12_byte(cmd >> 8) << 8; | |
| 231 | reply |= rf12_byte(cmd); | |
| 232 | bitSet(SS_PORT, cs_pin); | |
| 233 | #if F_CPU > 10000000 | |
| 234 | bitClear(SPCR, SPR0); | |
| 235 | #endif | |
| 236 | return reply; | |
| 237 | } | |
| 238 | ||
| 239 | #if OPTIMIZE_SPI | |
| 240 | static void rf12_xfer (uint16_t cmd) {
| |
| 241 | // writing can take place at full speed, even 8 MHz works | |
| 242 | bitClear(SS_PORT, cs_pin); | |
| 243 | rf12_byte(cmd >> 8) << 8; | |
| 244 | rf12_byte(cmd); | |
| 245 | bitSet(SS_PORT, cs_pin); | |
| 246 | } | |
| 247 | #else | |
| 248 | #define rf12_xfer rf12_xferSlow | |
| 249 | #endif | |
| 250 | ||
| 251 | /// @details | |
| 252 | /// This call provides direct access to the RFM12B registers. If you're careful | |
| 253 | /// to avoid configuring the wireless module in a way which stops the driver | |
| 254 | /// from functioning, this can be used to adjust frequencies, power levels, | |
| 255 | /// RSSI threshold, etc. See the RFM12B wireless module documentation. | |
| 256 | /// | |
| 257 | /// This call will briefly disable interrupts to avoid clashes on the SPI bus. | |
| 258 | /// | |
| 259 | /// Returns the 16-bit value returned by SPI. Probably only useful with a | |
| 260 | /// "0x0000" status poll command. | |
| 261 | /// @param cmd RF12 command, topmost bits determines which register is affected. | |
| 262 | uint16_t rf12_control(uint16_t cmd) {
| |
| 263 | #ifdef EIMSK | |
| 264 | #if PINCHG_IRQ | |
| 265 | #if RFM_IRQ < 8 | |
| 266 | bitClear(PCICR, PCIE2); | |
| 267 | #elif RFM_IRQ < 14 | |
| 268 | bitClear(PCICR, PCIE0); | |
| 269 | #else | |
| 270 | bitClear(PCICR, PCIE1); | |
| 271 | #endif | |
| 272 | #else | |
| 273 | bitClear(EIMSK, INT0); | |
| 274 | #endif | |
| 275 | uint16_t r = rf12_xferSlow(cmd); | |
| 276 | #if PINCHG_IRQ | |
| 277 | #if RFM_IRQ < 8 | |
| 278 | bitSet(PCICR, PCIE2); | |
| 279 | #elif RFM_IRQ < 14 | |
| 280 | bitSet(PCICR, PCIE0); | |
| 281 | #else | |
| 282 | bitSet(PCICR, PCIE1); | |
| 283 | #endif | |
| 284 | #else | |
| 285 | bitSet(EIMSK, INT0); | |
| 286 | #endif | |
| 287 | #else | |
| 288 | // ATtiny | |
| 289 | bitClear(GIMSK, INT0); | |
| 290 | uint16_t r = rf12_xferSlow(cmd); | |
| 291 | bitSet(GIMSK, INT0); | |
| 292 | #endif | |
| 293 | return r; | |
| 294 | } | |
| 295 | ||
| 296 | static void rf12_interrupt() {
| |
| 297 | // a transfer of 2x 16 bits @ 2 MHz over SPI takes 2x 8 us inside this ISR | |
| 298 | // correction: now takes 2 + 8 µs, since sending can be done at 8 MHz | |
| 299 | rf12_xfer(0x0000); | |
| 300 | ||
| 301 | if (rxstate == TXRECV) {
| |
| 302 | uint8_t in = rf12_xferSlow(RF_RX_FIFO_READ); | |
| 303 | ||
| 304 | if (rxfill == 0 && group != 0) | |
| 305 | rf12_buf[rxfill++] = group; | |
| 306 | ||
| 307 | rf12_buf[rxfill++] = in; | |
| 308 | rf12_crc = _crc16_update(rf12_crc, in); | |
| 309 | ||
| 310 | if (rxfill >= rf12_len + 5 || rxfill >= RF_MAX) | |
| 311 | rf12_xfer(RF_IDLE_MODE); | |
| 312 | } else {
| |
| 313 | uint8_t out; | |
| 314 | ||
| 315 | if (rxstate < 0) {
| |
| 316 | uint8_t pos = 3 + rf12_len + rxstate++; | |
| 317 | out = rf12_buf[pos]; | |
| 318 | rf12_crc = _crc16_update(rf12_crc, out); | |
| 319 | } else | |
| 320 | switch (rxstate++) {
| |
| 321 | case TXSYN1: out = 0x2D; break; | |
| 322 | case TXSYN2: out = group; rxstate = - (2 + rf12_len); break; | |
| 323 | case TXCRC1: out = rf12_crc; break; | |
| 324 | case TXCRC2: out = rf12_crc >> 8; break; | |
| 325 | case TXDONE: rf12_xfer(RF_IDLE_MODE); // fall through | |
| 326 | default: out = 0xAA; | |
| 327 | } | |
| 328 | ||
| 329 | rf12_xfer(RF_TXREG_WRITE + out); | |
| 330 | } | |
| 331 | } | |
| 332 | ||
| 333 | #if PINCHG_IRQ | |
| 334 | #if RFM_IRQ < 8 | |
| 335 | ISR(PCINT2_vect) {
| |
| 336 | while (!bitRead(PIND, RFM_IRQ)) | |
| 337 | rf12_interrupt(); | |
| 338 | } | |
| 339 | #elif RFM_IRQ < 14 | |
| 340 | ISR(PCINT0_vect) {
| |
| 341 | while (!bitRead(PINB, RFM_IRQ - 8)) | |
| 342 | rf12_interrupt(); | |
| 343 | } | |
| 344 | #else | |
| 345 | ISR(PCINT1_vect) {
| |
| 346 | while (!bitRead(PINC, RFM_IRQ - 14)) | |
| 347 | rf12_interrupt(); | |
| 348 | } | |
| 349 | #endif | |
| 350 | #endif | |
| 351 | ||
| 352 | static void rf12_recvStart () {
| |
| 353 | rxfill = rf12_len = 0; | |
| 354 | rf12_crc = ~0; | |
| 355 | #if RF12_VERSION >= 2 | |
| 356 | if (group != 0) | |
| 357 | rf12_crc = _crc16_update(~0, group); | |
| 358 | #endif | |
| 359 | rxstate = TXRECV; | |
| 360 | rf12_xfer(RF_RECEIVER_ON); | |
| 361 | } | |
| 362 | ||
| 363 | #include <RF12.h> | |
| 364 | #include <Ports.h> // needed to avoid a linker error :( | |
| 365 | ||
| 366 | byte rf12_recvDone(); | |
| 367 | ||
| 368 | /// @details | |
| 369 | /// The timing of this function is relatively coarse, because SPI transfers are | |
| 370 | /// used to enable / disable the transmitter. This will add some jitter to the | |
| 371 | /// signal, probably in the order of 10 µsec. | |
| 372 | /// | |
| 373 | /// If the result is true, then a packet has been received and is available for | |
| 374 | /// processing. The following global variables will be set: | |
| 375 | /// | |
| 376 | /// * volatile byte rf12_hdr - | |
| 377 | /// Contains the header byte of the received packet - with flag bits and | |
| 378 | /// node ID of either the sender or the receiver. | |
| 379 | /// * volatile byte rf12_len - | |
| 380 | /// The number of data bytes in the packet. A value in the range 0 .. 66. | |
| 381 | /// * volatile byte rf12_data - | |
| 382 | /// A pointer to the received data. | |
| 383 | /// * volatile byte rf12_crc - | |
| 384 | /// CRC of the received packet, zero indicates correct reception. If != 0 | |
| 385 | /// then rf12_hdr, rf12_len, and rf12_data should not be relied upon. | |
| 386 | /// | |
| 387 | /// To send an acknowledgement, call rf12_sendStart() - but only right after | |
| 388 | /// rf12_recvDone() returns true. This is commonly done using these macros: | |
| 389 | /// | |
| 390 | /// if(RF12_WANTS_ACK){
| |
| 391 | /// rf12_sendStart(RF12_ACK_REPLY,0,0); | |
| 392 | /// } | |
| 393 | /// @see http://jeelabs.org/2010/12/11/rf12-acknowledgements/ | |
| 394 | uint8_t rf12_recvDone () {
| |
| 395 | if (rxstate == TXRECV && (rxfill >= rf12_len + 5 || rxfill >= RF_MAX)) {
| |
| 396 | rxstate = TXIDLE; | |
| 397 | if (rf12_len > RF12_MAXDATA) | |
| 398 | rf12_crc = 1; // force bad crc if packet length is invalid | |
| 399 | if (!(rf12_hdr & RF12_HDR_DST) || (nodeid & NODE_ID) == 31 || | |
| 400 | (rf12_hdr & RF12_HDR_MASK) == (nodeid & NODE_ID)) {
| |
| 401 | if (rf12_crc == 0 && crypter != 0) | |
| 402 | crypter(0); | |
| 403 | else | |
| 404 | rf12_seq = -1; | |
| 405 | return 1; // it's a broadcast packet or it's addressed to this node | |
| 406 | } | |
| 407 | } | |
| 408 | if (rxstate == TXIDLE) | |
| 409 | rf12_recvStart(); | |
| 410 | return 0; | |
| 411 | } | |
| 412 | ||
| 413 | /// @details | |
| 414 | /// Call this when you have some data to send. If it returns true, then you can | |
| 415 | /// use rf12_sendStart() to start the transmission. Else you need to wait and | |
| 416 | /// retry this call at a later moment. | |
| 417 | /// | |
| 418 | /// Don't call this function if you have nothing to send, because rf12_canSend() | |
| 419 | /// will stop reception when it returns true. IOW, calling the function | |
| 420 | /// indicates your intention to send something, and once it returns true, you | |
| 421 | /// should follow through and call rf12_sendStart() to actually initiate a send. | |
| 422 | /// See [this weblog post](http://jeelabs.org/2010/05/20/a-subtle-rf12-detail/). | |
| 423 | /// | |
| 424 | /// Note that even if you only want to send out packets, you still have to call | |
| 425 | /// rf12_recvDone() periodically, because it keeps the RFM12B logic going. If | |
| 426 | /// you don't, rf12_canSend() will never return true. | |
| 427 | uint8_t rf12_canSend () {
| |
| 428 | // need interrupts off to avoid a race (and enable the RFM12B, thx Jorg!) | |
| 429 | // see http://openenergymonitor.org/emon/node/1051?page=3 | |
| 430 | if (rxstate == TXRECV && rxfill == 0 && | |
| 431 | (rf12_control(0x0000) & RF_RSSI_BIT) == 0) {
| |
| 432 | rf12_control(RF_IDLE_MODE); // stop receiver | |
| 433 | rxstate = TXIDLE; | |
| 434 | return 1; | |
| 435 | } | |
| 436 | return 0; | |
| 437 | } | |
| 438 | ||
| 439 | void rf12_sendStart (uint8_t hdr) {
| |
| 440 | rf12_hdr = hdr & RF12_HDR_DST ? hdr : | |
| 441 | (hdr & ~RF12_HDR_MASK) + (nodeid & NODE_ID); | |
| 442 | if (crypter != 0) | |
| 443 | crypter(1); | |
| 444 | ||
| 445 | rf12_crc = ~0; | |
| 446 | #if RF12_VERSION >= 2 | |
| 447 | rf12_crc = _crc16_update(rf12_crc, group); | |
| 448 | #endif | |
| 449 | rxstate = TXPRE1; | |
| 450 | rf12_xfer(RF_XMITTER_ON); // bytes will be fed via interrupts | |
| 451 | } | |
| 452 | ||
| 453 | /// @details | |
| 454 | /// Switch to transmission mode and send a packet. | |
| 455 | /// This can be either a request or a reply. | |
| 456 | /// | |
| 457 | /// Notes | |
| 458 | /// ----- | |
| 459 | /// | |
| 460 | /// The rf12_sendStart() function may only be called in two specific situations: | |
| 461 | /// | |
| 462 | /// * right after rf12_recvDone() returns true - used for sending replies / | |
| 463 | /// acknowledgements | |
| 464 | /// * right after rf12_canSend() returns true - used to send requests out | |
| 465 | /// | |
| 466 | /// Because transmissions may only be started when there is no other reception | |
| 467 | /// or transmission taking place. | |
| 468 | /// | |
| 469 | /// The short form, i.e. "rf12_sendStart(hdr)" is for a special buffer-less | |
| 470 | /// transmit mode, as described in this | |
| 471 | /// [weblog post](http://jeelabs.org/2010/09/15/more-rf12-driver-notes/). | |
| 472 | /// | |
| 473 | /// The call with 4 arguments, i.e. "rf12_sendStart(hdr, data, length, sync)" is | |
| 474 | /// deprecated, as described in that same weblog post. The recommended idiom is | |
| 475 | /// now to call it with 3 arguments, followed by a call to rf12_sendWait(). | |
| 476 | /// @param hdr The header contains information about the destination of the | |
| 477 | /// packet to send, and flags such as whether this should be | |
| 478 | /// acknowledged - or if it actually is an acknowledgement. | |
| 479 | /// @param ptr Pointer to the data to send as packet. | |
| 480 | /// @param len Number of data bytes to send. Must be in the range 0 .. 65. | |
| 481 | void rf12_sendStart (uint8_t hdr, const void* ptr, uint8_t len) {
| |
| 482 | rf12_len = len; | |
| 483 | memcpy((void*) rf12_data, ptr, len); | |
| 484 | rf12_sendStart(hdr); | |
| 485 | } | |
| 486 | ||
| 487 | /// @deprecated Use the 3-arg version, followed by a call to rf12_sendWait. | |
| 488 | void rf12_sendStart (uint8_t hdr, const void* ptr, uint8_t len, uint8_t sync) {
| |
| 489 | rf12_sendStart(hdr, ptr, len); | |
| 490 | rf12_sendWait(sync); | |
| 491 | } | |
| 492 | ||
| 493 | /// @details | |
| 494 | /// Wait until transmission is possible, then start it as soon as possible. | |
| 495 | /// @note This uses a (brief) busy loop and will discard any incoming packets. | |
| 496 | /// @param hdr The header contains information about the destination of the | |
| 497 | /// packet to send, and flags such as whether this should be | |
| 498 | /// acknowledged - or if it actually is an acknowledgement. | |
| 499 | /// @param ptr Pointer to the data to send as packet. | |
| 500 | /// @param len Number of data bytes to send. Must be in the range 0 .. 65. | |
| 501 | void rf12_sendNow (uint8_t hdr, const void* ptr, uint8_t len) {
| |
| 502 | while (!rf12_canSend()) | |
| 503 | rf12_recvDone(); // keep the driver state machine going, ignore incoming | |
| 504 | rf12_sendStart(hdr, ptr, len); | |
| 505 | } | |
| 506 | ||
| 507 | /// @details | |
| 508 | /// Wait for completion of the preceding rf12_sendStart() call, using the | |
| 509 | /// specified low-power mode. | |
| 510 | /// @note rf12_sendWait() should only be called right after rf12_sendStart(). | |
| 511 | /// @param mode Power-down mode during wait: 0 = NORMAL, 1 = IDLE, 2 = STANDBY, | |
| 512 | /// 3 = PWR_DOWN. Values 2 and 3 can cause the millisecond time to | |
| 513 | /// lose a few interrupts. Value 3 can only be used if the ATmega | |
| 514 | /// fuses have been set for fast startup, i.e. 258 CK - the default | |
| 515 | /// Arduino fuse settings are not suitable for full power down. | |
| 516 | void rf12_sendWait (uint8_t mode) {
| |
| 517 | // wait for packet to actually finish sending | |
| 518 | // go into low power mode, as interrupts are going to come in very soon | |
| 519 | while (rxstate != TXIDLE) | |
| 520 | if (mode) {
| |
| 521 | // power down mode is only possible if the fuses are set to start | |
| 522 | // up in 258 clock cycles, i.e. approx 4 us - else must use standby! | |
| 523 | // modes 2 and higher may lose a few clock timer ticks | |
| 524 | set_sleep_mode(mode == 3 ? SLEEP_MODE_PWR_DOWN : | |
| 525 | #ifdef SLEEP_MODE_STANDBY | |
| 526 | mode == 2 ? SLEEP_MODE_STANDBY : | |
| 527 | #endif | |
| 528 | SLEEP_MODE_IDLE); | |
| 529 | sleep_mode(); | |
| 530 | } | |
| 531 | } | |
| 532 | ||
| 533 | /// @details | |
| 534 | /// Call this once with the node ID (0-31), frequency band (0-3), and | |
| 535 | /// optional group (0-255 for RFM12B, only 212 allowed for RFM12). | |
| 536 | /// @param id The ID of this wireless node. ID's should be unique within the | |
| 537 | /// netGroup in which this node is operating. The ID range is 0 to 31, | |
| 538 | /// but only 1..30 are available for normal use. You can pass a single | |
| 539 | /// capital letter as node ID, with 'A' .. 'Z' corresponding to the | |
| 540 | /// node ID's 1..26, but this convention is now discouraged. ID 0 is | |
| 541 | /// reserved for OOK use, node ID 31 is special because it will pick | |
| 542 | /// up packets for any node (in the same netGroup). | |
| 543 | /// @param band This determines in which frequency range the wireless module | |
| 544 | /// will operate. The following pre-defined constants are available: | |
| 545 | /// RF12_433MHZ, RF12_868MHZ, RF12_915MHZ. You should use the one | |
| 546 | /// matching the module you have. | |
| 547 | /// @param g Net groups are used to separate nodes: only nodes in the same net | |
| 548 | /// group can communicate with each other. Valid values are 1 to 212. | |
| 549 | /// This parameter is optional, it defaults to 212 (0xD4) when omitted. | |
| 550 | /// This is the only allowed value for RFM12 modules, only RFM12B | |
| 551 | /// modules support other group values. | |
| 552 | /// @returns the nodeId, to be compatible with rf12_config(). | |
| 553 | /// | |
| 554 | /// Programming Tips | |
| 555 | /// ---------------- | |
| 556 | /// Note that rf12_initialize() does not use the EEprom netId and netGroup | |
| 557 | /// settings, nor does it change the EEPROM settings. To use the netId and | |
| 558 | /// netGroup settings saved in EEPROM use rf12_config() instead of | |
| 559 | /// rf12_initialize. The choice whether to use rf12_initialize() or | |
| 560 | /// rf12_config() at the top of every sketch is one of personal preference. | |
| 561 | /// To set EEPROM settings for use with rf12_config() use the RF12demo sketch. | |
| 562 | uint8_t rf12_initialize (uint8_t id, uint8_t band, uint8_t g) {
| |
| 563 | nodeid = id; | |
| 564 | group = g; | |
| 565 | ||
| 566 | rf12_spiInit(); | |
| 567 | ||
| 568 | rf12_xfer(0x0000); // intitial SPI transfer added to avoid power-up problem | |
| 569 | ||
| 570 | rf12_xfer(RF_SLEEP_MODE); // DC (disable clk pin), enable lbd | |
| 571 | ||
| 572 | // wait until RFM12B is out of power-up reset, this takes several *seconds* | |
| 573 | rf12_xfer(RF_TXREG_WRITE); // in case we're still in OOK mode | |
| 574 | while (digitalRead(RFM_IRQ) == 0) | |
| 575 | rf12_xfer(0x0000); | |
| 576 | ||
| 577 | rf12_xfer(0x80C7 | (band << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF | |
| 578 | rf12_xfer(0xA640); // 868MHz | |
| 579 | rf12_xfer(0xC606); // approx 49.2 Kbps, i.e. 10000/29/(1+6) Kbps | |
| 580 | rf12_xfer(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm | |
| 581 | rf12_xfer(0xC2AC); // AL,!ml,DIG,DQD4 | |
| 582 | if (group != 0) {
| |
| 583 | rf12_xfer(0xCA83); // FIFO8,2-SYNC,!ff,DR | |
| 584 | rf12_xfer(0xCE00 | group); // SYNC=2DXX; | |
| 585 | } else {
| |
| 586 | rf12_xfer(0xCA8B); // FIFO8,1-SYNC,!ff,DR | |
| 587 | rf12_xfer(0xCE2D); // SYNC=2D; | |
| 588 | } | |
| 589 | rf12_xfer(0xC483); // @PWR,NO RSTRIC,!st,!fi,OE,EN | |
| 590 | rf12_xfer(0x9850); // !mp,90kHz,MAX OUT | |
| 591 | rf12_xfer(0xCC77); // OB1,OB0, LPX,!ddy,DDIT,BW0 | |
| 592 | rf12_xfer(0xE000); // NOT USE | |
| 593 | rf12_xfer(0xC800); // NOT USE | |
| 594 | rf12_xfer(0xC049); // 1.66MHz,3.1V | |
| 595 | ||
| 596 | rxstate = TXIDLE; | |
| 597 | #if PINCHG_IRQ | |
| 598 | #if RFM_IRQ < 8 | |
| 599 | if ((nodeid & NODE_ID) != 0) {
| |
| 600 | bitClear(DDRD, RFM_IRQ); // input | |
| 601 | bitSet(PORTD, RFM_IRQ); // pull-up | |
| 602 | bitSet(PCMSK2, RFM_IRQ); // pin-change | |
| 603 | bitSet(PCICR, PCIE2); // enable | |
| 604 | } else | |
| 605 | bitClear(PCMSK2, RFM_IRQ); | |
| 606 | #elif RFM_IRQ < 14 | |
| 607 | if ((nodeid & NODE_ID) != 0) {
| |
| 608 | bitClear(DDRB, RFM_IRQ - 8); // input | |
| 609 | bitSet(PORTB, RFM_IRQ - 8); // pull-up | |
| 610 | bitSet(PCMSK0, RFM_IRQ - 8); // pin-change | |
| 611 | bitSet(PCICR, PCIE0); // enable | |
| 612 | } else | |
| 613 | bitClear(PCMSK0, RFM_IRQ - 8); | |
| 614 | #else | |
| 615 | if ((nodeid & NODE_ID) != 0) {
| |
| 616 | bitClear(DDRC, RFM_IRQ - 14); // input | |
| 617 | bitSet(PORTC, RFM_IRQ - 14); // pull-up | |
| 618 | bitSet(PCMSK1, RFM_IRQ - 14); // pin-change | |
| 619 | bitSet(PCICR, PCIE1); // enable | |
| 620 | } else | |
| 621 | bitClear(PCMSK1, RFM_IRQ - 14); | |
| 622 | #endif | |
| 623 | #else | |
| 624 | if ((nodeid & NODE_ID) != 0) | |
| 625 | attachInterrupt(0, rf12_interrupt, LOW); | |
| 626 | else | |
| 627 | detachInterrupt(0); | |
| 628 | #endif | |
| 629 | ||
| 630 | return nodeid; | |
| 631 | } | |
| 632 | ||
| 633 | /// @details | |
| 634 | /// This can be used to send out slow bit-by-bit On Off Keying signals to other | |
| 635 | /// devices such as remotely controlled power switches operating in the 433, | |
| 636 | /// 868, or 915 MHz bands. | |
| 637 | /// | |
| 638 | /// To use this, you need to first call rf12initialize() with a zero node ID | |
| 639 | /// and the proper frequency band. Then call rf12onOff() in the exact timing | |
| 640 | /// you need for sending out the signal. Once done, either call rf12onOff(0) to | |
| 641 | /// turn the transmitter off, or reinitialize the wireless module completely | |
| 642 | /// with a call to rf12initialize(). | |
| 643 | /// @param value Turn the transmitter on (if true) or off (if false). | |
| 644 | /// @note The timing of this function is relatively coarse, because SPI | |
| 645 | /// transfers are used to enable / disable the transmitter. This will add some | |
| 646 | /// jitter to the signal, probably in the order of 10 µsec. | |
| 647 | void rf12_onOff (uint8_t value) {
| |
| 648 | rf12_xfer(value ? RF_XMITTER_ON : RF_IDLE_MODE); | |
| 649 | } | |
| 650 | ||
| 651 | /// @details | |
| 652 | /// This calls rf12_initialize() with settings obtained from EEPROM address | |
| 653 | /// 0x20 .. 0x3F. These settings can be filled in by the RF12demo sketch in the | |
| 654 | /// RFM12B library. If the checksum included in those bytes is not valid, | |
| 655 | /// rf12_initialize() will not be called. | |
| 656 | /// | |
| 657 | /// As side effect, rf12_config() also writes the current configuration to the | |
| 658 | /// serial port, ending with a newline. | |
| 659 | /// @returns the node ID obtained from EEPROM, or 0 if there was none. | |
| 660 | uint8_t rf12_config (uint8_t show) {
| |
| 661 | uint16_t crc = ~0; | |
| 662 | for (uint8_t i = 0; i < RF12_EEPROM_SIZE; ++i) | |
| 663 | crc = _crc16_update(crc, eeprom_read_byte(RF12_EEPROM_ADDR + i)); | |
| 664 | if (crc != 0) | |
| 665 | return 0; | |
| 666 | ||
| 667 | uint8_t nodeId = 0, group = 0; | |
| 668 | for (uint8_t i = 0; i < RF12_EEPROM_SIZE - 2; ++i) {
| |
| 669 | uint8_t b = eeprom_read_byte(RF12_EEPROM_ADDR + i); | |
| 670 | if (i == 0) | |
| 671 | nodeId = b; | |
| 672 | else if (i == 1) | |
| 673 | group = b; | |
| 674 | else if (b == 0) | |
| 675 | break; | |
| 676 | else if (show) | |
| 677 | Serial.print((char) b); | |
| 678 | } | |
| 679 | if (show) | |
| 680 | Serial.println(); | |
| 681 | ||
| 682 | rf12_initialize(nodeId, nodeId >> 6, group); | |
| 683 | return nodeId & RF12_HDR_MASK; | |
| 684 | } | |
| 685 | ||
| 686 | /// @details | |
| 687 | /// This function can put the radio module to sleep and wake it up again. | |
| 688 | /// In sleep mode, the radio will draw only one or two microamps of current. | |
| 689 | /// | |
| 690 | /// This function can also be used as low-power watchdog, by putting the radio | |
| 691 | /// to sleep and having it raise an interrupt between about 30 milliseconds | |
| 692 | /// and 4 seconds later. | |
| 693 | /// @param n If RF12SLEEP (0), put the radio to sleep - no scheduled wakeup. | |
| 694 | /// If RF12WAKEUP (-1), wake the radio up so that the next call to | |
| 695 | /// rf12_recvDone() can restore normal reception. If value is in the | |
| 696 | /// range 1 .. 127, then the radio will go to sleep and generate an | |
| 697 | /// interrupt approximately 32*value miliiseconds later. | |
| 698 | /// @todo Figure out how to get the "watchdog" mode working reliably. | |
| 699 | void rf12_sleep (char n) {
| |
| 700 | if (n < 0) | |
| 701 | rf12_control(RF_IDLE_MODE); | |
| 702 | else {
| |
| 703 | rf12_control(RF_WAKEUP_TIMER | 0x0500 | n); | |
| 704 | rf12_control(RF_SLEEP_MODE); | |
| 705 | if (n > 0) | |
| 706 | rf12_control(RF_WAKEUP_MODE); | |
| 707 | } | |
| 708 | rxstate = TXIDLE; | |
| 709 | } | |
| 710 | ||
| 711 | /// @details | |
| 712 | /// This checks the status of the RF12 low-battery detector. It wil be 1 when | |
| 713 | /// the supply voltage drops below 3.1V, and 0 otherwise. This can be used to | |
| 714 | /// detect an impending power failure, but there are no guarantees that the | |
| 715 | /// power still remaining will be sufficient to send or receive further packets. | |
| 716 | char rf12_lowbat () {
| |
| 717 | return (rf12_control(0x0000) & RF_LBD_BIT) != 0; | |
| 718 | } | |
| 719 | ||
| 720 | /// @details | |
| 721 | /// Set up the easy transmission mechanism. The argument is the minimal number | |
| 722 | /// of seconds between new data packets (from 1 to 255). With 0 as argument, | |
| 723 | /// packets will be sent as fast as possible: | |
| 724 | /// | |
| 725 | /// * On the 433 and 915 MHz frequency bands, this is fixed at 100 msec (10 | |
| 726 | /// packets/second). | |
| 727 | /// | |
| 728 | /// * On the 866 MHz band, the frequency depends on the number of bytes sent: | |
| 729 | /// for 1-byte packets, it will be up to 7 packets/second, for 66-byte bytes of | |
| 730 | /// data it will be around 1 packet/second. | |
| 731 | /// | |
| 732 | /// This function should be called after the RF12 driver has been initialized, | |
| 733 | /// using either rf12_initialize() or rf12_config(). | |
| 734 | /// @param secs The minimal number of seconds between new data packets (from 1 | |
| 735 | /// to 255). With a 0 argument, packets will be sent as fast as | |
| 736 | /// possible: on the 433 and 915 MHz frequency bands, this is fixed | |
| 737 | /// at 100 msec (10 packets/second). On 866 MHz, the frequency | |
| 738 | /// depends on the number of bytes sent: for 1-byte packets, it will | |
| 739 | /// be up to 7 packets/second, for 66-byte bytes of data it will be | |
| 740 | /// approx. 1 packet/second. | |
| 741 | /// @note To be used in combination with rf12_easyPoll() and rf12_easySend(). | |
| 742 | void rf12_easyInit (uint8_t secs) {
| |
| 743 | ezInterval = secs; | |
| 744 | } | |
| 745 | ||
| 746 | /// @details | |
| 747 | /// This needs to be called often to keep the easy transmission mechanism going, | |
| 748 | /// i.e. once per millisecond or more in normal use. Failure to poll frequently | |
| 749 | /// enough is relatively harmless but may lead to lost acknowledgements. | |
| 750 | /// @returns 1 = an ack has been received with actual data in it, use rf12len | |
| 751 | /// and rf12data to access it. 0 = there is nothing to do, the last | |
| 752 | /// send has been ack'ed or more than 8 re-transmits have failed. | |
| 753 | /// -1 = still sending or waiting for an ack to come in | |
| 754 | /// @note To be used in combination with rf12_easyInit() and rf12_easySend(). | |
| 755 | char rf12_easyPoll () {
| |
| 756 | if (rf12_recvDone() && rf12_crc == 0) {
| |
| 757 | byte myAddr = nodeid & RF12_HDR_MASK; | |
| 758 | if (rf12_hdr == (RF12_HDR_CTL | RF12_HDR_DST | myAddr)) {
| |
| 759 | ezPending = 0; | |
| 760 | ezNextSend[0] = 0; // flags succesful packet send | |
| 761 | if (rf12_len > 0) | |
| 762 | return 1; | |
| 763 | } | |
| 764 | } | |
| 765 | if (ezPending > 0) {
| |
| 766 | // new data sends should not happen less than ezInterval seconds apart | |
| 767 | // ... whereas retries should not happen less than RETRY_MS apart | |
| 768 | byte newData = ezPending == RETRIES; | |
| 769 | long now = millis(); | |
| 770 | if (now >= ezNextSend[newData] && rf12_canSend()) {
| |
| 771 | ezNextSend[0] = now + RETRY_MS; | |
| 772 | // must send new data packets at least ezInterval seconds apart | |
| 773 | // ezInterval == 0 is a special case: | |
| 774 | // for the 868 MHz band: enforce 1% max bandwidth constraint | |
| 775 | // for other bands: use 100 msec, i.e. max 10 packets/second | |
| 776 | if (newData) | |
| 777 | ezNextSend[1] = now + | |
| 778 | (ezInterval > 0 ? 1000L * ezInterval | |
| 779 | : (nodeid >> 6) == RF12_868MHZ ? | |
| 780 | 13 * (ezSendLen + 10) : 100); | |
| 781 | rf12_sendStart(RF12_HDR_ACK, ezSendBuf, ezSendLen); | |
| 782 | --ezPending; | |
| 783 | } | |
| 784 | } | |
| 785 | return ezPending ? -1 : 0; | |
| 786 | } | |
| 787 | ||
| 788 | /// @details | |
| 789 | /// Submit some data bytes to send using the easy transmission mechanism. The | |
| 790 | /// data bytes will be copied to an internal buffer since the actual send may | |
| 791 | /// take place later than specified, and may need to be re-transmitted in case | |
| 792 | /// packets are lost of damaged in transit. | |
| 793 | /// | |
| 794 | /// Packets will be sent no faster than the rate specified in the | |
| 795 | /// rf12_easyInit() call, even if called more often. | |
| 796 | /// | |
| 797 | /// Only packets which differ from the previous packet will actually be sent. | |
| 798 | /// To force re-transmission even if the data hasn't changed, call | |
| 799 | /// "rf12_easySend(0,0)". This can be used to give a "sign of life" every once | |
| 800 | /// in a while, and to recover when the receiving node has been rebooted and no | |
| 801 | /// longer has the previous data. | |
| 802 | /// | |
| 803 | /// The return value indicates whether a new packet transmission will be started | |
| 804 | /// (1), or the data is the same as before and no send is needed (0). | |
| 805 | /// | |
| 806 | /// Note that you also have to call rf12_easyPoll periodically, because it keeps | |
| 807 | /// the RFM12B logic going. If you don't, rf12_easySend() will never send out | |
| 808 | /// any packets. | |
| 809 | /// @note To be used in combination with rf12_easyInit() and rf12_easyPoll(). | |
| 810 | char rf12_easySend (const void* data, uint8_t size) {
| |
| 811 | if (data != 0 && size != 0) {
| |
| 812 | if (ezNextSend[0] == 0 && size == ezSendLen && | |
| 813 | memcmp(ezSendBuf, data, size) == 0) | |
| 814 | return 0; | |
| 815 | memcpy(ezSendBuf, data, size); | |
| 816 | ezSendLen = size; | |
| 817 | } | |
| 818 | ezPending = RETRIES; | |
| 819 | return 1; | |
| 820 | } | |
| 821 | ||
| 822 | // XXTEA by David Wheeler, adapted from http://en.wikipedia.org/wiki/XXTEA | |
| 823 | ||
| 824 | #define DELTA 0x9E3779B9 | |
| 825 | #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + \ | |
| 826 | (cryptKey[(uint8_t)((p&3)^e)] ^ z))) | |
| 827 | ||
| 828 | static void cryptFun (uint8_t send) {
| |
| 829 | uint32_t y, z, sum, *v = (uint32_t*) rf12_data; | |
| 830 | uint8_t p, e, rounds = 6; | |
| 831 | ||
| 832 | if (send) {
| |
| 833 | // pad with 1..4-byte sequence number | |
| 834 | *(uint32_t*)(rf12_data + rf12_len) = ++seqNum; | |
| 835 | uint8_t pad = 3 - (rf12_len & 3); | |
| 836 | rf12_len += pad; | |
| 837 | rf12_data[rf12_len] &= 0x3F; | |
| 838 | rf12_data[rf12_len] |= pad << 6; | |
| 839 | ++rf12_len; | |
| 840 | // actual encoding | |
| 841 | char n = rf12_len / 4; | |
| 842 | if (n > 1) {
| |
| 843 | sum = 0; | |
| 844 | z = v[n-1]; | |
| 845 | do {
| |
| 846 | sum += DELTA; | |
| 847 | e = (sum >> 2) & 3; | |
| 848 | for (p=0; p<n-1; p++) | |
| 849 | y = v[p+1], z = v[p] += MX; | |
| 850 | y = v[0]; | |
| 851 | z = v[n-1] += MX; | |
| 852 | } while (--rounds); | |
| 853 | } | |
| 854 | } else if (rf12_crc == 0) {
| |
| 855 | // actual decoding | |
| 856 | char n = rf12_len / 4; | |
| 857 | if (n > 1) {
| |
| 858 | sum = rounds*DELTA; | |
| 859 | y = v[0]; | |
| 860 | do {
| |
| 861 | e = (sum >> 2) & 3; | |
| 862 | for (p=n-1; p>0; p--) | |
| 863 | z = v[p-1], y = v[p] -= MX; | |
| 864 | z = v[n-1]; | |
| 865 | y = v[0] -= MX; | |
| 866 | } while ((sum -= DELTA) != 0); | |
| 867 | } | |
| 868 | // strip sequence number from the end again | |
| 869 | if (n > 0) {
| |
| 870 | uint8_t pad = rf12_data[--rf12_len] >> 6; | |
| 871 | rf12_seq = rf12_data[rf12_len] & 0x3F; | |
| 872 | while (pad-- > 0) | |
| 873 | rf12_seq = (rf12_seq << 8) | rf12_data[--rf12_len]; | |
| 874 | } | |
| 875 | } | |
| 876 | } | |
| 877 | ||
| 878 | /// @details | |
| 879 | /// This enables or disables encryption using the public domain XXTEA algorithm | |
| 880 | /// by David Wheeler. The payload will be extended with 1 .. 4 bytes, containing | |
| 881 | /// a 6..30-bit sequence number which is incremented in the sender for each new | |
| 882 | /// packet. | |
| 883 | /// | |
| 884 | /// The number of bits sent across depends on the number of padding bytes needed | |
| 885 | /// to make the resulting payload an exact mulitple of 4 bytes. A longer | |
| 886 | /// sequence number field can provide more protection against replay attacks | |
| 887 | /// (note that verification of this sequence number must be implemented in the | |
| 888 | /// receiver code). | |
| 889 | /// | |
| 890 | /// Encrypted packets (and acknowledgements) must be 4..62 bytes long. Packets | |
| 891 | /// less than 4 bytes will not be encrypted. On reception, the payload length is | |
| 892 | /// adjusted back to the original length passed to rf12_sendStart(). | |
| 893 | /// | |
| 894 | /// There is a "long rf12seq" global which is set to the received sequence | |
| 895 | /// number (only valid right after rf12recvDone() returns true). When encryption | |
| 896 | /// is not enabled, this global is set to -1. | |
| 897 | /// @param key Pointer to a 16-byte (128-bit) encryption key to use for all | |
| 898 | /// packet data. A null pointer disables encryption again. Note: | |
| 899 | /// this is an EEPROM address, not RAM! - RF12_EEPROM_EKEY is a great | |
| 900 | /// value to use, as defined in the include file, but another address | |
| 901 | /// can be specified if needed. | |
| 902 | /// @see http://jeelabs.org/2010/02/23/secure-transmissions/ | |
| 903 | void rf12_encrypt (const uint8_t* key) {
| |
| 904 | // by using a pointer to cryptFun, we only link it in when actually used | |
| 905 | if (key != 0) {
| |
| 906 | for (uint8_t i = 0; i < sizeof cryptKey; ++i) | |
| 907 | ((uint8_t*) cryptKey)[i] = eeprom_read_byte(key + i); | |
| 908 | crypter = cryptFun; | |
| 909 | } else | |
| 910 | crypter = 0; | |
| 911 | } |