Merge branch 'master' into tft-gui-work

This commit is contained in:
Manuel 2024-06-27 10:49:34 +02:00 committed by GitHub
commit ad5dbc2a84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 411 additions and 240 deletions

View File

@ -35,7 +35,7 @@
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"frameworks": ["arduino", "freertos"],
"name": "WisCore RAK4631 Board",
"upload": {
"maximum_ram_size": 248832,

View File

@ -80,7 +80,7 @@ monitor_speed = 115200
lib_deps =
jgromes/RadioLib@~6.6.0
https://github.com/meshtastic/esp8266-oled-ssd1306.git#2b40affbe7f7dc63b6c00fa88e7e12ed1f8e1719 ; ESP8266_SSD1306
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
@ -151,4 +151,3 @@ lib_deps =
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee

@ -1 +1 @@
Subproject commit 4da558d0f73c46ef91b74431facee73c09affbfc
Subproject commit a3030d5ff187091c9fbbd08dd797cca5085736fe

7
pyocd.yaml Normal file
View File

@ -0,0 +1,7 @@
# This is a config file to control pyocd ICE debugger probe options (only used for NRF52 targets with hardware debugging connections)
# for more info see FIXMEURL
# console or telnet
semihost_console_type: telnet
enable_semihosting: True
telnet_port: 4444

View File

@ -16,6 +16,8 @@
#include <Wire.h>
#ifdef RAK_4631
#include "Fusion/Fusion.h"
#include "graphics/Screen.h"
#include "graphics/ScreenFonts.h"
#include <Rak_BMX160.h>
#endif
@ -101,7 +103,11 @@ class AccelerometerThread : public concurrency::OSThread
bmx160.getAllData(&magAccel, NULL, &gAccel);
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
if (millis() > 10 * 1000 && millis() < 30 * 1000) {
if (millis() > 12 * 1000 && millis() < 30 * 1000) {
if (!showingScreen) {
showingScreen = true;
screen->startAlert((FrameCallback)drawFrameCalibration);
}
if (magAccel.x > highestX)
highestX = magAccel.x;
if (magAccel.x < lowestX)
@ -114,6 +120,9 @@ class AccelerometerThread : public concurrency::OSThread
highestZ = magAccel.z;
if (magAccel.z < lowestZ)
lowestZ = magAccel.z;
} else if (showingScreen && millis() >= 30 * 1000) {
showingScreen = false;
screen->endAlert();
}
int highestRealX = highestX - (highestX + lowestX) / 2;
@ -255,11 +264,33 @@ class AccelerometerThread : public concurrency::OSThread
Adafruit_LIS3DH lis;
Adafruit_LSM6DS3TRC lsm;
SensorBMA423 bmaSensor;
bool BMA_IRQ = false;
#ifdef RAK_4631
bool showingScreen = false;
RAK_BMX160 bmx160;
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
int x_offset = display->width() / 2;
int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
display->drawString(x, y, "Calibrating\nCompass");
int16_t compassX = 0, compassY = 0;
// coordinates for the center of the compass/circle
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
compassX = x + display->getWidth() - getCompassDiam(display) / 2 - 5;
compassY = y + display->getHeight() / 2;
} else {
compassX = x + display->getWidth() - getCompassDiam(display) / 2 - 5;
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
}
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
}
#endif
bool BMA_IRQ = false;
};
#endif

View File

@ -181,8 +181,9 @@ int32_t ButtonThread::runOnce()
case BUTTON_EVENT_LONG_PRESSED: {
LOG_BUTTON("Long press!\n");
powerFSM.trigger(EVENT_PRESS);
if (screen)
screen->startShutdownScreen();
if (screen) {
screen->startAlert("Shutting down...");
}
playBeep();
break;
}

View File

@ -25,6 +25,14 @@
#include "SerialConsole.h"
// If defined we will include support for ARM ICE "semihosting" for a virtual
// console over the JTAG port (to replace the normal serial port)
// Note: Normally this flag is passed into the gcc commandline by platformio.ini.
// for an example see env:rak4631_dap.
// #ifndef USE_SEMIHOSTING
// #define USE_SEMIHOSTING
// #endif
#define DEBUG_PORT (*console) // Serial debug port
#ifdef USE_SEGGER

View File

@ -8,13 +8,11 @@ enum class Cmd {
SET_ON,
SET_OFF,
ON_PRESS,
START_BLUETOOTH_PIN_SCREEN,
START_ALERT_FRAME,
STOP_ALERT_FRAME,
START_FIRMWARE_UPDATE_SCREEN,
STOP_BLUETOOTH_PIN_SCREEN,
STOP_BOOT_SCREEN,
PRINT,
START_SHUTDOWN_SCREEN,
START_REBOOT_SCREEN,
SHOW_PREV_FRAME,
SHOW_NEXT_FRAME
};

View File

@ -379,7 +379,7 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
// in the array of "drawScreen" functions; however,
// the passed-state doesn't quite reflect the "current"
// screen, so we have to detect it.
if (state->frameState == IN_TRANSITION && state->transitionFrameRelationship == INCOMING) {
if (state->frameState == IN_TRANSITION && state->transitionFrameRelationship == TransitionRelationship_INCOMING) {
// if we're transitioning from the end of the frame list back around to the first
// frame, then we want this to be `0`
module_frame = state->transitionFrameTarget;
@ -393,31 +393,6 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
pi.drawFrame(display, state, x, y);
}
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
int x_offset = display->width() / 2;
int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
display->setFont(FONT_SMALL);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM - 4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
display->drawString(x_offset + x, y_offset + y, "Enter this code");
display->setFont(FONT_LARGE);
String displayPin(btPIN);
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
display->drawString(x_offset + x, y_offset + y, pin);
display->setFont(FONT_SMALL);
String deviceName = "Name: ";
deviceName.concat(getDeviceName());
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
display->drawString(x_offset + x, y_offset + y, deviceName);
}
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_CENTER);
@ -1307,49 +1282,6 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
}
}
#endif
namespace
{
/// A basic 2D point class for drawing
class Point
{
public:
float x, y;
Point(float _x, float _y) : x(_x), y(_y) {}
/// Apply a rotation around zero (standard rotation matrix math)
void rotate(float radian)
{
float cos = cosf(radian), sin = sinf(radian);
float rx = x * cos + y * sin, ry = -x * sin + y * cos;
x = rx;
y = ry;
}
void translate(int16_t dx, int dy)
{
x += dx;
y += dy;
}
void scale(float f)
{
// We use -f here to counter the flip that happens
// on the y axis when drawing and rotating on screen
x *= f;
y *= -f;
}
};
} // namespace
static void drawLine(OLEDDisplay *d, const Point &p1, const Point &p2)
{
d->drawLine(p1.x, p1.y, p2.x, p2.y);
}
/**
* Given a recent lat/lon return a guess of the heading the user is walking on.
*
@ -1380,31 +1312,6 @@ static float estimatedHeading(double lat, double lon)
return b;
}
static uint16_t getCompassDiam(OLEDDisplay *display)
{
uint16_t diam = 0;
uint16_t offset = 0;
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT)
offset = FONT_HEIGHT_SMALL;
// get the smaller of the 2 dimensions and subtract 20
if (display->getWidth() > (display->getHeight() - offset)) {
diam = display->getHeight() - offset;
// if 2/3 of the other size would be smaller, use that
if (diam > (display->getWidth() * 2 / 3)) {
diam = display->getWidth() * 2 / 3;
}
} else {
diam = display->getWidth();
if (diam > ((display->getHeight() - offset) * 2 / 3)) {
diam = (display->getHeight() - offset) * 2 / 3;
}
}
return diam - 20;
};
/// We will skip one node - the one for us, so we just blindly loop over all
/// nodes
static size_t nodeIndex;
@ -1428,7 +1335,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
drawLine(display, leftArrow, tip);
drawLine(display, rightArrow, tip);
}
/*
// Draw north
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
{
@ -1449,7 +1356,7 @@ static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t com
drawLine(display, N1, N3);
drawLine(display, N2, N4);
drawLine(display, N1, N4);
}
}*/
// Get a string representation of the time passed since something happened
static void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength)
@ -2023,13 +1930,22 @@ int32_t Screen::runOnce()
case Cmd::SHOW_NEXT_FRAME:
handleShowNextFrame();
break;
case Cmd::START_BLUETOOTH_PIN_SCREEN:
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
case Cmd::START_ALERT_FRAME: {
showingBootScreen = false; // this should avoid the edge case where an alert triggers before the boot screen goes away
showingNormalScreen = false;
alertFrames[0] = alertFrame;
#ifdef USE_EINK
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
#endif
setFrameImmediateDraw(alertFrames);
break;
}
case Cmd::START_FIRMWARE_UPDATE_SCREEN:
handleStartFirmwareUpdateScreen();
break;
case Cmd::STOP_BLUETOOTH_PIN_SCREEN:
case Cmd::STOP_ALERT_FRAME:
case Cmd::STOP_BOOT_SCREEN:
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // E-Ink: Explicitly use full-refresh for next frame
setFrames();
@ -2038,12 +1954,6 @@ int32_t Screen::runOnce()
handlePrint(cmd.print_text);
free(cmd.print_text);
break;
case Cmd::START_SHUTDOWN_SCREEN:
handleShutdownScreen();
break;
case Cmd::START_REBOOT_SCREEN:
handleRebootScreen();
break;
default:
LOG_ERROR("Invalid screen cmd\n");
}
@ -2284,17 +2194,6 @@ void Screen::setFrames()
setFastFramerate(); // Draw ASAP
}
void Screen::handleStartBluetoothPinScreen(uint32_t pin)
{
LOG_DEBUG("showing bluetooth screen\n");
showingNormalScreen = false;
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
static FrameCallback frames[] = {drawFrameBluetooth};
snprintf(btPIN, sizeof(btPIN), "%06u", pin);
setFrameImmediateDraw(frames);
}
void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
{
ui->disableAllIndicators();
@ -2302,41 +2201,6 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
setFastFramerate();
}
void Screen::handleShutdownScreen()
{
LOG_DEBUG("showing shutdown screen\n");
showingNormalScreen = false;
#ifdef USE_EINK
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
#endif
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
drawFrameText(display, state, x, y, "Shutting down...");
};
static FrameCallback frames[] = {frame};
setFrameImmediateDraw(frames);
}
void Screen::handleRebootScreen()
{
LOG_DEBUG("showing reboot screen\n");
showingNormalScreen = false;
#ifdef USE_EINK
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
handleSetOn(true); // Power-on to show rebooting screen (PowerFSM should handle?)
#endif
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
drawFrameText(display, state, x, y, "Rebooting...");
};
static FrameCallback frames[] = {frame};
setFrameImmediateDraw(frames);
}
void Screen::handleStartFirmwareUpdateScreen()
{
LOG_DEBUG("showing firmware screen\n");

View File

@ -21,15 +21,13 @@ class Screen
void print(const char *) {}
void doDeepSleep() {}
void forceDisplay(bool forceUiUpdate = false) {}
void startBluetoothPinScreen(uint32_t pin) {}
void stopBluetoothPinScreen() {}
void startRebootScreen() {}
void startShutdownScreen() {}
void startFirmwareUpdateScreen() {}
void increaseBrightness() {}
void decreaseBrightness() {}
void setFunctionSymbal(std::string) {}
void removeFunctionSymbal(std::string) {}
void startAlert(const char *) {}
void endAlert() {}
};
} // namespace graphics
#else
@ -38,6 +36,8 @@ class Screen
#include <OLEDDisplayUi.h>
#include "../configuration.h"
#include "gps/GeoCoord.h"
#include "graphics/ScreenFonts.h"
#ifdef USE_ST7567
#include <ST7567Wire.h>
@ -177,15 +177,29 @@ class Screen : public concurrency::OSThread
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
/// Starts showing the Bluetooth PIN screen.
//
// Switches over to a static frame showing the Bluetooth pairing screen
// with the PIN.
void startBluetoothPinScreen(uint32_t pin)
// generic alert start
void startAlert(FrameCallback _alertFrame)
{
alertFrame = _alertFrame;
ScreenCmd cmd;
cmd.cmd = Cmd::START_ALERT_FRAME;
enqueueCmd(cmd);
}
void startAlert(const char *_alertMessage)
{
startAlert([_alertMessage](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
uint16_t x_offset = display->width() / 2;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, 26 + y, _alertMessage);
});
}
void endAlert()
{
ScreenCmd cmd;
cmd.cmd = Cmd::START_BLUETOOTH_PIN_SCREEN;
cmd.bluetooth_pin = pin;
cmd.cmd = Cmd::STOP_ALERT_FRAME;
enqueueCmd(cmd);
}
@ -196,20 +210,6 @@ class Screen : public concurrency::OSThread
enqueueCmd(cmd);
}
void startShutdownScreen()
{
ScreenCmd cmd;
cmd.cmd = Cmd::START_SHUTDOWN_SCREEN;
enqueueCmd(cmd);
}
void startRebootScreen()
{
ScreenCmd cmd;
cmd.cmd = Cmd::START_REBOOT_SCREEN;
enqueueCmd(cmd);
}
// Function to allow the AccelerometerThread to set the heading if a sensor provides it
// Mutex needed?
void setHeading(long _heading)
@ -228,9 +228,6 @@ class Screen : public concurrency::OSThread
void setFunctionSymbal(std::string sym);
void removeFunctionSymbal(std::string sym);
/// Stops showing the bluetooth PIN screen.
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
/// Stops showing the boot screen.
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
@ -366,6 +363,7 @@ class Screen : public concurrency::OSThread
bool isAUTOOled = false;
private:
FrameCallback alertFrames[1];
struct ScreenCmd {
Cmd cmd;
union {
@ -391,11 +389,8 @@ class Screen : public concurrency::OSThread
void handleOnPress();
void handleShowNextFrame();
void handleShowPrevFrame();
void handleStartBluetoothPinScreen(uint32_t pin);
void handlePrint(const char *text);
void handleStartFirmwareUpdateScreen();
void handleShutdownScreen();
void handleRebootScreen();
/// Rebuilds our list of frames (screens) to default ones.
void setFrames();
@ -433,6 +428,9 @@ class Screen : public concurrency::OSThread
bool digitalWatchFace = true;
#endif
/// callback for current alert frame
FrameCallback alertFrame;
/// Queue of commands to execute in doTask.
TypedQueue<ScreenCmd> cmdQueue;
/// Whether we are using a display
@ -459,4 +457,92 @@ class Screen : public concurrency::OSThread
};
} // namespace graphics
namespace
{
/// A basic 2D point class for drawing
class Point
{
public:
float x, y;
Point(float _x, float _y) : x(_x), y(_y) {}
/// Apply a rotation around zero (standard rotation matrix math)
void rotate(float radian)
{
float cos = cosf(radian), sin = sinf(radian);
float rx = x * cos + y * sin, ry = -x * sin + y * cos;
x = rx;
y = ry;
}
void translate(int16_t dx, int dy)
{
x += dx;
y += dy;
}
void scale(float f)
{
// We use -f here to counter the flip that happens
// on the y axis when drawing and rotating on screen
x *= f;
y *= -f;
}
};
} // namespace
static void drawLine(OLEDDisplay *d, const Point &p1, const Point &p2)
{
d->drawLine(p1.x, p1.y, p2.x, p2.y);
}
static uint16_t getCompassDiam(OLEDDisplay *display)
{
uint16_t diam = 0;
uint16_t offset = 0;
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT)
offset = FONT_HEIGHT_SMALL;
// get the smaller of the 2 dimensions and subtract 20
if (display->getWidth() > (display->getHeight() - offset)) {
diam = display->getHeight() - offset;
// if 2/3 of the other size would be smaller, use that
if (diam > (display->getWidth() * 2 / 3)) {
diam = display->getWidth() * 2 / 3;
}
} else {
diam = display->getWidth();
if (diam > ((display->getHeight() - offset) * 2 / 3)) {
diam = (display->getHeight() - offset) * 2 / 3;
}
}
return diam - 20;
};
// Draw north
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
{
// If north is supposed to be at the top of the compass we want rotation to be +0
if (config.display.compass_north_top)
myHeading = -0;
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f);
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
for (int i = 0; i < 4; i++) {
// North on compass will be negative of heading
rosePoints[i]->rotate(-myHeading);
rosePoints[i]->scale(getCompassDiam(display));
rosePoints[i]->translate(compassX, compassY);
}
drawLine(display, N1, N3);
drawLine(display, N2, N4);
drawLine(display, N1, N4);
}
#endif

View File

@ -28,8 +28,8 @@
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
#define FONT_HEIGHT_LARGE fontHeight(FONT_LARGE)
#define FONT_HEIGHT_SMALL _fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM _fontHeight(FONT_MEDIUM)
#define FONT_HEIGHT_LARGE _fontHeight(FONT_LARGE)

View File

@ -1029,7 +1029,7 @@ void setup()
nodeDB->saveToDisk(SEGMENT_CONFIG);
if (!rIf->reconfigure()) {
LOG_WARN("Reconfigure failed, rebooting\n");
screen->startRebootScreen();
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + 5000;
}
}

View File

@ -180,7 +180,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
if (didFactoryReset) {
LOG_INFO("Rebooting due to factory reset");
screen->startRebootScreen();
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + (5 * 1000);
}

View File

@ -45,6 +45,9 @@ PB_BIND(meshtastic_QueueStatus, meshtastic_QueueStatus, AUTO)
PB_BIND(meshtastic_FromRadio, meshtastic_FromRadio, 2)
PB_BIND(meshtastic_FileInfo, meshtastic_FileInfo, AUTO)
PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)

View File

@ -711,6 +711,14 @@ typedef struct _meshtastic_QueueStatus {
uint32_t mesh_packet_id;
} meshtastic_QueueStatus;
/* Individual File info for the device */
typedef struct _meshtastic_FileInfo {
/* The fully qualified path of the file */
char file_name[228];
/* The size of the file in bytes */
uint32_t size_bytes;
} meshtastic_FileInfo;
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
/* Compressed message payload */
typedef struct _meshtastic_Compressed {
@ -815,6 +823,8 @@ typedef struct _meshtastic_FromRadio {
meshtastic_DeviceMetadata metadata;
/* MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) */
meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
/* File system manifest messages */
meshtastic_FileInfo fileInfo;
};
} meshtastic_FromRadio;
@ -958,6 +968,7 @@ extern "C" {
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
@ -985,6 +996,7 @@ extern "C" {
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_FileInfo_init_default {"", 0}
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
@ -1008,6 +1020,7 @@ extern "C" {
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_FileInfo_init_zero {"", 0}
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
@ -1110,6 +1123,8 @@ extern "C" {
#define meshtastic_QueueStatus_free_tag 2
#define meshtastic_QueueStatus_maxlen_tag 3
#define meshtastic_QueueStatus_mesh_packet_id_tag 4
#define meshtastic_FileInfo_file_name_tag 1
#define meshtastic_FileInfo_size_bytes_tag 2
#define meshtastic_Compressed_portnum_tag 1
#define meshtastic_Compressed_data_tag 2
#define meshtastic_Neighbor_node_id_tag 1
@ -1144,6 +1159,7 @@ extern "C" {
#define meshtastic_FromRadio_xmodemPacket_tag 12
#define meshtastic_FromRadio_metadata_tag 13
#define meshtastic_FromRadio_mqttClientProxyMessage_tag 14
#define meshtastic_FromRadio_fileInfo_tag 15
#define meshtastic_ToRadio_packet_tag 1
#define meshtastic_ToRadio_want_config_id_tag 3
#define meshtastic_ToRadio_disconnect_tag 4
@ -1321,7 +1337,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,fileInfo,fileInfo), 15)
#define meshtastic_FromRadio_CALLBACK NULL
#define meshtastic_FromRadio_DEFAULT NULL
#define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
@ -1335,6 +1352,13 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttC
#define meshtastic_FromRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
#define meshtastic_FromRadio_payload_variant_metadata_MSGTYPE meshtastic_DeviceMetadata
#define meshtastic_FromRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
#define meshtastic_FromRadio_payload_variant_fileInfo_MSGTYPE meshtastic_FileInfo
#define meshtastic_FileInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, file_name, 1) \
X(a, STATIC, SINGULAR, UINT32, size_bytes, 2)
#define meshtastic_FileInfo_CALLBACK NULL
#define meshtastic_FileInfo_DEFAULT NULL
#define meshtastic_ToRadio_FIELDLIST(X, a) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \
@ -1434,6 +1458,7 @@ extern const pb_msgdesc_t meshtastic_MyNodeInfo_msg;
extern const pb_msgdesc_t meshtastic_LogRecord_msg;
extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
extern const pb_msgdesc_t meshtastic_FromRadio_msg;
extern const pb_msgdesc_t meshtastic_FileInfo_msg;
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
extern const pb_msgdesc_t meshtastic_Compressed_msg;
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
@ -1459,6 +1484,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_LogRecord_fields &meshtastic_LogRecord_msg
#define meshtastic_QueueStatus_fields &meshtastic_QueueStatus_msg
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
#define meshtastic_FileInfo_fields &meshtastic_FileInfo_msg
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
@ -1478,6 +1504,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_Compressed_size 243
#define meshtastic_Data_size 270
#define meshtastic_DeviceMetadata_size 46
#define meshtastic_FileInfo_size 236
#define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0
#define meshtastic_LogRecord_size 81

View File

@ -137,7 +137,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
if (BleOta::getOtaAppVersion().isEmpty()) {
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
screen->startRebootScreen();
screen->startAlert("Rebooting...");
} else {
screen->startFirmwareUpdateScreen();
BleOta::switchToOtaApp();
@ -145,7 +145,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
}
#else
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds\n", s);
screen->startRebootScreen();
screen->startAlert("Rebooting...");
#endif
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
@ -815,7 +815,7 @@ void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t ch
void AdminModule::reboot(int32_t seconds)
{
LOG_INFO("Rebooting in %d seconds\n", seconds);
screen->startRebootScreen();
screen->startAlert("Rebooting...");
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
}

View File

@ -597,14 +597,14 @@ int32_t CannedMessageModule::runOnce()
// handle fn+s for shutdown
case 0x9b:
if (screen)
screen->startShutdownScreen();
screen->startAlert("Shutting down...");
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
break;
// and fn+r for reboot
case 0x90:
if (screen)
screen->startRebootScreen();
screen->startAlert("Rebooting...");
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
break;

View File

@ -188,7 +188,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (lastMeasurementPacket == nullptr) {
// If there's no valid packet, display "Environment"
display->drawString(x, y, "Environment");
display->drawString(x, y += fontHeight(FONT_SMALL), "No measurement");
display->drawString(x, y += _fontHeight(FONT_SMALL), "No measurement");
return;
}
@ -213,31 +213,31 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
}
// Continue with the remaining details
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Temp/Hum: " + last_temp + " / " +
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
}
if (lastMeasurement.variant.environment_metrics.voltage != 0) {
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " +
String(lastMeasurement.variant.environment_metrics.current, 0) + "mA");
}
if (lastMeasurement.variant.environment_metrics.iaq != 0) {
display->drawString(x, y += fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq));
display->drawString(x, y += _fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq));
}
if (lastMeasurement.variant.environment_metrics.distance != 0)
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Water Level: " + String(lastMeasurement.variant.environment_metrics.distance, 0) + "mm");
if (lastMeasurement.variant.environment_metrics.weight != 0)
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
}

View File

@ -108,7 +108,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s
display->drawString(x, y, "Power Telemetry");
if (lastMeasurementPacket == nullptr) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement");
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "No measurement");
return;
}
@ -120,22 +120,22 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s
auto &p = lastMeasurementPacket->decoded;
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "Measurement Error");
LOG_ERROR("Unable to decode last packet");
return;
}
display->setFont(FONT_SMALL);
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
display->drawString(x, y += fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
display->drawString(x, y += _fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
if (lastMeasurement.variant.power_metrics.ch1_voltage != 0) {
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Ch 1 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch1_voltage, 0) + "V / " +
String(lastMeasurement.variant.power_metrics.ch1_current, 0) + "mA");
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Ch 2 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch2_voltage, 0) + "V / " +
String(lastMeasurement.variant.power_metrics.ch2_current, 0) + "mA");
display->drawString(x, y += fontHeight(FONT_SMALL),
display->drawString(x, y += _fontHeight(FONT_SMALL),
"Ch 3 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch3_voltage, 0) + "V / " +
String(lastMeasurement.variant.power_metrics.ch3_current, 0) + "mA");
}

View File

@ -82,7 +82,33 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
LOG_INFO("*** Enter passkey %d on the peer side ***\n", passkey);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
screen->startBluetoothPinScreen(passkey);
#if HAS_SCREEN
screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
char btPIN[16] = "888888";
snprintf(btPIN, sizeof(btPIN), "%06u", passkey);
int x_offset = display->width() / 2;
int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
display->setFont(FONT_SMALL);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM - 4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
display->drawString(x_offset + x, y_offset + y, "Enter this code");
display->setFont(FONT_LARGE);
String displayPin(btPIN);
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
display->drawString(x_offset + x, y_offset + y, pin);
display->setFont(FONT_SMALL);
String deviceName = "Name: ";
deviceName.concat(getDeviceName());
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
display->drawString(x_offset + x, y_offset + y, deviceName);
});
#endif
passkeyShowing = true;
return passkey;
@ -94,7 +120,7 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
if (passkeyShowing) {
passkeyShowing = false;
screen->stopBluetoothPinScreen();
screen->endAlert();
}
}

View File

@ -290,7 +290,31 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke
{
LOG_INFO("BLE pairing process started with passkey %.3s %.3s\n", passkey, passkey + 3);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
screen->startBluetoothPinScreen(configuredPasskey);
screen->startAlert([](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
char btPIN[16] = "888888";
snprintf(btPIN, sizeof(btPIN), "%06u", configuredPasskey);
int x_offset = display->width() / 2;
int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
display->setFont(FONT_SMALL);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM - 4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
display->drawString(x_offset + x, y_offset + y, "Enter this code");
display->setFont(FONT_LARGE);
String displayPin(btPIN);
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
display->drawString(x_offset + x, y_offset + y, pin);
display->setFont(FONT_SMALL);
String deviceName = "Name: ";
deviceName.concat(getDeviceName());
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
display->drawString(x_offset + x, y_offset + y, deviceName);
});
if (match_request) {
uint32_t start_time = millis();
while (millis() < start_time + 30000) {
@ -307,7 +331,7 @@ void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_statu
LOG_INFO("BLE pairing success\n");
else
LOG_INFO("BLE pairing failed\n");
screen->stopBluetoothPinScreen();
screen->endAlert();
}
void NRF52Bluetooth::sendLog(const char *logMessage)

View File

@ -149,13 +149,43 @@ void nrf52Loop()
checkSDEvents();
}
#ifdef USE_SEMIHOSTING
#include <SemihostingStream.h>
/**
* Note: this variable is in BSS and therfore false by default. But the gdbinit
* file will be installing a temporary breakpoint that changes wantSemihost to true.
*/
bool wantSemihost;
/**
* Turn on semihosting if the ICE debugger wants it.
*/
void nrf52InitSemiHosting()
{
if (wantSemihost) {
static SemihostingStream semiStream;
// We must dynamically alloc because the constructor does semihost operations which
// would crash any load not talking to a debugger
semiStream.open();
semiStream.println("Semihosting starts!");
// Redirect our serial output to instead go via the ICE port
console->setDestination(&semiStream);
}
}
#endif
void nrf52Setup()
{
auto why = NRF_POWER->RESETREAS;
uint32_t why = NRF_POWER->RESETREAS;
// per
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
LOG_DEBUG("Reset reason: 0x%x\n", why);
#ifdef USE_SEMIHOSTING
nrf52InitSemiHosting();
#endif
// Per
// https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
// This is the recommended setting for Monitor Mode Debugging

View File

@ -38,7 +38,7 @@ void powerCommandsCheck()
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
if (shutdownAtMsec) {
screen->startShutdownScreen();
screen->startAlert("Shutting down...");
}
#endif

View File

@ -20,6 +20,7 @@ lib_deps =
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
;upload_protocol = jlink
@ -27,26 +28,92 @@ debug_tool = jlink
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
; programming time is about the same as the bootloader version.
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
[env:rak4631_dap]
[env:rak4631_dbg]
extends = env:rak4631
board_level = extra
; pyocd pack --i nrf52840
; if the builtin version of openocd has a buggy version of semihosting, so use the external version
; platform_packages = platformio/tool-openocd@^3.1200.0
build_flags =
${env:rak4631.build_flags}
-D USE_SEMIHOSTING
lib_deps =
${env:rak4631.lib_deps}
https://github.com/geeksville/Armduino-Semihosting.git#35b538fdf208c3530c1434cd099a08e486672ee4
; NOTE: the pyocd support for semihosting is buggy. So I switched to using the builtin platformio support for the stlink adapter which worked much better.
; However the built in openocd version in platformio has buggy support for TCP to semihosting.
;
; So I'm now trying the external openocd - but the openocd scripts for nrf52.cfg assume you are using a DAP adapter not an STLINK adapter.
; In theory I could change those scripts. But for now I'm trying going back to a DAP adapter but with the external openocd.
upload_protocol = stlink
; eventually use platformio/tool-pyocd@^2.3600.0 instad
upload_protocol = custom
upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
;upload_protocol = custom
;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
; We want the initial breakpoint at setup() instead of main(). Also we want to enable semihosting at that point so instead of
; debug_init_break = tbreak setup
; we just turn off the platformio tbreak and do it in .gdbinit (where we have more flexibility for scripting)
; also we use a permanent breakpoint so it gets reused each time we restart the debugging session?
debug_init_break = tbreak setup
; Note: add "monitor arm semihosting_redirect tcp 4444 all" if you want the stdout from the device to go to that port number instead
; (for use by meshtastic command line)
; monitor arm semihosting disable
; monitor debug_level 3
;
; IMPORTANT: fileio must be disabled before using port 5555 - openocd ver 0.12 has a bug where if enabled it never properly parses the special :tt name
; for stdio access.
; monitor arm semihosting_redirect tcp 5555 stdio
; Also note: it is _impossible_ to do non blocking reads on the semihost console port (an oversight when ARM specified the semihost API).
; So we'll neve be able to general purpose bi-directional communication with the device over semihosting.
debug_extra_cmds =
echo Running .gdbinit script
monitor arm semihosting enable
monitor arm semihosting_fileio enable
monitor arm semihosting_redirect disable
commands 1
echo Breakpoint at setup() has semihosting console, connect to it with "telnet localhost 5555"
set wantSemihost = true
end
; Only reprogram the board if the code has changed
debug_load_mode = modified
;debug_load_mode = manual
debug_tool = custom
debug_tool = stlink
;debug_tool = custom
; debug_server =
; openocd
; -f
; /usr/local/share/openocd/scripts/interface/stlink.cfg
; -f
; /usr/local/share/openocd/scripts/target/nrf52.cfg
; $PLATFORMIO_CORE_DIR/packages/tool-openocd/openocd/scripts/interface/cmsis-dap.cfg
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
; programming time is about the same as the bootloader version.
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...)
debug_server =
pyocd
gdbserver
-t
nrf52840
--elf
${platformio.build_dir}/${this.__env__}/firmware.elf
;debug_server =
; pyocd
; gdbserver
; -j
; ${platformio.workspace_dir}/..
; -t
; nrf52840
; --semihosting
; --elf
; ${platformio.build_dir}/${this.__env__}/firmware.elf
; If you want to debug the semihosting support you can turn on extra logging in pyocd with
; -L
; pyocd.debug.semihost.trace=debug
; The following is not needed because it automatically tries do this
;debug_server_ready_pattern = -.*GDB server started on port \d+.*
;debug_port = localhost:3333

View File

@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 3
build = 14
build = 15