V148

Fork of RadioHead-148 by David Rimer

Committer:
davidr99
Date:
Thu Oct 15 01:27:00 2015 +0000
Revision:
0:ab4e012489ef
Messy start, but a port for RadioHead.; Currently the SPI modulus are the only ones that work.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:ab4e012489ef 1 // RH_RF69.cpp
davidr99 0:ab4e012489ef 2 //
davidr99 0:ab4e012489ef 3 // Copyright (C) 2011 Mike McCauley
davidr99 0:ab4e012489ef 4 // $Id: RH_RF69.cpp,v 1.25 2015/05/17 00:11:26 mikem Exp $
davidr99 0:ab4e012489ef 5
davidr99 0:ab4e012489ef 6 #include <RH_RF69.h>
davidr99 0:ab4e012489ef 7
davidr99 0:ab4e012489ef 8 // Interrupt vectors for the 3 Arduino interrupt pins
davidr99 0:ab4e012489ef 9 // Each interrupt can be handled by a different instance of RH_RF69, allowing you to have
davidr99 0:ab4e012489ef 10 // 2 or more RF69s per Arduino
davidr99 0:ab4e012489ef 11 RH_RF69* RH_RF69::_deviceForInterrupt[RH_RF69_NUM_INTERRUPTS] = {0, 0, 0};
davidr99 0:ab4e012489ef 12 uint8_t RH_RF69::_interruptCount = 0; // Index into _deviceForInterrupt for next device
davidr99 0:ab4e012489ef 13
davidr99 0:ab4e012489ef 14 // These are indexed by the values of ModemConfigChoice
davidr99 0:ab4e012489ef 15 // Stored in flash (program) memory to save SRAM
davidr99 0:ab4e012489ef 16 // It is important to keep the modulation index for FSK between 0.5 and 10
davidr99 0:ab4e012489ef 17 // modulation index = 2 * Fdev / BR
davidr99 0:ab4e012489ef 18 // Note that I have not had much success with FSK with Fd > ~5
davidr99 0:ab4e012489ef 19 // You have to construct these by hand, using the data from the RF69 Datasheet :-(
davidr99 0:ab4e012489ef 20 // or use the SX1231 starter kit software (Ctl-Alt-N to use that without a connected radio)
davidr99 0:ab4e012489ef 21 #define CONFIG_FSK (RH_RF69_DATAMODUL_DATAMODE_PACKET | RH_RF69_DATAMODUL_MODULATIONTYPE_FSK | RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_NONE)
davidr99 0:ab4e012489ef 22 #define CONFIG_GFSK (RH_RF69_DATAMODUL_DATAMODE_PACKET | RH_RF69_DATAMODUL_MODULATIONTYPE_FSK | RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT1_0)
davidr99 0:ab4e012489ef 23 #define CONFIG_OOK (RH_RF69_DATAMODUL_DATAMODE_PACKET | RH_RF69_DATAMODUL_MODULATIONTYPE_OOK | RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE)
davidr99 0:ab4e012489ef 24
davidr99 0:ab4e012489ef 25 // Choices for RH_RF69_REG_37_PACKETCONFIG1:
davidr99 0:ab4e012489ef 26 #define CONFIG_NOWHITE (RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RH_RF69_PACKETCONFIG1_DCFREE_NONE | RH_RF69_PACKETCONFIG1_CRC_ON | RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE)
davidr99 0:ab4e012489ef 27 #define CONFIG_WHITE (RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RH_RF69_PACKETCONFIG1_DCFREE_WHITENING | RH_RF69_PACKETCONFIG1_CRC_ON | RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE)
davidr99 0:ab4e012489ef 28 #define CONFIG_MANCHESTER (RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RH_RF69_PACKETCONFIG1_DCFREE_MANCHESTER | RH_RF69_PACKETCONFIG1_CRC_ON | RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE)
davidr99 0:ab4e012489ef 29 PROGMEM static const RH_RF69::ModemConfig MODEM_CONFIG_TABLE[] =
davidr99 0:ab4e012489ef 30 {
davidr99 0:ab4e012489ef 31 // 02, 03, 04, 05, 06, 19, 1a, 37
davidr99 0:ab4e012489ef 32 // FSK, No Manchester, no shaping, whitening, CRC, no address filtering
davidr99 0:ab4e012489ef 33 // AFC BW == RX BW == 2 x bit rate
davidr99 0:ab4e012489ef 34 // Low modulation indexes of ~ 1 at slow speeds do not seem to work very well. Choose MI of 2.
davidr99 0:ab4e012489ef 35 { CONFIG_FSK, 0x3e, 0x80, 0x00, 0x52, 0xf4, 0xf4, CONFIG_WHITE}, // FSK_Rb2Fd5
davidr99 0:ab4e012489ef 36 { CONFIG_FSK, 0x34, 0x15, 0x00, 0x4f, 0xf4, 0xf4, CONFIG_WHITE}, // FSK_Rb2_4Fd4_8
davidr99 0:ab4e012489ef 37 { CONFIG_FSK, 0x1a, 0x0b, 0x00, 0x9d, 0xf4, 0xf4, CONFIG_WHITE}, // FSK_Rb4_8Fd9_6
davidr99 0:ab4e012489ef 38
davidr99 0:ab4e012489ef 39 { CONFIG_FSK, 0x0d, 0x05, 0x01, 0x3b, 0xf4, 0xf4, CONFIG_WHITE}, // FSK_Rb9_6Fd19_2
davidr99 0:ab4e012489ef 40 { CONFIG_FSK, 0x06, 0x83, 0x02, 0x75, 0xf3, 0xf3, CONFIG_WHITE}, // FSK_Rb19_2Fd38_4
davidr99 0:ab4e012489ef 41 { CONFIG_FSK, 0x03, 0x41, 0x04, 0xea, 0xf2, 0xf2, CONFIG_WHITE}, // FSK_Rb38_4Fd76_8
davidr99 0:ab4e012489ef 42
davidr99 0:ab4e012489ef 43 { CONFIG_FSK, 0x02, 0x2c, 0x07, 0xae, 0xe2, 0xe2, CONFIG_WHITE}, // FSK_Rb57_6Fd120
davidr99 0:ab4e012489ef 44 { CONFIG_FSK, 0x01, 0x00, 0x08, 0x00, 0xe1, 0xe1, CONFIG_WHITE}, // FSK_Rb125Fd125
davidr99 0:ab4e012489ef 45 { CONFIG_FSK, 0x00, 0x80, 0x10, 0x00, 0xe0, 0xe0, CONFIG_WHITE}, // FSK_Rb250Fd250
davidr99 0:ab4e012489ef 46 { CONFIG_FSK, 0x02, 0x40, 0x03, 0x33, 0x42, 0x42, CONFIG_WHITE}, // FSK_Rb55555Fd50
davidr99 0:ab4e012489ef 47
davidr99 0:ab4e012489ef 48 // 02, 03, 04, 05, 06, 19, 1a, 37
davidr99 0:ab4e012489ef 49 // GFSK (BT=1.0), No Manchester, whitening, CRC, no address filtering
davidr99 0:ab4e012489ef 50 // AFC BW == RX BW == 2 x bit rate
davidr99 0:ab4e012489ef 51 { CONFIG_GFSK, 0x3e, 0x80, 0x00, 0x52, 0xf4, 0xf5, CONFIG_WHITE}, // GFSK_Rb2Fd5
davidr99 0:ab4e012489ef 52 { CONFIG_GFSK, 0x34, 0x15, 0x00, 0x4f, 0xf4, 0xf4, CONFIG_WHITE}, // GFSK_Rb2_4Fd4_8
davidr99 0:ab4e012489ef 53 { CONFIG_GFSK, 0x1a, 0x0b, 0x00, 0x9d, 0xf4, 0xf4, CONFIG_WHITE}, // GFSK_Rb4_8Fd9_6
davidr99 0:ab4e012489ef 54
davidr99 0:ab4e012489ef 55 { CONFIG_GFSK, 0x0d, 0x05, 0x01, 0x3b, 0xf4, 0xf4, CONFIG_WHITE}, // GFSK_Rb9_6Fd19_2
davidr99 0:ab4e012489ef 56 { CONFIG_GFSK, 0x06, 0x83, 0x02, 0x75, 0xf3, 0xf3, CONFIG_WHITE}, // GFSK_Rb19_2Fd38_4
davidr99 0:ab4e012489ef 57 { CONFIG_GFSK, 0x03, 0x41, 0x04, 0xea, 0xf2, 0xf2, CONFIG_WHITE}, // GFSK_Rb38_4Fd76_8
davidr99 0:ab4e012489ef 58
davidr99 0:ab4e012489ef 59 { CONFIG_GFSK, 0x02, 0x2c, 0x07, 0xae, 0xe2, 0xe2, CONFIG_WHITE}, // GFSK_Rb57_6Fd120
davidr99 0:ab4e012489ef 60 { CONFIG_GFSK, 0x01, 0x00, 0x08, 0x00, 0xe1, 0xe1, CONFIG_WHITE}, // GFSK_Rb125Fd125
davidr99 0:ab4e012489ef 61 { CONFIG_GFSK, 0x00, 0x80, 0x10, 0x00, 0xe0, 0xe0, CONFIG_WHITE}, // GFSK_Rb250Fd250
davidr99 0:ab4e012489ef 62 { CONFIG_GFSK, 0x02, 0x40, 0x03, 0x33, 0x42, 0x42, CONFIG_WHITE}, // GFSK_Rb55555Fd50
davidr99 0:ab4e012489ef 63
davidr99 0:ab4e012489ef 64 // 02, 03, 04, 05, 06, 19, 1a, 37
davidr99 0:ab4e012489ef 65 // OOK, No Manchester, no shaping, whitening, CRC, no address filtering
davidr99 0:ab4e012489ef 66 // with the help of the SX1231 configuration program
davidr99 0:ab4e012489ef 67 // AFC BW == RX BW
davidr99 0:ab4e012489ef 68 // All OOK configs have the default:
davidr99 0:ab4e012489ef 69 // Threshold Type: Peak
davidr99 0:ab4e012489ef 70 // Peak Threshold Step: 0.5dB
davidr99 0:ab4e012489ef 71 // Peak threshiold dec: ONce per chip
davidr99 0:ab4e012489ef 72 // Fixed threshold: 6dB
davidr99 0:ab4e012489ef 73 { CONFIG_OOK, 0x7d, 0x00, 0x00, 0x10, 0x88, 0x88, CONFIG_WHITE}, // OOK_Rb1Bw1
davidr99 0:ab4e012489ef 74 { CONFIG_OOK, 0x68, 0x2b, 0x00, 0x10, 0xf1, 0xf1, CONFIG_WHITE}, // OOK_Rb1_2Bw75
davidr99 0:ab4e012489ef 75 { CONFIG_OOK, 0x34, 0x15, 0x00, 0x10, 0xf5, 0xf5, CONFIG_WHITE}, // OOK_Rb2_4Bw4_8
davidr99 0:ab4e012489ef 76 { CONFIG_OOK, 0x1a, 0x0b, 0x00, 0x10, 0xf4, 0xf4, CONFIG_WHITE}, // OOK_Rb4_8Bw9_6
davidr99 0:ab4e012489ef 77 { CONFIG_OOK, 0x0d, 0x05, 0x00, 0x10, 0xf3, 0xf3, CONFIG_WHITE}, // OOK_Rb9_6Bw19_2
davidr99 0:ab4e012489ef 78 { CONFIG_OOK, 0x06, 0x83, 0x00, 0x10, 0xf2, 0xf2, CONFIG_WHITE}, // OOK_Rb19_2Bw38_4
davidr99 0:ab4e012489ef 79 { CONFIG_OOK, 0x03, 0xe8, 0x00, 0x10, 0xe2, 0xe2, CONFIG_WHITE}, // OOK_Rb32Bw64
davidr99 0:ab4e012489ef 80
davidr99 0:ab4e012489ef 81 // { CONFIG_FSK, 0x68, 0x2b, 0x00, 0x52, 0x55, 0x55, CONFIG_WHITE}, // works: Rb1200 Fd 5000 bw10000, DCC 400
davidr99 0:ab4e012489ef 82 // { CONFIG_FSK, 0x0c, 0x80, 0x02, 0x8f, 0x52, 0x52, CONFIG_WHITE}, // works 10/40/80
davidr99 0:ab4e012489ef 83 // { CONFIG_FSK, 0x0c, 0x80, 0x02, 0x8f, 0x53, 0x53, CONFIG_WHITE}, // works 10/40/40
davidr99 0:ab4e012489ef 84
davidr99 0:ab4e012489ef 85 };
davidr99 0:ab4e012489ef 86 RH_RF69::RH_RF69(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi)
davidr99 0:ab4e012489ef 87 :
davidr99 0:ab4e012489ef 88 RHSPIDriver(slaveSelectPin, spi),
davidr99 0:ab4e012489ef 89 _interruptPin(interruptPin)
davidr99 0:ab4e012489ef 90 {
davidr99 0:ab4e012489ef 91 _idleMode = RH_RF69_OPMODE_MODE_STDBY;
davidr99 0:ab4e012489ef 92 _myInterruptIndex = 0xff; // Not allocated yet
davidr99 0:ab4e012489ef 93 }
davidr99 0:ab4e012489ef 94
davidr99 0:ab4e012489ef 95 void RH_RF69::setIdleMode(uint8_t idleMode)
davidr99 0:ab4e012489ef 96 {
davidr99 0:ab4e012489ef 97 _idleMode = idleMode;
davidr99 0:ab4e012489ef 98 }
davidr99 0:ab4e012489ef 99
davidr99 0:ab4e012489ef 100 bool RH_RF69::init()
davidr99 0:ab4e012489ef 101 {
davidr99 0:ab4e012489ef 102 if (!RHSPIDriver::init())
davidr99 0:ab4e012489ef 103 return false;
davidr99 0:ab4e012489ef 104
davidr99 0:ab4e012489ef 105 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 106 // Determine the interrupt number that corresponds to the interruptPin
davidr99 0:ab4e012489ef 107 int interruptNumber = digitalPinToInterrupt(_interruptPin);
davidr99 0:ab4e012489ef 108 if (interruptNumber == NOT_AN_INTERRUPT)
davidr99 0:ab4e012489ef 109 return false;
davidr99 0:ab4e012489ef 110 #endif
davidr99 0:ab4e012489ef 111
davidr99 0:ab4e012489ef 112 // Get the device type and check it
davidr99 0:ab4e012489ef 113 // This also tests whether we are really connected to a device
davidr99 0:ab4e012489ef 114 // My test devices return 0x24
davidr99 0:ab4e012489ef 115 _deviceType = spiRead(RH_RF69_REG_10_VERSION);
davidr99 0:ab4e012489ef 116 if (_deviceType == 00 ||
davidr99 0:ab4e012489ef 117 _deviceType == 0xff)
davidr99 0:ab4e012489ef 118 return false;
davidr99 0:ab4e012489ef 119
davidr99 0:ab4e012489ef 120 // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy
davidr99 0:ab4e012489ef 121 // ARM M4 requires the below. else pin interrupt doesn't work properly.
davidr99 0:ab4e012489ef 122 // On all other platforms, its innocuous, belt and braces
davidr99 0:ab4e012489ef 123 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 124 pinMode(_interruptPin, INPUT);
davidr99 0:ab4e012489ef 125 #endif
davidr99 0:ab4e012489ef 126
davidr99 0:ab4e012489ef 127
davidr99 0:ab4e012489ef 128
davidr99 0:ab4e012489ef 129 // Set up interrupt handler
davidr99 0:ab4e012489ef 130 // Since there are a limited number of interrupt glue functions isr*() available,
davidr99 0:ab4e012489ef 131 // we can only support a limited number of devices simultaneously
davidr99 0:ab4e012489ef 132 // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the
davidr99 0:ab4e012489ef 133 // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
davidr99 0:ab4e012489ef 134 // yourself based on knwledge of what Arduino board you are running on.
davidr99 0:ab4e012489ef 135 if (_myInterruptIndex == 0xff)
davidr99 0:ab4e012489ef 136 {
davidr99 0:ab4e012489ef 137 // First run, no interrupt allocated yet
davidr99 0:ab4e012489ef 138 if (_interruptCount <= RH_RF69_NUM_INTERRUPTS)
davidr99 0:ab4e012489ef 139 _myInterruptIndex = _interruptCount++;
davidr99 0:ab4e012489ef 140 else
davidr99 0:ab4e012489ef 141 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 142 }
davidr99 0:ab4e012489ef 143 _deviceForInterrupt[_myInterruptIndex] = this;
davidr99 0:ab4e012489ef 144 #if (RH_PLATFORM == RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 145 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 146 _interruptPin.rise(&isr0);
davidr99 0:ab4e012489ef 147 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 148 _interruptPin.rise(&isr1);
davidr99 0:ab4e012489ef 149 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 150 _interruptPin.rise(&isr2);
davidr99 0:ab4e012489ef 151 else
davidr99 0:ab4e012489ef 152 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 153 #else
davidr99 0:ab4e012489ef 154 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 155 attachInterrupt(interruptNumber, isr0, RISING);
davidr99 0:ab4e012489ef 156 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 157 attachInterrupt(interruptNumber, isr1, RISING);
davidr99 0:ab4e012489ef 158 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 159 attachInterrupt(interruptNumber, isr2, RISING);
davidr99 0:ab4e012489ef 160 else
davidr99 0:ab4e012489ef 161 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 162 #endif
davidr99 0:ab4e012489ef 163
davidr99 0:ab4e012489ef 164
davidr99 0:ab4e012489ef 165 setModeIdle();
davidr99 0:ab4e012489ef 166
davidr99 0:ab4e012489ef 167 // Configure important RH_RF69 registers
davidr99 0:ab4e012489ef 168 // Here we set up the standard packet format for use by the RH_RF69 library:
davidr99 0:ab4e012489ef 169 // 4 bytes preamble
davidr99 0:ab4e012489ef 170 // 2 SYNC words 2d, d4
davidr99 0:ab4e012489ef 171 // 2 CRC CCITT octets computed on the header, length and data (this in the modem config data)
davidr99 0:ab4e012489ef 172 // 0 to 60 bytes data
davidr99 0:ab4e012489ef 173 // RSSI Threshold -114dBm
davidr99 0:ab4e012489ef 174 // We dont use the RH_RF69s address filtering: instead we prepend our own headers to the beginning
davidr99 0:ab4e012489ef 175 // of the RH_RF69 payload
davidr99 0:ab4e012489ef 176 spiWrite(RH_RF69_REG_3C_FIFOTHRESH, RH_RF69_FIFOTHRESH_TXSTARTCONDITION_NOTEMPTY | 0x0f); // thresh 15 is default
davidr99 0:ab4e012489ef 177 // RSSITHRESH is default
davidr99 0:ab4e012489ef 178 // spiWrite(RH_RF69_REG_29_RSSITHRESH, 220); // -110 dbM
davidr99 0:ab4e012489ef 179 // SYNCCONFIG is default. SyncSize is set later by setSyncWords()
davidr99 0:ab4e012489ef 180 // spiWrite(RH_RF69_REG_2E_SYNCCONFIG, RH_RF69_SYNCCONFIG_SYNCON); // auto, tolerance 0
davidr99 0:ab4e012489ef 181 // PAYLOADLENGTH is default
davidr99 0:ab4e012489ef 182 // spiWrite(RH_RF69_REG_38_PAYLOADLENGTH, RH_RF69_FIFO_SIZE); // max size only for RX
davidr99 0:ab4e012489ef 183 // PACKETCONFIG 2 is default
davidr99 0:ab4e012489ef 184 spiWrite(RH_RF69_REG_6F_TESTDAGC, RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAOFF);
davidr99 0:ab4e012489ef 185 // If high power boost set previously, disable it
davidr99 0:ab4e012489ef 186 spiWrite(RH_RF69_REG_5A_TESTPA1, RH_RF69_TESTPA1_NORMAL);
davidr99 0:ab4e012489ef 187 spiWrite(RH_RF69_REG_5C_TESTPA2, RH_RF69_TESTPA2_NORMAL);
davidr99 0:ab4e012489ef 188
davidr99 0:ab4e012489ef 189 // The following can be changed later by the user if necessary.
davidr99 0:ab4e012489ef 190 // Set up default configuration
davidr99 0:ab4e012489ef 191 uint8_t syncwords[] = { 0x2d, 0xd4 };
davidr99 0:ab4e012489ef 192 setSyncWords(syncwords, sizeof(syncwords)); // Same as RF22's
davidr99 0:ab4e012489ef 193 // Reasonably fast and reliable default speed and modulation
davidr99 0:ab4e012489ef 194 setModemConfig(GFSK_Rb250Fd250);
davidr99 0:ab4e012489ef 195
davidr99 0:ab4e012489ef 196 // 3 would be sufficient, but this is the same as RF22's
davidr99 0:ab4e012489ef 197 setPreambleLength(4);
davidr99 0:ab4e012489ef 198 // An innocuous ISM frequency, same as RF22's
davidr99 0:ab4e012489ef 199 setFrequency(434.0);
davidr99 0:ab4e012489ef 200 // No encryption
davidr99 0:ab4e012489ef 201 setEncryptionKey(NULL);
davidr99 0:ab4e012489ef 202 // +13dBm, same as power-on default
davidr99 0:ab4e012489ef 203 setTxPower(13);
davidr99 0:ab4e012489ef 204
davidr99 0:ab4e012489ef 205 return true;
davidr99 0:ab4e012489ef 206 }
davidr99 0:ab4e012489ef 207
davidr99 0:ab4e012489ef 208 // C++ level interrupt handler for this instance
davidr99 0:ab4e012489ef 209 // RH_RF69 is unusual in Mthat it has several interrupt lines, and not a single, combined one.
davidr99 0:ab4e012489ef 210 // On Moteino, only one of the several interrupt lines (DI0) from the RH_RF69 is connnected to the processor.
davidr99 0:ab4e012489ef 211 // We use this to get PACKETSDENT and PAYLOADRADY interrupts.
davidr99 0:ab4e012489ef 212 void RH_RF69::handleInterrupt()
davidr99 0:ab4e012489ef 213 {
davidr99 0:ab4e012489ef 214 // Get the interrupt cause
davidr99 0:ab4e012489ef 215 uint8_t irqflags2 = spiRead(RH_RF69_REG_28_IRQFLAGS2);
davidr99 0:ab4e012489ef 216 if (_mode == RHModeTx && (irqflags2 & RH_RF69_IRQFLAGS2_PACKETSENT))
davidr99 0:ab4e012489ef 217 {
davidr99 0:ab4e012489ef 218 // A transmitter message has been fully sent
davidr99 0:ab4e012489ef 219 setModeIdle(); // Clears FIFO
davidr99 0:ab4e012489ef 220 _txGood++;
davidr99 0:ab4e012489ef 221 // Serial.println("PACKETSENT");
davidr99 0:ab4e012489ef 222 }
davidr99 0:ab4e012489ef 223 // Must look for PAYLOADREADY, not CRCOK, since only PAYLOADREADY occurs _after_ AES decryption
davidr99 0:ab4e012489ef 224 // has been done
davidr99 0:ab4e012489ef 225 if (_mode == RHModeRx && (irqflags2 & RH_RF69_IRQFLAGS2_PAYLOADREADY))
davidr99 0:ab4e012489ef 226 {
davidr99 0:ab4e012489ef 227 // A complete message has been received with good CRC
davidr99 0:ab4e012489ef 228 _lastRssi = -((int8_t)(spiRead(RH_RF69_REG_24_RSSIVALUE) >> 1));
davidr99 0:ab4e012489ef 229 _lastPreambleTime = millis();
davidr99 0:ab4e012489ef 230
davidr99 0:ab4e012489ef 231 setModeIdle();
davidr99 0:ab4e012489ef 232 // Save it in our buffer
davidr99 0:ab4e012489ef 233 readFifo();
davidr99 0:ab4e012489ef 234 // Serial.println("PAYLOADREADY");
davidr99 0:ab4e012489ef 235 }
davidr99 0:ab4e012489ef 236 }
davidr99 0:ab4e012489ef 237
davidr99 0:ab4e012489ef 238 // Low level function reads the FIFO and checks the address
davidr99 0:ab4e012489ef 239 // Caution: since we put our headers in what the RH_RF69 considers to be the payload, if encryption is enabled
davidr99 0:ab4e012489ef 240 // we have to suffer the cost of decryption before we can determine whether the address is acceptable.
davidr99 0:ab4e012489ef 241 // Performance issue?
davidr99 0:ab4e012489ef 242 void RH_RF69::readFifo()
davidr99 0:ab4e012489ef 243 {
davidr99 0:ab4e012489ef 244 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 245 digitalWrite(_slaveSelectPin, LOW);
davidr99 0:ab4e012489ef 246 _spi.transfer(RH_RF69_REG_00_FIFO); // Send the start address with the write mask off
davidr99 0:ab4e012489ef 247 uint8_t payloadlen = _spi.transfer(0); // First byte is payload len (counting the headers)
davidr99 0:ab4e012489ef 248 if (payloadlen <= RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN &&
davidr99 0:ab4e012489ef 249 payloadlen >= RH_RF69_HEADER_LEN)
davidr99 0:ab4e012489ef 250 {
davidr99 0:ab4e012489ef 251 _rxHeaderTo = _spi.transfer(0);
davidr99 0:ab4e012489ef 252 // Check addressing
davidr99 0:ab4e012489ef 253 if (_promiscuous ||
davidr99 0:ab4e012489ef 254 _rxHeaderTo == _thisAddress ||
davidr99 0:ab4e012489ef 255 _rxHeaderTo == RH_BROADCAST_ADDRESS)
davidr99 0:ab4e012489ef 256 {
davidr99 0:ab4e012489ef 257 // Get the rest of the headers
davidr99 0:ab4e012489ef 258 _rxHeaderFrom = _spi.transfer(0);
davidr99 0:ab4e012489ef 259 _rxHeaderId = _spi.transfer(0);
davidr99 0:ab4e012489ef 260 _rxHeaderFlags = _spi.transfer(0);
davidr99 0:ab4e012489ef 261 // And now the real payload
davidr99 0:ab4e012489ef 262 for (_bufLen = 0; _bufLen < (payloadlen - RH_RF69_HEADER_LEN); _bufLen++)
davidr99 0:ab4e012489ef 263 _buf[_bufLen] = _spi.transfer(0);
davidr99 0:ab4e012489ef 264 _rxGood++;
davidr99 0:ab4e012489ef 265 _rxBufValid = true;
davidr99 0:ab4e012489ef 266 }
davidr99 0:ab4e012489ef 267 }
davidr99 0:ab4e012489ef 268 digitalWrite(_slaveSelectPin, HIGH);
davidr99 0:ab4e012489ef 269 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 270 // Any junk remaining in the FIFO will be cleared next time we go to receive mode.
davidr99 0:ab4e012489ef 271 }
davidr99 0:ab4e012489ef 272
davidr99 0:ab4e012489ef 273 // These are low level functions that call the interrupt handler for the correct
davidr99 0:ab4e012489ef 274 // instance of RH_RF69.
davidr99 0:ab4e012489ef 275 // 3 interrupts allows us to have 3 different devices
davidr99 0:ab4e012489ef 276 void RH_RF69::isr0()
davidr99 0:ab4e012489ef 277 {
davidr99 0:ab4e012489ef 278 if (_deviceForInterrupt[0])
davidr99 0:ab4e012489ef 279 _deviceForInterrupt[0]->handleInterrupt();
davidr99 0:ab4e012489ef 280 }
davidr99 0:ab4e012489ef 281 void RH_RF69::isr1()
davidr99 0:ab4e012489ef 282 {
davidr99 0:ab4e012489ef 283 if (_deviceForInterrupt[1])
davidr99 0:ab4e012489ef 284 _deviceForInterrupt[1]->handleInterrupt();
davidr99 0:ab4e012489ef 285 }
davidr99 0:ab4e012489ef 286 void RH_RF69::isr2()
davidr99 0:ab4e012489ef 287 {
davidr99 0:ab4e012489ef 288 if (_deviceForInterrupt[2])
davidr99 0:ab4e012489ef 289 _deviceForInterrupt[2]->handleInterrupt();
davidr99 0:ab4e012489ef 290 }
davidr99 0:ab4e012489ef 291
davidr99 0:ab4e012489ef 292 int8_t RH_RF69::temperatureRead()
davidr99 0:ab4e012489ef 293 {
davidr99 0:ab4e012489ef 294 // Caution: must be ins standby.
davidr99 0:ab4e012489ef 295 // setModeIdle();
davidr99 0:ab4e012489ef 296 spiWrite(RH_RF69_REG_4E_TEMP1, RH_RF69_TEMP1_TEMPMEASSTART); // Start the measurement
davidr99 0:ab4e012489ef 297 while (spiRead(RH_RF69_REG_4E_TEMP1) & RH_RF69_TEMP1_TEMPMEASRUNNING)
davidr99 0:ab4e012489ef 298 ; // Wait for the measurement to complete
davidr99 0:ab4e012489ef 299 return 166 - spiRead(RH_RF69_REG_4F_TEMP2); // Very approximate, based on observation
davidr99 0:ab4e012489ef 300 }
davidr99 0:ab4e012489ef 301
davidr99 0:ab4e012489ef 302 bool RH_RF69::setFrequency(float centre, float afcPullInRange)
davidr99 0:ab4e012489ef 303 {
davidr99 0:ab4e012489ef 304 // Frf = FRF / FSTEP
davidr99 0:ab4e012489ef 305 uint32_t frf = (uint32_t)((centre * 1000000.0) / RH_RF69_FSTEP);
davidr99 0:ab4e012489ef 306 spiWrite(RH_RF69_REG_07_FRFMSB, (frf >> 16) & 0xff);
davidr99 0:ab4e012489ef 307 spiWrite(RH_RF69_REG_08_FRFMID, (frf >> 8) & 0xff);
davidr99 0:ab4e012489ef 308 spiWrite(RH_RF69_REG_09_FRFLSB, frf & 0xff);
davidr99 0:ab4e012489ef 309
davidr99 0:ab4e012489ef 310 // afcPullInRange is not used
davidr99 0:ab4e012489ef 311 return true;
davidr99 0:ab4e012489ef 312 }
davidr99 0:ab4e012489ef 313
davidr99 0:ab4e012489ef 314 int8_t RH_RF69::rssiRead()
davidr99 0:ab4e012489ef 315 {
davidr99 0:ab4e012489ef 316 // Force a new value to be measured
davidr99 0:ab4e012489ef 317 // Hmmm, this hangs forever!
davidr99 0:ab4e012489ef 318 #if 0
davidr99 0:ab4e012489ef 319 spiWrite(RH_RF69_REG_23_RSSICONFIG, RH_RF69_RSSICONFIG_RSSISTART);
davidr99 0:ab4e012489ef 320 while (!(spiRead(RH_RF69_REG_23_RSSICONFIG) & RH_RF69_RSSICONFIG_RSSIDONE))
davidr99 0:ab4e012489ef 321 ;
davidr99 0:ab4e012489ef 322 #endif
davidr99 0:ab4e012489ef 323 return -((int8_t)(spiRead(RH_RF69_REG_24_RSSIVALUE) >> 1));
davidr99 0:ab4e012489ef 324 }
davidr99 0:ab4e012489ef 325
davidr99 0:ab4e012489ef 326 void RH_RF69::setOpMode(uint8_t mode)
davidr99 0:ab4e012489ef 327 {
davidr99 0:ab4e012489ef 328 uint8_t opmode = spiRead(RH_RF69_REG_01_OPMODE);
davidr99 0:ab4e012489ef 329 opmode &= ~RH_RF69_OPMODE_MODE;
davidr99 0:ab4e012489ef 330 opmode |= (mode & RH_RF69_OPMODE_MODE);
davidr99 0:ab4e012489ef 331 spiWrite(RH_RF69_REG_01_OPMODE, opmode);
davidr99 0:ab4e012489ef 332
davidr99 0:ab4e012489ef 333 // Wait for mode to change.
davidr99 0:ab4e012489ef 334 while (!(spiRead(RH_RF69_REG_27_IRQFLAGS1) & RH_RF69_IRQFLAGS1_MODEREADY))
davidr99 0:ab4e012489ef 335 ;
davidr99 0:ab4e012489ef 336 }
davidr99 0:ab4e012489ef 337
davidr99 0:ab4e012489ef 338 void RH_RF69::setModeIdle()
davidr99 0:ab4e012489ef 339 {
davidr99 0:ab4e012489ef 340 if (_mode != RHModeIdle)
davidr99 0:ab4e012489ef 341 {
davidr99 0:ab4e012489ef 342 if (_power >= 18)
davidr99 0:ab4e012489ef 343 {
davidr99 0:ab4e012489ef 344 // If high power boost, return power amp to receive mode
davidr99 0:ab4e012489ef 345 spiWrite(RH_RF69_REG_5A_TESTPA1, RH_RF69_TESTPA1_NORMAL);
davidr99 0:ab4e012489ef 346 spiWrite(RH_RF69_REG_5C_TESTPA2, RH_RF69_TESTPA2_NORMAL);
davidr99 0:ab4e012489ef 347 }
davidr99 0:ab4e012489ef 348 setOpMode(_idleMode);
davidr99 0:ab4e012489ef 349 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 350 }
davidr99 0:ab4e012489ef 351 }
davidr99 0:ab4e012489ef 352
davidr99 0:ab4e012489ef 353 bool RH_RF69::sleep()
davidr99 0:ab4e012489ef 354 {
davidr99 0:ab4e012489ef 355 if (_mode != RHModeSleep)
davidr99 0:ab4e012489ef 356 {
davidr99 0:ab4e012489ef 357 spiWrite(RH_RF69_REG_01_OPMODE, RH_RF69_OPMODE_MODE_SLEEP);
davidr99 0:ab4e012489ef 358 _mode = RHModeSleep;
davidr99 0:ab4e012489ef 359 }
davidr99 0:ab4e012489ef 360 return true;
davidr99 0:ab4e012489ef 361 }
davidr99 0:ab4e012489ef 362
davidr99 0:ab4e012489ef 363 void RH_RF69::setModeRx()
davidr99 0:ab4e012489ef 364 {
davidr99 0:ab4e012489ef 365 if (_mode != RHModeRx)
davidr99 0:ab4e012489ef 366 {
davidr99 0:ab4e012489ef 367 if (_power >= 18)
davidr99 0:ab4e012489ef 368 {
davidr99 0:ab4e012489ef 369 // If high power boost, return power amp to receive mode
davidr99 0:ab4e012489ef 370 spiWrite(RH_RF69_REG_5A_TESTPA1, RH_RF69_TESTPA1_NORMAL);
davidr99 0:ab4e012489ef 371 spiWrite(RH_RF69_REG_5C_TESTPA2, RH_RF69_TESTPA2_NORMAL);
davidr99 0:ab4e012489ef 372 }
davidr99 0:ab4e012489ef 373 spiWrite(RH_RF69_REG_25_DIOMAPPING1, RH_RF69_DIOMAPPING1_DIO0MAPPING_01); // Set interrupt line 0 PayloadReady
davidr99 0:ab4e012489ef 374 setOpMode(RH_RF69_OPMODE_MODE_RX); // Clears FIFO
davidr99 0:ab4e012489ef 375 _mode = RHModeRx;
davidr99 0:ab4e012489ef 376 }
davidr99 0:ab4e012489ef 377 }
davidr99 0:ab4e012489ef 378
davidr99 0:ab4e012489ef 379 void RH_RF69::setModeTx()
davidr99 0:ab4e012489ef 380 {
davidr99 0:ab4e012489ef 381 if (_mode != RHModeTx)
davidr99 0:ab4e012489ef 382 {
davidr99 0:ab4e012489ef 383 if (_power >= 18)
davidr99 0:ab4e012489ef 384 {
davidr99 0:ab4e012489ef 385 // Set high power boost mode
davidr99 0:ab4e012489ef 386 // Note that OCP defaults to ON so no need to change that.
davidr99 0:ab4e012489ef 387 spiWrite(RH_RF69_REG_5A_TESTPA1, RH_RF69_TESTPA1_BOOST);
davidr99 0:ab4e012489ef 388 spiWrite(RH_RF69_REG_5C_TESTPA2, RH_RF69_TESTPA2_BOOST);
davidr99 0:ab4e012489ef 389 }
davidr99 0:ab4e012489ef 390 spiWrite(RH_RF69_REG_25_DIOMAPPING1, RH_RF69_DIOMAPPING1_DIO0MAPPING_00); // Set interrupt line 0 PacketSent
davidr99 0:ab4e012489ef 391 setOpMode(RH_RF69_OPMODE_MODE_TX); // Clears FIFO
davidr99 0:ab4e012489ef 392 _mode = RHModeTx;
davidr99 0:ab4e012489ef 393 }
davidr99 0:ab4e012489ef 394 }
davidr99 0:ab4e012489ef 395
davidr99 0:ab4e012489ef 396 void RH_RF69::setTxPower(int8_t power)
davidr99 0:ab4e012489ef 397 {
davidr99 0:ab4e012489ef 398 _power = power;
davidr99 0:ab4e012489ef 399
davidr99 0:ab4e012489ef 400 uint8_t palevel;
davidr99 0:ab4e012489ef 401 if (_power < -18)
davidr99 0:ab4e012489ef 402 _power = -18;
davidr99 0:ab4e012489ef 403
davidr99 0:ab4e012489ef 404 // See http://www.hoperf.com/upload/rfchip/RF69-V1.2.pdf section 3.3.6
davidr99 0:ab4e012489ef 405 // for power formulas
davidr99 0:ab4e012489ef 406 if (_power <= 13)
davidr99 0:ab4e012489ef 407 {
davidr99 0:ab4e012489ef 408 // -18dBm to +13dBm
davidr99 0:ab4e012489ef 409 palevel = RH_RF69_PALEVEL_PA0ON | ((_power + 18) & RH_RF69_PALEVEL_OUTPUTPOWER);
davidr99 0:ab4e012489ef 410 }
davidr99 0:ab4e012489ef 411 else if (_power >= 18)
davidr99 0:ab4e012489ef 412 {
davidr99 0:ab4e012489ef 413 // +18dBm to +20dBm
davidr99 0:ab4e012489ef 414 // Need PA1+PA2
davidr99 0:ab4e012489ef 415 // Also need PA boost settings change when tx is turned on and off, see setModeTx()
davidr99 0:ab4e012489ef 416 palevel = RH_RF69_PALEVEL_PA1ON | RH_RF69_PALEVEL_PA2ON | ((_power + 11) & RH_RF69_PALEVEL_OUTPUTPOWER);
davidr99 0:ab4e012489ef 417 }
davidr99 0:ab4e012489ef 418 else
davidr99 0:ab4e012489ef 419 {
davidr99 0:ab4e012489ef 420 // +14dBm to +17dBm
davidr99 0:ab4e012489ef 421 // Need PA1+PA2
davidr99 0:ab4e012489ef 422 palevel = RH_RF69_PALEVEL_PA1ON | RH_RF69_PALEVEL_PA2ON | ((_power + 14) & RH_RF69_PALEVEL_OUTPUTPOWER);
davidr99 0:ab4e012489ef 423 }
davidr99 0:ab4e012489ef 424 spiWrite(RH_RF69_REG_11_PALEVEL, palevel);
davidr99 0:ab4e012489ef 425 }
davidr99 0:ab4e012489ef 426
davidr99 0:ab4e012489ef 427 // Sets registers from a canned modem configuration structure
davidr99 0:ab4e012489ef 428 void RH_RF69::setModemRegisters(const ModemConfig* config)
davidr99 0:ab4e012489ef 429 {
davidr99 0:ab4e012489ef 430 spiBurstWrite(RH_RF69_REG_02_DATAMODUL, &config->reg_02, 5);
davidr99 0:ab4e012489ef 431 spiBurstWrite(RH_RF69_REG_19_RXBW, &config->reg_19, 2);
davidr99 0:ab4e012489ef 432 spiWrite(RH_RF69_REG_37_PACKETCONFIG1, config->reg_37);
davidr99 0:ab4e012489ef 433 }
davidr99 0:ab4e012489ef 434
davidr99 0:ab4e012489ef 435 // Set one of the canned FSK Modem configs
davidr99 0:ab4e012489ef 436 // Returns true if its a valid choice
davidr99 0:ab4e012489ef 437 bool RH_RF69::setModemConfig(ModemConfigChoice index)
davidr99 0:ab4e012489ef 438 {
davidr99 0:ab4e012489ef 439 if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
davidr99 0:ab4e012489ef 440 return false;
davidr99 0:ab4e012489ef 441
davidr99 0:ab4e012489ef 442 ModemConfig cfg;
davidr99 0:ab4e012489ef 443 memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF69::ModemConfig));
davidr99 0:ab4e012489ef 444 setModemRegisters(&cfg);
davidr99 0:ab4e012489ef 445
davidr99 0:ab4e012489ef 446 return true;
davidr99 0:ab4e012489ef 447 }
davidr99 0:ab4e012489ef 448
davidr99 0:ab4e012489ef 449 void RH_RF69::setPreambleLength(uint16_t bytes)
davidr99 0:ab4e012489ef 450 {
davidr99 0:ab4e012489ef 451 spiWrite(RH_RF69_REG_2C_PREAMBLEMSB, bytes >> 8);
davidr99 0:ab4e012489ef 452 spiWrite(RH_RF69_REG_2D_PREAMBLELSB, bytes & 0xff);
davidr99 0:ab4e012489ef 453 }
davidr99 0:ab4e012489ef 454
davidr99 0:ab4e012489ef 455 void RH_RF69::setSyncWords(const uint8_t* syncWords, uint8_t len)
davidr99 0:ab4e012489ef 456 {
davidr99 0:ab4e012489ef 457 uint8_t syncconfig = spiRead(RH_RF69_REG_2E_SYNCCONFIG);
davidr99 0:ab4e012489ef 458 if (syncWords && len && len <= 4)
davidr99 0:ab4e012489ef 459 {
davidr99 0:ab4e012489ef 460 spiBurstWrite(RH_RF69_REG_2F_SYNCVALUE1, syncWords, len);
davidr99 0:ab4e012489ef 461 syncconfig |= RH_RF69_SYNCCONFIG_SYNCON;
davidr99 0:ab4e012489ef 462 }
davidr99 0:ab4e012489ef 463 else
davidr99 0:ab4e012489ef 464 syncconfig &= ~RH_RF69_SYNCCONFIG_SYNCON;
davidr99 0:ab4e012489ef 465 syncconfig &= ~RH_RF69_SYNCCONFIG_SYNCSIZE;
davidr99 0:ab4e012489ef 466 syncconfig |= (len-1) << 3;
davidr99 0:ab4e012489ef 467 spiWrite(RH_RF69_REG_2E_SYNCCONFIG, syncconfig);
davidr99 0:ab4e012489ef 468 }
davidr99 0:ab4e012489ef 469
davidr99 0:ab4e012489ef 470 void RH_RF69::setEncryptionKey(uint8_t* key)
davidr99 0:ab4e012489ef 471 {
davidr99 0:ab4e012489ef 472 if (key)
davidr99 0:ab4e012489ef 473 {
davidr99 0:ab4e012489ef 474 spiBurstWrite(RH_RF69_REG_3E_AESKEY1, key, 16);
davidr99 0:ab4e012489ef 475 spiWrite(RH_RF69_REG_3D_PACKETCONFIG2, spiRead(RH_RF69_REG_3D_PACKETCONFIG2) | RH_RF69_PACKETCONFIG2_AESON);
davidr99 0:ab4e012489ef 476 }
davidr99 0:ab4e012489ef 477 else
davidr99 0:ab4e012489ef 478 {
davidr99 0:ab4e012489ef 479 spiWrite(RH_RF69_REG_3D_PACKETCONFIG2, spiRead(RH_RF69_REG_3D_PACKETCONFIG2) & ~RH_RF69_PACKETCONFIG2_AESON);
davidr99 0:ab4e012489ef 480 }
davidr99 0:ab4e012489ef 481 }
davidr99 0:ab4e012489ef 482
davidr99 0:ab4e012489ef 483 bool RH_RF69::available()
davidr99 0:ab4e012489ef 484 {
davidr99 0:ab4e012489ef 485 if (_mode == RHModeTx)
davidr99 0:ab4e012489ef 486 return false;
davidr99 0:ab4e012489ef 487 setModeRx(); // Make sure we are receiving
davidr99 0:ab4e012489ef 488 return _rxBufValid;
davidr99 0:ab4e012489ef 489 }
davidr99 0:ab4e012489ef 490
davidr99 0:ab4e012489ef 491 bool RH_RF69::recv(uint8_t* buf, uint8_t* len)
davidr99 0:ab4e012489ef 492 {
davidr99 0:ab4e012489ef 493 if (!available())
davidr99 0:ab4e012489ef 494 return false;
davidr99 0:ab4e012489ef 495
davidr99 0:ab4e012489ef 496 if (buf && len)
davidr99 0:ab4e012489ef 497 {
davidr99 0:ab4e012489ef 498 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 499 if (*len > _bufLen)
davidr99 0:ab4e012489ef 500 *len = _bufLen;
davidr99 0:ab4e012489ef 501 memcpy(buf, _buf, *len);
davidr99 0:ab4e012489ef 502 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 503 }
davidr99 0:ab4e012489ef 504 _rxBufValid = false; // Got the most recent message
davidr99 0:ab4e012489ef 505 // printBuffer("recv:", buf, *len);
davidr99 0:ab4e012489ef 506 return true;
davidr99 0:ab4e012489ef 507 }
davidr99 0:ab4e012489ef 508
davidr99 0:ab4e012489ef 509 bool RH_RF69::send(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 510 {
davidr99 0:ab4e012489ef 511 if (len > RH_RF69_MAX_MESSAGE_LEN)
davidr99 0:ab4e012489ef 512 return false;
davidr99 0:ab4e012489ef 513
davidr99 0:ab4e012489ef 514 waitPacketSent(); // Make sure we dont interrupt an outgoing message
davidr99 0:ab4e012489ef 515 setModeIdle(); // Prevent RX while filling the fifo
davidr99 0:ab4e012489ef 516
davidr99 0:ab4e012489ef 517 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 518 digitalWrite(_slaveSelectPin, LOW);
davidr99 0:ab4e012489ef 519 _spi.transfer(RH_RF69_REG_00_FIFO | RH_RF69_SPI_WRITE_MASK); // Send the start address with the write mask on
davidr99 0:ab4e012489ef 520 _spi.transfer(len + RH_RF69_HEADER_LEN); // Include length of headers
davidr99 0:ab4e012489ef 521 // First the 4 headers
davidr99 0:ab4e012489ef 522 _spi.transfer(_txHeaderTo);
davidr99 0:ab4e012489ef 523 _spi.transfer(_txHeaderFrom);
davidr99 0:ab4e012489ef 524 _spi.transfer(_txHeaderId);
davidr99 0:ab4e012489ef 525 _spi.transfer(_txHeaderFlags);
davidr99 0:ab4e012489ef 526 // Now the payload
davidr99 0:ab4e012489ef 527 while (len--)
davidr99 0:ab4e012489ef 528 _spi.transfer(*data++);
davidr99 0:ab4e012489ef 529 digitalWrite(_slaveSelectPin, HIGH);
davidr99 0:ab4e012489ef 530 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 531
davidr99 0:ab4e012489ef 532 setModeTx(); // Start the transmitter
davidr99 0:ab4e012489ef 533 return true;
davidr99 0:ab4e012489ef 534 }
davidr99 0:ab4e012489ef 535
davidr99 0:ab4e012489ef 536 uint8_t RH_RF69::maxMessageLength()
davidr99 0:ab4e012489ef 537 {
davidr99 0:ab4e012489ef 538 return RH_RF69_MAX_MESSAGE_LEN;
davidr99 0:ab4e012489ef 539 }
davidr99 0:ab4e012489ef 540
davidr99 0:ab4e012489ef 541 bool RH_RF69::printRegister(uint8_t reg)
davidr99 0:ab4e012489ef 542 {
davidr99 0:ab4e012489ef 543 #ifdef RH_HAVE_SERIAL
davidr99 0:ab4e012489ef 544 Serial.print(reg, HEX);
davidr99 0:ab4e012489ef 545 Serial.print(" ");
davidr99 0:ab4e012489ef 546 Serial.println(spiRead(reg), HEX);
davidr99 0:ab4e012489ef 547 #endif
davidr99 0:ab4e012489ef 548 return true;
davidr99 0:ab4e012489ef 549 }
davidr99 0:ab4e012489ef 550
davidr99 0:ab4e012489ef 551 bool RH_RF69::printRegisters()
davidr99 0:ab4e012489ef 552 {
davidr99 0:ab4e012489ef 553 uint8_t i;
davidr99 0:ab4e012489ef 554 for (i = 0; i < 0x50; i++)
davidr99 0:ab4e012489ef 555 printRegister(i);
davidr99 0:ab4e012489ef 556 // Non-contiguous registers
davidr99 0:ab4e012489ef 557 printRegister(RH_RF69_REG_58_TESTLNA);
davidr99 0:ab4e012489ef 558 printRegister(RH_RF69_REG_6F_TESTDAGC);
davidr99 0:ab4e012489ef 559 printRegister(RH_RF69_REG_71_TESTAFC);
davidr99 0:ab4e012489ef 560
davidr99 0:ab4e012489ef 561 return true;
davidr99 0:ab4e012489ef 562 }