firmware/src/mesh/SX128xInterface.cpp

264 lines
8.0 KiB
C++
Raw Normal View History

2022-10-16 17:07:58 +00:00
#include "SX128xInterface.h"
2023-01-21 13:34:29 +00:00
#include "configuration.h"
2022-10-16 17:07:58 +00:00
#include "error.h"
2023-01-21 13:34:29 +00:00
#include "mesh/NodeDB.h"
2022-10-16 17:07:58 +00:00
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX128X_MAX_POWER
2022-11-11 07:59:16 +00:00
#define SX128X_MAX_POWER 13
2022-10-16 17:07:58 +00:00
#endif
2023-01-21 13:34:29 +00:00
template <typename T>
2022-10-16 17:07:58 +00:00
SX128xInterface<T>::SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
2023-01-21 13:34:29 +00:00
SPIClass &spi)
2022-10-16 17:07:58 +00:00
: 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.
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::init()
2022-10-16 17:07:58 +00:00
{
#ifdef SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, HIGH);
pinMode(SX128X_POWER_EN, OUTPUT);
#endif
2023-01-21 13:34:29 +00:00
2023-01-07 12:05:16 +00:00
#ifdef RF95_FAN_EN
pinMode(RF95_FAN_EN, OUTPUT);
digitalWrite(RF95_FAN_EN, 1);
#endif
2023-01-21 13:34:29 +00:00
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
2023-01-21 13:34:29 +00:00
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
2022-10-16 17:07:58 +00:00
pinMode(SX128X_RXEN, OUTPUT);
#endif
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_TXEN, LOW);
pinMode(SX128X_TXEN, OUTPUT);
#endif
RadioLibInterface::init();
if (power == 0)
power = SX128X_MAX_POWER;
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
limitPower();
preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all
2022-10-16 17:07:58 +00:00
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
// \todo Display actual typename of the adapter, not just `SX128x`
LOG_INFO("SX128x init result %d\n", res);
2022-10-16 17:07:58 +00:00
if ((config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (res == RADIOLIB_ERR_INVALID_FREQUENCY)) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Radio chip only supports 2.4GHz LoRa. Adjusting Region and rebooting.\n");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_LORA_24;
2022-12-28 12:56:56 +00:00
nodeDB.saveToDisk(SEGMENT_CONFIG);
delay(2000);
#if defined(ARCH_ESP32)
ESP.restart();
#elif defined(ARCH_NRF52)
NVIC_SystemReset();
#else
LOG_ERROR("FIXME implement reboot for this platform. Skipping for now.\n");
2022-12-28 12:56:56 +00:00
#endif
}
2023-01-21 13:34:29 +00:00
LOG_INFO("Frequency set to %f\n", getFreq());
LOG_INFO("Bandwidth set to %f\n", bw);
LOG_INFO("Power output set to %d\n", power);
2022-10-16 17:07:58 +00:00
if (res == RADIOLIB_ERR_NONE)
2022-11-10 22:00:01 +00:00
res = lora.setCRC(2);
2022-10-16 17:07:58 +00:00
if (res == RADIOLIB_ERR_NONE)
startReceive(); // start receiving
return res == RADIOLIB_ERR_NONE;
}
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::reconfigure()
2022-10-16 17:07:58 +00:00
{
RadioLibInterface::reconfigure();
// set mode to standby
setStandby();
// configure publicly accessible settings
int err = lora.setSpreadingFactor(sf);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
2022-10-16 17:07:58 +00:00
err = lora.setBandwidth(bw);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
2022-10-16 17:07:58 +00:00
err = lora.setCodingRate(cr);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
2022-10-16 17:07:58 +00:00
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
// TODO: Confirm gain registers are okay now
// err = lora.setRxGain(true);
// assert(err == RADIOLIB_ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setPreambleLength(preambleLength);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setFrequency(getFreq());
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
2022-10-16 17:07:58 +00:00
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
2022-11-14 09:53:16 +00:00
2022-10-16 17:07:58 +00:00
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;
}
2023-01-21 13:34:29 +00:00
template <typename T> void INTERRUPT_ATTR SX128xInterface<T>::disableInterrupt()
2022-10-16 17:07:58 +00:00
{
lora.clearDio1Action();
}
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::wideLora()
{
return true;
}
2023-01-21 13:34:29 +00:00
template <typename T> void SX128xInterface<T>::setStandby()
2022-10-16 17:07:58 +00:00
{
checkNotification(); // handle any pending interrupts before we force standby
2023-01-21 13:34:29 +00:00
2022-10-16 17:07:58 +00:00
int err = lora.standby();
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR("SX128x standby failed with error %d\n", err);
2022-10-16 17:07:58 +00:00
assert(err == RADIOLIB_ERR_NONE);
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_RXEN, LOW);
#endif
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_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
*/
template <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_MeshPacket *mp)
2022-10-16 17:07:58 +00:00
{
2022-12-30 02:41:37 +00:00
// LOG_DEBUG("PacketStatus %x\n", lora.getPacketStatus());
2022-10-16 17:07:58 +00:00
mp->rx_snr = lora.getSNR();
mp->rx_rssi = lround(lora.getRSSI());
}
/** We override to turn on transmitter power as needed.
*/
2023-01-21 13:34:29 +00:00
template <typename T> void SX128xInterface<T>::configHardwareForSend()
2022-10-16 17:07:58 +00:00
{
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_TXEN, HIGH);
#endif
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_RXEN, LOW);
#endif
RadioLibInterface::configHardwareForSend();
}
// For power draw measurements, helpful to force radio to stay sleeping
// #define SLEEP_ONLY
2023-01-21 13:34:29 +00:00
template <typename T> void SX128xInterface<T>::startReceive()
2022-10-16 17:07:58 +00:00
{
#ifdef SLEEP_ONLY
sleep();
#else
setStandby();
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_RXEN, HIGH);
#endif
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
2022-10-16 17:07:58 +00:00
digitalWrite(SX128X_TXEN, LOW);
#endif
2023-01-21 13:34:29 +00:00
// We use the HEADER_VALID IRQ flag to detect whether we are actively receiving
int err =
lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_HEADER_VALID);
2022-10-16 17:07:58 +00:00
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);
#endif
}
/** Is the channel currently active? */
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::isChannelActive()
2022-10-16 17:07:58 +00:00
{
// check if we can detect a LoRa preamble on the current channel
int16_t result;
2023-01-21 13:34:29 +00:00
setStandby();
2022-10-16 17:07:58 +00:00
result = lora.scanChannel();
if (result == RADIOLIB_LORA_DETECTED)
2022-10-16 17:07:58 +00:00
return true;
2023-01-21 13:34:29 +00:00
2022-10-16 17:07:58 +00:00
assert(result != RADIOLIB_ERR_WRONG_MODEM);
2023-01-21 13:34:29 +00:00
2022-10-16 17:07:58 +00:00
return false;
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
2022-10-16 17:07:58 +00:00
{
uint16_t irq = lora.getIrqStatus();
bool hasHeader = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID);
return hasHeader;
2022-10-16 17:07:58 +00:00
}
2023-01-21 13:34:29 +00:00
template <typename T> bool SX128xInterface<T>::sleep()
2022-10-16 17:07:58 +00:00
{
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
// \todo Display actual typename of the adapter, not just `SX128x`
2022-12-30 02:41:37 +00:00
LOG_DEBUG("SX128x entering sleep mode (FIXME, don't keep config)\n");
2022-10-16 17:07:58 +00:00
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 SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, LOW);
#endif
return true;
}