V148
Fork of RadioHead-148 by
RH_RF69.cpp@1:b7641da2b203, 2017-10-25 (annotated)
- Committer:
- ilkaykozak
- Date:
- Wed Oct 25 05:14:09 2017 +0000
- Revision:
- 1:b7641da2b203
- Parent:
- 0:ab4e012489ef
V148
Who changed what in which revision?
User | Revision | Line number | New 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 | } |