From dffb6c2f0639bc842b77077ebf87a9dd804be612 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 17:38:23 -0700 Subject: [PATCH] If display is on on the @BigCorvus board and we xmit the board browns out? --- platformio.ini | 2 +- src/SPILock.cpp | 11 ++++++++ src/SPILock.h | 12 +++++++++ src/graphics/TFT.cpp | 11 ++++++-- src/graphics/TFT.h | 3 ++- src/main.cpp | 20 +++++++------- src/mesh/RadioLibInterface.cpp | 14 ++++++++++ src/mesh/RadioLibInterface.h | 45 +++++++++++++++++++++++++++++++- variants/lora_relay_v1/variant.h | 8 ++++-- 9 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 src/SPILock.cpp create mode 100644 src/SPILock.h diff --git a/platformio.ini b/platformio.ini index 57b4be3f..6c42ec40 100644 --- a/platformio.ini +++ b/platformio.ini @@ -66,7 +66,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/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f + https://github.com/meshtastic/RadioLib.git#7989a269be590a5d4914ac04069b58f4930c45c1 https://github.com/meshtastic/TinyGPSPlus.git https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 diff --git a/src/SPILock.cpp b/src/SPILock.cpp new file mode 100644 index 00000000..43d841fc --- /dev/null +++ b/src/SPILock.cpp @@ -0,0 +1,11 @@ +#include "SPILock.h" +#include +#include + +concurrency::Lock *spiLock; + +void initSPI() +{ + assert(!spiLock); + spiLock = new concurrency::Lock(); +} \ No newline at end of file diff --git a/src/SPILock.h b/src/SPILock.h new file mode 100644 index 00000000..8a4bd5db --- /dev/null +++ b/src/SPILock.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../concurrency/LockGuard.h" + +/** + * Used to provide mutual exclusion for access to the SPI bus. Usage: + * concurrency::LockGuard g(spiLock); + */ +extern concurrency::Lock *spiLock; + +/** Setup SPI access and create the spiLock lock. */ +void initSPI(); \ No newline at end of file diff --git a/src/graphics/TFT.cpp b/src/graphics/TFT.cpp index ed367990..dcaf53ec 100644 --- a/src/graphics/TFT.cpp +++ b/src/graphics/TFT.cpp @@ -1,12 +1,13 @@ #include "configuration.h" #ifdef ST7735_CS +#include "SPILock.h" #include "TFT.h" #include "graphics/configs.h" #include #include // Graphics and font library for ST7735 driver chip -TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h +static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) { @@ -17,6 +18,9 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) // Write the buffer to the display memory void TFTDisplay::display(void) { + concurrency::LockGuard g(spiLock); + +#if 1 // FIXME - only draw bits have changed (use backbuf similar to the other displays) // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) { @@ -28,6 +32,7 @@ void TFTDisplay::display(void) tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK); } } +#endif } // Send a command to the display (low level function) @@ -47,10 +52,12 @@ bool TFTDisplay::connect() pinMode(ST7735_BACKLIGHT_EN, OUTPUT); #endif +#if 1 tft.init(); tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label - // tft.fillScreen(TFT_BLUE); + tft.fillScreen(TFT_BLACK); // tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left +#endif return true; } diff --git a/src/graphics/TFT.h b/src/graphics/TFT.h index eec6d07b..83168e2e 100644 --- a/src/graphics/TFT.h +++ b/src/graphics/TFT.h @@ -9,7 +9,8 @@ * optimize display() to only draw changed pixels (see other OLED subclasses for examples) * implement displayOn/displayOff to turn off the TFT device (and backlight) * Use the fast NRF52 SPI API rather than the slow standard arduino version - * turn radio back on + * + * turn radio back on - currently with both on spi bus is fucked? or are we leaving chip select asserted? */ class TFTDisplay : public OLEDDisplay { diff --git a/src/main.cpp b/src/main.cpp index bd4bd079..53780f6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ // #include "rom/rtc.h" #include "DSRRouter.h" // #include "debug.h" +#include "SPILock.h" #include "graphics/Screen.h" #include "main.h" #include "sleep.h" @@ -220,6 +221,16 @@ void setup() nrf52Setup(); #endif + // Init our SPI controller (must be before screen and lora) + initSPI(); +#ifdef NRF52_SERIES + SPI.begin(); +#else + // ESP32 + SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); + SPI.setFrequency(4000000); +#endif + // Initialize the screen first so we can show the logo while we start up everything else. #ifdef ST7735_CS screen.setup(); @@ -278,15 +289,6 @@ void setup() digitalWrite(SX1262_ANT_SW, 1); #endif - // Init our SPI controller -#ifdef NRF52_SERIES - SPI.begin(); -#else - // ESP32 - SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); - SPI.setFrequency(4000000); -#endif - // MUST BE AFTER service.init, so we have our radio config settings (from nodedb init) RadioInterface *rIf = NULL; diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index ae94231d..30f7de50 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -1,6 +1,7 @@ #include "RadioLibInterface.h" #include "MeshTypes.h" #include "NodeDB.h" +#include "SPILock.h" #include "mesh-pb-constants.h" #include #include @@ -9,6 +10,13 @@ // FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); +void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) +{ + concurrency::LockGuard g(spiLock); + + Module::SPItransfer(cmd, reg, dataOut, dataIn, numBytes); +} + RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi, PhysicalLayer *_iface) : concurrency::PeriodicTask(0), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface) @@ -126,6 +134,8 @@ bool RadioLibInterface::canSendImmediately() /// bluetooth comms code. If the txmit queue is empty it might return an error ErrorCode RadioLibInterface::send(MeshPacket *p) { + // Sometimes when testing it is useful to be able to never turn on the xmitter +#ifndef LORA_DISABLE_SENDING printPacket("enqueuing for send", p); DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad); ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN; @@ -140,6 +150,10 @@ ErrorCode RadioLibInterface::send(MeshPacket *p) startTransmitTimer(true); return res; +#else + packetPool.release(p); + return ERRNO_UNKNOWN; +#endif } bool RadioLibInterface::canSleep() diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index a19c4741..d393077b 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -16,6 +16,49 @@ #define INTERRUPT_ATTR #endif +/** + * A wrapper for the RadioLib Module class, that adds mutex for SPI bus access + */ +class LockingModule : public Module +{ + public: + /*! + \brief Extended SPI-based module constructor. + + \param cs Arduino pin to be used as chip select. + + \param irq Arduino pin to be used as interrupt/GPIO. + + \param rst Arduino pin to be used as hardware reset for the module. + + \param gpio Arduino pin to be used as additional interrupt/GPIO. + + \param spi SPI interface to be used, can also use software SPI implementations. + + \param spiSettings SPI interface settings. + */ + LockingModule(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass &spi, + SPISettings spiSettings) + : Module(cs, irq, rst, gpio, spi, spiSettings) + { + } + + /*! + \brief SPI single transfer method. + + \param cmd SPI access command (read/write/burst/...). + + \param reg Address of SPI register to transfer to/from. + + \param dataOut Data that will be transfered from master to slave. + + \param dataIn Data that was transfered from slave to master. + + \param numBytes Number of bytes to transfer. + */ + virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes); +}; + class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTask { /// Used as our notification from the ISR @@ -49,7 +92,7 @@ class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTa float currentLimit = 100; // FIXME uint16_t preambleLength = 32; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving - Module module; // The HW interface to the radio + LockingModule module; // The HW interface to the radio /** * provides lowest common denominator RadioLib API diff --git a/variants/lora_relay_v1/variant.h b/variants/lora_relay_v1/variant.h index 3562724f..763cac00 100644 --- a/variants/lora_relay_v1/variant.h +++ b/variants/lora_relay_v1/variant.h @@ -117,8 +117,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define I2C_ADDR_BQ27441 0x55 // Battery gauge // CUSTOM GPIOs the SX1262 -// #define SX1262_CS (32) -#define USE_SIM_RADIO +#define SX1262_CS (32) + #define USE_SEGGER #define SX1262_DIO1 (29) #define SX1262_DIO2 (30) @@ -136,6 +136,10 @@ static const uint8_t SCK = PIN_SPI_SCK; #define ST7735_BACKLIGHT_EN (13) #define ST7735_RS (9) +#define LORA_DISABLE_SENDING // The 1.1 version of this board browns out if the SX1262 transmits while the screen is on. So you + // can +// have either a working SX1262 or a working screen + #ifdef __cplusplus } #endif