From b1b5bafddab7a80ffd3f496cc32d1eef317dd269 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 15 Nov 2023 17:04:41 -0600 Subject: [PATCH] Add PiHal and get Waveshare SX1262 XXXM working --- arch/portduino/portduino.ini | 3 +- src/main.cpp | 21 ++- src/platform/portduino/PiHal.h | 159 +++++++++++++++++++++++ src/platform/portduino/PortduinoGlue.cpp | 17 ++- variants/portduino/variant.h | 30 ++--- 5 files changed, 207 insertions(+), 23 deletions(-) create mode 100644 src/platform/portduino/PiHal.h diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index b39974853..312b52e9d 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -27,4 +27,5 @@ lib_deps = build_flags = ${arduino_base.build_flags} -fPIC - -Isrc/platform/portduino \ No newline at end of file + -Isrc/platform/portduino + -lpigpio \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a18ee4099..634ddeb25 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,6 +67,10 @@ NRF52Bluetooth *nrf52Bluetooth; #include "platform/portduino/SimRadio.h" #endif +#if defined(HAS_RADIO) && defined(ARCH_PORTDUINO) +#include "platform/portduino/PiHal.h" +#endif + #if HAS_BUTTON #include "ButtonThread.h" #endif @@ -662,7 +666,20 @@ void setup() digitalWrite(SX126X_ANT_SW, 1); #endif -#ifdef HW_SPI1_DEVICE +#ifdef ARCH_RASPBERRY_PI + PiHal *RadioLibHAL = new PiHal(1); + if (!rIf) { + rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, 21, 16, 18, 20); + if (!rIf->init()) { + LOG_WARN("Failed to find SX1262 radio\n"); + delete rIf; + rIf = NULL; + } else { + LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n"); + } + } + +#elif HW_SPI1_DEVICE LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings); #else // HW_SPI1_DEVICE LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); @@ -708,7 +725,7 @@ void setup() } #endif -#if defined(USE_SX1262) +#if defined(USE_SX1262) && !defined(ARCH_RASPBERRY_PI) if (!rIf) { rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); if (!rIf->init()) { diff --git a/src/platform/portduino/PiHal.h b/src/platform/portduino/PiHal.h new file mode 100644 index 000000000..9ffaa7fa0 --- /dev/null +++ b/src/platform/portduino/PiHal.h @@ -0,0 +1,159 @@ +#ifndef PI_HAL_H +#define PI_HAL_H + +// include RadioLib +#include + +// include the library for Raspberry GPIO pins +#include "pigpio.h" + +// create a new Raspberry Pi hardware abstraction layer +// using the pigpio library +// the HAL must inherit from the base RadioLibHal class +// and implement all of its virtual methods +class PiHal : public RadioLibHal +{ + public: + // default constructor - initializes the base HAL and any needed private members + PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000) + : RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, RISING_EDGE, FALLING_EDGE), _spiChannel(spiChannel), + _spiSpeed(spiSpeed) + { + } + + void init() override + { + // first initialise pigpio library + gpioInitialise(); + + // now the SPI + spiBegin(); + + // Waveshare LoRaWAN Hat also needs pin 18 to be pulled high to enable the radio + // gpioSetMode(18, PI_OUTPUT); + // gpioWrite(18, PI_HIGH); + } + + void term() override + { + // stop the SPI + spiEnd(); + + // pull the enable pin low + // gpioSetMode(18, PI_OUTPUT); + // gpioWrite(18, PI_LOW); + + // finally, stop the pigpio library + gpioTerminate(); + } + + // GPIO-related methods (pinMode, digitalWrite etc.) should check + // RADIOLIB_NC as an alias for non-connected pins + void pinMode(uint32_t pin, uint32_t mode) override + { + if (pin == RADIOLIB_NC) { + return; + } + + gpioSetMode(pin, mode); + } + + void digitalWrite(uint32_t pin, uint32_t value) override + { + if (pin == RADIOLIB_NC) { + return; + } + + gpioWrite(pin, value); + } + + uint32_t digitalRead(uint32_t pin) override + { + if (pin == RADIOLIB_NC) { + return (0); + } + + return (gpioRead(pin)); + } + + void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override + { + LOG_DEBUG("Here to enable pin %d!\n", interruptNum); + if (interruptNum == RADIOLIB_NC) { + return; + } + if (gpioRead(interruptNum) == 1) { + interruptCb(); + } else { + gpioSetAlertFunc(interruptNum, (gpioISRFunc_t)interruptCb); + } + LOG_DEBUG("Pin enabled %d!\n", interruptNum); + } + + void detachInterrupt(uint32_t interruptNum) override + { + LOG_DEBUG("Here for pin %d!\n", interruptNum); + if (interruptNum == RADIOLIB_NC) { + return; + } + + gpioSetAlertFunc(interruptNum, NULL); + LOG_DEBUG("Finished\n"); + } + + void delay(unsigned long ms) override { gpioDelay(ms * 1000); } + + void delayMicroseconds(unsigned long us) override { gpioDelay(us); } + + unsigned long millis() override { return (gpioTick() / 1000); } + + unsigned long micros() override { return (gpioTick()); } + + long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override + { + if (pin == RADIOLIB_NC) { + return (0); + } + + this->pinMode(pin, PI_INPUT); + uint32_t start = this->micros(); + uint32_t curtick = this->micros(); + + while (this->digitalRead(pin) == state) { + if ((this->micros() - curtick) > timeout) { + return (0); + } + } + + return (this->micros() - start); + } + + void spiBegin() + { + if (_spiHandle < 0) { + _spiHandle = spiOpen(_spiChannel, _spiSpeed, 0); + } + } + + void spiBeginTransaction() {} + + void spiTransfer(uint8_t *out, size_t len, uint8_t *in) { spiXfer(_spiHandle, (char *)out, (char *)in, len); } + + void spiEndTransaction() {} + + void spiEnd() + { + if (_spiHandle >= 0) { + spiClose(_spiHandle); + _spiHandle = -1; + } + } + + private: + // the HAL can contain any additional private members + const unsigned int _spiSpeed; + const uint8_t _spiChannel; + int _spiHandle = -1; +}; + +#endif \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index af38b61a0..3af65be38 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -7,8 +7,11 @@ #include #include +#ifdef ARCH_RASPBERRY_PI +#include "pigpio.h" +#else #include - +#endif // FIXME - move setBluetoothEnable into a HALPlatform class void setBluetoothEnable(bool on) @@ -89,12 +92,15 @@ void portduinoSetup() printf("Setting up Meshtastic on Portduino...\n"); #ifdef ARCH_RASPBERRY_PI - printf("using GPIOD Version: %s\n", gpiod_version_string()); + return; +/* + //printf("using GPIOD Version: %s\n", gpiod_version_string()); + gpioInitialise(); // We need to create SPI SPI.begin(); if (!spiChip->isSimulated()) { printf("Connecting to RFM95 board...\n"); - loraIrq = new LinuxGPIOPin(LORA_DIO0, GPIOD_CHIP_LABEL, LORA_DIO0_LABEL, "loraIrq"); + loraIrq = new LinuxGPIOPin(LORA_DIO0, "gpiochip0", LORA_DIO0_LABEL, "loraIrq"); loraIrq->setSilent(); gpioBind(loraIrq); @@ -151,7 +157,8 @@ void portduinoSetup() gpioBind(new SimGPIOPin(SX126X_RESET, "fakeLoraReset")); gpioBind(new SimGPIOPin(LORA_DIO1, "fakeLoraIrq")); } - +*/ +#endif // gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET"))); // gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); -} +} \ No newline at end of file diff --git a/variants/portduino/variant.h b/variants/portduino/variant.h index 5ee92bacf..2ce871ddc 100644 --- a/variants/portduino/variant.h +++ b/variants/portduino/variant.h @@ -1,10 +1,11 @@ #if defined(ARCH_RASPBERRY_PI) - +#define HAS_RADIO 1 #define GPIOD_CHIP_LABEL "pinctrl-bcm2711" -#define USE_RF95 +// define USE_RF95 #define USE_SX1262 - +#define SX126X_TXEN 6 +#define SX126X_DIO2_AS_RF_SWITCH #define NO_SCREEN #define RF95_SCK 11 @@ -12,19 +13,18 @@ #define RF95_MOSI 10 #define RF95_NSS RADIOLIB_NC -#define LORA_DIO0 4 // a No connect on the SX1262 module -#define LORA_DIO0_LABEL "GPIO_GCLK" -#define LORA_RESET 17 -#define LORA_RESET_LABEL "GPIO17" -#define LORA_DIO1 \ - RADIOLIB_NC // SX1262 IRQ, called DIO0 on pinelora schematic, pin 7 on ch341f "ack" - FIXME, enable hwints in linux -#define LORA_DIO2 RADIOLIB_NC // SX1262 BUSY, actually connected to "DIO5" on pinelora schematic, pin 8 on ch341f "slct" -#define LORA_DIO3 RADIOLIB_NC // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled +// #define LORA_DIO0 4 // a No connect on the SX1262 module +// #define LORA_DIO0_LABEL "GPIO_GCLK" +#define LORA_RESET 18 +#define LORA_RESET_LABEL "GPIO18" +#define LORA_DIO1 16 // SX1262 IRQ, called DIO0 on pinelora schematic, pin 7 on ch341f "ack" - FIXME, enable hwints in linux +// #define LORA_DIO2 20 // SX1262 BUSY, actually connected to "DIO5" on pinelora schematic, pin 8 on ch341f "slct" +// #define LORA_DIO3 6 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled #ifdef USE_SX1262 -#define SX126X_CS RF95_NSS -#define SX126X_DIO1 LORA_DIO0 -#define SX126X_BUSY LORA_DIO2 +#define SX126X_CS 21 +#define SX126X_DIO1 16 +#define SX126X_BUSY 20 #define SX126X_RESET LORA_RESET // HOPE RFM90 does not have a TCXO therefore not SX126X_E22 #endif @@ -56,4 +56,4 @@ #define SX126X_DIO2_AS_RF_SWITCH #endif -#endif +#endif \ No newline at end of file