|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- // RH_MRF89.cpp
- //
- // Copyright (C) 2015 Mike McCauley
- // $Id: RH_MRF89.cpp,v 1.7 2015/12/31 04:23:12 mikem Exp $
-
- #include <RH_MRF89.h>
- #define BAND_915
- #define DATA_RATE_200
- #define LNA_GAIN LNA_GAIN_0_DB
- #define TX_POWER TX_POWER_13_DB
-
- // Interrupt vectors for the 3 Arduino interrupt pins
- // Each interrupt can be handled by a different instance of RH_MRF89, allowing you to have
- // 2 or more LORAs per Arduino
- RH_MRF89* RH_MRF89::_deviceForInterrupt[RH_MRF89_NUM_INTERRUPTS] = {0, 0, 0};
- uint8_t RH_MRF89::_interruptCount = 0; // Index into _deviceForInterrupt for next device
-
- // These are indexed by the values of ModemConfigChoice
- // Values based on sample modulation values from MRF89XA.h
- // TXIPOLFV set to be more than Fd
- PROGMEM static const RH_MRF89::ModemConfig MODEM_CONFIG_TABLE[] =
- {
- // MODSEL, FDVAL, BRVAL, FILCREG=(PASFILV|BUTFILV), TXIPOLFV
- // FSK, No Manchester, Whitening
- { RH_MRF89_MODSEL_FSK, 0x0B, 0x63, 0x40 | 0x01, 0x20 }, // FSK_Rb2Fd33
- { RH_MRF89_MODSEL_FSK, 0x0B, 0x27, 0x40 | 0x01, 0x20 }, // FSK_Rb5Fd33
- { RH_MRF89_MODSEL_FSK, 0x0B, 0x13, 0x40 | 0x01, 0x20 }, // FSK_Rb10Fd33
- { RH_MRF89_MODSEL_FSK, 0x09, 0x09, 0x70 | 0x02, 0x20 }, // FSK_Rb20Fd40
- { RH_MRF89_MODSEL_FSK, 0x04, 0x04, 0xB0 | 0x05, 0x40 }, // FSK_Rb40Fd80
- { RH_MRF89_MODSEL_FSK, 0x03, 0x03, 0xD0 | 0x06, 0x40 }, // FSK_Rb50Fd100
- { RH_MRF89_MODSEL_FSK, 0x02, 0x02, 0xE0 | 0x09, 0x60 }, // FSK_Rb66Fd133
- { RH_MRF89_MODSEL_FSK, 0x01, 0x01, 0xF0 | 0x0F, 0x80 }, // FSK_Rb100Fd200
- { RH_MRF89_MODSEL_FSK, 0x01, 0x00, 0xF0 | 0x0F, 0x80 } // FSK_Rb200Fd200
-
- };
-
-
- RH_MRF89::RH_MRF89(uint8_t csconPin, uint8_t csdatPin, uint8_t interruptPin, RHGenericSPI& spi)
- :
- RHNRFSPIDriver(csconPin, spi),
- _csconPin(csconPin),
- _csdatPin(csdatPin),
- _interruptPin(interruptPin)
- {
- _myInterruptIndex = 0xff; // Not allocated yet
- }
-
- bool RH_MRF89::init()
- {
- // MRF89 data cant handle SPI greater than 1MHz.
- // Sigh on teensy at 1MHz, need special delay after writes, see RHNRFSPIDriver::spiWrite
- _spi.setFrequency(RHGenericSPI::Frequency1MHz);
- if (!RHNRFSPIDriver::init())
- return false;
-
- // Initialise the chip select pins
- pinMode(_csconPin, OUTPUT);
- digitalWrite(_csconPin, HIGH);
- pinMode(_csdatPin, OUTPUT);
- digitalWrite(_csdatPin, HIGH);
-
- // Determine the interrupt number that corresponds to the interruptPin
- int interruptNumber = digitalPinToInterrupt(_interruptPin);
- if (interruptNumber == NOT_AN_INTERRUPT)
- return false;
- #ifdef RH_ATTACHINTERRUPT_TAKES_PIN_NUMBER
- interruptNumber = _interruptPin;
- #endif
-
- // Make sure we are not in some unexpected mode from a previous run
- setOpMode(RH_MRF89_CMOD_STANDBY);
-
- // No way to check the device type but lets trivially check there is something there
- // by trying to change a register:
- spiWriteRegister(RH_MRF89_REG_02_FDEVREG, 0xaa);
- if (spiReadRegister(RH_MRF89_REG_02_FDEVREG) != 0xaa)
- return false;
- spiWriteRegister(RH_MRF89_REG_02_FDEVREG, 0x3); // Back to the default for FDEV
- if (spiReadRegister(RH_MRF89_REG_02_FDEVREG) != 0x3)
- return false;
-
- // Add by Adrien van den Bossche <vandenbo@univ-tlse2.fr> for Teensy
- // ARM M4 requires the below. else pin interrupt doesn't work properly.
- // On all other platforms, its innocuous, belt and braces
- pinMode(_interruptPin, INPUT);
-
- // Set up interrupt handler
- // Since there are a limited number of interrupt glue functions isr*() available,
- // we can only support a limited number of devices simultaneously
- // On some devices, notably most Arduinos, the interrupt pin passed in is actually the
- // interrupt number. You have to figure out the interruptnumber-to-interruptpin mapping
- // yourself based on knowledge of what Arduino board you are running on.
- if (_myInterruptIndex == 0xff)
- {
- // First run, no interrupt allocated yet
- if (_interruptCount <= RH_MRF89_NUM_INTERRUPTS)
- _myInterruptIndex = _interruptCount++;
- else
- return false; // Too many devices, not enough interrupt vectors
- }
- _deviceForInterrupt[_myInterruptIndex] = this;
- if (_myInterruptIndex == 0)
- attachInterrupt(interruptNumber, isr0, RISING);
- else if (_myInterruptIndex == 1)
- attachInterrupt(interruptNumber, isr1, RISING);
- else if (_myInterruptIndex == 2)
- attachInterrupt(interruptNumber, isr2, RISING);
- else
- return false; // Too many devices, not enough interrupt vectors
-
- // When used with the MRF89XAM9A module, per 75017B.pdf section 1.3, need:
- // crystal freq = 12.8MHz
- // clock output disabled
- // frequency bands 902-915 or 915-928
- // VCOT 60mV
- // OOK max 28kbps
- // Based on 70622C.pdf, section 3.12:
- spiWriteRegister(RH_MRF89_REG_00_GCONREG, RH_MRF89_CMOD_STANDBY | RH_MRF89_FBS_950_960 | RH_MRF89_VCOT_60MV);
- spiWriteRegister(RH_MRF89_REG_01_DMODREG, RH_MRF89_MODSEL_FSK | RH_MRF89_OPMODE_PACKET); // FSK, Packet mode, LNA 0dB
- spiWriteRegister(RH_MRF89_REG_02_FDEVREG, 0); // Set by setModemConfig
- spiWriteRegister(RH_MRF89_REG_03_BRSREG, 0); // Set by setModemConfig
- spiWriteRegister(RH_MRF89_REG_04_FLTHREG, 0); // Set by setModemConfig (OOK only)
- spiWriteRegister(RH_MRF89_REG_05_FIFOCREG, RH_MRF89_FSIZE_64);
- spiWriteRegister(RH_MRF89_REG_06_R1CREG, 0); // Set by setFrequency
- spiWriteRegister(RH_MRF89_REG_07_P1CREG, 0); // Set by setFrequency
- spiWriteRegister(RH_MRF89_REG_08_S1CREG, 0); // Set by setFrequency
- spiWriteRegister(RH_MRF89_REG_09_R2CREG, 0); // Frequency set 2 not used
- spiWriteRegister(RH_MRF89_REG_0A_P2CREG, 0); // Frequency set 2 not used
- spiWriteRegister(RH_MRF89_REG_0B_S2CREG, 0); // Frequency set 2 not used
- spiWriteRegister(RH_MRF89_REG_0C_PACREG, RH_MRF89_PARC_23);
- // IRQ0 rx mode: SYNC (not used)
- // IRQ1 rx mode: CRCOK
- // IRQ1 tx mode: TXDONE
- spiWriteRegister(RH_MRF89_REG_0D_FTXRXIREG, RH_MRF89_IRQ0RXS_PACKET_SYNC | RH_MRF89_IRQ1RXS_PACKET_CRCOK | RH_MRF89_IRQ1TX);
- spiWriteRegister(RH_MRF89_REG_0E_FTPRIREG, RH_MRF89_LENPLL);
- spiWriteRegister(RH_MRF89_REG_0F_RSTHIREG, 0x00); // default not used if no RSSI interrupts
- spiWriteRegister(RH_MRF89_REG_10_FILCREG, 0); // Set by setModemConfig
-
- spiWriteRegister(RH_MRF89_REG_11_PFCREG, 0x38);// 100kHz, recommended, but not used, see RH_MRF89_REG_12_SYNCREG OOK only?
- spiWriteRegister(RH_MRF89_REG_12_SYNCREG, RH_MRF89_SYNCREN | RH_MRF89_SYNCWSZ_32); // No polyphase, no bsync, sync, 0 errors
- spiWriteRegister(RH_MRF89_REG_13_RSVREG, 0x07);//default
- // spiWriteRegister(RH_MRF89_REG_14_RSTSREG, 0x00); // NO, read only
- spiWriteRegister(RH_MRF89_REG_15_OOKCREG, 0x00); // Set by setModemConfig OOK only
- spiWriteRegister(RH_MRF89_REG_16_SYNCV31REG, 0x69); // Set by setSyncWords
- spiWriteRegister(RH_MRF89_REG_17_SYNCV23REG, 0x81); // Set by setSyncWords
- spiWriteRegister(RH_MRF89_REG_18_SYNCV15REG, 0x7E); // Set by setSyncWords
- spiWriteRegister(RH_MRF89_REG_19_SYNCV07REG, 0x96); // Set by setSyncWords
- // TXIPOLFV set by setModemConfig. power set by setTxPower
- spiWriteRegister(RH_MRF89_REG_1A_TXCONREG, 0xf0 | RH_MRF89_TXOPVAL_13DBM); // TX cutoff freq=375kHz,
- spiWriteRegister(RH_MRF89_REG_1B_CLKOREG, 0x00); // Disable clock output to save power
- spiWriteRegister(RH_MRF89_REG_1C_PLOADREG, 0x40); // payload=64bytes (no RX-filtering on packet length)
- spiWriteRegister(RH_MRF89_REG_1D_NADDSREG, 0x00); // Node Address (0=default) Not used
- spiWriteRegister(RH_MRF89_REG_1E_PKTCREG, RH_MRF89_PKTLENF | RH_MRF89_PRESIZE_4 | RH_MRF89_WHITEON | RH_MRF89_CHKCRCEN | RH_MRF89_ADDFIL_OFF);
- spiWriteRegister(RH_MRF89_REG_1F_FCRCREG, 0x00); // default (FIFO access in standby=write, clear FIFO on CRC mismatch)
-
- // Looking OK now
- // Set some suitable defaults:
- setPreambleLength(3); // The default
- uint8_t syncwords[] = { 0x69, 0x81, 0x7e, 0x96 }; // Same as RH_MRF89XA
- setSyncWords(syncwords, sizeof(syncwords));
- setTxPower(RH_MRF89_TXOPVAL_1DBM);
- if (!setFrequency(915.4))
- return false;
- // Some slow, reliable default speed and modulation
- if (!setModemConfig(FSK_Rb20Fd40))
- return false;
-
- return true;
- }
-
- bool RH_MRF89::printRegisters()
- {
- #ifdef RH_HAVE_SERIAL
- uint8_t i;
- for (i = 0; i <= 0x1f; i++)
- {
- Serial.print(i, HEX);
- Serial.print(": ");
- Serial.println(spiReadRegister(i), HEX);
- }
- #endif
- return true;
- }
-
- // C++ level interrupt handler for this instance
- // MRF89XA is unusual in that it has 2 interrupt lines, and not a single, combined one.
- // Only one of the several interrupt lines (IRQ1) from the RFM95 needs to be
- // connnected to the processor.
- // We use this to get CRCOK and TXDONE interrupts
- void RH_MRF89::handleInterrupt()
- {
- // Serial.println("I");
- if (_mode == RHModeTx)
- {
- // Serial.println("T");
- // TXDONE
- // Transmit is complete
- _txGood++;
- setModeIdle();
- }
- else if (_mode == RHModeRx)
- {
- // Serial.println("R");
- // CRCOK
- // We have received a packet.
- // First byte in FIFO is packet length
-
- // REVISIT: Capture last rssi from RSTSREG
- // based roughly on Figure 3-9
- _lastRssi = (spiReadRegister(RH_MRF89_REG_14_RSTSREG) >> 1) - 120;
-
- _bufLen = spiReadData();
- if (_bufLen < 4)
- {
- // Drain the FIFO
- uint8_t i;
- for (i = 0; spiReadRegister(RH_MRF89_REG_0D_FTXRXIREG) & RH_MRF89_FIFOEMPTY; i++)
- spiReadData();
- clearRxBuf();
- return;
- }
-
- // Now drain all the data from the FIFO into _buf
- uint8_t i;
- for (i = 0; spiReadRegister(RH_MRF89_REG_0D_FTXRXIREG) & RH_MRF89_FIFOEMPTY; i++)
- _buf[i] = spiReadData();
-
- // All good. See if its for us
- validateRxBuf();
- if (_rxBufValid)
- setModeIdle(); // Got one
- }
- }
-
- // These are low level functions that call the interrupt handler for the correct
- // instance of RH_MRF89.
- // 3 interrupts allows us to have 3 different devices
- void RH_MRF89::isr0()
- {
- if (_deviceForInterrupt[0])
- _deviceForInterrupt[0]->handleInterrupt();
- }
- void RH_MRF89::isr1()
- {
- if (_deviceForInterrupt[1])
- _deviceForInterrupt[1]->handleInterrupt();
- }
- void RH_MRF89::isr2()
- {
- if (_deviceForInterrupt[2])
- _deviceForInterrupt[2]->handleInterrupt();
- }
-
- uint8_t RH_MRF89::spiReadRegister(uint8_t reg)
- {
- // Tell the chip we want to talk to the configuration registers
- setSlaveSelectPin(_csconPin);
- digitalWrite(_csdatPin, HIGH);
- return spiRead(((reg & 0x1f) << 1) | RH_MRF89_SPI_READ_MASK);
- }
-
- uint8_t RH_MRF89::spiWriteRegister(uint8_t reg, uint8_t val)
- {
- // Tell the chip we want to talk to the configuration registers
- setSlaveSelectPin(_csconPin);
- digitalWrite(_csdatPin, HIGH);
- // Hmmm, on teensy 3.1, needed some special behaviour in RHNRFSPIDriver::spiWrite
- // because otherwise, CSCON returns high before the final clock goes low,
- // which prevents the MRF89XA spi write succeeding. Clock must be low when CSCON goes high.
- return spiWrite(((reg & 0x1f) << 1), val);
- }
-
- uint8_t RH_MRF89::spiWriteData(uint8_t data)
- {
- spiWriteRegister(RH_MRF89_REG_1F_FCRCREG, RH_MRF89_ACFCRC); // Write to FIFO
- setSlaveSelectPin(_csdatPin);
- digitalWrite(_csconPin, HIGH);
- return spiCommand(data);
- }
-
- uint8_t RH_MRF89::spiWriteData(const uint8_t* data, uint8_t len)
- {
- spiWriteRegister(RH_MRF89_REG_1F_FCRCREG, RH_MRF89_ACFCRC); // Write to FIFO
- setSlaveSelectPin(_csdatPin);
- digitalWrite(_csconPin, HIGH);
-
- uint8_t status = 0;
- ATOMIC_BLOCK_START;
- _spi.beginTransaction();
- digitalWrite(_slaveSelectPin, LOW);
- while (len--)
- _spi.transfer(*data++);
- digitalWrite(_slaveSelectPin, HIGH);
- _spi.endTransaction();
- ATOMIC_BLOCK_END;
- return status;
-
- }
-
- uint8_t RH_MRF89::spiReadData()
- {
- spiWriteRegister(RH_MRF89_REG_1F_FCRCREG, RH_MRF89_ACFCRC | RH_MRF89_FRWAXS); // Read from FIFO
- setSlaveSelectPin(_csdatPin);
- digitalWrite(_csconPin, HIGH);
- return spiCommand(0);
- }
-
- void RH_MRF89::setOpMode(uint8_t mode)
- {
- // REVISIT: do we need to have time delays when switching between modes?
- uint8_t val = spiReadRegister(RH_MRF89_REG_00_GCONREG);
- val = (val & ~RH_MRF89_CMOD) | (mode & RH_MRF89_CMOD);
- spiWriteRegister(RH_MRF89_REG_00_GCONREG, val);
- }
-
- void RH_MRF89::setModeIdle()
- {
- if (_mode != RHModeIdle)
- {
- setOpMode(RH_MRF89_CMOD_STANDBY);
- _mode = RHModeIdle;
- }
- }
-
- bool RH_MRF89::sleep()
- {
- if (_mode != RHModeSleep)
- {
- setOpMode(RH_MRF89_CMOD_SLEEP);
- _mode = RHModeSleep;
- }
- return true;
- }
-
- void RH_MRF89::setModeRx()
- {
- if (_mode != RHModeRx)
- {
- setOpMode(RH_MRF89_CMOD_RECEIVE);
- _mode = RHModeRx;
- }
- }
-
- void RH_MRF89::setModeTx()
- {
- if (_mode != RHModeTx)
- {
- setOpMode(RH_MRF89_CMOD_TRANSMIT);
- _mode = RHModeTx;
- }
- }
-
- void RH_MRF89::setTxPower(uint8_t power)
- {
- uint8_t txconreg = spiReadRegister(RH_MRF89_REG_1A_TXCONREG);
- txconreg |= (power & RH_MRF89_TXOPVAL);
- spiWriteRegister(RH_MRF89_REG_1A_TXCONREG, txconreg);
- }
-
- bool RH_MRF89::available()
- {
- if (_mode == RHModeTx)
- return false;
- setModeRx();
-
- return _rxBufValid; // Will be set by the interrupt handler when a good message is received
- }
-
- bool RH_MRF89::recv(uint8_t* buf, uint8_t* len)
- {
- if (!available())
- return false;
-
- if (buf && len)
- {
- ATOMIC_BLOCK_START;
- // Skip the 4 headers that are at the beginning of the rxBuf
- if (*len > _bufLen - RH_MRF89_HEADER_LEN)
- *len = _bufLen - RH_MRF89_HEADER_LEN;
- memcpy(buf, _buf + RH_MRF89_HEADER_LEN, *len);
- ATOMIC_BLOCK_END;
- }
- clearRxBuf(); // This message accepted and cleared
-
- return true;
- }
-
- bool RH_MRF89::send(const uint8_t* data, uint8_t len)
- {
- if (len > RH_MRF89_MAX_MESSAGE_LEN)
- return false;
-
- waitPacketSent(); // Make sure we dont interrupt an outgoing message
- setModeIdle();
-
- // First octet is the length of the chip payload
- // 0 length messages are transmitted but never trigger a receive!
- spiWriteData(len + RH_MRF89_HEADER_LEN);
- spiWriteData(_txHeaderTo);
- spiWriteData(_txHeaderFrom);
- spiWriteData(_txHeaderId);
- spiWriteData(_txHeaderFlags);
- spiWriteData(data, len);
- setModeTx(); // Start transmitting
-
- return true;
- }
-
- uint8_t RH_MRF89::maxMessageLength()
- {
- return RH_MRF89_MAX_MESSAGE_LEN;
- }
-
- // Check whether the latest received message is complete and uncorrupted
- void RH_MRF89::validateRxBuf()
- {
- if (_bufLen < 4)
- return; // Too short to be a real message
- // Extract the 4 headers
- _rxHeaderTo = _buf[0];
- _rxHeaderFrom = _buf[1];
- _rxHeaderId = _buf[2];
- _rxHeaderFlags = _buf[3];
- if (_promiscuous ||
- _rxHeaderTo == _thisAddress ||
- _rxHeaderTo == RH_BROADCAST_ADDRESS)
- {
- _rxGood++;
- _rxBufValid = true;
- }
- }
-
- void RH_MRF89::clearRxBuf()
- {
- ATOMIC_BLOCK_START;
- _rxBufValid = false;
- _bufLen = 0;
- ATOMIC_BLOCK_END;
- }
-
- bool RH_MRF89::verifyPLLLock()
- {
- // Verify PLL-lock per instructions in Note 1 section 3.12
- // Need to do this after changing frequency.
- uint8_t ftpriVal = spiReadRegister(RH_MRF89_REG_0E_FTPRIREG);
- spiWriteRegister(RH_MRF89_REG_0E_FTPRIREG, ftpriVal | RH_MRF89_LSTSPLL); // Clear PLL lock bit
- setOpMode(RH_MRF89_CMOD_FS);
- unsigned long ulStartTime = millis();
- while ((millis() - ulStartTime < 1000))
- {
- ftpriVal = spiReadRegister(RH_MRF89_REG_0E_FTPRIREG);
- if ((ftpriVal & RH_MRF89_LSTSPLL) != 0)
- break;
- }
- setOpMode(RH_MRF89_CMOD_STANDBY);
- return ((ftpriVal & RH_MRF89_LSTSPLL) != 0);
- }
-
- bool RH_MRF89::setFrequency(float centre)
- {
- // REVISIT: FSK only: its different for OOK :-(
-
- uint8_t FBS;
- if (centre >= 902.0 && centre < 915.0)
- {
- FBS = RH_MRF89_FBS_902_915;
- }
- else if (centre >= 915.0 && centre <= 928.0)
- {
- FBS = RH_MRF89_FBS_915_928;
- }
- else if (centre >= 950.0 && centre <= 960.0)
- {
- // Not all modules support this frequency band:
- // The MRF98XAM9A does not
- FBS = RH_MRF89_FBS_950_960;
- }
- // else if (centre >= 863.0 && centre <= 870.0)
- // {
- // // Not all modules support this frequency band:
- // // The MRF98XAM9A does not
- // FBS = RH_MRF89_FBS_950_960; // Yes same as above
- // }
- else
- {
- // Cant do this freq
- return false;
- }
-
- // Based on frequency calcs done in MRF89XA.h
- // uint8_t R = 100; // Recommended
- uint8_t R = 119; // Also recommended :-(
- uint32_t centre_kHz = centre * 1000;
- uint32_t xtal_kHz = (RH_MRF89_XTAL_FREQ * 1000);
- uint32_t compare = (centre_kHz * 8 * (R + 1)) / (9 * xtal_kHz);
- uint8_t P = ((compare - 75) / 76) + 1;
- uint8_t S = compare - (75 * (P + 1));
-
- // Now set the new register values:
- uint8_t val = spiReadRegister(RH_MRF89_REG_00_GCONREG);
- val = (val & ~RH_MRF89_FBS) | (FBS & RH_MRF89_FBS);
- spiWriteRegister(RH_MRF89_REG_00_GCONREG, val);
-
- spiWriteRegister(RH_MRF89_REG_06_R1CREG, R);
- spiWriteRegister(RH_MRF89_REG_07_P1CREG, P);
- spiWriteRegister(RH_MRF89_REG_08_S1CREG, S);
-
- return verifyPLLLock();
- }
-
- // Set one of the canned FSK Modem configs
- // Returns true if its a valid choice
- bool RH_MRF89::setModemConfig(ModemConfigChoice index)
- {
- if (index > (signed int)(sizeof(MODEM_CONFIG_TABLE) / sizeof(ModemConfig)))
- return false;
-
- RH_MRF89::ModemConfig cfg;
- memcpy_P(&cfg, &MODEM_CONFIG_TABLE[index], sizeof(cfg));
-
- // Now update the registers
- uint8_t val = spiReadRegister(RH_MRF89_REG_01_DMODREG);
- val = (val & ~RH_MRF89_MODSEL) | cfg.MODSEL;
- spiWriteRegister(RH_MRF89_REG_01_DMODREG, val);
-
- spiWriteRegister(RH_MRF89_REG_02_FDEVREG, cfg.FDVAL);
- spiWriteRegister(RH_MRF89_REG_03_BRSREG, cfg.BRVAL);
- spiWriteRegister(RH_MRF89_REG_10_FILCREG, cfg.FILCREG);
-
- // The sample configs in MRF89XA.h all use TXIPOLFV = 0xf0 => 375kHz, which is too wide for most modulations
- val = spiReadRegister(RH_MRF89_REG_1A_TXCONREG);
- val = (val & ~RH_MRF89_TXIPOLFV) | (cfg.TXIPOLFV & RH_MRF89_TXIPOLFV);
- spiWriteRegister(RH_MRF89_REG_1A_TXCONREG, val);
-
- return true;
- }
-
- void RH_MRF89::setPreambleLength(uint8_t bytes)
- {
- if (bytes >= 1 && bytes <= 4)
- {
- bytes--;
- uint8_t pktcreg = spiReadRegister(RH_MRF89_REG_1E_PKTCREG);
- pktcreg = (pktcreg & ~RH_MRF89_PRESIZE) | ((bytes << 5) & RH_MRF89_PRESIZE);
- spiWriteRegister(RH_MRF89_REG_1E_PKTCREG, pktcreg);
- }
- }
-
- void RH_MRF89::setSyncWords(const uint8_t* syncWords, uint8_t len)
- {
- if (syncWords && (len > 0 and len <= 4))
- {
- uint8_t syncreg = spiReadRegister(RH_MRF89_REG_12_SYNCREG);
- syncreg = (syncreg & ~RH_MRF89_SYNCWSZ) | (((len - 1) << 3) & RH_MRF89_SYNCWSZ);
- spiWriteRegister(RH_MRF89_REG_12_SYNCREG, syncreg);
- uint8_t i;
- for (i = 0; i < 4; i++)
- {
- if (len > i)
- spiWriteRegister(RH_MRF89_REG_16_SYNCV31REG + i, syncWords[i]);
- }
- }
- }
-
|