Library for HopeRF RFM22 transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/

Fork of RF22 by Karl Zweimüller

Committer:
floha
Date:
Thu Aug 29 21:57:14 2013 +0000
Revision:
9:46fb41f4259d
Parent:
8:d9e2ca137f2e
changed the LED default numbers in the RF22 constructor as the former values interfered with pins used on an KL25Z board. The library didn't work with those.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charly 0:79c6d0071c4c 1 // RF22.cpp
charly 0:79c6d0071c4c 2 //
charly 0:79c6d0071c4c 3 // Copyright (C) 2011 Mike McCauley
charly 5:0386600f3408 4 // $Id: RF22.cpp,v 1.17 2013/02/06 21:33:56 mikem Exp mikem $
charly 0:79c6d0071c4c 5 // ported to mbed by Karl Zweimueller
charly 0:79c6d0071c4c 6
charly 0:79c6d0071c4c 7
charly 0:79c6d0071c4c 8 #include "mbed.h"
charly 0:79c6d0071c4c 9 #include "RF22.h"
charly 0:79c6d0071c4c 10 //#include <SPI.h>
charly 0:79c6d0071c4c 11
charly 0:79c6d0071c4c 12
charly 0:79c6d0071c4c 13 // Interrupt vectors for the 2 Arduino interrupt pins
charly 0:79c6d0071c4c 14 // Each interrupt can be handled by a different instance of RF22, allowing you to have
charly 0:79c6d0071c4c 15 // 2 RF22s per Arduino
charly 0:79c6d0071c4c 16 //RF22* RF22::_RF22ForInterrupt[2] = {0, 0};
charly 0:79c6d0071c4c 17
charly 0:79c6d0071c4c 18 // These are indexed by the values of ModemConfigChoice
charly 8:d9e2ca137f2e 19 // Canned modem configurations generated with
charly 5:0386600f3408 20 // http://www.hoperf.com/upload/rf/RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
charly 0:79c6d0071c4c 21 // Stored in flash (program) memory to save SRAM
charly 8:d9e2ca137f2e 22 /*PROGMEM */ static const RF22::ModemConfig MODEM_CONFIG_TABLE[] = {
charly 0:79c6d0071c4c 23 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier
charly 0:79c6d0071c4c 24 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5
charly 0:79c6d0071c4c 25
charly 5:0386600f3408 26 // All the following enable FIFO with reg 71
charly 0:79c6d0071c4c 27 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72
charly 0:79c6d0071c4c 28 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
charly 0:79c6d0071c4c 29 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5
charly 0:79c6d0071c4c 30 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36
charly 0:79c6d0071c4c 31 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45
charly 0:79c6d0071c4c 32 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45
charly 0:79c6d0071c4c 33 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6
charly 0:79c6d0071c4c 34 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6
charly 0:79c6d0071c4c 35 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8
charly 0:79c6d0071c4c 36 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125
charly 0:79c6d0071c4c 37
charly 0:79c6d0071c4c 38 // GFSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
charly 0:79c6d0071c4c 39 // These differ from FSK only in register 71, for the modulation type
charly 0:79c6d0071c4c 40 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x23, 0x08 }, // 2, 5
charly 0:79c6d0071c4c 41 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x23, 0x3a }, // 2.4, 36
charly 0:79c6d0071c4c 42 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x23, 0x48 }, // 4.8, 45
charly 0:79c6d0071c4c 43 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x23, 0x48 }, // 9.6, 45
charly 0:79c6d0071c4c 44 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x23, 0x0f }, // 19.2, 9.6
charly 0:79c6d0071c4c 45 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x23, 0x1f }, // 38.4, 19.6
charly 0:79c6d0071c4c 46 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x23, 0x2e }, // 57.6. 28.8
charly 0:79c6d0071c4c 47 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x23, 0xc8 }, // 125, 125
charly 0:79c6d0071c4c 48
charly 0:79c6d0071c4c 49 // OOK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
charly 0:79c6d0071c4c 50 { 0x51, 0x03, 0x68, 0x00, 0x3a, 0x93, 0x01, 0x3d, 0x2c, 0x11, 0x28, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x21, 0x08 }, // 1.2, 75
charly 0:79c6d0071c4c 51 { 0xc8, 0x03, 0x39, 0x20, 0x68, 0xdc, 0x00, 0x6b, 0x2a, 0x08, 0x2a, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x21, 0x08 }, // 2.4, 335
charly 0:79c6d0071c4c 52 { 0xc8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x29, 0x04, 0x29, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x21, 0x08 }, // 4.8, 335
charly 0:79c6d0071c4c 53 { 0xb8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x82, 0x29, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x21, 0x08 }, // 9.6, 335
charly 0:79c6d0071c4c 54 { 0xa8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x41, 0x29, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x21, 0x08 }, // 19.2, 335
charly 0:79c6d0071c4c 55 { 0x98, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x20, 0x29, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x21, 0x08 }, // 38.4, 335
charly 0:79c6d0071c4c 56 { 0x98, 0x03, 0x96, 0x00, 0xda, 0x74, 0x00, 0xdc, 0x28, 0x1f, 0x29, 0x80, 0x60, 0x0a, 0x3d, 0x0c, 0x21, 0x08 }, // 40, 335
charly 0:79c6d0071c4c 57
charly 0:79c6d0071c4c 58 };
charly 0:79c6d0071c4c 59
charly 0:79c6d0071c4c 60 RF22::RF22(PinName slaveSelectPin, PinName mosi, PinName miso, PinName sclk, PinName interrupt)
floha 9:46fb41f4259d 61 : _slaveSelectPin(slaveSelectPin), _spi(mosi, miso, sclk), _interrupt(interrupt), led1(LED4), led2(LED2), led3(LED3), led4(LED4)
charly 0:79c6d0071c4c 62 {
charly 0:79c6d0071c4c 63
charly 0:79c6d0071c4c 64
charly 0:79c6d0071c4c 65 _idleMode = RF22_XTON; // Default idle state is READY mode
charly 0:79c6d0071c4c 66 _mode = RF22_MODE_IDLE; // We start up in idle mode
charly 0:79c6d0071c4c 67 _rxGood = 0;
charly 0:79c6d0071c4c 68 _rxBad = 0;
charly 0:79c6d0071c4c 69 _txGood = 0;
charly 8:d9e2ca137f2e 70
charly 8:d9e2ca137f2e 71
charly 0:79c6d0071c4c 72 }
charly 0:79c6d0071c4c 73
charly 0:79c6d0071c4c 74 boolean RF22::init()
charly 0:79c6d0071c4c 75 {
charly 0:79c6d0071c4c 76 // Wait for RF22 POR (up to 16msec)
charly 0:79c6d0071c4c 77 //delay(16);
charly 0:79c6d0071c4c 78 wait_ms(16);
charly 0:79c6d0071c4c 79
charly 0:79c6d0071c4c 80 // Initialise the slave select pin
charly 0:79c6d0071c4c 81 //pinMode(_slaveSelectPin, OUTPUT);
charly 0:79c6d0071c4c 82 //digitalWrite(_slaveSelectPin, HIGH);
charly 0:79c6d0071c4c 83 _slaveSelectPin = 1;
charly 8:d9e2ca137f2e 84
charly 0:79c6d0071c4c 85 wait_ms(100);
charly 8:d9e2ca137f2e 86
charly 0:79c6d0071c4c 87 // start the SPI library:
charly 0:79c6d0071c4c 88 // Note the RF22 wants mode 0, MSB first and default to 1 Mbps
charly 0:79c6d0071c4c 89 /*SPI.begin();
charly 0:79c6d0071c4c 90 SPI.setDataMode(SPI_MODE0);
charly 0:79c6d0071c4c 91 SPI.setBitOrder(MSBFIRST);
charly 0:79c6d0071c4c 92 SPI.setClockDivider(SPI_CLOCK_DIV16); // (16 Mhz / 16) = 1 MHz
charly 0:79c6d0071c4c 93 */
charly 0:79c6d0071c4c 94
charly 0:79c6d0071c4c 95 // Setup the spi for 8 bit data : 1RW-bit 7 adressbit and 8 databit
charly 0:79c6d0071c4c 96 // second edge capture, with a 10MHz clock rate
charly 0:79c6d0071c4c 97 _spi.format(8,0);
charly 0:79c6d0071c4c 98 _spi.frequency(10000000);
charly 0:79c6d0071c4c 99
charly 0:79c6d0071c4c 100 // Software reset the device
charly 0:79c6d0071c4c 101 reset();
charly 0:79c6d0071c4c 102
charly 0:79c6d0071c4c 103 // Get the device type and check it
charly 0:79c6d0071c4c 104 // This also tests whether we are really connected to a device
charly 0:79c6d0071c4c 105 _deviceType = spiRead(RF22_REG_00_DEVICE_TYPE);
charly 0:79c6d0071c4c 106 if ( _deviceType != RF22_DEVICE_TYPE_RX_TRX
charly 8:d9e2ca137f2e 107 && _deviceType != RF22_DEVICE_TYPE_TX)
charly 8:d9e2ca137f2e 108 return false;
charly 0:79c6d0071c4c 109
charly 0:79c6d0071c4c 110 // Set up interrupt handler
charly 0:79c6d0071c4c 111 // if (_interrupt == 0)
charly 0:79c6d0071c4c 112 // {
charly 0:79c6d0071c4c 113 //_RF22ForInterrupt[0] = this;
charly 8:d9e2ca137f2e 114 //attachInterrupt(0, RF22::isr0, LOW);
charly 0:79c6d0071c4c 115 _interrupt.fall(this, &RF22::isr0);
charly 8:d9e2ca137f2e 116 /* }
charly 8:d9e2ca137f2e 117 else if (_interrupt == 1)
charly 8:d9e2ca137f2e 118 {
charly 8:d9e2ca137f2e 119 _RF22ForInterrupt[1] = this;
charly 8:d9e2ca137f2e 120 attachInterrupt(1, RF22::isr1, LOW);
charly 8:d9e2ca137f2e 121 }
charly 8:d9e2ca137f2e 122 else
charly 8:d9e2ca137f2e 123 return false;
charly 8:d9e2ca137f2e 124 */
charly 0:79c6d0071c4c 125 clearTxBuf();
charly 0:79c6d0071c4c 126 clearRxBuf();
charly 8:d9e2ca137f2e 127
charly 0:79c6d0071c4c 128 // Most of these are the POR default
charly 0:79c6d0071c4c 129 spiWrite(RF22_REG_7D_TX_FIFO_CONTROL2, RF22_TXFFAEM_THRESHOLD);
charly 0:79c6d0071c4c 130 spiWrite(RF22_REG_7E_RX_FIFO_CONTROL, RF22_RXFFAFULL_THRESHOLD);
charly 0:79c6d0071c4c 131 spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_ENPACRX | RF22_ENPACTX | RF22_ENCRC | RF22_CRC_CRC_16_IBM);
charly 0:79c6d0071c4c 132 // Configure the message headers
charly 0:79c6d0071c4c 133 // Here we set up the standard packet format for use by the RF22 library
charly 0:79c6d0071c4c 134 // 8 nibbles preamble
charly 0:79c6d0071c4c 135 // 2 SYNC words 2d, d4
charly 0:79c6d0071c4c 136 // Header length 4 (to, from, id, flags)
charly 0:79c6d0071c4c 137 // 1 octet of data length (0 to 255)
charly 0:79c6d0071c4c 138 // 0 to 255 octets data
charly 0:79c6d0071c4c 139 // 2 CRC octets as CRC16(IBM), computed on the header, length and data
charly 0:79c6d0071c4c 140 // On reception the to address is check for validity against RF22_REG_3F_CHECK_HEADER3
charly 0:79c6d0071c4c 141 // or the broadcast address of 0xff
charly 0:79c6d0071c4c 142 // If no changes are made after this, the transmitted
charly 0:79c6d0071c4c 143 // to address will be 0xff, the from address will be 0xff
charly 0:79c6d0071c4c 144 // and all such messages will be accepted. This permits the out-of the box
charly 0:79c6d0071c4c 145 // RF22 config to act as an unaddresed, unreliable datagram service
charly 0:79c6d0071c4c 146 spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_HEADER3 | RF22_HDCH_HEADER3);
charly 0:79c6d0071c4c 147 spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_4 | RF22_SYNCLEN_2);
charly 0:79c6d0071c4c 148 setPreambleLength(8);
charly 0:79c6d0071c4c 149 uint8_t syncwords[] = { 0x2d, 0xd4 };
charly 0:79c6d0071c4c 150 setSyncWords(syncwords, sizeof(syncwords));
charly 8:d9e2ca137f2e 151 setPromiscuous(false);
charly 0:79c6d0071c4c 152 // Check the TO header against RF22_DEFAULT_NODE_ADDRESS
charly 0:79c6d0071c4c 153 spiWrite(RF22_REG_3F_CHECK_HEADER3, RF22_DEFAULT_NODE_ADDRESS);
charly 0:79c6d0071c4c 154 // Set the default transmit header values
charly 0:79c6d0071c4c 155 setHeaderTo(RF22_DEFAULT_NODE_ADDRESS);
charly 0:79c6d0071c4c 156 setHeaderFrom(RF22_DEFAULT_NODE_ADDRESS);
charly 0:79c6d0071c4c 157 setHeaderId(0);
charly 0:79c6d0071c4c 158 setHeaderFlags(0);
charly 0:79c6d0071c4c 159
charly 0:79c6d0071c4c 160 // Ensure the antenna can be switched automatically according to transmit and receive
charly 0:79c6d0071c4c 161 // This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
charly 0:79c6d0071c4c 162 // This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive
charly 0:79c6d0071c4c 163 spiWrite (RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state
charly 0:79c6d0071c4c 164 spiWrite (RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state
charly 0:79c6d0071c4c 165
charly 0:79c6d0071c4c 166 // Enable interrupts
charly 8:d9e2ca137f2e 167 // this is original from arduion, which crashes on mbed after some hours
charly 8:d9e2ca137f2e 168 //see https://groups.google.com/forum/?fromgroups#!topic/rf22-arduino/Ezkw256yQI8
charly 8:d9e2ca137f2e 169 //spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM | RF22_ENRXFFAFULL | RF22_ENPKSENT | RF22_ENPKVALID | RF22_ENCRCERROR | RF22_ENFFERR);
charly 8:d9e2ca137f2e 170 //without RF22_ENFFERR it works - Charly
charly 8:d9e2ca137f2e 171 spiWrite(RF22_REG_05_INTERRUPT_ENABLE1, RF22_ENTXFFAEM |RF22_ENRXFFAFULL | RF22_ENPKSENT |RF22_ENPKVALID| RF22_ENCRCERROR);
charly 8:d9e2ca137f2e 172
charly 0:79c6d0071c4c 173 spiWrite(RF22_REG_06_INTERRUPT_ENABLE2, RF22_ENPREAVAL);
charly 0:79c6d0071c4c 174
charly 8:d9e2ca137f2e 175
charly 5:0386600f3408 176 // Set some defaults. An innocuous ISM frequency, and reasonable pull-in
charly 5:0386600f3408 177 setFrequency(434.0, 0.05);
charly 0:79c6d0071c4c 178 // setFrequency(900.0);
charly 0:79c6d0071c4c 179 // Some slow, reliable default speed and modulation
charly 0:79c6d0071c4c 180 setModemConfig(FSK_Rb2_4Fd36);
charly 0:79c6d0071c4c 181 // setModemConfig(FSK_Rb125Fd125);
charly 0:79c6d0071c4c 182 // Minimum power
charly 0:79c6d0071c4c 183 setTxPower(RF22_TXPOW_8DBM);
charly 0:79c6d0071c4c 184 // setTxPower(RF22_TXPOW_17DBM);
charly 0:79c6d0071c4c 185
charly 8:d9e2ca137f2e 186
charly 2:f6f42c2ba9f2 187
charly 0:79c6d0071c4c 188 return true;
charly 0:79c6d0071c4c 189 }
charly 0:79c6d0071c4c 190
charly 0:79c6d0071c4c 191 // C++ level interrupt handler for this instance
charly 0:79c6d0071c4c 192 void RF22::handleInterrupt()
charly 0:79c6d0071c4c 193 {
charly 0:79c6d0071c4c 194 uint8_t _lastInterruptFlags[2];
charly 8:d9e2ca137f2e 195
charly 8:d9e2ca137f2e 196 led1 = 1;
charly 8:d9e2ca137f2e 197
charly 0:79c6d0071c4c 198 // Read the interrupt flags which clears the interrupt
charly 0:79c6d0071c4c 199 spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2);
charly 0:79c6d0071c4c 200
charly 0:79c6d0071c4c 201 #if 0
charly 5:0386600f3408 202 // Caution: Serial printing in this interrupt routine can cause mysterious crashes
charly 5:0386600f3408 203 Serial.print("interrupt ");
charly 0:79c6d0071c4c 204 Serial.print(_lastInterruptFlags[0], HEX);
charly 0:79c6d0071c4c 205 Serial.print(" ");
charly 0:79c6d0071c4c 206 Serial.println(_lastInterruptFlags[1], HEX);
charly 0:79c6d0071c4c 207 if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0)
charly 8:d9e2ca137f2e 208 Serial.println("FUNNY: no interrupt!");
charly 0:79c6d0071c4c 209 #endif
charly 0:79c6d0071c4c 210
charly 5:0386600f3408 211 #if 0
charly 0:79c6d0071c4c 212 // TESTING: fake an RF22_IFFERROR
charly 0:79c6d0071c4c 213 static int counter = 0;
charly 8:d9e2ca137f2e 214 if (_lastInterruptFlags[0] & RF22_IPKSENT && counter++ == 10) {
charly 8:d9e2ca137f2e 215 _lastInterruptFlags[0] = RF22_IFFERROR;
charly 8:d9e2ca137f2e 216 counter = 0;
charly 0:79c6d0071c4c 217 }
charly 5:0386600f3408 218 #endif
charly 0:79c6d0071c4c 219
charly 8:d9e2ca137f2e 220
charly 8:d9e2ca137f2e 221 if (_lastInterruptFlags[0] & RF22_IFFERROR) {
charly 8:d9e2ca137f2e 222 // Serial.println("IFFERROR");
charly 8:d9e2ca137f2e 223 led4 = !led4;
charly 8:d9e2ca137f2e 224 resetFifos(); // Clears the interrupt
charly 8:d9e2ca137f2e 225 if (_mode == RF22_MODE_TX)
charly 8:d9e2ca137f2e 226 restartTransmit();
charly 8:d9e2ca137f2e 227 else if (_mode == RF22_MODE_RX){
charly 8:d9e2ca137f2e 228 clearRxBuf();
charly 8:d9e2ca137f2e 229 //stop and start Rx
charly 8:d9e2ca137f2e 230 setModeIdle();
charly 8:d9e2ca137f2e 231 setModeRx();
charly 8:d9e2ca137f2e 232 }
charly 8:d9e2ca137f2e 233 // stop handling the remaining interruppts as something went wrong here
charly 8:d9e2ca137f2e 234 return;
charly 0:79c6d0071c4c 235 }
charly 8:d9e2ca137f2e 236
charly 8:d9e2ca137f2e 237 // Caution, any delay here may cause a FF underflow or overflow
charly 8:d9e2ca137f2e 238 if (_lastInterruptFlags[0] & RF22_ITXFFAEM) {
charly 8:d9e2ca137f2e 239 // See if more data has to be loaded into the Tx FIFO
charly 8:d9e2ca137f2e 240 //led2 = !led2;
charly 8:d9e2ca137f2e 241 sendNextFragment();
charly 8:d9e2ca137f2e 242 // Serial.println("ITXFFAEM");
charly 0:79c6d0071c4c 243 }
charly 8:d9e2ca137f2e 244
charly 8:d9e2ca137f2e 245 if (_lastInterruptFlags[0] & RF22_IRXFFAFULL) {
charly 8:d9e2ca137f2e 246 // Caution, any delay here may cause a FF overflow
charly 8:d9e2ca137f2e 247 // Read some data from the Rx FIFO
charly 8:d9e2ca137f2e 248 //led4 = !led4;
charly 8:d9e2ca137f2e 249 readNextFragment();
charly 8:d9e2ca137f2e 250 // Serial.println("IRXFFAFULL");
charly 8:d9e2ca137f2e 251 }
charly 8:d9e2ca137f2e 252 if (_lastInterruptFlags[0] & RF22_IEXT) {
charly 8:d9e2ca137f2e 253 // This is not enabled by the base code, but users may want to enable it
charly 8:d9e2ca137f2e 254 //led2 = !led2;
charly 8:d9e2ca137f2e 255 handleExternalInterrupt();
charly 8:d9e2ca137f2e 256 // Serial.println("IEXT");
charly 0:79c6d0071c4c 257 }
charly 8:d9e2ca137f2e 258 if (_lastInterruptFlags[1] & RF22_IWUT) {
charly 8:d9e2ca137f2e 259 // This is not enabled by the base code, but users may want to enable it
charly 8:d9e2ca137f2e 260 //led2 = !led2;
charly 8:d9e2ca137f2e 261 handleWakeupTimerInterrupt();
charly 8:d9e2ca137f2e 262 // Serial.println("IWUT");
charly 8:d9e2ca137f2e 263 }
charly 8:d9e2ca137f2e 264 if (_lastInterruptFlags[0] & RF22_IPKSENT) {
charly 8:d9e2ca137f2e 265 // Serial.println("IPKSENT");
charly 8:d9e2ca137f2e 266 _txGood++;
charly 8:d9e2ca137f2e 267 //led4 = !led4;
charly 8:d9e2ca137f2e 268 // Transmission does not automatically clear the tx buffer.
charly 8:d9e2ca137f2e 269 // Could retransmit if we wanted
charly 8:d9e2ca137f2e 270 // RF22 transitions automatically to Idle
charly 8:d9e2ca137f2e 271 _mode = RF22_MODE_IDLE;
charly 0:79c6d0071c4c 272 }
charly 8:d9e2ca137f2e 273
charly 8:d9e2ca137f2e 274 if (_lastInterruptFlags[0] & RF22_IPKVALID) {
charly 8:d9e2ca137f2e 275 uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH);
charly 8:d9e2ca137f2e 276 // Serial.println("IPKVALID");
charly 8:d9e2ca137f2e 277 // Serial.println(len);
charly 8:d9e2ca137f2e 278 // Serial.println(_bufLen);
charly 5:0386600f3408 279
charly 8:d9e2ca137f2e 280 // May have already read one or more fragments
charly 8:d9e2ca137f2e 281 // Get any remaining unread octets, based on the expected length
charly 8:d9e2ca137f2e 282 // First make sure we dont overflow the buffer in the case of a stupid length
charly 8:d9e2ca137f2e 283 // or partial bad receives
charly 8:d9e2ca137f2e 284
charly 8:d9e2ca137f2e 285 if ( len > RF22_MAX_MESSAGE_LEN
charly 8:d9e2ca137f2e 286 || len < _bufLen) {
charly 8:d9e2ca137f2e 287 _rxBad++;
charly 8:d9e2ca137f2e 288 led2 = !led2;
charly 8:d9e2ca137f2e 289 _mode = RF22_MODE_IDLE;
charly 8:d9e2ca137f2e 290 clearRxBuf();
charly 8:d9e2ca137f2e 291 return; // Hmmm receiver buffer overflow.
charly 8:d9e2ca137f2e 292 }
charly 8:d9e2ca137f2e 293
charly 8:d9e2ca137f2e 294 spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen);
charly 8:d9e2ca137f2e 295 //__disable_irq(); // Disable Interrupts
charly 8:d9e2ca137f2e 296 _rxGood++;
charly 8:d9e2ca137f2e 297 _bufLen = len;
charly 5:0386600f3408 298 _mode = RF22_MODE_IDLE;
charly 8:d9e2ca137f2e 299 _rxBufValid = true;
charly 8:d9e2ca137f2e 300 // reset the fifo for next packet??
charly 8:d9e2ca137f2e 301 //resetRxFifo();
charly 8:d9e2ca137f2e 302 //__enable_irq(); // Enable Interrupts
charly 5:0386600f3408 303
charly 8:d9e2ca137f2e 304 led3 = !led3;
charly 5:0386600f3408 305
charly 0:79c6d0071c4c 306 }
charly 8:d9e2ca137f2e 307
charly 8:d9e2ca137f2e 308 if (_lastInterruptFlags[0] & RF22_ICRCERROR) {
charly 8:d9e2ca137f2e 309 // Serial.println("ICRCERR");
charly 8:d9e2ca137f2e 310 _rxBad++;
charly 8:d9e2ca137f2e 311 led2 = !led2;
charly 8:d9e2ca137f2e 312 clearRxBuf();
charly 8:d9e2ca137f2e 313 resetRxFifo();
charly 8:d9e2ca137f2e 314 _mode = RF22_MODE_IDLE;
charly 8:d9e2ca137f2e 315 setModeRx(); // Keep trying
charly 0:79c6d0071c4c 316 }
charly 8:d9e2ca137f2e 317
charly 8:d9e2ca137f2e 318 if (_lastInterruptFlags[1] & RF22_IPREAVAL) {
charly 8:d9e2ca137f2e 319 // Serial.println("IPREAVAL");
charly 8:d9e2ca137f2e 320
charly 8:d9e2ca137f2e 321 _lastRssi = spiRead(RF22_REG_26_RSSI);
charly 8:d9e2ca137f2e 322
charly 8:d9e2ca137f2e 323
charly 8:d9e2ca137f2e 324 // why clear the rx-buf here? charly
charly 8:d9e2ca137f2e 325 clearRxBuf();
charly 8:d9e2ca137f2e 326
charly 8:d9e2ca137f2e 327
charly 0:79c6d0071c4c 328 }
charly 7:b86825b9d74b 329 led1 = 0;
charly 0:79c6d0071c4c 330 }
charly 0:79c6d0071c4c 331
charly 0:79c6d0071c4c 332 // These are low level functions that call the interrupt handler for the correct
charly 0:79c6d0071c4c 333 // instance of RF22.
charly 0:79c6d0071c4c 334 // 2 interrupts allows us to have 2 different devices
charly 0:79c6d0071c4c 335 void RF22::isr0()
charly 0:79c6d0071c4c 336 {
charly 0:79c6d0071c4c 337 //if (_RF22ForInterrupt[0])
charly 0:79c6d0071c4c 338 //_RF22ForInterrupt[0]->handleInterrupt();
charly 0:79c6d0071c4c 339 handleInterrupt();
charly 0:79c6d0071c4c 340 }
charly 0:79c6d0071c4c 341 /*
charly 0:79c6d0071c4c 342 void RF22::isr1()
charly 0:79c6d0071c4c 343 {
charly 0:79c6d0071c4c 344 if (_RF22ForInterrupt[1])
charly 0:79c6d0071c4c 345 _RF22ForInterrupt[1]->handleInterrupt();
charly 0:79c6d0071c4c 346 }
charly 0:79c6d0071c4c 347 */
charly 0:79c6d0071c4c 348 void RF22::reset()
charly 0:79c6d0071c4c 349 {
charly 0:79c6d0071c4c 350 spiWrite(RF22_REG_07_OPERATING_MODE1, RF22_SWRES);
charly 0:79c6d0071c4c 351 // Wait for it to settle
charly 0:79c6d0071c4c 352 //delay(1); // SWReset time is nominally 100usec
charly 0:79c6d0071c4c 353 wait_ms(1);
charly 0:79c6d0071c4c 354 }
charly 0:79c6d0071c4c 355
charly 0:79c6d0071c4c 356 uint8_t RF22::spiRead(uint8_t reg)
charly 0:79c6d0071c4c 357 {
charly 7:b86825b9d74b 358 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 359 //digitalWrite(_slaveSelectPin, LOW);
charly 0:79c6d0071c4c 360 _slaveSelectPin=0;
charly 0:79c6d0071c4c 361 //_spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the address with the write mask off
charly 0:79c6d0071c4c 362 _spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the address with the write mask off
charly 0:79c6d0071c4c 363 uint8_t val = _spi.write(0); // The written value is ignored, reg value is read
charly 0:79c6d0071c4c 364 //digitalWrite(_slaveSelectPin, HIGH);
charly 0:79c6d0071c4c 365 _slaveSelectPin = 1;
charly 7:b86825b9d74b 366 __enable_irq(); // Enable Interrupts
charly 0:79c6d0071c4c 367 return val;
charly 0:79c6d0071c4c 368 }
charly 0:79c6d0071c4c 369
charly 0:79c6d0071c4c 370 void RF22::spiWrite(uint8_t reg, uint8_t val)
charly 0:79c6d0071c4c 371 {
charly 7:b86825b9d74b 372 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 373 //digitalWrite(_slaveSelectPin, LOW);
charly 0:79c6d0071c4c 374 _slaveSelectPin = 0;
charly 0:79c6d0071c4c 375 _spi.write(reg | RF22_SPI_WRITE_MASK); // Send the address with the write mask on
charly 0:79c6d0071c4c 376 _spi.write(val); // New value follows
charly 0:79c6d0071c4c 377 //digitalWrite(_slaveSelectPin, HIGH);
charly 0:79c6d0071c4c 378 _slaveSelectPin = 1;
charly 7:b86825b9d74b 379 __enable_irq(); // Enable Interrupts
charly 0:79c6d0071c4c 380 }
charly 0:79c6d0071c4c 381
charly 0:79c6d0071c4c 382 void RF22::spiBurstRead(uint8_t reg, uint8_t* dest, uint8_t len)
charly 0:79c6d0071c4c 383 {
charly 0:79c6d0071c4c 384 //digitalWrite(_slaveSelectPin, LOW);
charly 0:79c6d0071c4c 385 _slaveSelectPin = 0;
charly 0:79c6d0071c4c 386 _spi.write(reg & ~RF22_SPI_WRITE_MASK); // Send the start address with the write mask off
charly 0:79c6d0071c4c 387 while (len--)
charly 8:d9e2ca137f2e 388 *dest++ = _spi.write(0);
charly 0:79c6d0071c4c 389 //digitalWrite(_slaveSelectPin, HIGH);
charly 0:79c6d0071c4c 390 _slaveSelectPin = 1;
charly 0:79c6d0071c4c 391 }
charly 0:79c6d0071c4c 392
charly 5:0386600f3408 393 void RF22::spiBurstWrite(uint8_t reg, const uint8_t* src, uint8_t len)
charly 0:79c6d0071c4c 394 {
charly 0:79c6d0071c4c 395 //digitalWrite(_slaveSelectPin, LOW);
charly 0:79c6d0071c4c 396 _slaveSelectPin = 0;
charly 0:79c6d0071c4c 397 _spi.write(reg | RF22_SPI_WRITE_MASK); // Send the start address with the write mask on
charly 0:79c6d0071c4c 398 while (len--)
charly 8:d9e2ca137f2e 399 _spi.write(*src++);
charly 0:79c6d0071c4c 400 //digitalWrite(_slaveSelectPin, HIGH);
charly 0:79c6d0071c4c 401 _slaveSelectPin = 1;
charly 0:79c6d0071c4c 402 }
charly 0:79c6d0071c4c 403
charly 0:79c6d0071c4c 404 uint8_t RF22::statusRead()
charly 0:79c6d0071c4c 405 {
charly 0:79c6d0071c4c 406 return spiRead(RF22_REG_02_DEVICE_STATUS);
charly 0:79c6d0071c4c 407 }
charly 0:79c6d0071c4c 408
charly 0:79c6d0071c4c 409 uint8_t RF22::adcRead(uint8_t adcsel,
charly 0:79c6d0071c4c 410 uint8_t adcref ,
charly 8:d9e2ca137f2e 411 uint8_t adcgain,
charly 0:79c6d0071c4c 412 uint8_t adcoffs)
charly 0:79c6d0071c4c 413 {
charly 0:79c6d0071c4c 414 uint8_t configuration = adcsel | adcref | (adcgain & RF22_ADCGAIN);
charly 0:79c6d0071c4c 415 spiWrite(RF22_REG_0F_ADC_CONFIGURATION, configuration | RF22_ADCSTART);
charly 0:79c6d0071c4c 416 spiWrite(RF22_REG_10_ADC_SENSOR_AMP_OFFSET, adcoffs);
charly 0:79c6d0071c4c 417
charly 0:79c6d0071c4c 418 // Conversion time is nominally 305usec
charly 0:79c6d0071c4c 419 // Wait for the DONE bit
charly 0:79c6d0071c4c 420 while (!(spiRead(RF22_REG_0F_ADC_CONFIGURATION) & RF22_ADCDONE))
charly 8:d9e2ca137f2e 421 ;
charly 8:d9e2ca137f2e 422 // Return the value
charly 0:79c6d0071c4c 423 return spiRead(RF22_REG_11_ADC_VALUE);
charly 0:79c6d0071c4c 424 }
charly 0:79c6d0071c4c 425
charly 0:79c6d0071c4c 426 uint8_t RF22::temperatureRead(uint8_t tsrange, uint8_t tvoffs)
charly 0:79c6d0071c4c 427 {
charly 0:79c6d0071c4c 428 spiWrite(RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RF22_ENTSOFFS);
charly 0:79c6d0071c4c 429 spiWrite(RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs);
charly 8:d9e2ca137f2e 430 return adcRead(RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RF22_ADCREF_BANDGAP_VOLTAGE);
charly 0:79c6d0071c4c 431 }
charly 0:79c6d0071c4c 432
charly 0:79c6d0071c4c 433 uint16_t RF22::wutRead()
charly 0:79c6d0071c4c 434 {
charly 0:79c6d0071c4c 435 uint8_t buf[2];
charly 0:79c6d0071c4c 436 spiBurstRead(RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2);
charly 0:79c6d0071c4c 437 return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order
charly 0:79c6d0071c4c 438 }
charly 0:79c6d0071c4c 439
charly 0:79c6d0071c4c 440 // RFM-22 doc appears to be wrong: WUT for wtm = 10000, r, = 0, d = 0 is about 1 sec
charly 0:79c6d0071c4c 441 void RF22::setWutPeriod(uint16_t wtm, uint8_t wtr, uint8_t wtd)
charly 0:79c6d0071c4c 442 {
charly 0:79c6d0071c4c 443 uint8_t period[3];
charly 0:79c6d0071c4c 444
charly 0:79c6d0071c4c 445 period[0] = ((wtr & 0xf) << 2) | (wtd & 0x3);
charly 0:79c6d0071c4c 446 period[1] = wtm >> 8;
charly 0:79c6d0071c4c 447 period[2] = wtm & 0xff;
charly 0:79c6d0071c4c 448 spiBurstWrite(RF22_REG_14_WAKEUP_TIMER_PERIOD1, period, sizeof(period));
charly 0:79c6d0071c4c 449 }
charly 0:79c6d0071c4c 450
charly 0:79c6d0071c4c 451 // Returns true if centre + (fhch * fhs) is within limits
charly 5:0386600f3408 452 // Caution, different versions of the RF22 support different max freq
charly 0:79c6d0071c4c 453 // so YMMV
charly 5:0386600f3408 454 boolean RF22::setFrequency(float centre, float afcPullInRange)
charly 0:79c6d0071c4c 455 {
charly 0:79c6d0071c4c 456 uint8_t fbsel = RF22_SBSEL;
charly 5:0386600f3408 457 uint8_t afclimiter;
charly 0:79c6d0071c4c 458 if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon
charly 5:0386600f3408 459 return false;
charly 8:d9e2ca137f2e 460 if (centre >= 480.0) {
charly 8:d9e2ca137f2e 461 if (afcPullInRange < 0.0 || afcPullInRange > 0.318750)
charly 8:d9e2ca137f2e 462 return false;
charly 8:d9e2ca137f2e 463 centre /= 2;
charly 8:d9e2ca137f2e 464 fbsel |= RF22_HBSEL;
charly 8:d9e2ca137f2e 465 afclimiter = afcPullInRange * 1000000.0 / 1250.0;
charly 8:d9e2ca137f2e 466 } else {
charly 8:d9e2ca137f2e 467 if (afcPullInRange < 0.0 || afcPullInRange > 0.159375)
charly 8:d9e2ca137f2e 468 return false;
charly 8:d9e2ca137f2e 469 afclimiter = afcPullInRange * 1000000.0 / 625.0;
charly 0:79c6d0071c4c 470 }
charly 0:79c6d0071c4c 471 centre /= 10.0;
charly 0:79c6d0071c4c 472 float integerPart = floor(centre);
charly 0:79c6d0071c4c 473 float fractionalPart = centre - integerPart;
charly 0:79c6d0071c4c 474
charly 0:79c6d0071c4c 475 uint8_t fb = (uint8_t)integerPart - 24; // Range 0 to 23
charly 0:79c6d0071c4c 476 fbsel |= fb;
charly 0:79c6d0071c4c 477 uint16_t fc = fractionalPart * 64000;
charly 0:79c6d0071c4c 478 spiWrite(RF22_REG_73_FREQUENCY_OFFSET1, 0); // REVISIT
charly 0:79c6d0071c4c 479 spiWrite(RF22_REG_74_FREQUENCY_OFFSET2, 0);
charly 0:79c6d0071c4c 480 spiWrite(RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel);
charly 0:79c6d0071c4c 481 spiWrite(RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8);
charly 0:79c6d0071c4c 482 spiWrite(RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff);
charly 5:0386600f3408 483 spiWrite(RF22_REG_2A_AFC_LIMITER, afclimiter);
charly 0:79c6d0071c4c 484 return !(statusRead() & RF22_FREQERR);
charly 0:79c6d0071c4c 485 }
charly 0:79c6d0071c4c 486
charly 0:79c6d0071c4c 487 // Step size in 10kHz increments
charly 0:79c6d0071c4c 488 // Returns true if centre + (fhch * fhs) is within limits
charly 0:79c6d0071c4c 489 boolean RF22::setFHStepSize(uint8_t fhs)
charly 0:79c6d0071c4c 490 {
charly 0:79c6d0071c4c 491 spiWrite(RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE, fhs);
charly 0:79c6d0071c4c 492 return !(statusRead() & RF22_FREQERR);
charly 0:79c6d0071c4c 493 }
charly 0:79c6d0071c4c 494
charly 0:79c6d0071c4c 495 // Adds fhch * fhs to centre frequency
charly 0:79c6d0071c4c 496 // Returns true if centre + (fhch * fhs) is within limits
charly 0:79c6d0071c4c 497 boolean RF22::setFHChannel(uint8_t fhch)
charly 0:79c6d0071c4c 498 {
charly 0:79c6d0071c4c 499 spiWrite(RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT, fhch);
charly 0:79c6d0071c4c 500 return !(statusRead() & RF22_FREQERR);
charly 0:79c6d0071c4c 501 }
charly 0:79c6d0071c4c 502
charly 0:79c6d0071c4c 503 uint8_t RF22::rssiRead()
charly 0:79c6d0071c4c 504 {
charly 0:79c6d0071c4c 505 return spiRead(RF22_REG_26_RSSI);
charly 0:79c6d0071c4c 506 }
charly 0:79c6d0071c4c 507
charly 0:79c6d0071c4c 508 uint8_t RF22::ezmacStatusRead()
charly 0:79c6d0071c4c 509 {
charly 0:79c6d0071c4c 510 return spiRead(RF22_REG_31_EZMAC_STATUS);
charly 0:79c6d0071c4c 511 }
charly 0:79c6d0071c4c 512
charly 0:79c6d0071c4c 513 void RF22::setMode(uint8_t mode)
charly 0:79c6d0071c4c 514 {
charly 0:79c6d0071c4c 515 spiWrite(RF22_REG_07_OPERATING_MODE1, mode);
charly 0:79c6d0071c4c 516 }
charly 0:79c6d0071c4c 517
charly 0:79c6d0071c4c 518 void RF22::setModeIdle()
charly 0:79c6d0071c4c 519 {
charly 8:d9e2ca137f2e 520 if (_mode != RF22_MODE_IDLE) {
charly 8:d9e2ca137f2e 521 setMode(_idleMode);
charly 8:d9e2ca137f2e 522 _mode = RF22_MODE_IDLE;
charly 0:79c6d0071c4c 523 }
charly 0:79c6d0071c4c 524 }
charly 0:79c6d0071c4c 525
charly 0:79c6d0071c4c 526 void RF22::setModeRx()
charly 0:79c6d0071c4c 527 {
charly 8:d9e2ca137f2e 528 if (_mode != RF22_MODE_RX) {
charly 8:d9e2ca137f2e 529 setMode(_idleMode | RF22_RXON);
charly 8:d9e2ca137f2e 530 _mode = RF22_MODE_RX;
charly 0:79c6d0071c4c 531 }
charly 0:79c6d0071c4c 532 }
charly 0:79c6d0071c4c 533
charly 0:79c6d0071c4c 534 void RF22::setModeTx()
charly 0:79c6d0071c4c 535 {
charly 8:d9e2ca137f2e 536 if (_mode != RF22_MODE_TX) {
charly 8:d9e2ca137f2e 537 setMode(_idleMode | RF22_TXON);
charly 8:d9e2ca137f2e 538 _mode = RF22_MODE_TX;
charly 8:d9e2ca137f2e 539 // Hmmm, if you dont clear the RX FIFO here, then it appears that going
charly 8:d9e2ca137f2e 540 // to transmit mode in the middle of a receive can corrupt the
charly 8:d9e2ca137f2e 541 // RX FIFO
charly 8:d9e2ca137f2e 542 resetRxFifo();
charly 8:d9e2ca137f2e 543 // clearRxBuf();
charly 0:79c6d0071c4c 544 }
charly 8:d9e2ca137f2e 545 }
charly 5:0386600f3408 546
charly 5:0386600f3408 547 uint8_t RF22::mode()
charly 5:0386600f3408 548 {
charly 5:0386600f3408 549 return _mode;
charly 0:79c6d0071c4c 550 }
charly 0:79c6d0071c4c 551
charly 0:79c6d0071c4c 552 void RF22::setTxPower(uint8_t power)
charly 0:79c6d0071c4c 553 {
charly 0:79c6d0071c4c 554 spiWrite(RF22_REG_6D_TX_POWER, power);
charly 0:79c6d0071c4c 555 }
charly 0:79c6d0071c4c 556
charly 0:79c6d0071c4c 557 // Sets registers from a canned modem configuration structure
charly 5:0386600f3408 558 void RF22::setModemRegisters(const ModemConfig* config)
charly 0:79c6d0071c4c 559 {
charly 0:79c6d0071c4c 560 spiWrite(RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c);
charly 0:79c6d0071c4c 561 spiWrite(RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f);
charly 0:79c6d0071c4c 562 spiBurstWrite(RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE, &config->reg_20, 6);
charly 0:79c6d0071c4c 563 spiBurstWrite(RF22_REG_2C_OOK_COUNTER_VALUE_1, &config->reg_2c, 3);
charly 0:79c6d0071c4c 564 spiWrite(RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING, config->reg_58);
charly 0:79c6d0071c4c 565 spiWrite(RF22_REG_69_AGC_OVERRIDE1, config->reg_69);
charly 0:79c6d0071c4c 566 spiBurstWrite(RF22_REG_6E_TX_DATA_RATE1, &config->reg_6e, 5);
charly 0:79c6d0071c4c 567 }
charly 0:79c6d0071c4c 568
charly 0:79c6d0071c4c 569 // Set one of the canned FSK Modem configs
charly 0:79c6d0071c4c 570 // Returns true if its a valid choice
charly 0:79c6d0071c4c 571 boolean RF22::setModemConfig(ModemConfigChoice index)
charly 0:79c6d0071c4c 572 {
charly 0:79c6d0071c4c 573 if (index > (sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
charly 0:79c6d0071c4c 574 return false;
charly 0:79c6d0071c4c 575
charly 0:79c6d0071c4c 576 RF22::ModemConfig cfg;
charly 0:79c6d0071c4c 577 memcpy(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RF22::ModemConfig));
charly 0:79c6d0071c4c 578 setModemRegisters(&cfg);
charly 0:79c6d0071c4c 579
charly 0:79c6d0071c4c 580 return true;
charly 0:79c6d0071c4c 581 }
charly 0:79c6d0071c4c 582
charly 0:79c6d0071c4c 583 // REVISIT: top bit is in Header Control 2 0x33
charly 0:79c6d0071c4c 584 void RF22::setPreambleLength(uint8_t nibbles)
charly 0:79c6d0071c4c 585 {
charly 0:79c6d0071c4c 586 spiWrite(RF22_REG_34_PREAMBLE_LENGTH, nibbles);
charly 0:79c6d0071c4c 587 }
charly 0:79c6d0071c4c 588
charly 0:79c6d0071c4c 589 // Caution doesnt set sync word len in Header Control 2 0x33
charly 5:0386600f3408 590 void RF22::setSyncWords(const uint8_t* syncWords, uint8_t len)
charly 0:79c6d0071c4c 591 {
charly 0:79c6d0071c4c 592 spiBurstWrite(RF22_REG_36_SYNC_WORD3, syncWords, len);
charly 0:79c6d0071c4c 593 }
charly 0:79c6d0071c4c 594
charly 0:79c6d0071c4c 595 void RF22::clearRxBuf()
charly 0:79c6d0071c4c 596 {
charly 7:b86825b9d74b 597 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 598 _bufLen = 0;
charly 0:79c6d0071c4c 599 _rxBufValid = false;
charly 7:b86825b9d74b 600 __enable_irq(); // Enable Interrupts
charly 0:79c6d0071c4c 601 }
charly 0:79c6d0071c4c 602
charly 0:79c6d0071c4c 603 boolean RF22::available()
charly 0:79c6d0071c4c 604 {
charly 5:0386600f3408 605 if (!_rxBufValid)
charly 8:d9e2ca137f2e 606 setModeRx(); // Make sure we are receiving
charly 0:79c6d0071c4c 607 return _rxBufValid;
charly 0:79c6d0071c4c 608 }
charly 0:79c6d0071c4c 609
charly 0:79c6d0071c4c 610 // Blocks until a valid message is received
charly 0:79c6d0071c4c 611 void RF22::waitAvailable()
charly 0:79c6d0071c4c 612 {
charly 0:79c6d0071c4c 613 while (!available())
charly 8:d9e2ca137f2e 614 ;
charly 0:79c6d0071c4c 615 }
charly 0:79c6d0071c4c 616
charly 0:79c6d0071c4c 617 // Blocks until a valid message is received or timeout expires
charly 0:79c6d0071c4c 618 // Return true if there is a message available
charly 0:79c6d0071c4c 619 bool RF22::waitAvailableTimeout(uint16_t timeout)
charly 0:79c6d0071c4c 620 {
charly 0:79c6d0071c4c 621 Timer t;
charly 0:79c6d0071c4c 622 t.start();
charly 0:79c6d0071c4c 623 unsigned long endtime = t.read_ms() + timeout;
charly 0:79c6d0071c4c 624 while (t.read_ms() < endtime)
charly 8:d9e2ca137f2e 625 if (available())
charly 8:d9e2ca137f2e 626 return true;
charly 0:79c6d0071c4c 627 return false;
charly 0:79c6d0071c4c 628 }
charly 0:79c6d0071c4c 629
charly 0:79c6d0071c4c 630 void RF22::waitPacketSent()
charly 0:79c6d0071c4c 631 {
charly 5:0386600f3408 632 while (_mode == RF22_MODE_TX)
charly 8:d9e2ca137f2e 633 ; // Wait for any previous transmit to finish
charly 5:0386600f3408 634 }
charly 5:0386600f3408 635
charly 5:0386600f3408 636 // Diagnostic help
charly 5:0386600f3408 637 void RF22::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len)
charly 5:0386600f3408 638 {
charly 5:0386600f3408 639 #ifdef RF22_HAVE_SERIAL
charly 5:0386600f3408 640 uint8_t i;
charly 5:0386600f3408 641
charly 5:0386600f3408 642 Serial.println(prompt);
charly 8:d9e2ca137f2e 643 for (i = 0; i < len; i++) {
charly 8:d9e2ca137f2e 644 if (i % 16 == 15)
charly 8:d9e2ca137f2e 645 Serial.println(buf[i], HEX);
charly 8:d9e2ca137f2e 646 else {
charly 8:d9e2ca137f2e 647 Serial.print(buf[i], HEX);
charly 8:d9e2ca137f2e 648 Serial.print(' ');
charly 8:d9e2ca137f2e 649 }
charly 5:0386600f3408 650 }
charly 5:0386600f3408 651 Serial.println(' ');
charly 5:0386600f3408 652 #endif
charly 0:79c6d0071c4c 653 }
charly 0:79c6d0071c4c 654
charly 0:79c6d0071c4c 655 boolean RF22::recv(uint8_t* buf, uint8_t* len)
charly 0:79c6d0071c4c 656 {
charly 0:79c6d0071c4c 657 if (!available())
charly 8:d9e2ca137f2e 658 return false;
charly 8:d9e2ca137f2e 659 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 660 if (*len > _bufLen)
charly 8:d9e2ca137f2e 661 *len = _bufLen;
charly 0:79c6d0071c4c 662 memcpy(buf, _buf, *len);
charly 0:79c6d0071c4c 663 clearRxBuf();
charly 8:d9e2ca137f2e 664 __enable_irq(); // Enable Interrupts
charly 5:0386600f3408 665 // printBuffer("recv:", buf, *len);
charly 5:0386600f3408 666 // }
charly 0:79c6d0071c4c 667 return true;
charly 0:79c6d0071c4c 668 }
charly 0:79c6d0071c4c 669
charly 0:79c6d0071c4c 670 void RF22::clearTxBuf()
charly 0:79c6d0071c4c 671 {
charly 7:b86825b9d74b 672 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 673 _bufLen = 0;
charly 0:79c6d0071c4c 674 _txBufSentIndex = 0;
charly 0:79c6d0071c4c 675 _txPacketSent = false;
charly 7:b86825b9d74b 676 __enable_irq(); // Enable Interrupts
charly 0:79c6d0071c4c 677 }
charly 0:79c6d0071c4c 678
charly 0:79c6d0071c4c 679 void RF22::startTransmit()
charly 0:79c6d0071c4c 680 {
charly 0:79c6d0071c4c 681 sendNextFragment(); // Actually the first fragment
charly 0:79c6d0071c4c 682 spiWrite(RF22_REG_3E_PACKET_LENGTH, _bufLen); // Total length that will be sent
charly 0:79c6d0071c4c 683 setModeTx(); // Start the transmitter, turns off the receiver
charly 0:79c6d0071c4c 684 }
charly 0:79c6d0071c4c 685
charly 5:0386600f3408 686 // Restart the transmission of a packet that had a problem
charly 0:79c6d0071c4c 687 void RF22::restartTransmit()
charly 0:79c6d0071c4c 688 {
charly 0:79c6d0071c4c 689 _mode = RF22_MODE_IDLE;
charly 0:79c6d0071c4c 690 _txBufSentIndex = 0;
charly 0:79c6d0071c4c 691 // Serial.println("Restart");
charly 0:79c6d0071c4c 692 startTransmit();
charly 0:79c6d0071c4c 693 }
charly 0:79c6d0071c4c 694
charly 5:0386600f3408 695 boolean RF22::send(const uint8_t* data, uint8_t len)
charly 0:79c6d0071c4c 696 {
charly 5:0386600f3408 697 waitPacketSent();
charly 5:0386600f3408 698 // ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
charly 5:0386600f3408 699 {
charly 8:d9e2ca137f2e 700 if (!fillTxBuf(data, len))
charly 8:d9e2ca137f2e 701 return false;
charly 8:d9e2ca137f2e 702 startTransmit();
charly 5:0386600f3408 703 }
charly 5:0386600f3408 704 // printBuffer("send:", data, len);
charly 0:79c6d0071c4c 705 return true;
charly 0:79c6d0071c4c 706 }
charly 0:79c6d0071c4c 707
charly 5:0386600f3408 708 boolean RF22::fillTxBuf(const uint8_t* data, uint8_t len)
charly 0:79c6d0071c4c 709 {
charly 0:79c6d0071c4c 710 clearTxBuf();
charly 5:0386600f3408 711 if (!len)
charly 8:d9e2ca137f2e 712 return false;
charly 0:79c6d0071c4c 713 return appendTxBuf(data, len);
charly 0:79c6d0071c4c 714 }
charly 0:79c6d0071c4c 715
charly 5:0386600f3408 716 boolean RF22::appendTxBuf(const uint8_t* data, uint8_t len)
charly 0:79c6d0071c4c 717 {
charly 0:79c6d0071c4c 718 if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN)
charly 8:d9e2ca137f2e 719 return false;
charly 8:d9e2ca137f2e 720 __disable_irq(); // Disable Interrupts
charly 0:79c6d0071c4c 721 memcpy(_buf + _bufLen, data, len);
charly 0:79c6d0071c4c 722 _bufLen += len;
charly 8:d9e2ca137f2e 723 __enable_irq(); // Enable Interrupts
charly 8:d9e2ca137f2e 724
charly 5:0386600f3408 725 // printBuffer("txbuf:", _buf, _bufLen);
charly 0:79c6d0071c4c 726 return true;
charly 0:79c6d0071c4c 727 }
charly 0:79c6d0071c4c 728
charly 0:79c6d0071c4c 729 // Assumption: there is currently <= RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO
charly 0:79c6d0071c4c 730 void RF22::sendNextFragment()
charly 0:79c6d0071c4c 731 {
charly 8:d9e2ca137f2e 732 if (_txBufSentIndex < _bufLen) {
charly 8:d9e2ca137f2e 733 // Some left to send?
charly 8:d9e2ca137f2e 734 uint8_t len = _bufLen - _txBufSentIndex;
charly 8:d9e2ca137f2e 735 // But dont send too much
charly 8:d9e2ca137f2e 736 if (len > (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1))
charly 8:d9e2ca137f2e 737 len = (RF22_FIFO_SIZE - RF22_TXFFAEM_THRESHOLD - 1);
charly 8:d9e2ca137f2e 738 spiBurstWrite(RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len);
charly 8:d9e2ca137f2e 739 _txBufSentIndex += len;
charly 0:79c6d0071c4c 740 }
charly 0:79c6d0071c4c 741 }
charly 0:79c6d0071c4c 742
charly 0:79c6d0071c4c 743 // Assumption: there are at least RF22_RXFFAFULL_THRESHOLD in the RX FIFO
charly 5:0386600f3408 744 // That means it should only be called after a RXFFAFULL interrupt
charly 0:79c6d0071c4c 745 void RF22::readNextFragment()
charly 0:79c6d0071c4c 746 {
charly 0:79c6d0071c4c 747 if (((uint16_t)_bufLen + RF22_RXFFAFULL_THRESHOLD) > RF22_MAX_MESSAGE_LEN)
charly 8:d9e2ca137f2e 748 return; // Hmmm receiver overflow. Should never occur
charly 5:0386600f3408 749
charly 0:79c6d0071c4c 750 // Read the RF22_RXFFAFULL_THRESHOLD octets that should be there
charly 0:79c6d0071c4c 751 spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RF22_RXFFAFULL_THRESHOLD);
charly 0:79c6d0071c4c 752 _bufLen += RF22_RXFFAFULL_THRESHOLD;
charly 0:79c6d0071c4c 753 }
charly 0:79c6d0071c4c 754
charly 0:79c6d0071c4c 755 // Clear the FIFOs
charly 0:79c6d0071c4c 756 void RF22::resetFifos()
charly 0:79c6d0071c4c 757 {
charly 0:79c6d0071c4c 758 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX | RF22_FFCLRTX);
charly 0:79c6d0071c4c 759 spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
charly 0:79c6d0071c4c 760 }
charly 0:79c6d0071c4c 761
charly 0:79c6d0071c4c 762 // Clear the Rx FIFO
charly 0:79c6d0071c4c 763 void RF22::resetRxFifo()
charly 0:79c6d0071c4c 764 {
charly 0:79c6d0071c4c 765 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRRX);
charly 0:79c6d0071c4c 766 spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
charly 0:79c6d0071c4c 767 }
charly 0:79c6d0071c4c 768
charly 0:79c6d0071c4c 769 // CLear the TX FIFO
charly 0:79c6d0071c4c 770 void RF22::resetTxFifo()
charly 0:79c6d0071c4c 771 {
charly 0:79c6d0071c4c 772 spiWrite(RF22_REG_08_OPERATING_MODE2, RF22_FFCLRTX);
charly 0:79c6d0071c4c 773 spiWrite(RF22_REG_08_OPERATING_MODE2, 0);
charly 0:79c6d0071c4c 774 }
charly 0:79c6d0071c4c 775
charly 0:79c6d0071c4c 776 // Default implmentation does nothing. Override if you wish
charly 0:79c6d0071c4c 777 void RF22::handleExternalInterrupt()
charly 0:79c6d0071c4c 778 {
charly 0:79c6d0071c4c 779 }
charly 0:79c6d0071c4c 780
charly 0:79c6d0071c4c 781 // Default implmentation does nothing. Override if you wish
charly 0:79c6d0071c4c 782 void RF22::handleWakeupTimerInterrupt()
charly 0:79c6d0071c4c 783 {
charly 0:79c6d0071c4c 784 }
charly 0:79c6d0071c4c 785
charly 0:79c6d0071c4c 786 void RF22::setHeaderTo(uint8_t to)
charly 0:79c6d0071c4c 787 {
charly 0:79c6d0071c4c 788 spiWrite(RF22_REG_3A_TRANSMIT_HEADER3, to);
charly 0:79c6d0071c4c 789 }
charly 0:79c6d0071c4c 790
charly 0:79c6d0071c4c 791 void RF22::setHeaderFrom(uint8_t from)
charly 0:79c6d0071c4c 792 {
charly 0:79c6d0071c4c 793 spiWrite(RF22_REG_3B_TRANSMIT_HEADER2, from);
charly 0:79c6d0071c4c 794 }
charly 0:79c6d0071c4c 795
charly 0:79c6d0071c4c 796 void RF22::setHeaderId(uint8_t id)
charly 0:79c6d0071c4c 797 {
charly 0:79c6d0071c4c 798 spiWrite(RF22_REG_3C_TRANSMIT_HEADER1, id);
charly 0:79c6d0071c4c 799 }
charly 0:79c6d0071c4c 800
charly 0:79c6d0071c4c 801 void RF22::setHeaderFlags(uint8_t flags)
charly 0:79c6d0071c4c 802 {
charly 0:79c6d0071c4c 803 spiWrite(RF22_REG_3D_TRANSMIT_HEADER0, flags);
charly 0:79c6d0071c4c 804 }
charly 0:79c6d0071c4c 805
charly 0:79c6d0071c4c 806 uint8_t RF22::headerTo()
charly 0:79c6d0071c4c 807 {
charly 0:79c6d0071c4c 808 return spiRead(RF22_REG_47_RECEIVED_HEADER3);
charly 0:79c6d0071c4c 809 }
charly 0:79c6d0071c4c 810
charly 0:79c6d0071c4c 811 uint8_t RF22::headerFrom()
charly 0:79c6d0071c4c 812 {
charly 0:79c6d0071c4c 813 return spiRead(RF22_REG_48_RECEIVED_HEADER2);
charly 0:79c6d0071c4c 814 }
charly 0:79c6d0071c4c 815
charly 0:79c6d0071c4c 816 uint8_t RF22::headerId()
charly 0:79c6d0071c4c 817 {
charly 0:79c6d0071c4c 818 return spiRead(RF22_REG_49_RECEIVED_HEADER1);
charly 0:79c6d0071c4c 819 }
charly 0:79c6d0071c4c 820
charly 0:79c6d0071c4c 821 uint8_t RF22::headerFlags()
charly 0:79c6d0071c4c 822 {
charly 0:79c6d0071c4c 823 return spiRead(RF22_REG_4A_RECEIVED_HEADER0);
charly 0:79c6d0071c4c 824 }
charly 0:79c6d0071c4c 825
charly 0:79c6d0071c4c 826 uint8_t RF22::lastRssi()
charly 0:79c6d0071c4c 827 {
charly 0:79c6d0071c4c 828 return _lastRssi;
charly 0:79c6d0071c4c 829 }
charly 0:79c6d0071c4c 830
charly 0:79c6d0071c4c 831 void RF22::setPromiscuous(boolean promiscuous)
charly 0:79c6d0071c4c 832 {
charly 0:79c6d0071c4c 833 spiWrite(RF22_REG_43_HEADER_ENABLE3, promiscuous ? 0x00 : 0xff);
charly 0:79c6d0071c4c 834 }