added SX1268 module adapter

1.2-legacy
Vladislav Osmanov 2021-09-03 17:15:58 +03:00
rodzic 2e48b88113
commit 2ba68c9b6e
3 zmienionych plików z 331 dodań i 0 usunięć

Wyświetl plik

@ -39,6 +39,7 @@
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#ifdef NRF52_SERIES
#include "variant.h"
@ -497,6 +498,12 @@ void setup()
digitalWrite(SX1262_ANT_SW, 1);
#endif
#ifdef SX1268_ANT_SW
// make analog PA vs not PA switch on SX1268 eval board work properly
pinMode(SX1268_ANT_SW, OUTPUT);
digitalWrite(SX1268_ANT_SW, 1);
#endif
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
#if defined(RF95_IRQ)
@ -525,6 +532,19 @@ void setup()
}
#endif
#if defined(SX1268_CS)
if (!rIf) {
rIf = new SX1268Interface(SX1268_CS, SX1268_DIO1, SX1268_RESET, SX1268_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find SX1268 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("SX1268 Radio init succeeded, using SX1268 radio\n");
}
}
#endif
#ifdef USE_SIM_RADIO
if (!rIf) {
rIf = new SimRadio;

Wyświetl plik

@ -0,0 +1,249 @@
#include "configuration.h"
#include "SX1268Interface.h"
#include "error.h"
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX1268_MAX_POWER
#define SX1268_MAX_POWER 22
#endif
SX1268Interface::SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
{
}
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
bool SX1268Interface::init()
{
#ifdef SX1268_POWER_EN
digitalWrite(SX1268_POWER_EN, HIGH);
pinMode(SX1268_POWER_EN, OUTPUT);
#endif
#ifdef SX1268_RXEN // set not rx or tx mode
digitalWrite(SX1268_RXEN, LOW); // Set low before becoming an output
pinMode(SX1268_RXEN, OUTPUT);
#endif
#ifdef SX1268_TXEN
digitalWrite(SX1268_TXEN, LOW);
pinMode(SX1268_TXEN, OUTPUT);
#endif
#ifndef SX1268_E22
float tcxoVoltage = 0; // None - we use an XTAL
#else
// Use DIO3 to power tcxo per https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575
float tcxoVoltage = 1.8;
#endif
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
RadioLibInterface::init();
if (power == 0)
power = SX1268_MAX_POWER;
if (power > SX1268_MAX_POWER) // This chip has lower power limits than some
power = SX1268_MAX_POWER;
limitPower();
int res = lora.begin(freq, bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
DEBUG_MSG("SX1268 init result %d\n", res);
#ifdef SX1268_TXEN
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
if (res == ERR_NONE)
res = lora.setDio2AsRfSwitch(false);
#endif
#if 0
// Read/write a register we are not using (only used for FSK mode) to test SPI comms
uint8_t crcLSB = 0;
int err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1268Failure);
//if(crcLSB != 0x0f)
// RECORD_CRITICALERROR(CriticalErrorCode_SX1268Failure);
crcLSB = 0x5a;
err = lora.writeRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1268Failure);
err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1268Failure);
if(crcLSB != 0x5a)
RECORD_CRITICALERROR(CriticalErrorCode_SX1268Failure);
// If we got this far register accesses (and therefore SPI comms) are good
#endif
if (res == ERR_NONE)
res = lora.setCRC(SX126X_LORA_CRC_ON);
if (res == ERR_NONE)
startReceive(); // start receiving
return res == ERR_NONE;
}
bool SX1268Interface::reconfigure()
{
RadioLibInterface::reconfigure();
// set mode to standby
setStandby();
// configure publicly accessible settings
int err = lora.setSpreadingFactor(sf);
if (err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora.setBandwidth(bw);
if (err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
err = lora.setCodingRate(cr);
if (err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
err = lora.setRxGain(true);
assert(err == ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == ERR_NONE);
err = lora.setCurrentLimit(currentLimit);
assert(err == ERR_NONE);
err = lora.setPreambleLength(preambleLength);
assert(err == ERR_NONE);
err = lora.setFrequency(freq);
if (err != ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
if (power > 22) // This chip has lower power limits than some
power = 22;
err = lora.setOutputPower(power);
assert(err == ERR_NONE);
startReceive(); // restart receiving
return ERR_NONE;
}
void INTERRUPT_ATTR SX1268Interface::disableInterrupt()
{
lora.clearDio1Action();
}
void SX1268Interface::setStandby()
{
int err = lora.standby();
assert(err == ERR_NONE);
#ifdef SX1268_RXEN // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX1268_RXEN, LOW);
#endif
#ifdef SX1268_TXEN
digitalWrite(SX1268_TXEN, LOW);
#endif
isReceiving = false; // If we were receiving, not any more
disableInterrupt();
completeSending(); // If we were sending, not anymore
}
/**
* Add SNR data to received messages
*/
void SX1268Interface::addReceiveMetadata(MeshPacket *mp)
{
// DEBUG_MSG("PacketStatus %x\n", lora.getPacketStatus());
mp->rx_snr = lora.getSNR();
mp->rx_rssi = lround(lora.getRSSI());
}
/** We override to turn on transmitter power as needed.
*/
void SX1268Interface::configHardwareForSend()
{
#ifdef SX1268_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX1268_TXEN, HIGH);
#endif
RadioLibInterface::configHardwareForSend();
}
// For power draw measurements, helpful to force radio to stay sleeping
// #define SLEEP_ONLY
void SX1268Interface::startReceive()
{
#ifdef SLEEP_ONLY
sleep();
#else
setStandby();
#ifdef SX1268_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX1268_RXEN, HIGH);
#endif
// int err = lora.startReceive();
int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in
// standby mostly.
assert(err == ERR_NONE);
isReceiving = true;
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);
#endif
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
bool SX1268Interface::isActivelyReceiving()
{
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// received and handled the interrupt for reading the packet/handling errors.
// FIXME: it would be better to check for preamble, but we currently have our ISR not set to fire for packets that
// never even get a valid header, so we don't want preamble to get set and stay set due to noise on the network.
uint16_t irq = lora.getIrqStatus();
bool hasPreamble = (irq & SX126X_IRQ_HEADER_VALID);
// this is not correct - often always true - need to add an extra conditional
// size_t bytesPending = lora.getPacketLength();
// if (hasPreamble) DEBUG_MSG("rx hasPreamble\n");
return hasPreamble;
}
bool SX1268Interface::sleep()
{
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
DEBUG_MSG("SX1268 entering sleep mode (FIXME, don't keep config)\n");
setStandby(); // Stop any pending operations
// turn off TCXO if it was powered
// FIXME - this isn't correct
// lora.setTCXO(0);
// put chipset into sleep mode (we've already disabled interrupts by now)
bool keepConfig = true;
lora.sleep(keepConfig); // Note: we do not keep the config, full reinit will be needed
#ifdef SX1268_POWER_EN
digitalWrite(SX1268_POWER_EN, LOW);
#endif
return true;
}

Wyświetl plik

@ -0,0 +1,62 @@
#pragma once
#include "RadioLibInterface.h"
/**
* Our adapter for SX1268 radios
*/
class SX1268Interface : public RadioLibInterface
{
SX1268 lora;
public:
SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool init();
/// Apply any radio provisioning changes
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool reconfigure();
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep();
bool isIRQPending() { return lora.getIrqStatus() != 0; }
protected:
/**
* Glue functions called from ISR land
*/
virtual void disableInterrupt();
/**
* Enable a particular ISR callback glue function
*/
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
/** are we actively receiving a packet (only called during receiving state) */
virtual bool isActivelyReceiving();
/**
* Start waiting to receive a message
*/
virtual void startReceive();
/**
* We override to turn on transmitter power as needed.
*/
virtual void configHardwareForSend();
/**
* Add SNR data to received messages
*/
virtual void addReceiveMetadata(MeshPacket *mp);
virtual void setStandby();
private:
};