Skip to content

Commit 7eb7727

Browse files
ponzanothebenterncaveman99vidplace7
authored
Add support for new NRF52 board, MeshLink (#5736)
* Add support for MeshLink * Updated, enabled watchdog and added button definition * added eink variant and removed some compile errors * Small board json file edit * Finally got trunk working (somehow?), this is just cleanup with trunk fmt * Various improvements and cleanup. Removed the use of PIN_3V3_En and defined a specific WD_EN pin instead for better clarity. Will do a bit more testing asap to make sure everything still works as intended :) * Enable on-board QSPI Flash * run trunk fmt with clang-format --------- Co-authored-by: Ben Meadors <benmmeadors@gmail.com> Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com> Co-authored-by: Austin <vidplace7@gmail.com>
1 parent 7648391 commit 7eb7727

File tree

13 files changed

+488
-7
lines changed

13 files changed

+488
-7
lines changed

boards/meshlink.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"build": {
3+
"arduino": {
4+
"ldscript": "nrf52840_s140_v6.ld"
5+
},
6+
"core": "nRF5",
7+
"cpu": "cortex-m4",
8+
"extra_flags": "-DMESHLINK -DNRF52840_XXAA",
9+
"f_cpu": "64000000L",
10+
"hwids": [
11+
["0x239A", "0x00B3"],
12+
["0x239A", "0x8029"],
13+
["0x239A", "0x0029"],
14+
["0x239A", "0x002A"],
15+
["0x239A", "0x802A"]
16+
],
17+
"usb_product": "MeshLink",
18+
"mcu": "nrf52840",
19+
"variant": "meshlink",
20+
"bsp": {
21+
"name": "adafruit"
22+
},
23+
"softdevice": {
24+
"sd_flags": "-DS140",
25+
"sd_name": "s140",
26+
"sd_version": "6.1.1",
27+
"sd_fwid": "0x00B6"
28+
},
29+
"bootloader": {
30+
"settings_addr": "0xFF000"
31+
}
32+
},
33+
"connectivity": ["bluetooth"],
34+
"debug": {
35+
"jlink_device": "nRF52840_xxAA",
36+
"svd_path": "nrf52840.svd"
37+
},
38+
"frameworks": ["arduino"],
39+
"name": "MeshLink",
40+
"upload": {
41+
"maximum_ram_size": 248832,
42+
"maximum_size": 815104,
43+
"speed": 115200,
44+
"protocol": "nrfutil",
45+
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
46+
"use_1200bps_touch": true,
47+
"require_upload_port": true,
48+
"wait_for_upload_port": true
49+
},
50+
"url": "https://www.loraitalia.it",
51+
"vendor": "LoraItalia"
52+
}

src/graphics/EInkDisplay2.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ bool EInkDisplay::connect()
140140
adafruitDisplay->setRotation(3);
141141
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
142142
}
143+
#elif defined(MESHLINK)
144+
{
145+
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
146+
147+
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
148+
adafruitDisplay->init();
149+
adafruitDisplay->setRotation(3);
150+
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
151+
}
143152
#elif defined(RAK4630) || defined(MAKERPYTHON)
144153
{
145154
if (eink_found) {

src/mesh/generated/meshtastic/mesh.pb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1775,4 +1775,4 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
17751775
} /* extern "C" */
17761776
#endif
17771777

1778-
#endif
1778+
#endif

src/modules/SerialModule.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
SerialModule *serialModule;
6161
SerialModuleRadio *serialModuleRadio;
6262

63-
#if defined(TTGO_T_ECHO) || defined(CANARYONE)
63+
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK)
6464
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
6565
static Print *serialPrint = &Serial;
6666
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
@@ -158,7 +158,7 @@ int32_t SerialModule::runOnce()
158158
Serial.begin(baud);
159159
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
160160
}
161-
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE)
161+
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
162162
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
163163
#ifdef ARCH_RP2040
164164
Serial2.setFIFOSize(RX_BUFFER);
@@ -214,7 +214,7 @@ int32_t SerialModule::runOnce()
214214
}
215215
}
216216

217-
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE)
217+
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
218218
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
219219
processWXSerial();
220220

@@ -416,7 +416,7 @@ uint32_t SerialModule::getBaudRate()
416416
*/
417417
void SerialModule::processWXSerial()
418418
{
419-
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6)
419+
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK)
420420
static unsigned int lastAveraged = 0;
421421
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
422422
static double dir_sum_sin = 0;

src/platform/nrf52/architecture.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,4 @@
127127
#if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA)
128128
// No serial ports on this board - ONLY use segger in memory console
129129
#define USE_SEGGER
130-
#endif
130+
#endif

src/platform/nrf52/main-nrf52.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ void cpuDeepSleep(uint32_t msecToWake)
304304
nrf_gpio_cfg_default(WB_I2C1_SDA);
305305
#endif
306306
#endif
307+
#ifdef MESHLINK
308+
#ifdef PIN_WD_EN
309+
digitalWrite(PIN_WD_EN, LOW);
310+
#endif
311+
#endif
307312

308313
#ifdef HELTEC_MESH_NODE_T114
309314
nrf_gpio_cfg_default(PIN_GPS_PPS);

src/sleep.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
245245
#ifdef PIN_3V3_EN
246246
digitalWrite(PIN_3V3_EN, LOW);
247247
#endif
248+
#ifdef PIN_WD_EN
249+
digitalWrite(PIN_WD_EN, LOW);
250+
#endif
248251
#endif
249252
ledBlink.set(false);
250253

@@ -530,4 +533,4 @@ void enableLoraInterrupt()
530533
}
531534
#endif
532535
}
533-
#endif
536+
#endif

variants/meshlink/platformio.ini

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; 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
2+
; https://www.loraitalia.it
3+
; firmware for boards with or without oled display
4+
[env:meshlink]
5+
extends = nrf52840_base
6+
board = meshlink
7+
;board_check = true
8+
build_flags = ${nrf52840_base.build_flags} -I variants/meshlink -D MESHLINK
9+
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
10+
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
11+
-D EINK_DISPLAY_MODEL=GxEPD2_213_B74
12+
-D EINK_WIDTH=250
13+
-D EINK_HEIGHT=122
14+
-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
15+
-D EINK_LIMIT_FASTREFRESH=5 ; How many consecutive fast-refreshes are permitted
16+
-D EINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates
17+
-D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
18+
-D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
19+
-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
20+
-D EINK_HASQUIRK_VICIOUSFASTREFRESH ; Identify that pixels drawn by fast-refresh are harder to clear
21+
22+
23+
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink>
24+
lib_deps =
25+
${nrf52840_base.lib_deps}
26+
https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a
27+
debug_tool = jlink
28+
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
29+
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
30+
;upload_protocol = jlink

variants/meshlink/variant.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "variant.h"
2+
#include "nrf.h"
3+
#include "wiring_constants.h"
4+
#include "wiring_digital.h"
5+
6+
const uint32_t g_ADigitalPinMap[] = {
7+
// P0
8+
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,
9+
10+
// P1
11+
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
12+
13+
void initVariant()
14+
{
15+
pinMode(PIN_LED1, OUTPUT);
16+
digitalWrite(PIN_LED1, HIGH); // turn off the white led while booting
17+
// otherwise it will stay lit for several seconds (could be annoying)
18+
19+
#ifdef PIN_WD_EN
20+
pinMode(PIN_WD_EN, OUTPUT);
21+
digitalWrite(PIN_WD_EN, HIGH); // Enable the Watchdog at boot
22+
#endif
23+
}

variants/meshlink/variant.h

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#ifndef _VARIANT_MESHLINK_
2+
#define _VARIANT_MESHLINK_
3+
#ifndef MESHLINK
4+
#define MESHLINK
5+
#endif
6+
/** Master clock frequency */
7+
#define VARIANT_MCK (64000000ul)
8+
9+
// #define USE_LFXO // Board uses 32khz crystal for LF
10+
#define USE_LFRC // Board uses RC for LF
11+
12+
/*----------------------------------------------------------------------------
13+
* Headers
14+
*----------------------------------------------------------------------------*/
15+
16+
#include "WVariant.h"
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif // __cplusplus
21+
22+
// Number of pins defined in PinDescription array
23+
#define PINS_COUNT (48)
24+
#define NUM_DIGITAL_PINS (48)
25+
#define NUM_ANALOG_INPUTS (2)
26+
#define NUM_ANALOG_OUTPUTS (0)
27+
28+
#define BUTTON_PIN (-1) // If defined, this will be used for user button presses,
29+
#define BUTTON_NEED_PULLUP
30+
31+
// LEDs
32+
#define PIN_LED1 (24) // Built in white led for status
33+
#define LED_BLUE PIN_LED1
34+
#define LED_BUILTIN PIN_LED1
35+
36+
#define LED_STATE_ON 0 // State when LED is litted
37+
#define LED_INVERTED 1
38+
39+
// Testing USB detection
40+
// #define NRF_APM
41+
42+
/*
43+
* Analog pins
44+
*/
45+
#define PIN_A1 (3) // P0.03/AIN1
46+
#define ADC_RESOLUTION 14
47+
48+
// Other pins
49+
// #define PIN_AREF (2)
50+
// static const uint8_t AREF = PIN_AREF;
51+
52+
/*
53+
* Serial interfaces
54+
*/
55+
#define PIN_SERIAL1_RX (32 + 8)
56+
#define PIN_SERIAL1_TX (7)
57+
58+
/*
59+
* SPI Interfaces
60+
*/
61+
#define SPI_INTERFACES_COUNT 2
62+
63+
#define PIN_SPI_MISO (8)
64+
#define PIN_SPI_MOSI (32 + 9)
65+
#define PIN_SPI_SCK (11)
66+
67+
#define PIN_SPI1_MISO (23)
68+
#define PIN_SPI1_MOSI (21)
69+
#define PIN_SPI1_SCK (19)
70+
71+
static const uint8_t SS = 12;
72+
static const uint8_t MOSI = PIN_SPI_MOSI;
73+
static const uint8_t MISO = PIN_SPI_MISO;
74+
static const uint8_t SCK = PIN_SPI_SCK;
75+
76+
/*
77+
* eink display pins
78+
*/
79+
// #define USE_EINK
80+
81+
#define PIN_EINK_CS (15)
82+
#define PIN_EINK_BUSY (16)
83+
#define PIN_EINK_DC (14)
84+
#define PIN_EINK_RES (17)
85+
#define PIN_EINK_SCLK (19)
86+
#define PIN_EINK_MOSI (21) // also called SDI
87+
88+
/*
89+
* Wire Interfaces
90+
*/
91+
#define WIRE_INTERFACES_COUNT 1
92+
93+
#define PIN_WIRE_SDA (1)
94+
#define PIN_WIRE_SCL (27)
95+
96+
// QSPI Pins
97+
#define PIN_QSPI_SCK 19
98+
#define PIN_QSPI_CS 22
99+
#define PIN_QSPI_IO0 21
100+
#define PIN_QSPI_IO1 23
101+
#define PIN_QSPI_IO2 32
102+
#define PIN_QSPI_IO3 20
103+
104+
// On-board QSPI Flash
105+
#define EXTERNAL_FLASH_DEVICES W25Q16JVUXIQ
106+
#define EXTERNAL_FLASH_USE_QSPI
107+
108+
#define USE_SX1262
109+
#define SX126X_CS (12)
110+
#define SX126X_DIO1 (32 + 1)
111+
#define SX126X_BUSY (32 + 3)
112+
#define SX126X_RESET (6)
113+
// #define SX126X_RXEN (13)
114+
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
115+
#define SX126X_DIO2_AS_RF_SWITCH
116+
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
117+
118+
// pin 25 is used to enable or disable the watchdog. This pin has to be disabled when cpu is put to sleep
119+
// otherwise the timer will expire and wd will reboot the cpu
120+
#define PIN_WD_EN (25)
121+
122+
#define PIN_GPS_PPS (26) // Pulse per second input from the GPS
123+
124+
#define GPS_TX_PIN PIN_SERIAL1_RX // This is for bits going TOWARDS the CPU
125+
#define GPS_RX_PIN PIN_SERIAL1_TX // This is for bits going TOWARDS the GPS
126+
127+
// #define GPS_THREAD_INTERVAL 50
128+
129+
// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
130+
#define PIN_GPS_EN (0)
131+
#define GPS_EN_ACTIVE LOW
132+
133+
#define PIN_BUZZER (31) // P0.31/AIN7
134+
135+
// Battery
136+
// The battery sense is hooked to pin A0 (2)
137+
#define BATTERY_PIN (2)
138+
// and has 12 bit resolution
139+
#define BATTERY_SENSE_RESOLUTION_BITS 12
140+
#define BATTERY_SENSE_RESOLUTION 4096.0
141+
#undef AREF_VOLTAGE
142+
#define AREF_VOLTAGE 3.0
143+
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
144+
#define ADC_MULTIPLIER 1.42 // fine tuning of voltage
145+
146+
#ifdef __cplusplus
147+
}
148+
#endif
149+
150+
/*----------------------------------------------------------------------------
151+
* Arduino objects - C++ only
152+
*----------------------------------------------------------------------------*/
153+
#endif

0 commit comments

Comments
 (0)