Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new NRF52 board, MeshLink #5736

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions boards/meshlink.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
ponzano marked this conversation as resolved.
Show resolved Hide resolved
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x00B3"],
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "MeshLink",
"mcu": "nrf52840",
"variant": "meshlink",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"name": "MeshLink",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.loraitalia.it",
"vendor": "LoraItalia"
}
9 changes: 9 additions & 0 deletions src/graphics/EInkDisplay2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ bool EInkDisplay::connect()
adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(MESHLINK)
{
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);

adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(RAK4630) || defined(MAKERPYTHON)
{
if (eink_found) {
Expand Down
2 changes: 2 additions & 0 deletions src/mesh/generated/meshtastic/mesh.pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ typedef enum _meshtastic_HardwareModel {
/* Mesh-Tab, esp32 based
https://github.com/valzzu/Mesh-Tab */
meshtastic_HardwareModel_MESH_TAB = 86,
/*MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog*/
meshtastic_HardwareModel_MESHLINK = 87,
ponzano marked this conversation as resolved.
Show resolved Hide resolved
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
Expand Down
8 changes: 4 additions & 4 deletions src/modules/SerialModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;

#if defined(TTGO_T_ECHO) || defined(CANARYONE)
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
Expand Down Expand Up @@ -158,7 +158,7 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE)
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
Expand Down Expand Up @@ -214,7 +214,7 @@ int32_t SerialModule::runOnce()
}
}

#if !defined(TTGO_T_ECHO) && !defined(CANARYONE)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();

Expand Down Expand Up @@ -416,7 +416,7 @@ uint32_t SerialModule::getBaudRate()
*/
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/platform/nrf52/architecture.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#elif defined(HELTEC_T114)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T114
#elif defined(MESHLINK)
#define HW_VENDOR meshtastic_HardwareModel_MESHLINK
#else
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/platform/nrf52/main-nrf52.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,11 @@ void cpuDeepSleep(uint32_t msecToWake)
nrf_gpio_cfg_default(WB_I2C1_SDA);
#endif
#endif
#ifdef MESHLINK
#ifdef PIN_3V3_EN
digitalWrite(PIN_3V3_EN, LOW);
#endif
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason behind this? i am asking because maybe we already have a way to accomodate this without the macro guards.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the PIN_3V3_EN definition for the watchdog enable pin, because i needed a pin that would have been turned off automatically by the firmware when we put the cpu to sleep with button longpress. Otherwise, the watchdog would remain enabled without being reset by the status led blink (because the cpu is sleeping). I could rename it to WD_EN and add a specific digitalwrite for my board in main-nrf52.cpp and src/sleep.cpp. I just noticed that there could also be an edge case scenario problem when using repeater role as 3v3_en pin would be disabled on startup
https://github.com/ponzano/MeshLink/blob/c82f23ed2aa81cb09ba4e57e281347da74e02cb0/src/main.cpp#L649C5-L649C121


#ifdef HELTEC_MESH_NODE_T114
nrf_gpio_cfg_default(PIN_GPS_PPS);
Expand Down
128 changes: 128 additions & 0 deletions variants/meshlink/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921
ponzano marked this conversation as resolved.
Show resolved Hide resolved
[env:meshlink]
extends = nrf52840_base
board = meshlink
;board_check = true
build_flags = ${nrf52840_base.build_flags} -I variants/meshlink -D MESHLINK
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-D EINK_DISPLAY_MODEL=GxEPD2_213_B74
-D EINK_WIDTH=250
-D EINK_HEIGHT=122
-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-D EINK_LIMIT_FASTREFRESH=5 ; How many consecutive fast-refreshes are permitted
-D EINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates
-D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
-D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
-D EINK_HASQUIRK_VICIOUSFASTREFRESH ; Identify that pixels drawn by fast-refresh are harder to clear


build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a
melopero/Melopero RV3028@^1.1.0
ponzano marked this conversation as resolved.
Show resolved Hide resolved
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
beegee-tokyo/RAKwireless RAK12034@^1.0.0
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

; 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:meshlink_dbg]
ponzano marked this conversation as resolved.
Show resolved Hide resolved
extends = env:meshlink
board_level = extra

; 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:meshlink.build_flags}
-D USE_SEMIHOSTING

lib_deps =
${env:meshlink.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

; 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
set useSoftDevice = false
end


; Only reprogram the board if the code has changed
debug_load_mode = modified
;debug_load_mode = manual
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
; -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
56 changes: 56 additions & 0 deletions variants/meshlink/variant.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"

const uint32_t g_ADigitalPinMap[] = {
// P0
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,

// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};

void initVariant()
{
// LED1 & LED2
//pinMode(PIN_LED1, OUTPUT);
//ledOff(PIN_LED1);

//pinMode(PIN_LED2, OUTPUT);
//ledOff(PIN_LED2);
//pinMode(PIN_LED1, OUTPUT);
//digitalWrite(PIN_LED1, LOW);
pinMode(24,OUTPUT);
digitalWrite(24, HIGH);
//pinMode(25,OUTPUT);
//digitalWrite(25, HIGH);

// 3V3 Power Rail
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
//pinMode(PIN_GPS_EN, OUTPUT);
//digitalWrite(PIN_GPS_EN, HIGH);
//pinMode(GPS_TX_PIN, OUTPUT);
//pinMode(GPS_RX_PIN, INPUT_PULLUP);

}
Loading
Loading