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_RF22.cpp
davidr99 0:ab4e012489ef 2 //
davidr99 0:ab4e012489ef 3 // Copyright (C) 2011 Mike McCauley
davidr99 0:ab4e012489ef 4 // $Id: RH_RF22.cpp,v 1.24 2015/05/17 00:11:26 mikem Exp $
davidr99 0:ab4e012489ef 5
davidr99 0:ab4e012489ef 6 #include <RH_RF22.h>
davidr99 0:ab4e012489ef 7
davidr99 0:ab4e012489ef 8 // Interrupt vectors for the 2 Arduino interrupt pins
davidr99 0:ab4e012489ef 9 // Each interrupt can be handled by a different instance of RH_RF22, allowing you to have
davidr99 0:ab4e012489ef 10 // 2 RH_RF22s per Arduino
davidr99 0:ab4e012489ef 11 RH_RF22* RH_RF22::_deviceForInterrupt[RH_RF22_NUM_INTERRUPTS] = {0, 0, 0};
davidr99 0:ab4e012489ef 12 uint8_t RH_RF22::_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 // Canned modem configurations generated with
davidr99 0:ab4e012489ef 16 // http://www.hoperf.com/upload/rf/RH_RF22B%2023B%2031B%2042B%2043B%20Register%20Settings_RevB1-v5.xls
davidr99 0:ab4e012489ef 17 // Stored in flash (program) memory to save SRAM
davidr99 0:ab4e012489ef 18 PROGMEM static const RH_RF22::ModemConfig MODEM_CONFIG_TABLE[] =
davidr99 0:ab4e012489ef 19 {
davidr99 0:ab4e012489ef 20 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x00, 0x08 }, // Unmodulated carrier
davidr99 0:ab4e012489ef 21 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x33, 0x08 }, // FSK, PN9 random modulation, 2, 5
davidr99 0:ab4e012489ef 22
davidr99 0:ab4e012489ef 23 // All the following enable FIFO with reg 71
davidr99 0:ab4e012489ef 24 // 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72
davidr99 0:ab4e012489ef 25 // FSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
davidr99 0:ab4e012489ef 26 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x22, 0x08 }, // 2, 5
davidr99 0:ab4e012489ef 27 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x22, 0x3a }, // 2.4, 36
davidr99 0:ab4e012489ef 28 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x22, 0x48 }, // 4.8, 45
davidr99 0:ab4e012489ef 29 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x22, 0x48 }, // 9.6, 45
davidr99 0:ab4e012489ef 30 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x22, 0x0f }, // 19.2, 9.6
davidr99 0:ab4e012489ef 31 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x22, 0x1f }, // 38.4, 19.6
davidr99 0:ab4e012489ef 32 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x22, 0x2e }, // 57.6. 28.8
davidr99 0:ab4e012489ef 33 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x22, 0xc8 }, // 125, 125
davidr99 0:ab4e012489ef 34
davidr99 0:ab4e012489ef 35 { 0x2b, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x09, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x04 }, // 512 baud, FSK, 2.5 Khz fd for POCSAG compatibility
davidr99 0:ab4e012489ef 36 { 0x27, 0x03, 0xa1, 0xe0, 0x10, 0xc7, 0x00, 0x06, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x04, 0x32, 0x2c, 0x22, 0x07 }, // 512 baud, FSK, 4.5 Khz fd for POCSAG compatibility
davidr99 0:ab4e012489ef 37
davidr99 0:ab4e012489ef 38 // GFSK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
davidr99 0:ab4e012489ef 39 // These differ from FSK only in register 71, for the modulation type
davidr99 0:ab4e012489ef 40 { 0x2b, 0x03, 0xf4, 0x20, 0x41, 0x89, 0x00, 0x36, 0x40, 0x0a, 0x1d, 0x80, 0x60, 0x10, 0x62, 0x2c, 0x23, 0x08 }, // 2, 5
davidr99 0:ab4e012489ef 41 { 0x1b, 0x03, 0x41, 0x60, 0x27, 0x52, 0x00, 0x07, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x23, 0x3a }, // 2.4, 36
davidr99 0:ab4e012489ef 42 { 0x1d, 0x03, 0xa1, 0x20, 0x4e, 0xa5, 0x00, 0x13, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x23, 0x48 }, // 4.8, 45
davidr99 0:ab4e012489ef 43 { 0x1e, 0x03, 0xd0, 0x00, 0x9d, 0x49, 0x00, 0x45, 0x40, 0x0a, 0x20, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x23, 0x48 }, // 9.6, 45
davidr99 0:ab4e012489ef 44 { 0x2b, 0x03, 0x34, 0x02, 0x75, 0x25, 0x07, 0xff, 0x40, 0x0a, 0x1b, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x23, 0x0f }, // 19.2, 9.6
davidr99 0:ab4e012489ef 45 { 0x02, 0x03, 0x68, 0x01, 0x3a, 0x93, 0x04, 0xd5, 0x40, 0x0a, 0x1e, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x23, 0x1f }, // 38.4, 19.6
davidr99 0:ab4e012489ef 46 { 0x06, 0x03, 0x45, 0x01, 0xd7, 0xdc, 0x07, 0x6e, 0x40, 0x0a, 0x2d, 0x80, 0x60, 0x0e, 0xbf, 0x0c, 0x23, 0x2e }, // 57.6. 28.8
davidr99 0:ab4e012489ef 47 { 0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x0c, 0x23, 0xc8 }, // 125, 125
davidr99 0:ab4e012489ef 48
davidr99 0:ab4e012489ef 49 // OOK, No Manchester, Max Rb err <1%, Xtal Tol 20ppm
davidr99 0:ab4e012489ef 50 { 0x51, 0x03, 0x68, 0x00, 0x3a, 0x93, 0x01, 0x3d, 0x2c, 0x11, 0x28, 0x80, 0x60, 0x09, 0xd5, 0x2c, 0x21, 0x08 }, // 1.2, 75
davidr99 0:ab4e012489ef 51 { 0xc8, 0x03, 0x39, 0x20, 0x68, 0xdc, 0x00, 0x6b, 0x2a, 0x08, 0x2a, 0x80, 0x60, 0x13, 0xa9, 0x2c, 0x21, 0x08 }, // 2.4, 335
davidr99 0:ab4e012489ef 52 { 0xc8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x29, 0x04, 0x29, 0x80, 0x60, 0x27, 0x52, 0x2c, 0x21, 0x08 }, // 4.8, 335
davidr99 0:ab4e012489ef 53 { 0xb8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x82, 0x29, 0x80, 0x60, 0x4e, 0xa5, 0x2c, 0x21, 0x08 }, // 9.6, 335
davidr99 0:ab4e012489ef 54 { 0xa8, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x41, 0x29, 0x80, 0x60, 0x9d, 0x49, 0x2c, 0x21, 0x08 }, // 19.2, 335
davidr99 0:ab4e012489ef 55 { 0x98, 0x03, 0x9c, 0x00, 0xd1, 0xb7, 0x00, 0xd4, 0x28, 0x20, 0x29, 0x80, 0x60, 0x09, 0xd5, 0x0c, 0x21, 0x08 }, // 38.4, 335
davidr99 0:ab4e012489ef 56 { 0x98, 0x03, 0x96, 0x00, 0xda, 0x74, 0x00, 0xdc, 0x28, 0x1f, 0x29, 0x80, 0x60, 0x0a, 0x3d, 0x0c, 0x21, 0x08 }, // 40, 335
davidr99 0:ab4e012489ef 57 };
davidr99 0:ab4e012489ef 58
davidr99 0:ab4e012489ef 59 RH_RF22::RH_RF22(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi)
davidr99 0:ab4e012489ef 60 :
davidr99 0:ab4e012489ef 61 RHSPIDriver(slaveSelectPin, spi),
davidr99 0:ab4e012489ef 62 _interruptPin(interruptPin)
davidr99 0:ab4e012489ef 63 {
davidr99 0:ab4e012489ef 64 _idleMode = RH_RF22_XTON; // Default idle state is READY mode
davidr99 0:ab4e012489ef 65 _polynomial = CRC_16_IBM; // Historical
davidr99 0:ab4e012489ef 66 _myInterruptIndex = 0xff; // Not allocated yet
davidr99 0:ab4e012489ef 67 }
davidr99 0:ab4e012489ef 68
davidr99 0:ab4e012489ef 69 void RH_RF22::setIdleMode(uint8_t idleMode)
davidr99 0:ab4e012489ef 70 {
davidr99 0:ab4e012489ef 71 _idleMode = idleMode;
davidr99 0:ab4e012489ef 72 }
davidr99 0:ab4e012489ef 73
davidr99 0:ab4e012489ef 74 bool RH_RF22::init()
davidr99 0:ab4e012489ef 75 {
davidr99 0:ab4e012489ef 76 if (!RHSPIDriver::init())
davidr99 0:ab4e012489ef 77 return false;
davidr99 0:ab4e012489ef 78
davidr99 0:ab4e012489ef 79 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 80 // Determine the interrupt number that corresponds to the interruptPin
davidr99 0:ab4e012489ef 81 int interruptNumber = digitalPinToInterrupt(_interruptPin);
davidr99 0:ab4e012489ef 82 if (interruptNumber == NOT_AN_INTERRUPT)
davidr99 0:ab4e012489ef 83 return false;
davidr99 0:ab4e012489ef 84 #endif
davidr99 0:ab4e012489ef 85
davidr99 0:ab4e012489ef 86 // Software reset the device
davidr99 0:ab4e012489ef 87 reset();
davidr99 0:ab4e012489ef 88
davidr99 0:ab4e012489ef 89 // Get the device type and check it
davidr99 0:ab4e012489ef 90 // This also tests whether we are really connected to a device
davidr99 0:ab4e012489ef 91 _deviceType = spiRead(RH_RF22_REG_00_DEVICE_TYPE);
davidr99 0:ab4e012489ef 92 if ( _deviceType != RH_RF22_DEVICE_TYPE_RX_TRX
davidr99 0:ab4e012489ef 93 && _deviceType != RH_RF22_DEVICE_TYPE_TX)
davidr99 0:ab4e012489ef 94 {
davidr99 0:ab4e012489ef 95 return false;
davidr99 0:ab4e012489ef 96 }
davidr99 0:ab4e012489ef 97
davidr99 0:ab4e012489ef 98
davidr99 0:ab4e012489ef 99 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 100 // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy
davidr99 0:ab4e012489ef 101 // ARM M4 requires the below. else pin interrupt doesn't work properly.
davidr99 0:ab4e012489ef 102 // On all other platforms, its innocuous, belt and braces
davidr99 0:ab4e012489ef 103 pinMode(_interruptPin, INPUT);
davidr99 0:ab4e012489ef 104 #endif
davidr99 0:ab4e012489ef 105
davidr99 0:ab4e012489ef 106 // Enable interrupt output on the radio. Interrupt line will now go high until
davidr99 0:ab4e012489ef 107 // an interrupt occurs
davidr99 0:ab4e012489ef 108 spiWrite(RH_RF22_REG_05_INTERRUPT_ENABLE1, RH_RF22_ENTXFFAEM | RH_RF22_ENRXFFAFULL | RH_RF22_ENPKSENT | RH_RF22_ENPKVALID | RH_RF22_ENCRCERROR | RH_RF22_ENFFERR);
davidr99 0:ab4e012489ef 109 spiWrite(RH_RF22_REG_06_INTERRUPT_ENABLE2, RH_RF22_ENPREAVAL);
davidr99 0:ab4e012489ef 110
davidr99 0:ab4e012489ef 111 // Set up interrupt handler
davidr99 0:ab4e012489ef 112 // Since there are a limited number of interrupt glue functions isr*() available,
davidr99 0:ab4e012489ef 113 // we can only support a limited number of devices simultaneously
davidr99 0:ab4e012489ef 114 // On some devices, notably most Arduinos, the interrupt pin passed in is actually the
davidr99 0:ab4e012489ef 115 // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
davidr99 0:ab4e012489ef 116 // yourself based on knowledge of what Arduino board you are running on.
davidr99 0:ab4e012489ef 117 if (_myInterruptIndex == 0xff)
davidr99 0:ab4e012489ef 118 {
davidr99 0:ab4e012489ef 119 // First run, no interrupt allocated yet
davidr99 0:ab4e012489ef 120 if (_interruptCount <= RH_RF22_NUM_INTERRUPTS)
davidr99 0:ab4e012489ef 121 _myInterruptIndex = _interruptCount++;
davidr99 0:ab4e012489ef 122 else
davidr99 0:ab4e012489ef 123 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 124 }
davidr99 0:ab4e012489ef 125 _deviceForInterrupt[_myInterruptIndex] = this;
davidr99 0:ab4e012489ef 126
davidr99 0:ab4e012489ef 127 #if (RH_PLATFORM == RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 128 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 129 _interruptPin.fall(&isr0);
davidr99 0:ab4e012489ef 130 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 131 _interruptPin.fall(&isr1);
davidr99 0:ab4e012489ef 132 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 133 _interruptPin.fall(&isr2);
davidr99 0:ab4e012489ef 134 else
davidr99 0:ab4e012489ef 135 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 136 #else
davidr99 0:ab4e012489ef 137 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 138 attachInterrupt(interruptNumber, isr0, FALLING);
davidr99 0:ab4e012489ef 139 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 140 attachInterrupt(interruptNumber, isr1, FALLING);
davidr99 0:ab4e012489ef 141 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 142 attachInterrupt(interruptNumber, isr2, FALLING);
davidr99 0:ab4e012489ef 143 else
davidr99 0:ab4e012489ef 144 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 145 #endif
davidr99 0:ab4e012489ef 146
davidr99 0:ab4e012489ef 147 setModeIdle();
davidr99 0:ab4e012489ef 148
davidr99 0:ab4e012489ef 149 clearTxBuf();
davidr99 0:ab4e012489ef 150 clearRxBuf();
davidr99 0:ab4e012489ef 151
davidr99 0:ab4e012489ef 152 // Most of these are the POR default
davidr99 0:ab4e012489ef 153 spiWrite(RH_RF22_REG_7D_TX_FIFO_CONTROL2, RH_RF22_TXFFAEM_THRESHOLD);
davidr99 0:ab4e012489ef 154 spiWrite(RH_RF22_REG_7E_RX_FIFO_CONTROL, RH_RF22_RXFFAFULL_THRESHOLD);
davidr99 0:ab4e012489ef 155 spiWrite(RH_RF22_REG_30_DATA_ACCESS_CONTROL, RH_RF22_ENPACRX | RH_RF22_ENPACTX | RH_RF22_ENCRC | (_polynomial & RH_RF22_CRC));
davidr99 0:ab4e012489ef 156
davidr99 0:ab4e012489ef 157 // Configure the message headers
davidr99 0:ab4e012489ef 158 // Here we set up the standard packet format for use by the RH_RF22 library
davidr99 0:ab4e012489ef 159 // 8 nibbles preamble
davidr99 0:ab4e012489ef 160 // 2 SYNC words 2d, d4
davidr99 0:ab4e012489ef 161 // Header length 4 (to, from, id, flags)
davidr99 0:ab4e012489ef 162 // 1 octet of data length (0 to 255)
davidr99 0:ab4e012489ef 163 // 0 to 255 octets data
davidr99 0:ab4e012489ef 164 // 2 CRC octets as CRC16(IBM), computed on the header, length and data
davidr99 0:ab4e012489ef 165 // On reception the to address is check for validity against RH_RF22_REG_3F_CHECK_HEADER3
davidr99 0:ab4e012489ef 166 // or the broadcast address of 0xff
davidr99 0:ab4e012489ef 167 // If no changes are made after this, the transmitted
davidr99 0:ab4e012489ef 168 // to address will be 0xff, the from address will be 0xff
davidr99 0:ab4e012489ef 169 // and all such messages will be accepted. This permits the out-of the box
davidr99 0:ab4e012489ef 170 // RH_RF22 config to act as an unaddresed, unreliable datagram service
davidr99 0:ab4e012489ef 171 spiWrite(RH_RF22_REG_32_HEADER_CONTROL1, RH_RF22_BCEN_HEADER3 | RH_RF22_HDCH_HEADER3);
davidr99 0:ab4e012489ef 172 spiWrite(RH_RF22_REG_33_HEADER_CONTROL2, RH_RF22_HDLEN_4 | RH_RF22_SYNCLEN_2);
davidr99 0:ab4e012489ef 173
davidr99 0:ab4e012489ef 174 setPreambleLength(8);
davidr99 0:ab4e012489ef 175 uint8_t syncwords[] = { 0x2d, 0xd4 };
davidr99 0:ab4e012489ef 176 setSyncWords(syncwords, sizeof(syncwords));
davidr99 0:ab4e012489ef 177 setPromiscuous(false);
davidr99 0:ab4e012489ef 178
davidr99 0:ab4e012489ef 179 // Set some defaults. An innocuous ISM frequency, and reasonable pull-in
davidr99 0:ab4e012489ef 180 setFrequency(434.0, 0.05);
davidr99 0:ab4e012489ef 181 // setFrequency(900.0);
davidr99 0:ab4e012489ef 182 // Some slow, reliable default speed and modulation
davidr99 0:ab4e012489ef 183 setModemConfig(FSK_Rb2_4Fd36);
davidr99 0:ab4e012489ef 184 // setModemConfig(FSK_Rb125Fd125);
davidr99 0:ab4e012489ef 185 setGpioReversed(false);
davidr99 0:ab4e012489ef 186 // Lowish power
davidr99 0:ab4e012489ef 187 setTxPower(RH_RF22_TXPOW_8DBM);
davidr99 0:ab4e012489ef 188
davidr99 0:ab4e012489ef 189 return true;
davidr99 0:ab4e012489ef 190 }
davidr99 0:ab4e012489ef 191
davidr99 0:ab4e012489ef 192 // C++ level interrupt handler for this instance
davidr99 0:ab4e012489ef 193 void RH_RF22::handleInterrupt()
davidr99 0:ab4e012489ef 194 {
davidr99 0:ab4e012489ef 195 uint8_t _lastInterruptFlags[2];
davidr99 0:ab4e012489ef 196 // Read the interrupt flags which clears the interrupt
davidr99 0:ab4e012489ef 197 spiBurstRead(RH_RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2);
davidr99 0:ab4e012489ef 198
davidr99 0:ab4e012489ef 199 #if 0
davidr99 0:ab4e012489ef 200 // DEVELOPER TESTING ONLY
davidr99 0:ab4e012489ef 201 // Caution: Serial printing in this interrupt routine can cause mysterious crashes
davidr99 0:ab4e012489ef 202 Serial.print("interrupt ");
davidr99 0:ab4e012489ef 203 Serial.print(_lastInterruptFlags[0], HEX);
davidr99 0:ab4e012489ef 204 Serial.print(" ");
davidr99 0:ab4e012489ef 205 Serial.println(_lastInterruptFlags[1], HEX);
davidr99 0:ab4e012489ef 206 if (_lastInterruptFlags[0] == 0 && _lastInterruptFlags[1] == 0)
davidr99 0:ab4e012489ef 207 Serial.println("FUNNY: no interrupt!");
davidr99 0:ab4e012489ef 208 #endif
davidr99 0:ab4e012489ef 209
davidr99 0:ab4e012489ef 210 #if 0
davidr99 0:ab4e012489ef 211 // DEVELOPER TESTING ONLY
davidr99 0:ab4e012489ef 212 // TESTING: fake an RH_RF22_IFFERROR
davidr99 0:ab4e012489ef 213 static int counter = 0;
davidr99 0:ab4e012489ef 214 if (_lastInterruptFlags[0] & RH_RF22_IPKSENT && counter++ == 10)
davidr99 0:ab4e012489ef 215 {
davidr99 0:ab4e012489ef 216 _lastInterruptFlags[0] = RH_RF22_IFFERROR;
davidr99 0:ab4e012489ef 217 counter = 0;
davidr99 0:ab4e012489ef 218 }
davidr99 0:ab4e012489ef 219 #endif
davidr99 0:ab4e012489ef 220
davidr99 0:ab4e012489ef 221 if (_lastInterruptFlags[0] & RH_RF22_IFFERROR)
davidr99 0:ab4e012489ef 222 {
davidr99 0:ab4e012489ef 223 resetFifos(); // Clears the interrupt
davidr99 0:ab4e012489ef 224 if (_mode == RHModeTx)
davidr99 0:ab4e012489ef 225 restartTransmit();
davidr99 0:ab4e012489ef 226 else if (_mode == RHModeRx)
davidr99 0:ab4e012489ef 227 clearRxBuf();
davidr99 0:ab4e012489ef 228 // Serial.println("IFFERROR");
davidr99 0:ab4e012489ef 229 }
davidr99 0:ab4e012489ef 230 // Caution, any delay here may cause a FF underflow or overflow
davidr99 0:ab4e012489ef 231 if (_lastInterruptFlags[0] & RH_RF22_ITXFFAEM)
davidr99 0:ab4e012489ef 232 {
davidr99 0:ab4e012489ef 233 // See if more data has to be loaded into the Tx FIFO
davidr99 0:ab4e012489ef 234 sendNextFragment();
davidr99 0:ab4e012489ef 235 // Serial.println("ITXFFAEM");
davidr99 0:ab4e012489ef 236 }
davidr99 0:ab4e012489ef 237 if (_lastInterruptFlags[0] & RH_RF22_IRXFFAFULL)
davidr99 0:ab4e012489ef 238 {
davidr99 0:ab4e012489ef 239 // Caution, any delay here may cause a FF overflow
davidr99 0:ab4e012489ef 240 // Read some data from the Rx FIFO
davidr99 0:ab4e012489ef 241 readNextFragment();
davidr99 0:ab4e012489ef 242 // Serial.println("IRXFFAFULL");
davidr99 0:ab4e012489ef 243 }
davidr99 0:ab4e012489ef 244 if (_lastInterruptFlags[0] & RH_RF22_IEXT)
davidr99 0:ab4e012489ef 245 {
davidr99 0:ab4e012489ef 246 // This is not enabled by the base code, but users may want to enable it
davidr99 0:ab4e012489ef 247 handleExternalInterrupt();
davidr99 0:ab4e012489ef 248 // Serial.println("IEXT");
davidr99 0:ab4e012489ef 249 }
davidr99 0:ab4e012489ef 250 if (_lastInterruptFlags[1] & RH_RF22_IWUT)
davidr99 0:ab4e012489ef 251 {
davidr99 0:ab4e012489ef 252 // This is not enabled by the base code, but users may want to enable it
davidr99 0:ab4e012489ef 253 handleWakeupTimerInterrupt();
davidr99 0:ab4e012489ef 254 // Serial.println("IWUT");
davidr99 0:ab4e012489ef 255 }
davidr99 0:ab4e012489ef 256 if (_lastInterruptFlags[0] & RH_RF22_IPKSENT)
davidr99 0:ab4e012489ef 257 {
davidr99 0:ab4e012489ef 258 // Serial.println("IPKSENT");
davidr99 0:ab4e012489ef 259 _txGood++;
davidr99 0:ab4e012489ef 260 // Transmission does not automatically clear the tx buffer.
davidr99 0:ab4e012489ef 261 // Could retransmit if we wanted
davidr99 0:ab4e012489ef 262 // RH_RF22 transitions automatically to Idle
davidr99 0:ab4e012489ef 263 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 264 }
davidr99 0:ab4e012489ef 265 if (_lastInterruptFlags[0] & RH_RF22_IPKVALID)
davidr99 0:ab4e012489ef 266 {
davidr99 0:ab4e012489ef 267 uint8_t len = spiRead(RH_RF22_REG_4B_RECEIVED_PACKET_LENGTH);
davidr99 0:ab4e012489ef 268 // Serial.println("IPKVALID");
davidr99 0:ab4e012489ef 269
davidr99 0:ab4e012489ef 270 // May have already read one or more fragments
davidr99 0:ab4e012489ef 271 // Get any remaining unread octets, based on the expected length
davidr99 0:ab4e012489ef 272 // First make sure we dont overflow the buffer in the case of a stupid length
davidr99 0:ab4e012489ef 273 // or partial bad receives
davidr99 0:ab4e012489ef 274 if ( len > RH_RF22_MAX_MESSAGE_LEN
davidr99 0:ab4e012489ef 275 || len < _bufLen)
davidr99 0:ab4e012489ef 276 {
davidr99 0:ab4e012489ef 277 _rxBad++;
davidr99 0:ab4e012489ef 278 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 279 clearRxBuf();
davidr99 0:ab4e012489ef 280 return; // Hmmm receiver buffer overflow.
davidr99 0:ab4e012489ef 281 }
davidr99 0:ab4e012489ef 282
davidr99 0:ab4e012489ef 283 spiBurstRead(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen);
davidr99 0:ab4e012489ef 284 _rxHeaderTo = spiRead(RH_RF22_REG_47_RECEIVED_HEADER3);
davidr99 0:ab4e012489ef 285 _rxHeaderFrom = spiRead(RH_RF22_REG_48_RECEIVED_HEADER2);
davidr99 0:ab4e012489ef 286 _rxHeaderId = spiRead(RH_RF22_REG_49_RECEIVED_HEADER1);
davidr99 0:ab4e012489ef 287 _rxHeaderFlags = spiRead(RH_RF22_REG_4A_RECEIVED_HEADER0);
davidr99 0:ab4e012489ef 288 _rxGood++;
davidr99 0:ab4e012489ef 289 _bufLen = len;
davidr99 0:ab4e012489ef 290 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 291 _rxBufValid = true;
davidr99 0:ab4e012489ef 292 }
davidr99 0:ab4e012489ef 293 if (_lastInterruptFlags[0] & RH_RF22_ICRCERROR)
davidr99 0:ab4e012489ef 294 {
davidr99 0:ab4e012489ef 295 // Serial.println("ICRCERR");
davidr99 0:ab4e012489ef 296 _rxBad++;
davidr99 0:ab4e012489ef 297 clearRxBuf();
davidr99 0:ab4e012489ef 298 resetRxFifo();
davidr99 0:ab4e012489ef 299 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 300 setModeRx(); // Keep trying
davidr99 0:ab4e012489ef 301 }
davidr99 0:ab4e012489ef 302 if (_lastInterruptFlags[1] & RH_RF22_IPREAVAL)
davidr99 0:ab4e012489ef 303 {
davidr99 0:ab4e012489ef 304 // Serial.println("IPREAVAL");
davidr99 0:ab4e012489ef 305 _lastRssi = (int8_t)(-120 + ((spiRead(RH_RF22_REG_26_RSSI) / 2)));
davidr99 0:ab4e012489ef 306 _lastPreambleTime = millis();
davidr99 0:ab4e012489ef 307 resetRxFifo();
davidr99 0:ab4e012489ef 308 clearRxBuf();
davidr99 0:ab4e012489ef 309 }
davidr99 0:ab4e012489ef 310 }
davidr99 0:ab4e012489ef 311
davidr99 0:ab4e012489ef 312 // These are low level functions that call the interrupt handler for the correct
davidr99 0:ab4e012489ef 313 // instance of RH_RF22.
davidr99 0:ab4e012489ef 314 // 3 interrupts allows us to have 3 different devices
davidr99 0:ab4e012489ef 315 void RH_RF22::isr0()
davidr99 0:ab4e012489ef 316 {
davidr99 0:ab4e012489ef 317 if (_deviceForInterrupt[0])
davidr99 0:ab4e012489ef 318 _deviceForInterrupt[0]->handleInterrupt();
davidr99 0:ab4e012489ef 319 }
davidr99 0:ab4e012489ef 320 void RH_RF22::isr1()
davidr99 0:ab4e012489ef 321 {
davidr99 0:ab4e012489ef 322 if (_deviceForInterrupt[1])
davidr99 0:ab4e012489ef 323 _deviceForInterrupt[1]->handleInterrupt();
davidr99 0:ab4e012489ef 324 }
davidr99 0:ab4e012489ef 325 void RH_RF22::isr2()
davidr99 0:ab4e012489ef 326 {
davidr99 0:ab4e012489ef 327 if (_deviceForInterrupt[2])
davidr99 0:ab4e012489ef 328 _deviceForInterrupt[2]->handleInterrupt();
davidr99 0:ab4e012489ef 329 }
davidr99 0:ab4e012489ef 330
davidr99 0:ab4e012489ef 331 void RH_RF22::reset()
davidr99 0:ab4e012489ef 332 {
davidr99 0:ab4e012489ef 333 spiWrite(RH_RF22_REG_07_OPERATING_MODE1, RH_RF22_SWRES);
davidr99 0:ab4e012489ef 334 // Wait for it to settle
davidr99 0:ab4e012489ef 335 delay(1); // SWReset time is nominally 100usec
davidr99 0:ab4e012489ef 336 }
davidr99 0:ab4e012489ef 337
davidr99 0:ab4e012489ef 338 uint8_t RH_RF22::statusRead()
davidr99 0:ab4e012489ef 339 {
davidr99 0:ab4e012489ef 340 return spiRead(RH_RF22_REG_02_DEVICE_STATUS);
davidr99 0:ab4e012489ef 341 }
davidr99 0:ab4e012489ef 342
davidr99 0:ab4e012489ef 343 uint8_t RH_RF22::adcRead(uint8_t adcsel,
davidr99 0:ab4e012489ef 344 uint8_t adcref ,
davidr99 0:ab4e012489ef 345 uint8_t adcgain,
davidr99 0:ab4e012489ef 346 uint8_t adcoffs)
davidr99 0:ab4e012489ef 347 {
davidr99 0:ab4e012489ef 348 uint8_t configuration = adcsel | adcref | (adcgain & RH_RF22_ADCGAIN);
davidr99 0:ab4e012489ef 349 spiWrite(RH_RF22_REG_0F_ADC_CONFIGURATION, configuration | RH_RF22_ADCSTART);
davidr99 0:ab4e012489ef 350 spiWrite(RH_RF22_REG_10_ADC_SENSOR_AMP_OFFSET, adcoffs);
davidr99 0:ab4e012489ef 351
davidr99 0:ab4e012489ef 352 // Conversion time is nominally 305usec
davidr99 0:ab4e012489ef 353 // Wait for the DONE bit
davidr99 0:ab4e012489ef 354 while (!(spiRead(RH_RF22_REG_0F_ADC_CONFIGURATION) & RH_RF22_ADCDONE))
davidr99 0:ab4e012489ef 355 ;
davidr99 0:ab4e012489ef 356 // Return the value
davidr99 0:ab4e012489ef 357 return spiRead(RH_RF22_REG_11_ADC_VALUE);
davidr99 0:ab4e012489ef 358 }
davidr99 0:ab4e012489ef 359
davidr99 0:ab4e012489ef 360 uint8_t RH_RF22::temperatureRead(uint8_t tsrange, uint8_t tvoffs)
davidr99 0:ab4e012489ef 361 {
davidr99 0:ab4e012489ef 362 spiWrite(RH_RF22_REG_12_TEMPERATURE_SENSOR_CALIBRATION, tsrange | RH_RF22_ENTSOFFS);
davidr99 0:ab4e012489ef 363 spiWrite(RH_RF22_REG_13_TEMPERATURE_VALUE_OFFSET, tvoffs);
davidr99 0:ab4e012489ef 364 return adcRead(RH_RF22_ADCSEL_INTERNAL_TEMPERATURE_SENSOR | RH_RF22_ADCREF_BANDGAP_VOLTAGE);
davidr99 0:ab4e012489ef 365 }
davidr99 0:ab4e012489ef 366
davidr99 0:ab4e012489ef 367 uint16_t RH_RF22::wutRead()
davidr99 0:ab4e012489ef 368 {
davidr99 0:ab4e012489ef 369 uint8_t buf[2];
davidr99 0:ab4e012489ef 370 spiBurstRead(RH_RF22_REG_17_WAKEUP_TIMER_VALUE1, buf, 2);
davidr99 0:ab4e012489ef 371 return ((uint16_t)buf[0] << 8) | buf[1]; // Dont rely on byte order
davidr99 0:ab4e012489ef 372 }
davidr99 0:ab4e012489ef 373
davidr99 0:ab4e012489ef 374 // RFM-22 doc appears to be wrong: WUT for wtm = 10000, r, = 0, d = 0 is about 1 sec
davidr99 0:ab4e012489ef 375 void RH_RF22::setWutPeriod(uint16_t wtm, uint8_t wtr, uint8_t wtd)
davidr99 0:ab4e012489ef 376 {
davidr99 0:ab4e012489ef 377 uint8_t period[3];
davidr99 0:ab4e012489ef 378
davidr99 0:ab4e012489ef 379 period[0] = ((wtr & 0xf) << 2) | (wtd & 0x3);
davidr99 0:ab4e012489ef 380 period[1] = wtm >> 8;
davidr99 0:ab4e012489ef 381 period[2] = wtm & 0xff;
davidr99 0:ab4e012489ef 382 spiBurstWrite(RH_RF22_REG_14_WAKEUP_TIMER_PERIOD1, period, sizeof(period));
davidr99 0:ab4e012489ef 383 }
davidr99 0:ab4e012489ef 384
davidr99 0:ab4e012489ef 385 // Returns true if centre + (fhch * fhs) is within limits
davidr99 0:ab4e012489ef 386 // Caution, different versions of the RH_RF22 support different max freq
davidr99 0:ab4e012489ef 387 // so YMMV
davidr99 0:ab4e012489ef 388 bool RH_RF22::setFrequency(float centre, float afcPullInRange)
davidr99 0:ab4e012489ef 389 {
davidr99 0:ab4e012489ef 390 uint8_t fbsel = RH_RF22_SBSEL;
davidr99 0:ab4e012489ef 391 uint8_t afclimiter;
davidr99 0:ab4e012489ef 392 if (centre < 240.0 || centre > 960.0) // 930.0 for early silicon
davidr99 0:ab4e012489ef 393 return false;
davidr99 0:ab4e012489ef 394 if (centre >= 480.0)
davidr99 0:ab4e012489ef 395 {
davidr99 0:ab4e012489ef 396 if (afcPullInRange < 0.0 || afcPullInRange > 0.318750)
davidr99 0:ab4e012489ef 397 return false;
davidr99 0:ab4e012489ef 398 centre /= 2;
davidr99 0:ab4e012489ef 399 fbsel |= RH_RF22_HBSEL;
davidr99 0:ab4e012489ef 400 afclimiter = afcPullInRange * 1000000.0 / 1250.0;
davidr99 0:ab4e012489ef 401 }
davidr99 0:ab4e012489ef 402 else
davidr99 0:ab4e012489ef 403 {
davidr99 0:ab4e012489ef 404 if (afcPullInRange < 0.0 || afcPullInRange > 0.159375)
davidr99 0:ab4e012489ef 405 return false;
davidr99 0:ab4e012489ef 406 afclimiter = afcPullInRange * 1000000.0 / 625.0;
davidr99 0:ab4e012489ef 407 }
davidr99 0:ab4e012489ef 408 centre /= 10.0;
davidr99 0:ab4e012489ef 409 float integerPart = floor(centre);
davidr99 0:ab4e012489ef 410 float fractionalPart = centre - integerPart;
davidr99 0:ab4e012489ef 411
davidr99 0:ab4e012489ef 412 uint8_t fb = (uint8_t)integerPart - 24; // Range 0 to 23
davidr99 0:ab4e012489ef 413 fbsel |= fb;
davidr99 0:ab4e012489ef 414 uint16_t fc = fractionalPart * 64000;
davidr99 0:ab4e012489ef 415 spiWrite(RH_RF22_REG_73_FREQUENCY_OFFSET1, 0); // REVISIT
davidr99 0:ab4e012489ef 416 spiWrite(RH_RF22_REG_74_FREQUENCY_OFFSET2, 0);
davidr99 0:ab4e012489ef 417 spiWrite(RH_RF22_REG_75_FREQUENCY_BAND_SELECT, fbsel);
davidr99 0:ab4e012489ef 418 spiWrite(RH_RF22_REG_76_NOMINAL_CARRIER_FREQUENCY1, fc >> 8);
davidr99 0:ab4e012489ef 419 spiWrite(RH_RF22_REG_77_NOMINAL_CARRIER_FREQUENCY0, fc & 0xff);
davidr99 0:ab4e012489ef 420 spiWrite(RH_RF22_REG_2A_AFC_LIMITER, afclimiter);
davidr99 0:ab4e012489ef 421 return !(statusRead() & RH_RF22_FREQERR);
davidr99 0:ab4e012489ef 422 }
davidr99 0:ab4e012489ef 423
davidr99 0:ab4e012489ef 424 // Step size in 10kHz increments
davidr99 0:ab4e012489ef 425 // Returns true if centre + (fhch * fhs) is within limits
davidr99 0:ab4e012489ef 426 bool RH_RF22::setFHStepSize(uint8_t fhs)
davidr99 0:ab4e012489ef 427 {
davidr99 0:ab4e012489ef 428 spiWrite(RH_RF22_REG_7A_FREQUENCY_HOPPING_STEP_SIZE, fhs);
davidr99 0:ab4e012489ef 429 return !(statusRead() & RH_RF22_FREQERR);
davidr99 0:ab4e012489ef 430 }
davidr99 0:ab4e012489ef 431
davidr99 0:ab4e012489ef 432 // Adds fhch * fhs to centre frequency
davidr99 0:ab4e012489ef 433 // Returns true if centre + (fhch * fhs) is within limits
davidr99 0:ab4e012489ef 434 bool RH_RF22::setFHChannel(uint8_t fhch)
davidr99 0:ab4e012489ef 435 {
davidr99 0:ab4e012489ef 436 spiWrite(RH_RF22_REG_79_FREQUENCY_HOPPING_CHANNEL_SELECT, fhch);
davidr99 0:ab4e012489ef 437 return !(statusRead() & RH_RF22_FREQERR);
davidr99 0:ab4e012489ef 438 }
davidr99 0:ab4e012489ef 439
davidr99 0:ab4e012489ef 440 uint8_t RH_RF22::rssiRead()
davidr99 0:ab4e012489ef 441 {
davidr99 0:ab4e012489ef 442 return spiRead(RH_RF22_REG_26_RSSI);
davidr99 0:ab4e012489ef 443 }
davidr99 0:ab4e012489ef 444
davidr99 0:ab4e012489ef 445 uint8_t RH_RF22::ezmacStatusRead()
davidr99 0:ab4e012489ef 446 {
davidr99 0:ab4e012489ef 447 return spiRead(RH_RF22_REG_31_EZMAC_STATUS);
davidr99 0:ab4e012489ef 448 }
davidr99 0:ab4e012489ef 449
davidr99 0:ab4e012489ef 450 void RH_RF22::setOpMode(uint8_t mode)
davidr99 0:ab4e012489ef 451 {
davidr99 0:ab4e012489ef 452 spiWrite(RH_RF22_REG_07_OPERATING_MODE1, mode);
davidr99 0:ab4e012489ef 453 }
davidr99 0:ab4e012489ef 454
davidr99 0:ab4e012489ef 455 void RH_RF22::setModeIdle()
davidr99 0:ab4e012489ef 456 {
davidr99 0:ab4e012489ef 457 if (_mode != RHModeIdle)
davidr99 0:ab4e012489ef 458 {
davidr99 0:ab4e012489ef 459 setOpMode(_idleMode);
davidr99 0:ab4e012489ef 460 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 461 }
davidr99 0:ab4e012489ef 462 }
davidr99 0:ab4e012489ef 463
davidr99 0:ab4e012489ef 464 bool RH_RF22::sleep()
davidr99 0:ab4e012489ef 465 {
davidr99 0:ab4e012489ef 466 if (_mode != RHModeSleep)
davidr99 0:ab4e012489ef 467 {
davidr99 0:ab4e012489ef 468 setOpMode(0);
davidr99 0:ab4e012489ef 469 _mode = RHModeSleep;
davidr99 0:ab4e012489ef 470 }
davidr99 0:ab4e012489ef 471 return true;
davidr99 0:ab4e012489ef 472 }
davidr99 0:ab4e012489ef 473
davidr99 0:ab4e012489ef 474 void RH_RF22::setModeRx()
davidr99 0:ab4e012489ef 475 {
davidr99 0:ab4e012489ef 476 if (_mode != RHModeRx)
davidr99 0:ab4e012489ef 477 {
davidr99 0:ab4e012489ef 478 setOpMode(_idleMode | RH_RF22_RXON);
davidr99 0:ab4e012489ef 479 _mode = RHModeRx;
davidr99 0:ab4e012489ef 480 }
davidr99 0:ab4e012489ef 481 }
davidr99 0:ab4e012489ef 482
davidr99 0:ab4e012489ef 483 void RH_RF22::setModeTx()
davidr99 0:ab4e012489ef 484 {
davidr99 0:ab4e012489ef 485 if (_mode != RHModeTx)
davidr99 0:ab4e012489ef 486 {
davidr99 0:ab4e012489ef 487 setOpMode(_idleMode | RH_RF22_TXON);
davidr99 0:ab4e012489ef 488 // Hmmm, if you dont clear the RX FIFO here, then it appears that going
davidr99 0:ab4e012489ef 489 // to transmit mode in the middle of a receive can corrupt the
davidr99 0:ab4e012489ef 490 // RX FIFO
davidr99 0:ab4e012489ef 491 resetRxFifo();
davidr99 0:ab4e012489ef 492 _mode = RHModeTx;
davidr99 0:ab4e012489ef 493 }
davidr99 0:ab4e012489ef 494 }
davidr99 0:ab4e012489ef 495
davidr99 0:ab4e012489ef 496 void RH_RF22::setTxPower(uint8_t power)
davidr99 0:ab4e012489ef 497 {
davidr99 0:ab4e012489ef 498 spiWrite(RH_RF22_REG_6D_TX_POWER, power | RH_RF22_LNA_SW); // On RF23, LNA_SW must be set.
davidr99 0:ab4e012489ef 499 }
davidr99 0:ab4e012489ef 500
davidr99 0:ab4e012489ef 501 // Sets registers from a canned modem configuration structure
davidr99 0:ab4e012489ef 502 void RH_RF22::setModemRegisters(const ModemConfig* config)
davidr99 0:ab4e012489ef 503 {
davidr99 0:ab4e012489ef 504 spiWrite(RH_RF22_REG_1C_IF_FILTER_BANDWIDTH, config->reg_1c);
davidr99 0:ab4e012489ef 505 spiWrite(RH_RF22_REG_1F_CLOCK_RECOVERY_GEARSHIFT_OVERRIDE, config->reg_1f);
davidr99 0:ab4e012489ef 506 spiBurstWrite(RH_RF22_REG_20_CLOCK_RECOVERY_OVERSAMPLING_RATE, &config->reg_20, 6);
davidr99 0:ab4e012489ef 507 spiBurstWrite(RH_RF22_REG_2C_OOK_COUNTER_VALUE_1, &config->reg_2c, 3);
davidr99 0:ab4e012489ef 508 spiWrite(RH_RF22_REG_58_CHARGE_PUMP_CURRENT_TRIMMING, config->reg_58);
davidr99 0:ab4e012489ef 509 spiWrite(RH_RF22_REG_69_AGC_OVERRIDE1, config->reg_69);
davidr99 0:ab4e012489ef 510 spiBurstWrite(RH_RF22_REG_6E_TX_DATA_RATE1, &config->reg_6e, 5);
davidr99 0:ab4e012489ef 511 }
davidr99 0:ab4e012489ef 512
davidr99 0:ab4e012489ef 513 // Set one of the canned FSK Modem configs
davidr99 0:ab4e012489ef 514 // Returns true if its a valid choice
davidr99 0:ab4e012489ef 515 bool RH_RF22::setModemConfig(ModemConfigChoice index)
davidr99 0:ab4e012489ef 516 {
davidr99 0:ab4e012489ef 517 if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
davidr99 0:ab4e012489ef 518 return false;
davidr99 0:ab4e012489ef 519
davidr99 0:ab4e012489ef 520 RH_RF22::ModemConfig cfg;
davidr99 0:ab4e012489ef 521 memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF22::ModemConfig));
davidr99 0:ab4e012489ef 522 setModemRegisters(&cfg);
davidr99 0:ab4e012489ef 523
davidr99 0:ab4e012489ef 524 return true;
davidr99 0:ab4e012489ef 525 }
davidr99 0:ab4e012489ef 526
davidr99 0:ab4e012489ef 527 // REVISIT: top bit is in Header Control 2 0x33
davidr99 0:ab4e012489ef 528 void RH_RF22::setPreambleLength(uint8_t nibbles)
davidr99 0:ab4e012489ef 529 {
davidr99 0:ab4e012489ef 530 spiWrite(RH_RF22_REG_34_PREAMBLE_LENGTH, nibbles);
davidr99 0:ab4e012489ef 531 }
davidr99 0:ab4e012489ef 532
davidr99 0:ab4e012489ef 533 // Caution doesnt set sync word len in Header Control 2 0x33
davidr99 0:ab4e012489ef 534 void RH_RF22::setSyncWords(const uint8_t* syncWords, uint8_t len)
davidr99 0:ab4e012489ef 535 {
davidr99 0:ab4e012489ef 536 spiBurstWrite(RH_RF22_REG_36_SYNC_WORD3, syncWords, len);
davidr99 0:ab4e012489ef 537 }
davidr99 0:ab4e012489ef 538
davidr99 0:ab4e012489ef 539 void RH_RF22::clearRxBuf()
davidr99 0:ab4e012489ef 540 {
davidr99 0:ab4e012489ef 541 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 542 _bufLen = 0;
davidr99 0:ab4e012489ef 543 _rxBufValid = false;
davidr99 0:ab4e012489ef 544 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 545 }
davidr99 0:ab4e012489ef 546
davidr99 0:ab4e012489ef 547 bool RH_RF22::available()
davidr99 0:ab4e012489ef 548 {
davidr99 0:ab4e012489ef 549 if (!_rxBufValid)
davidr99 0:ab4e012489ef 550 {
davidr99 0:ab4e012489ef 551 if (_mode == RHModeTx)
davidr99 0:ab4e012489ef 552 return false;
davidr99 0:ab4e012489ef 553 setModeRx(); // Make sure we are receiving
davidr99 0:ab4e012489ef 554 }
davidr99 0:ab4e012489ef 555 return _rxBufValid;
davidr99 0:ab4e012489ef 556 }
davidr99 0:ab4e012489ef 557
davidr99 0:ab4e012489ef 558 bool RH_RF22::recv(uint8_t* buf, uint8_t* len)
davidr99 0:ab4e012489ef 559 {
davidr99 0:ab4e012489ef 560 if (!available())
davidr99 0:ab4e012489ef 561 return false;
davidr99 0:ab4e012489ef 562
davidr99 0:ab4e012489ef 563 if (buf && len)
davidr99 0:ab4e012489ef 564 {
davidr99 0:ab4e012489ef 565 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 566 if (*len > _bufLen)
davidr99 0:ab4e012489ef 567 *len = _bufLen;
davidr99 0:ab4e012489ef 568 memcpy(buf, _buf, *len);
davidr99 0:ab4e012489ef 569 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 570 }
davidr99 0:ab4e012489ef 571 clearRxBuf();
davidr99 0:ab4e012489ef 572 // printBuffer("recv:", buf, *len);
davidr99 0:ab4e012489ef 573 return true;
davidr99 0:ab4e012489ef 574 }
davidr99 0:ab4e012489ef 575
davidr99 0:ab4e012489ef 576 void RH_RF22::clearTxBuf()
davidr99 0:ab4e012489ef 577 {
davidr99 0:ab4e012489ef 578 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 579 _bufLen = 0;
davidr99 0:ab4e012489ef 580 _txBufSentIndex = 0;
davidr99 0:ab4e012489ef 581 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 582 }
davidr99 0:ab4e012489ef 583
davidr99 0:ab4e012489ef 584 void RH_RF22::startTransmit()
davidr99 0:ab4e012489ef 585 {
davidr99 0:ab4e012489ef 586 sendNextFragment(); // Actually the first fragment
davidr99 0:ab4e012489ef 587 spiWrite(RH_RF22_REG_3E_PACKET_LENGTH, _bufLen); // Total length that will be sent
davidr99 0:ab4e012489ef 588 setModeTx(); // Start the transmitter, turns off the receiver
davidr99 0:ab4e012489ef 589 }
davidr99 0:ab4e012489ef 590
davidr99 0:ab4e012489ef 591 // Restart the transmission of a packet that had a problem
davidr99 0:ab4e012489ef 592 void RH_RF22::restartTransmit()
davidr99 0:ab4e012489ef 593 {
davidr99 0:ab4e012489ef 594 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 595 _txBufSentIndex = 0;
davidr99 0:ab4e012489ef 596 // Serial.println("Restart");
davidr99 0:ab4e012489ef 597 startTransmit();
davidr99 0:ab4e012489ef 598 }
davidr99 0:ab4e012489ef 599
davidr99 0:ab4e012489ef 600 bool RH_RF22::send(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 601 {
davidr99 0:ab4e012489ef 602 bool ret = true;
davidr99 0:ab4e012489ef 603 waitPacketSent();
davidr99 0:ab4e012489ef 604 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 605 spiWrite(RH_RF22_REG_3A_TRANSMIT_HEADER3, _txHeaderTo);
davidr99 0:ab4e012489ef 606 spiWrite(RH_RF22_REG_3B_TRANSMIT_HEADER2, _txHeaderFrom);
davidr99 0:ab4e012489ef 607 spiWrite(RH_RF22_REG_3C_TRANSMIT_HEADER1, _txHeaderId);
davidr99 0:ab4e012489ef 608 spiWrite(RH_RF22_REG_3D_TRANSMIT_HEADER0, _txHeaderFlags);
davidr99 0:ab4e012489ef 609 if (!fillTxBuf(data, len))
davidr99 0:ab4e012489ef 610 ret = false;
davidr99 0:ab4e012489ef 611 else
davidr99 0:ab4e012489ef 612 startTransmit();
davidr99 0:ab4e012489ef 613 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 614 // printBuffer("send:", data, len);
davidr99 0:ab4e012489ef 615 return ret;
davidr99 0:ab4e012489ef 616 }
davidr99 0:ab4e012489ef 617
davidr99 0:ab4e012489ef 618 bool RH_RF22::fillTxBuf(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 619 {
davidr99 0:ab4e012489ef 620 clearTxBuf();
davidr99 0:ab4e012489ef 621 if (!len)
davidr99 0:ab4e012489ef 622 return false;
davidr99 0:ab4e012489ef 623 return appendTxBuf(data, len);
davidr99 0:ab4e012489ef 624 }
davidr99 0:ab4e012489ef 625
davidr99 0:ab4e012489ef 626 bool RH_RF22::appendTxBuf(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 627 {
davidr99 0:ab4e012489ef 628 if (((uint16_t)_bufLen + len) > RH_RF22_MAX_MESSAGE_LEN)
davidr99 0:ab4e012489ef 629 return false;
davidr99 0:ab4e012489ef 630 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 631 memcpy(_buf + _bufLen, data, len);
davidr99 0:ab4e012489ef 632 _bufLen += len;
davidr99 0:ab4e012489ef 633 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 634 // printBuffer("txbuf:", _buf, _bufLen);
davidr99 0:ab4e012489ef 635 return true;
davidr99 0:ab4e012489ef 636 }
davidr99 0:ab4e012489ef 637
davidr99 0:ab4e012489ef 638 // Assumption: there is currently <= RH_RF22_TXFFAEM_THRESHOLD bytes in the Tx FIFO
davidr99 0:ab4e012489ef 639 void RH_RF22::sendNextFragment()
davidr99 0:ab4e012489ef 640 {
davidr99 0:ab4e012489ef 641 if (_txBufSentIndex < _bufLen)
davidr99 0:ab4e012489ef 642 {
davidr99 0:ab4e012489ef 643 // Some left to send?
davidr99 0:ab4e012489ef 644 uint8_t len = _bufLen - _txBufSentIndex;
davidr99 0:ab4e012489ef 645 // But dont send too much
davidr99 0:ab4e012489ef 646 if (len > (RH_RF22_FIFO_SIZE - RH_RF22_TXFFAEM_THRESHOLD - 1))
davidr99 0:ab4e012489ef 647 len = (RH_RF22_FIFO_SIZE - RH_RF22_TXFFAEM_THRESHOLD - 1);
davidr99 0:ab4e012489ef 648 spiBurstWrite(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _txBufSentIndex, len);
davidr99 0:ab4e012489ef 649 // printBuffer("frag:", _buf + _txBufSentIndex, len);
davidr99 0:ab4e012489ef 650 _txBufSentIndex += len;
davidr99 0:ab4e012489ef 651 }
davidr99 0:ab4e012489ef 652 }
davidr99 0:ab4e012489ef 653
davidr99 0:ab4e012489ef 654 // Assumption: there are at least RH_RF22_RXFFAFULL_THRESHOLD in the RX FIFO
davidr99 0:ab4e012489ef 655 // That means it should only be called after a RXFFAFULL interrupt
davidr99 0:ab4e012489ef 656 void RH_RF22::readNextFragment()
davidr99 0:ab4e012489ef 657 {
davidr99 0:ab4e012489ef 658 if (((uint16_t)_bufLen + RH_RF22_RXFFAFULL_THRESHOLD) > RH_RF22_MAX_MESSAGE_LEN)
davidr99 0:ab4e012489ef 659 return; // Hmmm receiver overflow. Should never occur
davidr99 0:ab4e012489ef 660
davidr99 0:ab4e012489ef 661 // Read the RH_RF22_RXFFAFULL_THRESHOLD octets that should be there
davidr99 0:ab4e012489ef 662 spiBurstRead(RH_RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, RH_RF22_RXFFAFULL_THRESHOLD);
davidr99 0:ab4e012489ef 663 _bufLen += RH_RF22_RXFFAFULL_THRESHOLD;
davidr99 0:ab4e012489ef 664 }
davidr99 0:ab4e012489ef 665
davidr99 0:ab4e012489ef 666 // Clear the FIFOs
davidr99 0:ab4e012489ef 667 void RH_RF22::resetFifos()
davidr99 0:ab4e012489ef 668 {
davidr99 0:ab4e012489ef 669 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRRX | RH_RF22_FFCLRTX);
davidr99 0:ab4e012489ef 670 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0);
davidr99 0:ab4e012489ef 671 }
davidr99 0:ab4e012489ef 672
davidr99 0:ab4e012489ef 673 // Clear the Rx FIFO
davidr99 0:ab4e012489ef 674 void RH_RF22::resetRxFifo()
davidr99 0:ab4e012489ef 675 {
davidr99 0:ab4e012489ef 676 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRRX);
davidr99 0:ab4e012489ef 677 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0);
davidr99 0:ab4e012489ef 678 }
davidr99 0:ab4e012489ef 679
davidr99 0:ab4e012489ef 680 // CLear the TX FIFO
davidr99 0:ab4e012489ef 681 void RH_RF22::resetTxFifo()
davidr99 0:ab4e012489ef 682 {
davidr99 0:ab4e012489ef 683 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, RH_RF22_FFCLRTX);
davidr99 0:ab4e012489ef 684 spiWrite(RH_RF22_REG_08_OPERATING_MODE2, 0);
davidr99 0:ab4e012489ef 685 }
davidr99 0:ab4e012489ef 686
davidr99 0:ab4e012489ef 687 // Default implmentation does nothing. Override if you wish
davidr99 0:ab4e012489ef 688 void RH_RF22::handleExternalInterrupt()
davidr99 0:ab4e012489ef 689 {
davidr99 0:ab4e012489ef 690 }
davidr99 0:ab4e012489ef 691
davidr99 0:ab4e012489ef 692 // Default implmentation does nothing. Override if you wish
davidr99 0:ab4e012489ef 693 void RH_RF22::handleWakeupTimerInterrupt()
davidr99 0:ab4e012489ef 694 {
davidr99 0:ab4e012489ef 695 }
davidr99 0:ab4e012489ef 696
davidr99 0:ab4e012489ef 697 void RH_RF22::setPromiscuous(bool promiscuous)
davidr99 0:ab4e012489ef 698 {
davidr99 0:ab4e012489ef 699 RHSPIDriver::setPromiscuous(promiscuous);
davidr99 0:ab4e012489ef 700 spiWrite(RH_RF22_REG_43_HEADER_ENABLE3, promiscuous ? 0x00 : 0xff);
davidr99 0:ab4e012489ef 701 }
davidr99 0:ab4e012489ef 702
davidr99 0:ab4e012489ef 703 bool RH_RF22::setCRCPolynomial(CRCPolynomial polynomial)
davidr99 0:ab4e012489ef 704 {
davidr99 0:ab4e012489ef 705 if (polynomial >= CRC_CCITT &&
davidr99 0:ab4e012489ef 706 polynomial <= CRC_Biacheva)
davidr99 0:ab4e012489ef 707 {
davidr99 0:ab4e012489ef 708 _polynomial = polynomial;
davidr99 0:ab4e012489ef 709 return true;
davidr99 0:ab4e012489ef 710 }
davidr99 0:ab4e012489ef 711 else
davidr99 0:ab4e012489ef 712 return false;
davidr99 0:ab4e012489ef 713 }
davidr99 0:ab4e012489ef 714
davidr99 0:ab4e012489ef 715 uint8_t RH_RF22::maxMessageLength()
davidr99 0:ab4e012489ef 716 {
davidr99 0:ab4e012489ef 717 return RH_RF22_MAX_MESSAGE_LEN;
davidr99 0:ab4e012489ef 718 }
davidr99 0:ab4e012489ef 719
davidr99 0:ab4e012489ef 720 void RH_RF22::setThisAddress(uint8_t thisAddress)
davidr99 0:ab4e012489ef 721 {
davidr99 0:ab4e012489ef 722 RHSPIDriver::setThisAddress(thisAddress);
davidr99 0:ab4e012489ef 723 spiWrite(RH_RF22_REG_3F_CHECK_HEADER3, thisAddress);
davidr99 0:ab4e012489ef 724 }
davidr99 0:ab4e012489ef 725
davidr99 0:ab4e012489ef 726 uint32_t RH_RF22::getLastPreambleTime()
davidr99 0:ab4e012489ef 727 {
davidr99 0:ab4e012489ef 728 return _lastPreambleTime;
davidr99 0:ab4e012489ef 729 }
davidr99 0:ab4e012489ef 730
davidr99 0:ab4e012489ef 731 void RH_RF22::setGpioReversed(bool gpioReversed)
davidr99 0:ab4e012489ef 732 {
davidr99 0:ab4e012489ef 733 // Ensure the antenna can be switched automatically according to transmit and receive
davidr99 0:ab4e012489ef 734 // This assumes GPIO0(out) is connected to TX_ANT(in) to enable tx antenna during transmit
davidr99 0:ab4e012489ef 735 // This assumes GPIO1(out) is connected to RX_ANT(in) to enable rx antenna during receive
davidr99 0:ab4e012489ef 736 if (gpioReversed)
davidr99 0:ab4e012489ef 737 {
davidr99 0:ab4e012489ef 738 // Reversed for HAB-RFM22B-BOA HAB-RFM22B-BO, also Si4432 sold by Dorji.com via Tindie.com.
davidr99 0:ab4e012489ef 739 spiWrite(RH_RF22_REG_0B_GPIO_CONFIGURATION0, 0x15) ; // RX state
davidr99 0:ab4e012489ef 740 spiWrite(RH_RF22_REG_0C_GPIO_CONFIGURATION1, 0x12) ; // TX state
davidr99 0:ab4e012489ef 741 }
davidr99 0:ab4e012489ef 742 else
davidr99 0:ab4e012489ef 743 {
davidr99 0:ab4e012489ef 744 spiWrite(RH_RF22_REG_0B_GPIO_CONFIGURATION0, 0x12) ; // TX state
davidr99 0:ab4e012489ef 745 spiWrite(RH_RF22_REG_0C_GPIO_CONFIGURATION1, 0x15) ; // RX state
davidr99 0:ab4e012489ef 746 }
davidr99 0:ab4e012489ef 747 }
davidr99 0:ab4e012489ef 748