sforkowany z mirror/meshtastic-firmware
added SX1268 module adapter
rodzic
2e48b88113
commit
2ba68c9b6e
20
src/main.cpp
20
src/main.cpp
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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:
|
||||
};
|
Ładowanie…
Reference in New Issue