Compare commits

..

37 Commits
0.9.2 ... 0.9.5

Author SHA1 Message Date
Kevin Hester
915427c964 Merge pull request #350 from geeksville/master
misc bugfix
2020-08-30 14:43:48 -07:00
geeksville
347484baaf 0.9.5 2020-08-30 14:38:23 -07:00
geeksville
bb6913a56a Merge remote-tracking branch 'root/master' 2020-08-30 13:48:16 -07:00
geeksville
6cdaf8c600 fix #349 channel suffix letter didn't match between device and phone 2020-08-30 12:38:15 -07:00
geeksville
c370eb4a88 allow restarting failed upgrades (fixes an android autobug report) 2020-08-30 12:21:05 -07:00
geeksville
8dc4492ba3 add taiwan frequencies 2020-08-30 12:20:43 -07:00
geeksville
901cc536ef less logspam 2020-08-29 15:17:32 -07:00
Kevin Hester
2d12a363db Merge pull request #348 from geeksville/master
finish (ish) corvus board
2020-08-29 13:13:25 -07:00
geeksville
5125126aec Merge branch 'corvus' 2020-08-29 12:47:01 -07:00
geeksville
f1ca1ee3c0 okay basic support for @bigcorvus board is done 2020-08-29 12:46:42 -07:00
geeksville
dffb6c2f06 If display is on on the @BigCorvus board and we xmit the board browns out? 2020-08-28 17:38:23 -07:00
geeksville
7f214ffbb0 TFT kinda correct now - but slow because of bit banging 2020-08-28 15:33:33 -07:00
geeksville
e049eac38a TFT display kinda draws stuff (badly) 2020-08-28 15:06:52 -07:00
geeksville
338445d175 basic init of the Corvus TFT display works 2020-08-28 14:24:22 -07:00
Kevin Hester
a5341d766e Merge pull request #344 from geeksville/master
lora32 again
2020-08-27 14:56:18 -07:00
geeksville
c78142b235 Merge remote-tracking branch 'root/post1' into post1 2020-08-27 14:50:54 -07:00
geeksville
9ebaa2b962 Merge remote-tracking branch 'root/master' 2020-08-27 14:49:52 -07:00
geeksville
79498580b1 If LORA32 battery voltage is super low, assume no battery installed 2020-08-27 14:46:59 -07:00
Kevin Hester
41901aed97 Merge pull request #342 from geeksville/master
ttgo lora32 fixes
2020-08-26 14:06:25 -07:00
geeksville
2729a513ab Merge remote-tracking branch 'root/master' 2020-08-26 14:00:43 -07:00
geeksville
af046e7dbd bug #322 - ttgo lora32 deep sleep
oh - I think I found the problem (probably)!  we were isolating gpio12 (which isn't used on other boards) to save power during sleep.  gpio12 is the button for this board. @thomslik would you mind pulling this commit and seeing if it works better?
2020-08-26 14:00:10 -07:00
Kevin Hester
0caf534b65 Merge pull request #338 from geeksville/master
fix heltec battery display
2020-08-25 13:06:32 -07:00
geeksville
f650222e94 Merge remote-tracking branch 'root/master' 2020-08-25 13:01:19 -07:00
geeksville
5c40378805 fix #336 don't send battery status on nodes without batteries 2020-08-25 13:00:55 -07:00
geeksville
780b7e3628 don't show battery status on boards that can't sense that #336 2020-08-25 12:48:47 -07:00
geeksville
83ae3c7714 doc rename 2020-08-25 12:48:19 -07:00
Kevin Hester
25ebb9adb8 Merge pull request #337 from geeksville/master
fix screen redrawing
2020-08-25 12:14:07 -07:00
geeksville
7f6a0e7ddc Merge remote-tracking branch 'root/master' 2020-08-25 12:08:38 -07:00
geeksville
f62e6793c5 Fix #333 screens were redrawing when they should not
thanks @drewsed for the clear report - made it easy to repro/fix
due to refactoring/cleanup a couple of weeks back
2020-08-25 12:08:18 -07:00
geeksville
babd57ecde add hw docs 2020-08-25 12:06:55 -07:00
geeksville
de196810a2 add debugging for SNR values on SX1262 2020-08-25 12:06:36 -07:00
Kevin Hester
82fe55471d Merge pull request #331 from geeksville/master
hotfix
2020-08-22 09:15:51 -07:00
Kevin Hester
83726086a9 Merge pull request #329 from geeksville/post1
Post1
2020-08-22 09:13:55 -07:00
geeksville
60d90c4533 Merge remote-tracking branch 'root/master' 2020-08-22 09:10:33 -07:00
geeksville
9145945efa 0.9.3 2020-08-22 09:10:08 -07:00
geeksville
7b09fbe049 fix #327 side effect noticed by @smarti2019 2020-08-22 09:06:54 -07:00
geeksville
a90bab5455 this seems bad - this value was not inited if it wasn't in bss 2020-08-21 10:56:54 -07:00
29 changed files with 436 additions and 556 deletions

View File

@@ -1,3 +1,3 @@
export VERSION=0.9.2 export VERSION=0.9.5

Binary file not shown.

BIN
docs/hardware/T-SX1262.pdf Normal file

Binary file not shown.

View File

@@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
default_envs = tbeam # lora-relay-v1 default_envs = tbeam # or if you'd like to change the default to something like lora-relay-v1 put that here
[common] [common]
; common is not currently used ; common is not currently used
@@ -66,7 +66,7 @@ lib_deps =
Wire ; explicitly needed here because the AXP202 library forgets to add it Wire ; explicitly needed here because the AXP202 library forgets to add it
https://github.com/meshtastic/arduino-fsm.git https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.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/TinyGPSPlus.git
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
@@ -220,7 +220,17 @@ lib_deps =
extends = nrf52_base extends = nrf52_base
board = lora-relay-v1 board = lora-relay-v1
# add our variants files to the include and src paths # add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v1 build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v1
-DUSER_SETUP_LOADED
-DTFT_WIDTH=80
-DTFT_HEIGHT=160
-DST7735_GREENTAB160x80
-DST7735_DRIVER
-DTFT_CS=ST7735_CS
-DTFT_DC=ST7735_RS
-DTFT_RST=ST7735_RESET
-DSPI_FREQUENCY=27000000
src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v1> src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v1>
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}

View File

@@ -16,6 +16,8 @@ bool pmu_irq = false;
Power *power; Power *power;
using namespace meshtastic;
/** /**
* If this board has a battery level sensor, set this to a valid implementation * If this board has a battery level sensor, set this to a valid implementation
*/ */
@@ -36,7 +38,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
float v = getBattVoltage() / 1000; float v = getBattVoltage() / 1000;
if (v < 2.1) if (v < 2.1)
return -1; return -1; // If voltage is super low assume no battery installed
return 100 * (v - 3.27) / (4.2 - 3.27); return 100 * (v - 3.27) / (4.2 - 3.27);
} }
@@ -57,7 +59,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/** /**
* return true if there is a battery installed in this unit * return true if there is a battery installed in this unit
*/ */
virtual bool isBatteryConnect() { return true; } virtual bool isBatteryConnect() { return getBattVoltage() != -1; }
} analogLevel; } analogLevel;
bool Power::analogInit() bool Power::analogInit()
@@ -97,7 +99,7 @@ void Power::readPowerStatus()
if (batteryLevel) { if (batteryLevel) {
bool hasBattery = batteryLevel->isBatteryConnect(); bool hasBattery = batteryLevel->isBatteryConnect();
int batteryVoltageMv = 0; int batteryVoltageMv = 0;
uint8_t batteryChargePercent = 0; int8_t batteryChargePercent = 0;
if (hasBattery) { if (hasBattery) {
batteryVoltageMv = batteryLevel->getBattVoltage(); batteryVoltageMv = batteryLevel->getBattVoltage();
// If the AXP192 returns a valid battery percentage, use it // If the AXP192 returns a valid battery percentage, use it
@@ -114,13 +116,18 @@ void Power::readPowerStatus()
} }
// Notify any status instances that are observing us // Notify any status instances that are observing us
const meshtastic::PowerStatus powerStatus = meshtastic::PowerStatus( const PowerStatus powerStatus =
hasBattery, batteryLevel->isVBUSPlug(), batteryLevel->isChargeing(), batteryVoltageMv, batteryChargePercent); PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse,
batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
newStatus.notifyObservers(&powerStatus); newStatus.notifyObservers(&powerStatus);
// If we have a battery at all and it is less than 10% full, force deep sleep // If we have a battery at all and it is less than 10% full, force deep sleep
if (powerStatus.getHasBattery() && !powerStatus.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) if (powerStatus.getHasBattery() && !powerStatus.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS)
powerFSM.trigger(EVENT_LOW_BATTERY); powerFSM.trigger(EVENT_LOW_BATTERY);
} else {
// No power sensing on this board - tell everyone else we have no idea what is happening
const PowerStatus powerStatus = PowerStatus(OptUnknown, OptUnknown, OptUnknown, -1, -1);
newStatus.notifyObservers(&powerStatus);
} }
} }

View File

@@ -1,34 +1,40 @@
#pragma once #pragma once
#include <Arduino.h>
#include "Status.h" #include "Status.h"
#include "configuration.h" #include "configuration.h"
#include <Arduino.h>
namespace meshtastic { namespace meshtastic
{
/// Describes the state of the GPS system. /**
class PowerStatus : public Status * A boolean where we have a third state of Unknown
{ */
enum OptionalBool { OptFalse = 0, OptTrue = 1, OptUnknown = 2 };
/// Describes the state of the GPS system.
class PowerStatus : public Status
{
private: private:
CallbackObserver<PowerStatus, const PowerStatus *> statusObserver = CallbackObserver<PowerStatus, const PowerStatus *>(this, &PowerStatus::updateStatus); CallbackObserver<PowerStatus, const PowerStatus *> statusObserver =
CallbackObserver<PowerStatus, const PowerStatus *>(this, &PowerStatus::updateStatus);
/// Whether we have a battery connected /// Whether we have a battery connected
bool hasBattery; OptionalBool hasBattery = OptUnknown;
/// Battery voltage in mV, valid if haveBattery is true /// Battery voltage in mV, valid if haveBattery is true
int batteryVoltageMv; int batteryVoltageMv = 0;
/// Battery charge percentage, either read directly or estimated /// Battery charge percentage, either read directly or estimated
uint8_t batteryChargePercent; int8_t batteryChargePercent = 0;
/// Whether USB is connected /// Whether USB is connected
bool hasUSB; OptionalBool hasUSB = OptUnknown;
/// Whether we are charging the battery /// Whether we are charging the battery
bool isCharging; OptionalBool isCharging = OptUnknown;
public: public:
PowerStatus() { statusType = STATUS_TYPE_POWER; }
PowerStatus() { PowerStatus(OptionalBool hasBattery, OptionalBool hasUSB, OptionalBool isCharging, int batteryVoltageMv = -1,
statusType = STATUS_TYPE_POWER; int8_t batteryChargePercent = 0)
} : Status()
PowerStatus( bool hasBattery, bool hasUSB, bool isCharging, int batteryVoltageMv, uint8_t batteryChargePercent ) : Status()
{ {
this->hasBattery = hasBattery; this->hasBattery = hasBattery;
this->hasUSB = hasUSB; this->hasUSB = hasUSB;
@@ -39,65 +45,50 @@ namespace meshtastic {
PowerStatus(const PowerStatus &); PowerStatus(const PowerStatus &);
PowerStatus &operator=(const PowerStatus &); PowerStatus &operator=(const PowerStatus &);
void observe(Observable<const PowerStatus *> *source) void observe(Observable<const PowerStatus *> *source) { statusObserver.observe(source); }
{
statusObserver.observe(source);
}
bool getHasBattery() const bool getHasBattery() const { return hasBattery == OptTrue; }
{
return hasBattery;
}
bool getHasUSB() const bool getHasUSB() const { return hasUSB == OptTrue; }
{
return hasUSB;
}
bool getIsCharging() const /// Can we even know if this board has USB power or not
{ bool knowsUSB() const { return hasUSB != OptUnknown; }
return isCharging;
}
int getBatteryVoltageMv() const bool getIsCharging() const { return isCharging == OptTrue; }
{
return batteryVoltageMv;
}
uint8_t getBatteryChargePercent() const int getBatteryVoltageMv() const { return batteryVoltageMv; }
{
return batteryChargePercent; /**
} * Note: 0% battery means 'unknown/this board doesn't have a battery installed'
*/
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 0; }
bool matches(const PowerStatus *newStatus) const bool matches(const PowerStatus *newStatus) const
{ {
return ( return (newStatus->getHasBattery() != hasBattery || newStatus->getHasUSB() != hasUSB ||
newStatus->getHasBattery() != hasBattery || newStatus->getBatteryVoltageMv() != batteryVoltageMv);
newStatus->getHasUSB() != hasUSB ||
newStatus->getBatteryVoltageMv() != batteryVoltageMv
);
} }
int updateStatus(const PowerStatus *newStatus) { int updateStatus(const PowerStatus *newStatus)
{
// Only update the status if values have actually changed // Only update the status if values have actually changed
bool isDirty; bool isDirty;
{ {
isDirty = matches(newStatus); isDirty = matches(newStatus);
initialized = true; initialized = true;
hasBattery = newStatus->getHasBattery(); hasBattery = newStatus->hasBattery;
batteryVoltageMv = newStatus->getBatteryVoltageMv(); batteryVoltageMv = newStatus->getBatteryVoltageMv();
batteryChargePercent = newStatus->getBatteryChargePercent(); batteryChargePercent = newStatus->getBatteryChargePercent();
hasUSB = newStatus->getHasUSB(); hasUSB = newStatus->hasUSB;
isCharging = newStatus->getIsCharging(); isCharging = newStatus->isCharging;
} }
if(isDirty) { if (isDirty) {
DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent); DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
onNewStatus.notifyObservers(this); onNewStatus.notifyObservers(this);
} }
return 0; return 0;
} }
};
}; } // namespace meshtastic
}
extern meshtastic::PowerStatus *powerStatus; extern meshtastic::PowerStatus *powerStatus;

11
src/SPILock.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "SPILock.h"
#include <Arduino.h>
#include <assert.h>
concurrency::Lock *spiLock;
void initSPI()
{
assert(!spiLock);
spiLock = new concurrency::Lock();
}

12
src/SPILock.h Normal file
View File

@@ -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();

View File

@@ -20,7 +20,7 @@ namespace meshtastic
CallbackObserver<Status, const Status *> statusObserver = CallbackObserver<Status, const Status *>(this, &Status::updateStatus); CallbackObserver<Status, const Status *> statusObserver = CallbackObserver<Status, const Status *>(this, &Status::updateStatus);
bool initialized = false; bool initialized = false;
// Workaround for no typeid support // Workaround for no typeid support
int statusType; int statusType = 0;
public: public:
// Allows us to generate observable events // Allows us to generate observable events

View File

@@ -1,339 +0,0 @@
// This file is used to set TFT/eInk preferences for the TFT.cpp driver
#include <variant.h>
// USER DEFINED SETTINGS
// Set driver type, fonts to be loaded, pins used and SPI control method etc
//
// See the User_Setup_Select.h file if you wish to be able to define multiple
// setups and then easily select which setup file is used by the compiler.
//
// If this file is edited correctly then all the library example sketches should
// run without the need to make any more changes for a particular hardware setup!
// Note that some sketches are designed for a particular TFT pixel width/height
// ##################################################################################
//
// Section 1. Call up the right driver file and any options for it
//
// ##################################################################################
// Define STM32 to invoke optimised processor support (only for STM32)
//#define STM32
// Defining the STM32 board allows the library to optimise the performance
// for UNO compatible "MCUfriend" style shields
//#define NUCLEO_64_TFT
//#define NUCLEO_144_TFT
// STM32 8 bit parallel only:
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
// then this will improve rendering performance by a factor of ~8x
//#define STM_PORTA_DATA_BUS
//#define STM_PORTA_DATA_BUS
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
// Display type - only define if RPi display
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
// Only define one driver, the other ones must be commented out
//#define ILI9341_DRIVER
#define ST7735_DRIVER // Define additional parameters below for this display
//#define ILI9163_DRIVER // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1963_480_DRIVER // Untested
//#define SSD1963_800_DRIVER // Untested
//#define SSD1963_800ALT_DRIVER // Untested
// Some displays support SPI reads via the MISO pin, other displays have a single
// bi-directional SDA pin and the library will try to read this via the MOSI line.
// To use the SDA line for reading data from the TFT uncomment the following line:
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only
// For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
// Try ONE option at a time to find the correct colour order for your display
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
// #define M5STACK
// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation
#define TFT_WIDTH 80
// #define TFT_WIDTH 128
// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 160
// #define TFT_HEIGHT 128
// #define TFT_HEIGHT 240 // ST7789 240 x 240
// #define TFT_HEIGHT 320 // ST7789 240 x 320
// For ST7735 ONLY, define the type of display, originally this was based on the
// colour of the tab on the screen protector film but this is not always true, so try
// out the different options below if the screen does not display graphics correctly,
// e.g. colours wrong, mirror images, or tray pixels at the edges.
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
// this User_Setup file, then rebuild and upload the sketch to the board again:
// #define ST7735_INITB
#define ST7735_GREENTAB
// #define ST7735_GREENTAB2
// #define ST7735_GREENTAB3
// #define ST7735_GREENTAB128 // For 128 x 128 display
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
// #define ST7735_REDTAB
// #define ST7735_BLACKTAB
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
// If colours are inverted (white shows as black) then uncomment one of the next
// 2 lines try both options, one of the options should correct the inversion.
// #define TFT_INVERSION_ON
// #define TFT_INVERSION_OFF
// ##################################################################################
//
// Section 2. Define the pins that are used to interface with the display here
//
// ##################################################################################
// If a backlight control signal is available then define the TFT_BL pin in Section 2
// below. The backlight will be turned ON when tft.begin() is called, but the library
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
#define TFT_BL ST7735_BACKLIGHT_EN // LED back-light control pin
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
// Typical setup for ESP8266 NodeMCU ESP-12 is :
//
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
// Display LED to NodeMCU pin VIN (or 5V, see below)
// Display SCK to NodeMCU pin D5
// Display SDI/MOSI to NodeMCU pin D7
// Display DC (RS/AO)to NodeMCU pin D3
// Display RESET to NodeMCU pin D4 (or RST, see below)
// Display CS to NodeMCU pin D8 (or GND, see below)
// Display GND to NodeMCU pin GND (0V)
// Display VCC to NodeMCU 5V or 3.3V
//
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
//
// The DC (Data Command) pin may be labeled AO or RS (Register Select)
//
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
//
// The NodeMCU D0 pin can be used for RST
//
//
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
// If 5V is not available at a pin you can use 3.3V but backlight brightness
// will be lower.
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
#define TFT_CS ST7735_CS // Chip select control pin D8
#define TFT_DC ST7735_RS // Data Command control pin
#define TFT_RST ST7735_RESET // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
// but saves pins for other functions. It is best not to connect MISO as some displays
// do not tristate that line wjen chip select is high!
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
// In ESP8266 overlap mode the following must be defined
//#define TFT_SPI_OVERLAP
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
//#define TFT_CS PIN_D3
//#define TFT_DC PIN_D5 // Data Command control pin
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS 15 // Chip select control pin
//#define TFT_DC 2 // Data Command control pin
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
// For the M5Stack module use these #define lines
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS 14 // Chip select control pin
//#define TFT_DC 27 // Data Command control pin
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL 32 // LED back-light (required for M5Stack)
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
// The library supports 8 bit parallel TFTs with the ESP32, the pin
// selection below is compatible with ESP32 boards in UNO format.
// Wemos D32 boards need to be modified, see diagram in Tools folder.
// Only ILI9481 and ILI9341 based displays have been tested!
// Parallel bus is only supported for the STM32 and ESP32
// Example below is for ESP32 Parallel interface with UNO displays
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
// The ESP32 and TFT the pins used for testing are:
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
//#define TFT_RST 32 // Reset pin, toggles on startup
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
//#define TFT_RD 2 // Read strobe control pin
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
//#define TFT_D1 13 // so a single register write sets/clears all bits.
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
//#define TFT_D3 25 // TFT screen update performance.
//#define TFT_D4 17
//#define TFT_D5 16
//#define TFT_D6 27
//#define TFT_D7 14
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
// The TFT can be connected to SPI port 1 or 2
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
//#define TFT_MOSI PA7
//#define TFT_MISO PA6
//#define TFT_SCLK PA5
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
//#define TFT_MOSI PB15
//#define TFT_MISO PB14
//#define TFT_SCLK PB13
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
//#define TFT_CS D5 // Chip select control pin to TFT CS
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
// OR alternatively, we can use STM32 port reference names PXnn
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
// Use an Arduino pin for initial testing as connecting to processor reset
// may not work (pulse too short at power up?)
// ##################################################################################
//
// Section 3. Define the fonts that are to be used here
//
// ##################################################################################
// Comment out the #defines below with // to stop that font being loaded
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
// normally necessary. If all fonts are loaded the extra FLASH space required is
// about 17Kbytes. To save FLASH space only enable the fonts you need!
//#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
//#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
//#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
//#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
//#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
//#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
//#define SMOOTH_FONT
// ##################################################################################
//
// Section 4. Other options
//
// ##################################################################################
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
// fast and the TFT driver will not keep up and display corruption appears.
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
// With an ILI9163 display 27 MHz works OK.
// #define SPI_FREQUENCY 1000000
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000
// #define SPI_FREQUENCY 40000000
// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY 80000000
// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY 20000000
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line:
//#define USE_HSPI_PORT
// Comment out the following #define if "SPI Transactions" do not need to be
// supported. When commented out the code size will be smaller and sketches will
// run slightly faster, so leave it commented out unless you need it!
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
// Transaction support is required if other SPI devices are connected.
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
// so changing it here has no effect
// #define SUPPORT_TRANSACTIONS

View File

@@ -309,6 +309,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BUTTON_PIN \ #define BUTTON_PIN \
12 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one 12 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one
// between this pin and ground // between this pin and ground
#define BUTTON_NEED_PULLUP
#define USE_RF95 #define USE_RF95
#define LORA_DIO0 26 // a No connect on the SX1262 module #define LORA_DIO0 26 // a No connect on the SX1262 module

View File

@@ -31,6 +31,8 @@ int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR && updateExpectedSize != 0) { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR && updateExpectedSize != 0) {
updateActualSize = 0; updateActualSize = 0;
crc.reset(); crc.reset();
if (Update.isRunning())
Update.abort();
bool canBegin = Update.begin(updateExpectedSize); bool canBegin = Update.begin(updateExpectedSize);
DEBUG_MSG("Setting update size %u, result %d\n", updateExpectedSize, canBegin); DEBUG_MSG("Setting update size %u, result %d\n", updateExpectedSize, canBegin);
if (!canBegin) { if (!canBegin) {

View File

@@ -102,8 +102,13 @@ bool UBloxGPS::factoryReset()
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have // It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
// GPS_TX connected) // GPS_TX connected)
ublox.factoryReset(); ublox.factoryReset();
delay(3000); delay(5000);
tryConnect(); // sets isConnected tryConnect(); // sets isConnected
// try a second time, the ublox lib serial parsing is buggy?
if (!tryConnect())
tryConnect();
DEBUG_MSG("GPS Factory reset success=%d\n", isConnected); DEBUG_MSG("GPS Factory reset success=%d\n", isConnected);
if (isConnected) if (isConnected)
ok = setUBXMode(); ok = setUBXMode();
@@ -122,12 +127,11 @@ int UBloxGPS::prepareSleep(void *unused)
void UBloxGPS::doTask() void UBloxGPS::doTask()
{ {
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix if (isConnected) {
assert(isConnected);
// Consume all characters that have arrived // Consume all characters that have arrived
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix
// if using i2c or serial look too see if any chars are ready // if using i2c or serial look too see if any chars are ready
ublox.checkUblox(); // See if new data is available. Process bytes as they come in. ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
@@ -145,9 +149,9 @@ void UBloxGPS::doTask()
if (ublox.getT(maxWait)) { if (ublox.getT(maxWait)) {
/* Convert to unix time /* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
*/ */
struct tm t; struct tm t;
t.tm_sec = ublox.getSecond(0); t.tm_sec = ublox.getSecond(0);
t.tm_min = ublox.getMinute(0); t.tm_min = ublox.getMinute(0);
@@ -185,9 +189,10 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
const meshtastic::GPSStatus status = const meshtastic::GPSStatus status =
meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites); meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
newStatus.notifyObservers(&status); newStatus.notifyObservers(&status);
}
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over // Once we have sent a location once we only poll the GPS rarely, otherwise check back every 10s until we have something
// the serial // over the serial
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000); setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000);
} }

View File

@@ -774,7 +774,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Display power status // Display power status
if (powerStatus->getHasBattery()) if (powerStatus->getHasBattery())
drawBattery(display, x, y + 2, imgBattery, powerStatus); drawBattery(display, x, y + 2, imgBattery, powerStatus);
else else if (powerStatus->knowsUSB())
display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
// Display nodes status // Display nodes status
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
@@ -819,14 +819,16 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
// DEBUG_MSG("Screen got status update %d\n", arg->getStatusType()); // DEBUG_MSG("Screen got status update %d\n", arg->getStatusType());
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_NODE: case STATUS_TYPE_NODE:
if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
setFrames(); setFrames(); // Regen the list of screens
prevFrame = -1; prevFrame = -1; // Force a GUI update
setPeriod(1); // Update the screen right away
}
nodeDB.updateGUI = false; nodeDB.updateGUI = false;
nodeDB.updateTextMessage = false; nodeDB.updateTextMessage = false;
break; break;
} }
setPeriod(1); // Update the screen right away
return 0; return 0;
} }
} // namespace graphics } // namespace graphics

View File

@@ -10,11 +10,12 @@
#include <SSD1306Wire.h> #include <SSD1306Wire.h>
#endif #endif
#include "concurrency/PeriodicTask.h" #include "TFT.h"
#include "TypedQueue.h" #include "TypedQueue.h"
#include "concurrency/LockGuard.h"
#include "power.h"
#include "commands.h" #include "commands.h"
#include "concurrency/LockGuard.h"
#include "concurrency/PeriodicTask.h"
#include "power.h"
#include <string> #include <string>
namespace graphics namespace graphics
@@ -60,9 +61,12 @@ class DebugInfo
*/ */
class Screen : public concurrency::PeriodicTask class Screen : public concurrency::PeriodicTask
{ {
CallbackObserver<Screen, const meshtastic::Status *> powerStatusObserver = CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *> powerStatusObserver =
CallbackObserver<Screen, const meshtastic::Status *> gpsStatusObserver = CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
CallbackObserver<Screen, const meshtastic::Status *> nodeStatusObserver = CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *> gpsStatusObserver =
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
CallbackObserver<Screen, const meshtastic::Status *> nodeStatusObserver =
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
public: public:
Screen(uint8_t address, int sda = -1, int scl = -1); Screen(uint8_t address, int sda = -1, int scl = -1);
@@ -125,7 +129,8 @@ class Screen : public concurrency::PeriodicTask
} }
/// Overrides the default utf8 character conversion, to replace empty space with question marks /// Overrides the default utf8 character conversion, to replace empty space with question marks
static char customFontTableLookup(const uint8_t ch) { static char customFontTableLookup(const uint8_t ch)
{
// UTF-8 to font table index converter // UTF-8 to font table index converter
// Code form http://playground.arduino.cc/Main/Utf8ascii // Code form http://playground.arduino.cc/Main/Utf8ascii
static uint8_t LASTCHAR; static uint8_t LASTCHAR;
@@ -141,24 +146,34 @@ class Screen : public concurrency::PeriodicTask
LASTCHAR = ch; LASTCHAR = ch;
switch (last) { // conversion depnding on first UTF8-character switch (last) { // conversion depnding on first UTF8-character
case 0xC2: { SKIPREST = false; return (uint8_t) ch; } case 0xC2: {
case 0xC3: { SKIPREST = false; return (uint8_t) (ch | 0xC0); } SKIPREST = false;
return (uint8_t)ch;
}
case 0xC3: {
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
}
} }
// We want to strip out prefix chars for two-byte char formats // We want to strip out prefix chars for two-byte char formats
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82) return (uint8_t) 0; if (ch == 0xC2 || ch == 0xC3 || ch == 0x82)
return (uint8_t)0;
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the rest of it // If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
if (SKIPREST) return (uint8_t) 0; // rest of it
if (SKIPREST)
return (uint8_t)0;
SKIPREST = true; SKIPREST = true;
return (uint8_t) 191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't stick to standard EASCII codes) return (uint8_t)191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't
// stick to standard EASCII codes)
} }
/// Returns a handle to the DebugInfo screen. /// Returns a handle to the DebugInfo screen.
// //
// Use this handle to set things like battery status, user count, GPS status, etc. // Use this handle to set things like battery status, user count, GPS status, etc.
DebugInfo* debug_info() { return &debugInfo; } DebugInfo *debug_info() { return &debugInfo; }
int handleStatusUpdate(const meshtastic::Status *arg); int handleStatusUpdate(const meshtastic::Status *arg);
@@ -215,8 +230,10 @@ class Screen : public concurrency::PeriodicTask
DebugInfo debugInfo; DebugInfo debugInfo;
/// Display device /// Display device
/** @todo display abstraction */ /** FIXME cleanup display abstraction */
#ifdef USE_SH1106 #ifdef ST7735_CS
TFTDisplay dispdev;
#elif defined(USE_SH1106)
SH1106Wire dispdev; SH1106Wire dispdev;
#else #else
SSD1306Wire dispdev; SSD1306Wire dispdev;

View File

@@ -1,17 +1,65 @@
#include "configuration.h" #include "configuration.h"
#ifdef ST7735_CS #ifdef ST7735_CS
#include "SPILock.h"
#include "TFT.h"
#include "graphics/configs.h"
#include <SPI.h> #include <SPI.h>
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip #include <TFT_eSPI.h> // 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
void TFTinit() TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl)
{ {
setGeometry(GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will
// work ie GEOMETRY_RAWMODE
}
// 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++) {
for (uint8_t x = 0; x < SCREEN_WIDTH; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto b = buffer[x + (y / 8) * SCREEN_WIDTH];
auto isset = b & (1 << (y & 7));
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
}
}
#endif
}
// Send a command to the display (low level function)
void TFTDisplay::sendCommand(uint8_t com)
{
(void)com;
// Drop all commands to device (we just update the buffer)
}
// Connect to the display
bool TFTDisplay::connect()
{
DEBUG_MSG("Doing TFT init\n");
#ifdef ST7735_BACKLIGHT_EN
digitalWrite(ST7735_BACKLIGHT_EN, HIGH);
pinMode(ST7735_BACKLIGHT_EN, OUTPUT);
#endif
#if 1
tft.init(); tft.init();
tft.setRotation(1); 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;
} }
#endif #endif

View File

@@ -1,3 +1,35 @@
#pragma once #pragma once
void TFTinit(); #include <OLEDDisplay.h>
/**
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation.
*
* Remaining TODO:
* 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 - currently with both on spi bus is fucked? or are we leaving chip select asserted?
*/
class TFTDisplay : public OLEDDisplay
{
public:
/* constructor
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
*/
TFTDisplay(uint8_t address, int sda, int scl);
// Write the buffer to the display memory
virtual void display(void);
protected:
// the header size of the buffer used, e.g. for the SPI command header
virtual int getBufferOffset(void) { return 0; }
// Send a command to the display (low level function)
virtual void sendCommand(uint8_t com);
// Connect to the display
virtual bool connect();
};

View File

@@ -34,6 +34,7 @@
// #include "rom/rtc.h" // #include "rom/rtc.h"
#include "DSRRouter.h" #include "DSRRouter.h"
// #include "debug.h" // #include "debug.h"
#include "SPILock.h"
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "main.h" #include "main.h"
#include "sleep.h" #include "sleep.h"
@@ -220,9 +221,23 @@ void setup()
nrf52Setup(); nrf52Setup();
#endif #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. // Initialize the screen first so we can show the logo while we start up everything else.
#ifdef ST7735_CS
screen.setup();
#else
if (ssd1306_found) if (ssd1306_found)
screen.setup(); screen.setup();
#endif
screen.print("Started...\n"); screen.print("Started...\n");
@@ -274,15 +289,6 @@ void setup()
digitalWrite(SX1262_ANT_SW, 1); digitalWrite(SX1262_ANT_SW, 1);
#endif #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) // MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
RadioInterface *rIf = NULL; RadioInterface *rIf = NULL;

View File

@@ -26,11 +26,16 @@
#define CH_SPACING_CN 2.0f // MHz FIXME, this is just a guess for 470-510 #define CH_SPACING_CN 2.0f // MHz FIXME, this is just a guess for 470-510
#define NUM_CHANNELS_CN 20 #define NUM_CHANNELS_CN 20
// JP channel settings // JP channel settings (AS1 bandplan)
#define CH0_JP 920.0f // MHz #define CH0_JP 920.0f // MHz
#define CH_SPACING_JP 0.5f // MHz FIXME, this is just a guess for 920-925 #define CH_SPACING_JP 0.5f
#define NUM_CHANNELS_JP 10 #define NUM_CHANNELS_JP 10
// TW channel settings (AS2 bandplan 923-925MHz)
#define CH0_TW 923.0f // MHz
#define CH_SPACING_TW 0.2
#define NUM_CHANNELS_TW 10
// FIXME add defs for other regions and use them here // FIXME add defs for other regions and use them here
#ifdef HW_VERSION_US #ifdef HW_VERSION_US
#define CH0 CH0_US #define CH0 CH0_US
@@ -49,13 +54,18 @@
#define CH_SPACING CH_SPACING_CN #define CH_SPACING CH_SPACING_CN
#define NUM_CHANNELS NUM_CHANNELS_CN #define NUM_CHANNELS NUM_CHANNELS_CN
#elif defined(HW_VERSION_JP) #elif defined(HW_VERSION_JP)
// Also called AS1 bandplan
#define CH0 CH0_JP #define CH0 CH0_JP
#define CH_SPACING CH_SPACING_JP #define CH_SPACING CH_SPACING_JP
#define NUM_CHANNELS NUM_CHANNELS_JP #define NUM_CHANNELS NUM_CHANNELS_JP
#elif defined(HW_VERSION_TW)
// Also called AS2 bandplan
#define CH0 CH0_TW
#define CH_SPACING CH_SPACING_TW
#define NUM_CHANNELS NUM_CHANNELS_TW
#else #else
// HW version not set - assume US // HW version not set - assume US
#define CH0 CH0_US #define CH0 CH0_US
#define CH_SPACING CH_SPACING_US #define CH_SPACING CH_SPACING_US
#define NUM_CHANNELS NUM_CHANNELS_US #define NUM_CHANNELS NUM_CHANNELS_US
#endif #endif

View File

@@ -86,7 +86,7 @@ const char *getChannelName()
static char buf[32]; static char buf[32];
uint8_t code = 0; uint8_t code = 0;
for (int i = 0; i < sizeof(channelSettings.psk.size); i++) for (int i = 0; i < channelSettings.psk.size; i++)
code ^= channelSettings.psk.bytes[i]; code ^= channelSettings.psk.bytes[i];
snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, 'A' + (code % 26)); snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, 'A' + (code % 26));
@@ -121,7 +121,7 @@ void NodeDB::resetRadioConfig()
channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range
channelSettings.tx_power = 0; // default channelSettings.tx_power = 0; // default
memcpy(&channelSettings.psk.bytes, &defaultpsk, sizeof(channelSettings.psk)); memcpy(&channelSettings.psk.bytes, defaultpsk, sizeof(channelSettings.psk));
channelSettings.psk.size = sizeof(defaultpsk); channelSettings.psk.size = sizeof(defaultpsk);
strcpy(channelSettings.name, "Default"); strcpy(channelSettings.name, "Default");
} }

View File

@@ -68,6 +68,9 @@ void printPacket(const char *prefix, const MeshPacket *p)
if (p->rx_time != 0) { if (p->rx_time != 0) {
DEBUG_MSG(" rxtime=%u", p->rx_time); DEBUG_MSG(" rxtime=%u", p->rx_time);
} }
if (p->rx_snr != 0.0) {
DEBUG_MSG(" rxSNR=%g", p->rx_snr);
}
DEBUG_MSG(")\n"); DEBUG_MSG(")\n");
} }
@@ -115,8 +118,6 @@ unsigned long hash(char *str)
return hash; return hash;
} }
#define POWER_DEFAULT 17 #define POWER_DEFAULT 17
/** /**

View File

@@ -1,6 +1,7 @@
#include "RadioLibInterface.h" #include "RadioLibInterface.h"
#include "MeshTypes.h" #include "MeshTypes.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "SPILock.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include <configuration.h> #include <configuration.h>
#include <pb_decode.h> #include <pb_decode.h>
@@ -9,6 +10,13 @@
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that // 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); 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, RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi, PhysicalLayer *_iface) SPIClass &spi, PhysicalLayer *_iface)
: concurrency::PeriodicTask(0), module(cs, irq, rst, busy, spi, spiSettings), iface(_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 /// bluetooth comms code. If the txmit queue is empty it might return an error
ErrorCode RadioLibInterface::send(MeshPacket *p) 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); printPacket("enqueuing for send", p);
DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad); DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN; ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN;
@@ -140,6 +150,10 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
startTransmitTimer(true); startTransmitTimer(true);
return res; return res;
#else
packetPool.release(p);
return ERRNO_UNKNOWN;
#endif
} }
bool RadioLibInterface::canSleep() bool RadioLibInterface::canSleep()

View File

@@ -16,6 +16,49 @@
#define INTERRUPT_ATTR #define INTERRUPT_ATTR
#endif #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 class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTask
{ {
/// Used as our notification from the ISR /// Used as our notification from the ISR
@@ -49,7 +92,7 @@ class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTa
float currentLimit = 100; // FIXME float currentLimit = 100; // FIXME
uint16_t preambleLength = 32; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving 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 * provides lowest common denominator RadioLib API

View File

@@ -74,6 +74,10 @@ bool SX1262Interface::reconfigure()
err = lora.setCodingRate(cr); err = lora.setCodingRate(cr);
assert(err == ERR_NONE); assert(err == ERR_NONE);
// 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); err = lora.setSyncWord(syncWord);
assert(err == ERR_NONE); assert(err == ERR_NONE);
@@ -123,6 +127,7 @@ void SX1262Interface::setStandby()
*/ */
void SX1262Interface::addReceiveMetadata(MeshPacket *mp) void SX1262Interface::addReceiveMetadata(MeshPacket *mp)
{ {
// DEBUG_MSG("PacketStatus %x\n", lora.getPacketStatus());
mp->rx_snr = lora.getSNR(); mp->rx_snr = lora.getSNR();
} }

View File

@@ -330,7 +330,7 @@ static void on_sync(void)
int isPrivate = 0; int isPrivate = 0;
rc = ble_hs_id_copy_addr(own_addr_type, addr_val, &isPrivate); rc = ble_hs_id_copy_addr(own_addr_type, addr_val, &isPrivate);
assert(rc == 0); assert(rc == 0);
DEBUG_MSG("Addr type %d, Private=%d, Device Address: ", own_addr_type, isPrivate); DEBUG_MSG("BLE advertisting type=%d, Private=%d, Device Address: ", own_addr_type, isPrivate);
print_addr(addr_val); print_addr(addr_val);
DEBUG_MSG("\n"); DEBUG_MSG("\n");
/* Begin advertising. */ /* Begin advertising. */
@@ -357,17 +357,17 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
break; break;
case BLE_GATT_REGISTER_OP_CHR: case BLE_GATT_REGISTER_OP_CHR:
DEBUG_MSG("registering characteristic %s with " /* DEBUG_MSG("registering characteristic %s with "
"def_handle=%d val_handle=%d\n", "def_handle=%d val_handle=%d\n",
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), ctxt->chr.def_handle, ctxt->chr.val_handle); ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), ctxt->chr.def_handle, ctxt->chr.val_handle); */
if (ctxt->chr.chr_def->uuid == &fromnum_uuid.u) { if (ctxt->chr.chr_def->uuid == &fromnum_uuid.u) {
fromNumValHandle = ctxt->chr.val_handle; fromNumValHandle = ctxt->chr.val_handle;
DEBUG_MSG("FromNum handle %d\n", fromNumValHandle); // DEBUG_MSG("FromNum handle %d\n", fromNumValHandle);
} }
if (ctxt->chr.chr_def->uuid == &update_result_uuid.u) { if (ctxt->chr.chr_def->uuid == &update_result_uuid.u) {
updateResultHandle = ctxt->chr.val_handle; updateResultHandle = ctxt->chr.val_handle;
DEBUG_MSG("update result handle %d\n", updateResultHandle); // DEBUG_MSG("update result handle %d\n", updateResultHandle);
} }
break; break;

View File

@@ -99,9 +99,4 @@ void nrf52Setup()
// randomSeed(r); // randomSeed(r);
DEBUG_MSG("FIXME, call randomSeed\n"); DEBUG_MSG("FIXME, call randomSeed\n");
// ::printf("TESTING PRINTF\n"); // ::printf("TESTING PRINTF\n");
// Setup TFT display - FIXME do somewhere else
#ifdef ST7735_CS
TFTinit();
#endif
} }

View File

@@ -197,7 +197,7 @@ void doDeepSleep(uint64_t msecToWake)
static const uint8_t rtcGpios[] = {/* 0, */ 2, static const uint8_t rtcGpios[] = {/* 0, */ 2,
/* 4, */ /* 4, */
#ifndef USE_JTAG #ifndef USE_JTAG
12, 13, 13,
/* 14, */ /* 15, */ /* 14, */ /* 15, */
#endif #endif
/* 25, */ 26, /* 27, */ /* 25, */ 26, /* 27, */

View File

@@ -118,6 +118,10 @@ static const uint8_t SCK = PIN_SPI_SCK;
// CUSTOM GPIOs the SX1262 // CUSTOM GPIOs the SX1262
#define SX1262_CS (32) #define SX1262_CS (32)
// If you would prefer to get console debug output over the JTAG ICE connection rather than the CDC-ACM USB serial device, just
// define this. #define USE_SEGGER
#define SX1262_DIO1 (29) #define SX1262_DIO1 (29)
#define SX1262_DIO2 (30) #define SX1262_DIO2 (30)
#define SX1262_BUSY (33) // Supposed to be P0.18 but because of reworks, now on P0.31 (18) #define SX1262_BUSY (33) // Supposed to be P0.18 but because of reworks, now on P0.31 (18)
@@ -134,6 +138,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define ST7735_BACKLIGHT_EN (13) #define ST7735_BACKLIGHT_EN (13)
#define ST7735_RS (9) #define ST7735_RS (9)
// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending
// to allow USB power only based debugging
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif