Port of RadioHead version 1.48 to mbed. It is a little messy and only works for SPI at this time.

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_RF95.cpp,v 1.8 2015/08/12 23:18:51 mikem Exp $
davidr99 0:ab4e012489ef 5
davidr99 0:ab4e012489ef 6 #include <RH_RF95.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_RF95, allowing you to have
davidr99 0:ab4e012489ef 10 // 2 or more LORAs per Arduino
davidr99 0:ab4e012489ef 11 RH_RF95* RH_RF95::_deviceForInterrupt[RH_RF95_NUM_INTERRUPTS] = {0, 0, 0};
davidr99 0:ab4e012489ef 12 uint8_t RH_RF95::_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 PROGMEM static const RH_RF95::ModemConfig MODEM_CONFIG_TABLE[] =
davidr99 0:ab4e012489ef 17 {
davidr99 0:ab4e012489ef 18 // 1d, 1e, 26
davidr99 0:ab4e012489ef 19 { 0x72, 0x74, 0x00}, // Bw125Cr45Sf128 (the chip default)
davidr99 0:ab4e012489ef 20 { 0x92, 0x74, 0x00}, // Bw500Cr45Sf128
davidr99 0:ab4e012489ef 21 { 0x48, 0x94, 0x00}, // Bw31_25Cr48Sf512
davidr99 0:ab4e012489ef 22 { 0x78, 0xc4, 0x00}, // Bw125Cr48Sf4096
davidr99 0:ab4e012489ef 23
davidr99 0:ab4e012489ef 24 };
davidr99 0:ab4e012489ef 25
davidr99 0:ab4e012489ef 26 RH_RF95::RH_RF95(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi)
davidr99 0:ab4e012489ef 27 :
davidr99 0:ab4e012489ef 28 RHSPIDriver(slaveSelectPin, spi),
davidr99 0:ab4e012489ef 29 _rxBufValid(0),
davidr99 0:ab4e012489ef 30 _interruptPin(interruptPin)
davidr99 0:ab4e012489ef 31 {
davidr99 0:ab4e012489ef 32 _myInterruptIndex = 0xff; // Not allocated yet
davidr99 0:ab4e012489ef 33 }
davidr99 0:ab4e012489ef 34
davidr99 0:ab4e012489ef 35 bool RH_RF95::init()
davidr99 0:ab4e012489ef 36 {
davidr99 0:ab4e012489ef 37 if (!RHSPIDriver::init())
davidr99 0:ab4e012489ef 38 return false;
davidr99 0:ab4e012489ef 39
davidr99 0:ab4e012489ef 40 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 41 // Determine the interrupt number that corresponds to the interruptPin
davidr99 0:ab4e012489ef 42 int interruptNumber = digitalPinToInterrupt(_interruptPin);
davidr99 0:ab4e012489ef 43 if (interruptNumber == NOT_AN_INTERRUPT)
davidr99 0:ab4e012489ef 44 return false;
davidr99 0:ab4e012489ef 45 #endif
davidr99 0:ab4e012489ef 46
davidr99 0:ab4e012489ef 47 // No way to check the device type :-(
davidr99 0:ab4e012489ef 48
davidr99 0:ab4e012489ef 49 // Set sleep mode, so we can also set LORA mode:
davidr99 0:ab4e012489ef 50 spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE);
davidr99 0:ab4e012489ef 51 delay(10); // Wait for sleep mode to take over from say, CAD
davidr99 0:ab4e012489ef 52 // Check we are in sleep mode, with LORA set
davidr99 0:ab4e012489ef 53 if (spiRead(RH_RF95_REG_01_OP_MODE) != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE))
davidr99 0:ab4e012489ef 54 {
davidr99 0:ab4e012489ef 55 // Serial.println(spiRead(RH_RF95_REG_01_OP_MODE), HEX);
davidr99 0:ab4e012489ef 56 return false; // No device present?
davidr99 0:ab4e012489ef 57 }
davidr99 0:ab4e012489ef 58
davidr99 0:ab4e012489ef 59 #if (RH_PLATFORM != RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 60 // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy
davidr99 0:ab4e012489ef 61 // ARM M4 requires the below. else pin interrupt doesn't work properly.
davidr99 0:ab4e012489ef 62 // On all other platforms, its innocuous, belt and braces
davidr99 0:ab4e012489ef 63 pinMode(_interruptPin, INPUT);
davidr99 0:ab4e012489ef 64 #endif
davidr99 0:ab4e012489ef 65
davidr99 0:ab4e012489ef 66 // Set up interrupt handler
davidr99 0:ab4e012489ef 67 // Since there are a limited number of interrupt glue functions isr*() available,
davidr99 0:ab4e012489ef 68 // we can only support a limited number of devices simultaneously
davidr99 0:ab4e012489ef 69 // ON some devices, notably most Arduinos, the interrupt pin passed in is actuallt the
davidr99 0:ab4e012489ef 70 // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
davidr99 0:ab4e012489ef 71 // yourself based on knwledge of what Arduino board you are running on.
davidr99 0:ab4e012489ef 72 if (_myInterruptIndex == 0xff)
davidr99 0:ab4e012489ef 73 {
davidr99 0:ab4e012489ef 74 // First run, no interrupt allocated yet
davidr99 0:ab4e012489ef 75 if (_interruptCount <= RH_RF95_NUM_INTERRUPTS)
davidr99 0:ab4e012489ef 76 _myInterruptIndex = _interruptCount++;
davidr99 0:ab4e012489ef 77 else
davidr99 0:ab4e012489ef 78 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 79 }
davidr99 0:ab4e012489ef 80 _deviceForInterrupt[_myInterruptIndex] = this;
davidr99 0:ab4e012489ef 81
davidr99 0:ab4e012489ef 82 #if (RH_PLATFORM == RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 83 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 84 _interruptPin.rise(&isr0);
davidr99 0:ab4e012489ef 85 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 86 _interruptPin.rise(&isr1);
davidr99 0:ab4e012489ef 87 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 88 _interruptPin.rise(&isr2);
davidr99 0:ab4e012489ef 89 else
davidr99 0:ab4e012489ef 90 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 91 #else
davidr99 0:ab4e012489ef 92 if (_myInterruptIndex == 0)
davidr99 0:ab4e012489ef 93 attachInterrupt(interruptNumber, isr0, RISING);
davidr99 0:ab4e012489ef 94 else if (_myInterruptIndex == 1)
davidr99 0:ab4e012489ef 95 attachInterrupt(interruptNumber, isr1, RISING);
davidr99 0:ab4e012489ef 96 else if (_myInterruptIndex == 2)
davidr99 0:ab4e012489ef 97 attachInterrupt(interruptNumber, isr2, RISING);
davidr99 0:ab4e012489ef 98 else
davidr99 0:ab4e012489ef 99 return false; // Too many devices, not enough interrupt vectors
davidr99 0:ab4e012489ef 100 #endif
davidr99 0:ab4e012489ef 101 // Set up FIFO
davidr99 0:ab4e012489ef 102 // We configure so that we can use the entire 256 byte FIFO for either receive
davidr99 0:ab4e012489ef 103 // or transmit, but not both at the same time
davidr99 0:ab4e012489ef 104 spiWrite(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0);
davidr99 0:ab4e012489ef 105 spiWrite(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0);
davidr99 0:ab4e012489ef 106
davidr99 0:ab4e012489ef 107 // Packet format is preamble + explicit-header + payload + crc
davidr99 0:ab4e012489ef 108 // Explicit Header Mode
davidr99 0:ab4e012489ef 109 // payload is TO + FROM + ID + FLAGS + message data
davidr99 0:ab4e012489ef 110 // RX mode is implmented with RXCONTINUOUS
davidr99 0:ab4e012489ef 111 // max message data length is 255 - 4 = 251 octets
davidr99 0:ab4e012489ef 112
davidr99 0:ab4e012489ef 113 setModeIdle();
davidr99 0:ab4e012489ef 114
davidr99 0:ab4e012489ef 115 // Set up default configuration
davidr99 0:ab4e012489ef 116 // No Sync Words in LORA mode.
davidr99 0:ab4e012489ef 117 setModemConfig(Bw125Cr45Sf128); // Radio default
davidr99 0:ab4e012489ef 118 // setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
davidr99 0:ab4e012489ef 119 setPreambleLength(8); // Default is 8
davidr99 0:ab4e012489ef 120 // An innocuous ISM frequency, same as RF22's
davidr99 0:ab4e012489ef 121 setFrequency(434.0);
davidr99 0:ab4e012489ef 122 // Lowish power
davidr99 0:ab4e012489ef 123 setTxPower(13);
davidr99 0:ab4e012489ef 124
davidr99 0:ab4e012489ef 125 return true;
davidr99 0:ab4e012489ef 126 }
davidr99 0:ab4e012489ef 127
davidr99 0:ab4e012489ef 128 // C++ level interrupt handler for this instance
davidr99 0:ab4e012489ef 129 // LORA is unusual in that it has several interrupt lines, and not a single, combined one.
davidr99 0:ab4e012489ef 130 // On MiniWirelessLoRa, only one of the several interrupt lines (DI0) from the RFM95 is usefuly
davidr99 0:ab4e012489ef 131 // connnected to the processor.
davidr99 0:ab4e012489ef 132 // We use this to get RxDone and TxDone interrupts
davidr99 0:ab4e012489ef 133 void RH_RF95::handleInterrupt()
davidr99 0:ab4e012489ef 134 {
davidr99 0:ab4e012489ef 135 // Read the interrupt register
davidr99 0:ab4e012489ef 136 uint8_t irq_flags = spiRead(RH_RF95_REG_12_IRQ_FLAGS);
davidr99 0:ab4e012489ef 137 if (_mode == RHModeRx && irq_flags & (RH_RF95_RX_TIMEOUT | RH_RF95_PAYLOAD_CRC_ERROR))
davidr99 0:ab4e012489ef 138 {
davidr99 0:ab4e012489ef 139 _rxBad++;
davidr99 0:ab4e012489ef 140 }
davidr99 0:ab4e012489ef 141 else if (_mode == RHModeRx && irq_flags & RH_RF95_RX_DONE)
davidr99 0:ab4e012489ef 142 {
davidr99 0:ab4e012489ef 143 // Have received a packet
davidr99 0:ab4e012489ef 144 uint8_t len = spiRead(RH_RF95_REG_13_RX_NB_BYTES);
davidr99 0:ab4e012489ef 145
davidr99 0:ab4e012489ef 146 // Reset the fifo read ptr to the beginning of the packet
davidr99 0:ab4e012489ef 147 spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, spiRead(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR));
davidr99 0:ab4e012489ef 148 spiBurstRead(RH_RF95_REG_00_FIFO, _buf, len);
davidr99 0:ab4e012489ef 149 _bufLen = len;
davidr99 0:ab4e012489ef 150 spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
davidr99 0:ab4e012489ef 151
davidr99 0:ab4e012489ef 152 // Remember the RSSI of this packet
davidr99 0:ab4e012489ef 153 // this is according to the doc, but is it really correct?
davidr99 0:ab4e012489ef 154 // weakest receiveable signals are reported RSSI at about -66
davidr99 0:ab4e012489ef 155 _lastRssi = spiRead(RH_RF95_REG_1A_PKT_RSSI_VALUE) - 137;
davidr99 0:ab4e012489ef 156
davidr99 0:ab4e012489ef 157 // We have received a message.
davidr99 0:ab4e012489ef 158 validateRxBuf();
davidr99 0:ab4e012489ef 159 if (_rxBufValid)
davidr99 0:ab4e012489ef 160 setModeIdle(); // Got one
davidr99 0:ab4e012489ef 161 }
davidr99 0:ab4e012489ef 162 else if (_mode == RHModeTx && irq_flags & RH_RF95_TX_DONE)
davidr99 0:ab4e012489ef 163 {
davidr99 0:ab4e012489ef 164 _txGood++;
davidr99 0:ab4e012489ef 165 setModeIdle();
davidr99 0:ab4e012489ef 166 }
davidr99 0:ab4e012489ef 167
davidr99 0:ab4e012489ef 168 spiWrite(RH_RF95_REG_12_IRQ_FLAGS, 0xff); // Clear all IRQ flags
davidr99 0:ab4e012489ef 169 }
davidr99 0:ab4e012489ef 170
davidr99 0:ab4e012489ef 171 // These are low level functions that call the interrupt handler for the correct
davidr99 0:ab4e012489ef 172 // instance of RH_RF95.
davidr99 0:ab4e012489ef 173 // 3 interrupts allows us to have 3 different devices
davidr99 0:ab4e012489ef 174 void RH_RF95::isr0()
davidr99 0:ab4e012489ef 175 {
davidr99 0:ab4e012489ef 176 if (_deviceForInterrupt[0])
davidr99 0:ab4e012489ef 177 _deviceForInterrupt[0]->handleInterrupt();
davidr99 0:ab4e012489ef 178 }
davidr99 0:ab4e012489ef 179 void RH_RF95::isr1()
davidr99 0:ab4e012489ef 180 {
davidr99 0:ab4e012489ef 181 if (_deviceForInterrupt[1])
davidr99 0:ab4e012489ef 182 _deviceForInterrupt[1]->handleInterrupt();
davidr99 0:ab4e012489ef 183 }
davidr99 0:ab4e012489ef 184 void RH_RF95::isr2()
davidr99 0:ab4e012489ef 185 {
davidr99 0:ab4e012489ef 186 if (_deviceForInterrupt[2])
davidr99 0:ab4e012489ef 187 _deviceForInterrupt[2]->handleInterrupt();
davidr99 0:ab4e012489ef 188 }
davidr99 0:ab4e012489ef 189
davidr99 0:ab4e012489ef 190 // Check whether the latest received message is complete and uncorrupted
davidr99 0:ab4e012489ef 191 void RH_RF95::validateRxBuf()
davidr99 0:ab4e012489ef 192 {
davidr99 0:ab4e012489ef 193 if (_bufLen < 4)
davidr99 0:ab4e012489ef 194 return; // Too short to be a real message
davidr99 0:ab4e012489ef 195 // Extract the 4 headers
davidr99 0:ab4e012489ef 196 _rxHeaderTo = _buf[0];
davidr99 0:ab4e012489ef 197 _rxHeaderFrom = _buf[1];
davidr99 0:ab4e012489ef 198 _rxHeaderId = _buf[2];
davidr99 0:ab4e012489ef 199 _rxHeaderFlags = _buf[3];
davidr99 0:ab4e012489ef 200 if (_promiscuous ||
davidr99 0:ab4e012489ef 201 _rxHeaderTo == _thisAddress ||
davidr99 0:ab4e012489ef 202 _rxHeaderTo == RH_BROADCAST_ADDRESS)
davidr99 0:ab4e012489ef 203 {
davidr99 0:ab4e012489ef 204 _rxGood++;
davidr99 0:ab4e012489ef 205 _rxBufValid = true;
davidr99 0:ab4e012489ef 206 }
davidr99 0:ab4e012489ef 207 }
davidr99 0:ab4e012489ef 208
davidr99 0:ab4e012489ef 209 bool RH_RF95::available()
davidr99 0:ab4e012489ef 210 {
davidr99 0:ab4e012489ef 211 if (_mode == RHModeTx)
davidr99 0:ab4e012489ef 212 return false;
davidr99 0:ab4e012489ef 213 setModeRx();
davidr99 0:ab4e012489ef 214 return _rxBufValid; // Will be set by the interrupt handler when a good message is received
davidr99 0:ab4e012489ef 215 }
davidr99 0:ab4e012489ef 216
davidr99 0:ab4e012489ef 217 void RH_RF95::clearRxBuf()
davidr99 0:ab4e012489ef 218 {
davidr99 0:ab4e012489ef 219 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 220 _rxBufValid = false;
davidr99 0:ab4e012489ef 221 _bufLen = 0;
davidr99 0:ab4e012489ef 222 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 223 }
davidr99 0:ab4e012489ef 224
davidr99 0:ab4e012489ef 225 bool RH_RF95::recv(uint8_t* buf, uint8_t* len)
davidr99 0:ab4e012489ef 226 {
davidr99 0:ab4e012489ef 227 if (!available())
davidr99 0:ab4e012489ef 228 return false;
davidr99 0:ab4e012489ef 229 if (buf && len)
davidr99 0:ab4e012489ef 230 {
davidr99 0:ab4e012489ef 231 ATOMIC_BLOCK_START;
davidr99 0:ab4e012489ef 232 // Skip the 4 headers that are at the beginning of the rxBuf
davidr99 0:ab4e012489ef 233 if (*len > _bufLen-RH_RF95_HEADER_LEN)
davidr99 0:ab4e012489ef 234 *len = _bufLen-RH_RF95_HEADER_LEN;
davidr99 0:ab4e012489ef 235 memcpy(buf, _buf+RH_RF95_HEADER_LEN, *len);
davidr99 0:ab4e012489ef 236 ATOMIC_BLOCK_END;
davidr99 0:ab4e012489ef 237 }
davidr99 0:ab4e012489ef 238 clearRxBuf(); // This message accepted and cleared
davidr99 0:ab4e012489ef 239 return true;
davidr99 0:ab4e012489ef 240 }
davidr99 0:ab4e012489ef 241
davidr99 0:ab4e012489ef 242 bool RH_RF95::send(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 243 {
davidr99 0:ab4e012489ef 244 if (len > RH_RF95_MAX_MESSAGE_LEN)
davidr99 0:ab4e012489ef 245 return false;
davidr99 0:ab4e012489ef 246
davidr99 0:ab4e012489ef 247 waitPacketSent(); // Make sure we dont interrupt an outgoing message
davidr99 0:ab4e012489ef 248 setModeIdle();
davidr99 0:ab4e012489ef 249
davidr99 0:ab4e012489ef 250 // Position at the beginning of the FIFO
davidr99 0:ab4e012489ef 251 spiWrite(RH_RF95_REG_0D_FIFO_ADDR_PTR, 0);
davidr99 0:ab4e012489ef 252 // The headers
davidr99 0:ab4e012489ef 253 spiWrite(RH_RF95_REG_00_FIFO, _txHeaderTo);
davidr99 0:ab4e012489ef 254 spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFrom);
davidr99 0:ab4e012489ef 255 spiWrite(RH_RF95_REG_00_FIFO, _txHeaderId);
davidr99 0:ab4e012489ef 256 spiWrite(RH_RF95_REG_00_FIFO, _txHeaderFlags);
davidr99 0:ab4e012489ef 257 // The message data
davidr99 0:ab4e012489ef 258 spiBurstWrite(RH_RF95_REG_00_FIFO, data, len);
davidr99 0:ab4e012489ef 259 spiWrite(RH_RF95_REG_22_PAYLOAD_LENGTH, len + RH_RF95_HEADER_LEN);
davidr99 0:ab4e012489ef 260
davidr99 0:ab4e012489ef 261 setModeTx(); // Start the transmitter
davidr99 0:ab4e012489ef 262 // when Tx is done, interruptHandler will fire and radio mode will return to STANDBY
davidr99 0:ab4e012489ef 263 return true;
davidr99 0:ab4e012489ef 264 }
davidr99 0:ab4e012489ef 265
davidr99 0:ab4e012489ef 266 bool RH_RF95::printRegisters()
davidr99 0:ab4e012489ef 267 {
davidr99 0:ab4e012489ef 268 #ifdef RH_HAVE_SERIAL
davidr99 0:ab4e012489ef 269 uint8_t registers[] = { 0x01, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x014, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27};
davidr99 0:ab4e012489ef 270
davidr99 0:ab4e012489ef 271 uint8_t i;
davidr99 0:ab4e012489ef 272 for (i = 0; i < sizeof(registers); i++)
davidr99 0:ab4e012489ef 273 {
davidr99 0:ab4e012489ef 274 Serial.print(registers[i], HEX);
davidr99 0:ab4e012489ef 275 Serial.print(": ");
davidr99 0:ab4e012489ef 276 Serial.println(spiRead(registers[i]), HEX);
davidr99 0:ab4e012489ef 277 }
davidr99 0:ab4e012489ef 278 #endif
davidr99 0:ab4e012489ef 279 return true;
davidr99 0:ab4e012489ef 280 }
davidr99 0:ab4e012489ef 281
davidr99 0:ab4e012489ef 282 uint8_t RH_RF95::maxMessageLength()
davidr99 0:ab4e012489ef 283 {
davidr99 0:ab4e012489ef 284 return RH_RF95_MAX_MESSAGE_LEN;
davidr99 0:ab4e012489ef 285 }
davidr99 0:ab4e012489ef 286
davidr99 0:ab4e012489ef 287 bool RH_RF95::setFrequency(float centre)
davidr99 0:ab4e012489ef 288 {
davidr99 0:ab4e012489ef 289 // Frf = FRF / FSTEP
davidr99 0:ab4e012489ef 290 uint32_t frf = (centre * 1000000.0) / RH_RF95_FSTEP;
davidr99 0:ab4e012489ef 291 spiWrite(RH_RF95_REG_06_FRF_MSB, (frf >> 16) & 0xff);
davidr99 0:ab4e012489ef 292 spiWrite(RH_RF95_REG_07_FRF_MID, (frf >> 8) & 0xff);
davidr99 0:ab4e012489ef 293 spiWrite(RH_RF95_REG_08_FRF_LSB, frf & 0xff);
davidr99 0:ab4e012489ef 294
davidr99 0:ab4e012489ef 295 return true;
davidr99 0:ab4e012489ef 296 }
davidr99 0:ab4e012489ef 297
davidr99 0:ab4e012489ef 298 void RH_RF95::setModeIdle()
davidr99 0:ab4e012489ef 299 {
davidr99 0:ab4e012489ef 300 if (_mode != RHModeIdle)
davidr99 0:ab4e012489ef 301 {
davidr99 0:ab4e012489ef 302 spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_STDBY);
davidr99 0:ab4e012489ef 303 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 304 }
davidr99 0:ab4e012489ef 305 }
davidr99 0:ab4e012489ef 306
davidr99 0:ab4e012489ef 307 bool RH_RF95::sleep()
davidr99 0:ab4e012489ef 308 {
davidr99 0:ab4e012489ef 309 if (_mode != RHModeSleep)
davidr99 0:ab4e012489ef 310 {
davidr99 0:ab4e012489ef 311 spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_SLEEP);
davidr99 0:ab4e012489ef 312 _mode = RHModeSleep;
davidr99 0:ab4e012489ef 313 }
davidr99 0:ab4e012489ef 314 return true;
davidr99 0:ab4e012489ef 315 }
davidr99 0:ab4e012489ef 316
davidr99 0:ab4e012489ef 317 void RH_RF95::setModeRx()
davidr99 0:ab4e012489ef 318 {
davidr99 0:ab4e012489ef 319 if (_mode != RHModeRx)
davidr99 0:ab4e012489ef 320 {
davidr99 0:ab4e012489ef 321 spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_RXCONTINUOUS);
davidr99 0:ab4e012489ef 322 spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone
davidr99 0:ab4e012489ef 323 _mode = RHModeRx;
davidr99 0:ab4e012489ef 324 }
davidr99 0:ab4e012489ef 325 }
davidr99 0:ab4e012489ef 326
davidr99 0:ab4e012489ef 327 void RH_RF95::setModeTx()
davidr99 0:ab4e012489ef 328 {
davidr99 0:ab4e012489ef 329 if (_mode != RHModeTx)
davidr99 0:ab4e012489ef 330 {
davidr99 0:ab4e012489ef 331 spiWrite(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_TX);
davidr99 0:ab4e012489ef 332 spiWrite(RH_RF95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone
davidr99 0:ab4e012489ef 333 _mode = RHModeTx;
davidr99 0:ab4e012489ef 334 }
davidr99 0:ab4e012489ef 335 }
davidr99 0:ab4e012489ef 336
davidr99 0:ab4e012489ef 337 void RH_RF95::setTxPower(int8_t power)
davidr99 0:ab4e012489ef 338 {
davidr99 0:ab4e012489ef 339 if (power > 23)
davidr99 0:ab4e012489ef 340 power = 23;
davidr99 0:ab4e012489ef 341 if (power < 5)
davidr99 0:ab4e012489ef 342 power = 5;
davidr99 0:ab4e012489ef 343
davidr99 0:ab4e012489ef 344 // For RH_RF95_PA_DAC_ENABLE, manual says '+20dBm on PA_BOOST when OutputPower=0xf'
davidr99 0:ab4e012489ef 345 // RH_RF95_PA_DAC_ENABLE actually adds about 3dBm to all power levels. We will us it
davidr99 0:ab4e012489ef 346 // for 21, 22 and 23dBm
davidr99 0:ab4e012489ef 347 if (power > 20)
davidr99 0:ab4e012489ef 348 {
davidr99 0:ab4e012489ef 349 spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_ENABLE);
davidr99 0:ab4e012489ef 350 power -= 3;
davidr99 0:ab4e012489ef 351 }
davidr99 0:ab4e012489ef 352 else
davidr99 0:ab4e012489ef 353 {
davidr99 0:ab4e012489ef 354 spiWrite(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_DISABLE);
davidr99 0:ab4e012489ef 355 }
davidr99 0:ab4e012489ef 356
davidr99 0:ab4e012489ef 357 // RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
davidr99 0:ab4e012489ef 358 // pin is connected, so must use PA_BOOST
davidr99 0:ab4e012489ef 359 // Pout = 2 + OutputPower.
davidr99 0:ab4e012489ef 360 // The documentation is pretty confusing on this topic: PaSelect says the max power is 20dBm,
davidr99 0:ab4e012489ef 361 // but OutputPower claims it would be 17dBm.
davidr99 0:ab4e012489ef 362 // My measurements show 20dBm is correct
davidr99 0:ab4e012489ef 363 spiWrite(RH_RF95_REG_09_PA_CONFIG, RH_RF95_PA_SELECT | (power-5));
davidr99 0:ab4e012489ef 364 }
davidr99 0:ab4e012489ef 365
davidr99 0:ab4e012489ef 366 // Sets registers from a canned modem configuration structure
davidr99 0:ab4e012489ef 367 void RH_RF95::setModemRegisters(const ModemConfig* config)
davidr99 0:ab4e012489ef 368 {
davidr99 0:ab4e012489ef 369 spiWrite(RH_RF95_REG_1D_MODEM_CONFIG1, config->reg_1d);
davidr99 0:ab4e012489ef 370 spiWrite(RH_RF95_REG_1E_MODEM_CONFIG2, config->reg_1e);
davidr99 0:ab4e012489ef 371 spiWrite(RH_RF95_REG_26_MODEM_CONFIG3, config->reg_26);
davidr99 0:ab4e012489ef 372 }
davidr99 0:ab4e012489ef 373
davidr99 0:ab4e012489ef 374 // Set one of the canned FSK Modem configs
davidr99 0:ab4e012489ef 375 // Returns true if its a valid choice
davidr99 0:ab4e012489ef 376 bool RH_RF95::setModemConfig(ModemConfigChoice index)
davidr99 0:ab4e012489ef 377 {
davidr99 0:ab4e012489ef 378 if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
davidr99 0:ab4e012489ef 379 return false;
davidr99 0:ab4e012489ef 380
davidr99 0:ab4e012489ef 381 ModemConfig cfg;
davidr99 0:ab4e012489ef 382 memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(RH_RF95::ModemConfig));
davidr99 0:ab4e012489ef 383 setModemRegisters(&cfg);
davidr99 0:ab4e012489ef 384
davidr99 0:ab4e012489ef 385 return true;
davidr99 0:ab4e012489ef 386 }
davidr99 0:ab4e012489ef 387
davidr99 0:ab4e012489ef 388 void RH_RF95::setPreambleLength(uint16_t bytes)
davidr99 0:ab4e012489ef 389 {
davidr99 0:ab4e012489ef 390 spiWrite(RH_RF95_REG_20_PREAMBLE_MSB, bytes >> 8);
davidr99 0:ab4e012489ef 391 spiWrite(RH_RF95_REG_21_PREAMBLE_LSB, bytes & 0xff);
davidr99 0:ab4e012489ef 392 }
davidr99 0:ab4e012489ef 393