ugly WIP on switching to RadioLib, still need to set freq etc...

This commit is contained in:
geeksville 2020-04-29 14:54:03 -07:00
parent a7d153abcb
commit 814c126e67
12 changed files with 291 additions and 15 deletions

View File

@ -10,7 +10,7 @@
"hwids": [["0x239A", "0x4403"]],
"usb_product": "PPR",
"mcu": "nrf52840",
"variant": "ppr",
"variant": "pca10056-rc-clock",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"

View File

@ -11,6 +11,7 @@ Minimum items needed to make sure hardware is good.
- switch to RadioLab? test it with current radio. https://github.com/jgromes/RadioLib
- use "variants" to get all gpio bindings
- plug in correct variants for the real board
- remove unused sx1262 lib from github
- Use the PMU driver on real hardware
- add a NEMA based GPS driver to test GPS
- Use new radio driver on real hardware - possibly start with https://os.mbed.com/teams/Semtech/code/SX126xLib/

View File

@ -73,7 +73,7 @@ lib_deps =
Wire ; explicitly needed here because the AXP202 library forgets to add it
https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
https://github.com/jgromes/RadioLib.git
https://github.com/meshtastic/RadioLib.git
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]

View File

@ -217,10 +217,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define LED_INVERTED 1
// Temporarily testing if we can build the RF95 driver for NRF52
#if 0
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
#endif
#endif

View File

@ -118,6 +118,9 @@ static uint32_t ledBlinker()
Periodic ledPeriodic(ledBlinker);
#include "RadioLibInterface.h"
#include "variant.h"
void setup()
{
#ifdef USE_SEGGER
@ -189,7 +192,15 @@ void setup()
realRouter.setup(); // required for our periodic task (kinda skanky FIXME)
// MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
radio = new MeshRadio();
RadioInterface *rIf =
#if defined(RF95_IRQ_GPIO)
new CustomRF95();
#elif defined(SX1262_CS)
new RadioLibInterface(SX1262_CS, SX1262_DIO1, SX1262_RESET, SX1262_BUSY, SPI);
#else
new SimRadio();
#endif
radio = new MeshRadio(rIf);
router.addInterface(&radio->radioIf);
if (radio && !radio->init())

View File

@ -24,7 +24,7 @@ separated by 2.16 MHz with respect to the adjacent channels. Channel zero starts
/// Sometimes while debugging it is useful to set this false, to disable rf95 accesses
bool useHardware = true;
MeshRadio::MeshRadio() // , manager(radioIf)
MeshRadio::MeshRadio(RadioInterface *rIf) : radioIf(*rIf) // , manager(radioIf)
{
myNodeInfo.num_channels = NUM_CHANNELS;
@ -122,4 +122,3 @@ int MeshRadio::reloadConfig(void *unused)
return 0;
}

View File

@ -63,23 +63,19 @@
/**
* A raw low level interface to our mesh. Only understands nodenums and bytes (not protobufs or node ids)
* FIXME - REMOVE THIS CLASS
*/
class MeshRadio
{
public:
// Kinda ugly way of selecting different radio implementations, but soon this MeshRadio class will be going away
// entirely. At that point we can make things pretty.
#ifdef RF95_IRQ_GPIO
CustomRF95
radioIf; // the raw radio interface - for now I'm leaving public - because this class is shrinking to be almost nothing
#else
SimRadio radioIf;
#endif
RadioInterface &radioIf;
/** pool is the pool we will alloc our rx packets from
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
*/
MeshRadio();
MeshRadio(RadioInterface *rIf);
bool init();

View File

@ -149,7 +149,7 @@ void CustomRF95::handleIdleISR()
startSend(txp);
else {
// Nothing to send, let's switch back to receive mode
setModeRx();
RH_RF95::setModeRx();
}
}
@ -193,9 +193,9 @@ void CustomRF95::loop()
// It should never take us more than 30 secs to send a packet, if it does, we have a bug, FIXME, move most of this
// into CustomRF95
uint32_t now = millis();
if (lastTxStart != 0 && (now - lastTxStart) > TX_WATCHDOG_TIMEOUT && mode() == RHGenericDriver::RHModeTx) {
if (lastTxStart != 0 && (now - lastTxStart) > TX_WATCHDOG_TIMEOUT && RH_RF95::mode() == RHGenericDriver::RHModeTx) {
DEBUG_MSG("ERROR! Bug! Tx packet took too long to send, forcing radio into rx mode\n");
setModeRx();
RH_RF95::setModeRx();
if (sendingPacket) { // There was probably a packet we were trying to send, free it
packetPool.release(sendingPacket);
sendingPacket = NULL;

View File

@ -55,6 +55,72 @@ class RadioInterface
* If the txmit queue is full it might return an error
*/
virtual ErrorCode send(MeshPacket *p) = 0;
// methods from radiohead
/// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
/// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
/// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
/// In promiscuous mode, all messages will be accepted regardless of the TO header.
/// In a conventional multinode system, all nodes will have a unique address
/// (which you could store in EEPROM).
/// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
/// allowing the possibilty of address spoofing).
/// \param[in] thisAddress The address of this node.
virtual void setThisAddress(uint8_t thisAddress) = 0;
/// 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() = 0;
/// Sets the transmitter and receiver
/// centre frequency.
/// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
/// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
/// \return true if the selected frquency centre is within range
virtual bool setFrequency(float centre) = 0;
/// Select one of the predefined modem configurations. If you need a modem configuration not provided
/// here, use setModemRegisters() with your own ModemConfig.
/// Caution: the slowest protocols may require a radio module with TCXO temperature controlled oscillator
/// for reliable operation.
/// \param[in] index The configuration choice.
/// \return true if index is a valid choice.
virtual bool setModemConfig(RH_RF95::ModemConfigChoice index) = 0;
/// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
/// disables them.
virtual void setModeIdle() = 0;
/// If current mode is Tx or Idle, changes it to Rx.
/// Starts the receiver in the RF95/96/97/98.
virtual void setModeRx() = 0;
/// Returns the operating mode of the library.
/// \return the current mode, one of RF69_MODE_*
virtual RHGenericDriver::RHMode mode() = 0;
/// Sets the transmitter power output level, and configures the transmitter pin.
/// Be a good neighbour and set the lowest power level you need.
/// Some SX1276/77/78/79 and compatible modules (such as RFM95/96/97/98)
/// use the PA_BOOST transmitter pin for high power output (and optionally the PA_DAC)
/// while some (such as the Modtronix inAir4 and inAir9)
/// use the RFO transmitter pin for lower power but higher efficiency.
/// You must set the appropriate power level and useRFO argument for your module.
/// Check with your module manufacturer which transmtter pin is used on your module
/// to ensure you are setting useRFO correctly.
/// Failure to do so will result in very low
/// transmitter power output.
/// Caution: legal power limits may apply in certain countries.
/// After init(), the power will be set to 13dBm, with useRFO false (ie PA_BOOST enabled).
/// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA with useRFO false,
/// valid values are from +5 to +23.
/// For Modtronix inAir4 and inAir9 with useRFO true (ie RFO pins in use),
/// valid values are from -1 to 14.
/// \param[in] useRFO If true, enables the use of the RFO transmitter pins instead of
/// the PA_BOOST pin (false). Choose the correct setting for your module.
void setTxPower(int8_t power, bool useRFO = false) {}
};
class SimRadio : public RadioInterface

View File

@ -0,0 +1,118 @@
#include "RadioLibInterface.h"
#include <configuration.h>
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
static SPISettings spiSettings;
RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: module(cs, irq, rst, busy, spi, spiSettings), lora(&module)
{
}
ErrorCode RadioLibInterface::send(MeshPacket *p)
{
return ERR_NONE;
}
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
bool RadioLibInterface::init()
{
// FIXME, move this to main
SPI.begin();
int res = lora.begin();
DEBUG_MSG("LORA init result %d\n", res);
return res == ERR_NONE;
}
/**
*
*
*
// include the library
// SX1262 has the following connections:
// NSS pin: 10
// DIO1 pin: 2
// NRST pin: 3
// BUSY pin: 9
SX1262 lora = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 lora = RadioShield.ModuleA;
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
// carrier frequency: 434.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 9
// coding rate: 7
// sync word: 0x12 (private network)
// output power: 14 dBm
// current limit: 60 mA
// preamble length: 8 symbols
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
// regulator: DC-DC (set to true to use LDO)
// CRC: enabled
int state = lora.begin();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
}
void loop() {
Serial.print(F("[SX1262] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
// NOTE: transmit() is a blocking method!
// See example SX126x_Transmit_Interrupt for details
// on non-blocking transmission method.
int state = lora.transmit("Hello World!");
// you can also transmit byte array up to 256 bytes long
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
int state = lora.transmit(byteArr, 8);
if (state == ERR_NONE) {
// the packet was successfully transmitted
Serial.println(F("success!"));
// print measured data rate
Serial.print(F("[SX1262] Datarate:\t"));
Serial.print(lora.getDataRate());
Serial.println(F(" bps"));
} else if (state == ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(F("too long!"));
} else if (state == ERR_TX_TIMEOUT) {
// timeout occured while transmitting packet
Serial.println(F("timeout!"));
} else {
// some other error occurred
Serial.print(F("failed, code "));
Serial.println(state);
}
// wait for a second before transmitting again
delay(1000);
}
*/

View File

@ -0,0 +1,82 @@
#pragma once
#include "RadioInterface.h"
#include <RadioLib.h>
class RadioLibInterface : public RadioInterface
{
Module module; // The HW interface to the radio
SX1262 lora;
public:
RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
virtual ErrorCode send(MeshPacket *p);
// methods from radiohead
/// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
/// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
/// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
/// In promiscuous mode, all messages will be accepted regardless of the TO header.
/// In a conventional multinode system, all nodes will have a unique address
/// (which you could store in EEPROM).
/// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
/// allowing the possibilty of address spoofing).
/// \param[in] thisAddress The address of this node.
virtual void setThisAddress(uint8_t thisAddress) {}
/// 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();
/// Sets the transmitter and receiver
/// centre frequency.
/// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
/// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
/// \return true if the selected frquency centre is within range
bool setFrequency(float centre) { return true; }
/// Select one of the predefined modem configurations. If you need a modem configuration not provided
/// here, use setModemRegisters() with your own ModemConfig.
/// Caution: the slowest protocols may require a radio module with TCXO temperature controlled oscillator
/// for reliable operation.
/// \param[in] index The configuration choice.
/// \return true if index is a valid choice.
bool setModemConfig(RH_RF95::ModemConfigChoice index) { return true; }
/// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
/// disables them.
void setModeIdle() {}
/// If current mode is Tx or Idle, changes it to Rx.
/// Starts the receiver in the RF95/96/97/98.
void setModeRx() {}
/// Returns the operating mode of the library.
/// \return the current mode, one of RF69_MODE_*
virtual RHGenericDriver::RHMode mode() { return RHGenericDriver::RHModeIdle; }
/// Sets the transmitter power output level, and configures the transmitter pin.
/// Be a good neighbour and set the lowest power level you need.
/// Some SX1276/77/78/79 and compatible modules (such as RFM95/96/97/98)
/// use the PA_BOOST transmitter pin for high power output (and optionally the PA_DAC)
/// while some (such as the Modtronix inAir4 and inAir9)
/// use the RFO transmitter pin for lower power but higher efficiency.
/// You must set the appropriate power level and useRFO argument for your module.
/// Check with your module manufacturer which transmtter pin is used on your module
/// to ensure you are setting useRFO correctly.
/// Failure to do so will result in very low
/// transmitter power output.
/// Caution: legal power limits may apply in certain countries.
/// After init(), the power will be set to 13dBm, with useRFO false (ie PA_BOOST enabled).
/// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA with useRFO false,
/// valid values are from +5 to +23.
/// For Modtronix inAir4 and inAir9 with useRFO true (ie RFO pins in use),
/// valid values are from -1 to 14.
/// \param[in] useRFO If true, enables the use of the RFO transmitter pins instead of
/// the PA_BOOST pin (false). Choose the correct setting for your module.
void setTxPower(int8_t power, bool useRFO = false) {}
};

View File

@ -142,6 +142,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
// CUSTOM GPIOs the SX1262MB2CAS shield when installed on the NRF52840-DK development board
#define SX1262_CS (32 + 8) // P1.08
#define SX1262_DIO1 (32 + 6) // P1.06
#define SX1262_BUSY (32 + 4) // P1.04
#define SX1262_RESET (0 + 3) // P0.03
#define SX1262_ANT_SW (32 + 10) // P1.10