This driver is a stripped down version of the Radiohead 1.45 driver, and covers fewer radios. Threading and an event queue have been added to make the ISR's more stable across architectures. Specifically The STM32L4 parts

Dependents:   Threaded_LoRa_Modem

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 }