diff --git a/boards/ThinkNode-M3.json b/boards/ThinkNode-M3.json
new file mode 100644
index 000000000..ff21e046a
--- /dev/null
+++ b/boards/ThinkNode-M3.json
@@ -0,0 +1,53 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "nrf52840_s140_v6.ld"
+ },
+ "core": "nRF5",
+ "cpu": "cortex-m4",
+ "extra_flags": "-DNRF52840_XXAA",
+ "f_cpu": "64000000L",
+ "hwids": [
+ ["0x239A", "0x4405"],
+ ["0x239A", "0x0029"],
+ ["0x239A", "0x002A"]
+ ],
+ "usb_product": "elecrow_eink",
+ "mcu": "nrf52840",
+ "variant": "ELECROW-ThinkNode-M3",
+ "variants_dir": "variants",
+ "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",
+ "onboard_tools": ["jlink"],
+ "svd_path": "nrf52840.svd",
+ "openocd_target": "nrf52840-mdk-rs"
+ },
+ "frameworks": ["arduino"],
+ "name": "elecrow nrf",
+ "upload": {
+ "maximum_ram_size": 248832,
+ "maximum_size": 815104,
+ "speed": 115200,
+ "protocol": "nrfutil",
+ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
+ "use_1200bps_touch": true,
+ "require_upload_port": true,
+ "wait_for_upload_port": true
+ },
+ "url": "",
+ "vendor": "ELECROW"
+}
diff --git a/src/configuration.h b/src/configuration.h
index 8ec3b2211..d37269995 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -396,6 +396,13 @@ along with this program. If not, see .
#define HAS_RGB_LED
#endif
+#ifndef LED_STATE_OFF
+#define LED_STATE_OFF 0
+#endif
+#ifndef LED_STATE_ON
+#define LED_STATE_ON 1
+#endif
+
// default mapping of pins
#if defined(PIN_BUTTON2) && !defined(CANCEL_BUTTON_PIN)
#define ALT_BUTTON_PIN PIN_BUTTON2
diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp
index e477574dd..9e4401e05 100644
--- a/src/modules/Modules.cpp
+++ b/src/modules/Modules.cpp
@@ -13,6 +13,8 @@
#include "input/TrackballInterruptImpl1.h"
#endif
+#include "modules/StatusLEDModule.h"
+
#if !MESHTASTIC_EXCLUDE_I2C
#include "input/cardKbI2cImpl.h"
#endif
@@ -119,6 +121,10 @@ void setupModules()
buzzerFeedbackThread = new BuzzerFeedbackThread();
}
#endif
+#if defined(LED_CHARGE) || defined(LED_PAIRING)
+ statusLEDModule = new StatusLEDModule();
+#endif
+
#if !MESHTASTIC_EXCLUDE_ADMIN
adminModule = new AdminModule();
#endif
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index 575e9fa96..d04daf594 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -64,7 +64,7 @@ SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
- defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE)
+ defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || defined(ELECROW_ThinkNode_M3)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial")
{
api_type = TYPE_SERIAL;
@@ -204,7 +204,7 @@ int32_t SerialModule::runOnce()
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
- !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
+ !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@@ -261,7 +261,7 @@ int32_t SerialModule::runOnce()
}
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
- !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
+ !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@@ -536,7 +536,8 @@ ParsedLine parseLine(const char *line)
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
- !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) && !defined(ARCH_STM32WL)
+ !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \
+ !defined(ARCH_STM32WL)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;
diff --git a/src/modules/StatusLEDModule.cpp b/src/modules/StatusLEDModule.cpp
new file mode 100644
index 000000000..fc9ed310e
--- /dev/null
+++ b/src/modules/StatusLEDModule.cpp
@@ -0,0 +1,94 @@
+#include "StatusLEDModule.h"
+#include "MeshService.h"
+#include "configuration.h"
+#include
+
+/*
+StatusLEDModule manages the device's status LEDs, updating their states based on power and Bluetooth status.
+It reflects charging, charged, discharging, and Bluetooth connection states using the appropriate LEDs.
+*/
+StatusLEDModule *statusLEDModule;
+
+StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
+{
+ bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
+ powerStatusObserver.observe(&powerStatus->onNewStatus);
+}
+
+int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
+{
+ switch (arg->getStatusType()) {
+ case STATUS_TYPE_POWER: {
+ meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
+ if (powerStatus->getHasUSB()) {
+ power_state = charging;
+ if (powerStatus->getBatteryChargePercent() >= 100) {
+ power_state = charged;
+ }
+ } else {
+ power_state = discharging;
+ }
+ break;
+ }
+ case STATUS_TYPE_BLUETOOTH: {
+ meshtastic::BluetoothStatus *bluetoothStatus = (meshtastic::BluetoothStatus *)arg;
+ switch (bluetoothStatus->getConnectionState()) {
+ case meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED: {
+ ble_state = unpaired;
+ PAIRING_LED_starttime = millis();
+ break;
+ }
+ case meshtastic::BluetoothStatus::ConnectionState::PAIRING: {
+ ble_state = pairing;
+ PAIRING_LED_starttime = millis();
+ break;
+ }
+ case meshtastic::BluetoothStatus::ConnectionState::CONNECTED: {
+ ble_state = connected;
+ PAIRING_LED_starttime = millis();
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+ return 0;
+};
+
+int32_t StatusLEDModule::runOnce()
+{
+
+ if (power_state == charging) {
+ CHARGE_LED_state = !CHARGE_LED_state;
+ } else if (power_state == charged) {
+ CHARGE_LED_state = LED_STATE_ON;
+ } else {
+ CHARGE_LED_state = LED_STATE_OFF;
+ }
+
+ if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis()) {
+ PAIRING_LED_state = LED_STATE_OFF;
+ } else if (ble_state == unpaired) {
+ if (slowTrack) {
+ PAIRING_LED_state = !PAIRING_LED_state;
+ slowTrack = false;
+ } else {
+ slowTrack = true;
+ }
+ } else if (ble_state == pairing) {
+ PAIRING_LED_state = !PAIRING_LED_state;
+ } else {
+ PAIRING_LED_state = LED_STATE_ON;
+ }
+
+#ifdef LED_CHARGE
+ digitalWrite(LED_CHARGE, CHARGE_LED_state);
+#endif
+ // digitalWrite(green_LED_PIN, LED_STATE_OFF);
+#ifdef LED_PAIRING
+ digitalWrite(LED_PAIRING, PAIRING_LED_state);
+#endif
+
+ return (my_interval);
+}
diff --git a/src/modules/StatusLEDModule.h b/src/modules/StatusLEDModule.h
new file mode 100644
index 000000000..d9e3a4f33
--- /dev/null
+++ b/src/modules/StatusLEDModule.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "BluetoothStatus.h"
+#include "MeshModule.h"
+#include "PowerStatus.h"
+#include "concurrency/OSThread.h"
+#include "configuration.h"
+#include
+#include
+
+class StatusLEDModule : private concurrency::OSThread
+{
+ bool slowTrack = false;
+
+ public:
+ StatusLEDModule();
+
+ int handleStatusUpdate(const meshtastic::Status *);
+
+ protected:
+ unsigned int my_interval = 1000; // interval in millisconds
+ virtual int32_t runOnce() override;
+
+ CallbackObserver bluetoothStatusObserver =
+ CallbackObserver(this, &StatusLEDModule::handleStatusUpdate);
+ CallbackObserver powerStatusObserver =
+ CallbackObserver(this, &StatusLEDModule::handleStatusUpdate);
+
+ private:
+ bool CHARGE_LED_state = LED_STATE_OFF;
+ bool PAIRING_LED_state = LED_STATE_OFF;
+
+ uint32_t PAIRING_LED_starttime = 0;
+
+ enum PowerState { discharging, charging, charged };
+
+ PowerState power_state = discharging;
+
+ enum BLEState { unpaired, pairing, connected };
+
+ BLEState ble_state = unpaired;
+};
+
+extern StatusLEDModule *statusLEDModule;
diff --git a/src/modules/Telemetry/Sensor/AHT10.cpp b/src/modules/Telemetry/Sensor/AHT10.cpp
index 52fdc05c0..c38fd2a92 100644
--- a/src/modules/Telemetry/Sensor/AHT10.cpp
+++ b/src/modules/Telemetry/Sensor/AHT10.cpp
@@ -35,7 +35,7 @@ bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement)
// prefer other sensors like bmp280, bmp3xx
if (!measurement->variant.environment_metrics.has_temperature) {
measurement->variant.environment_metrics.has_temperature = true;
- measurement->variant.environment_metrics.temperature = temp.temperature;
+ measurement->variant.environment_metrics.temperature = temp.temperature + AHT10_TEMP_OFFSET;
}
if (!measurement->variant.environment_metrics.has_relative_humidity) {
diff --git a/src/modules/Telemetry/Sensor/AHT10.h b/src/modules/Telemetry/Sensor/AHT10.h
index ab3f5806c..f85f04aa0 100644
--- a/src/modules/Telemetry/Sensor/AHT10.h
+++ b/src/modules/Telemetry/Sensor/AHT10.h
@@ -6,6 +6,10 @@
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+#ifndef AHT10_TEMP_OFFSET
+#define AHT10_TEMP_OFFSET 0
+#endif
+
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include
diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h
index 6ddb41b16..75ca7567e 100644
--- a/src/platform/nrf52/architecture.h
+++ b/src/platform/nrf52/architecture.h
@@ -68,6 +68,8 @@
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
+#elif defined(ELECROW_ThinkNode_M3)
+#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M3
#elif defined(ELECROW_ThinkNode_M6)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M6
#elif defined(NANO_G2_ULTRA)
@@ -130,7 +132,9 @@
#endif
+#ifdef PIN_LED1
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
+#endif
#ifdef PIN_BUTTON1
#define BUTTON_PIN PIN_BUTTON1
diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp
index 827863f33..c03cc4454 100644
--- a/src/platform/nrf52/main-nrf52.cpp
+++ b/src/platform/nrf52/main-nrf52.cpp
@@ -30,6 +30,11 @@
#include "BQ25713.h"
#endif
+// Weak empty variant initialization function.
+// May be redefined by variant files.
+void variant_shutdown() __attribute__((weak));
+void variant_shutdown() {}
+
static nrfx_wdt_t nrfx_wdt = NRFX_WDT_INSTANCE(0);
static nrfx_wdt_channel_id nrfx_wdt_channel_id_nrf52_main;
@@ -391,6 +396,7 @@ void cpuDeepSleep(uint32_t msecToWake)
NRF_GPIO->DIRCLR = (1 << pin);
}
#endif
+ variant_shutdown();
// Sleepy trackers or sensors can low power "sleep"
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini b/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini
new file mode 100644
index 000000000..958e48e48
--- /dev/null
+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini
@@ -0,0 +1,17 @@
+[env:thinknode_m3]
+extends = nrf52840_base
+board = ThinkNode-M3
+board_check = true
+debug_tool = jlink
+build_flags =
+ ${nrf52840_base.build_flags}
+ -Ivariants/nrf52840/ELECROW-ThinkNode-M3
+ -DELECROW_ThinkNode_M3
+ -DGPS_POWER_TOGGLE
+ -D CONFIG_NFCT_PINS_AS_GPIOS=1
+ -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
+build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ELECROW-ThinkNode-M3>
+lib_deps =
+ ${nrf52840_base.lib_deps}
+ khoih-prog/nRF52_PWM@^1.0.1
+ lewisxhe/PCF8563_Library@^1.0.1
diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h b/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h
new file mode 100644
index 000000000..77ae9ef73
--- /dev/null
+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h
@@ -0,0 +1,15 @@
+#include "RadioLib.h"
+#include "nrf.h"
+
+// set RF switch configuration for ELECROW ThinkNode M3
+// ELECROW ThinkNode M3 uses DIO5 and DIO6 for RF switching
+
+static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
+
+static const Module::RfSwitchMode_t rfswitch_table[] = {
+ // mode DIO5 DIO6
+ {LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}},
+ {LR11x0::MODE_TX, {HIGH, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}},
+ {LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}},
+ {LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE,
+};
diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp
new file mode 100644
index 000000000..b7a7b7342
--- /dev/null
+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp
@@ -0,0 +1,93 @@
+/*
+ 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 "meshUtils.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()
+{
+ pinMode(KEY_POWER, OUTPUT);
+ digitalWrite(KEY_POWER, HIGH);
+ pinMode(RGB_POWER, OUTPUT);
+ digitalWrite(RGB_POWER, HIGH);
+ pinMode(green_LED_PIN, OUTPUT);
+ digitalWrite(green_LED_PIN, LED_STATE_OFF);
+ pinMode(LED_BLUE, OUTPUT);
+ pinMode(PIN_POWER_USB, INPUT);
+ pinMode(PIN_POWER_DONE, INPUT);
+ pinMode(PIN_POWER_CHRG, INPUT);
+ pinMode(BUTTON_PIN, INPUT_PULLUP);
+ pinMode(EEPROM_POWER, OUTPUT);
+ digitalWrite(EEPROM_POWER, HIGH);
+ pinMode(PIN_EN1, OUTPUT);
+ digitalWrite(PIN_EN1, HIGH);
+ pinMode(PIN_EN2, OUTPUT);
+ digitalWrite(PIN_EN2, HIGH);
+ pinMode(ACC_POWER, OUTPUT);
+ digitalWrite(ACC_POWER, LOW);
+ pinMode(DHT_POWER, OUTPUT);
+ digitalWrite(DHT_POWER, HIGH);
+ pinMode(Battery_POWER, OUTPUT);
+ digitalWrite(Battery_POWER, HIGH);
+ pinMode(GPS_POWER, OUTPUT);
+ digitalWrite(GPS_POWER, HIGH);
+}
+
+// called from main-nrf52.cpp during the cpuDeepSleep() function
+void variant_shutdown()
+{
+ digitalWrite(EEPROM_POWER, LOW);
+ digitalWrite(KEY_POWER, LOW);
+
+ for (int pin = 0; pin < 48; pin++) {
+ if (pin == PIN_POWER_USB || pin == BUTTON_PIN || pin == PIN_EN1 || pin == PIN_EN2 || pin == DHT_POWER ||
+ pin == ACC_POWER || pin == Battery_POWER || pin == GPS_POWER || pin == LR1110_SPI_MISO_PIN ||
+ pin == LR1110_SPI_MOSI_PIN || pin == LR1110_SPI_SCK_PIN || pin == LR1110_SPI_NSS_PIN || pin == LR1110_BUSY_PIN ||
+ pin == LR1110_NRESET_PIN || pin == LR1110_IRQ_PIN || pin == GPS_TX_PIN || pin == GPS_RX_PIN || pin == green_LED_PIN ||
+ pin == red_LED_PIN || pin == LED_BLUE) {
+ continue;
+ }
+ pinMode(pin, OUTPUT);
+ digitalWrite(pin, LOW);
+ if (pin >= 32) {
+ NRF_P1->DIRCLR = (1 << (pin - 32));
+ } else {
+ NRF_GPIO->DIRCLR = (1 << pin);
+ }
+ }
+
+ nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
+ nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
+ nrf_gpio_cfg_sense_set(BUTTON_PIN, sense1);
+
+ nrf_gpio_cfg_input(PIN_POWER_USB, NRF_GPIO_PIN_PULLDOWN); // Configure the pin to be woken up as an input
+ nrf_gpio_pin_sense_t sense2 = NRF_GPIO_PIN_SENSE_HIGH;
+ nrf_gpio_cfg_sense_set(PIN_POWER_USB, sense2);
+}
\ No newline at end of file
diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h
new file mode 100644
index 000000000..cf940172b
--- /dev/null
+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h
@@ -0,0 +1,122 @@
+/*
+ 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
+*/
+
+#ifndef _VARIANT_ELECROW_EINK_V1_0_
+#define _VARIANT_ELECROW_EINK_V1_0_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include "WVariant.h"
+
+#define VARIANT_MCK (64000000ul)
+#define USE_LFXO // Board uses 32khz crystal for LF
+
+#define ELECROW_ThinkNode_M3 1
+// Number of pins defined in PinDescription array
+#define PINS_COUNT (48)
+#define NUM_DIGITAL_PINS (48)
+#define NUM_ANALOG_INPUTS (1)
+#define NUM_ANALOG_OUTPUTS (0)
+
+// Power Pin
+#define NRF_APM
+#define GPS_POWER 14
+#define PIN_POWER_USB 31
+#define EXT_PWR_DETECT PIN_POWER_USB
+#define PIN_POWER_DONE 24
+#define PIN_POWER_CHRG 32
+#define KEY_POWER 16
+#define ACC_POWER 2
+#define DHT_POWER 3
+#define Battery_POWER 17
+#define RGB_POWER 29
+#define EEPROM_POWER 7
+
+// LED
+#define red_LED_PIN 33
+#define LED_POWER red_LED_PIN
+#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED
+#define green_LED_PIN 35
+#define LED_BLUE 37
+#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED
+
+#define LED_BUILTIN -1
+#define LED_STATE_ON LOW
+#define LED_STATE_OFF HIGH
+
+// BUZZER
+#define PIN_BUZZER 23
+#define PIN_EN1 36
+#define PIN_EN2 34
+/*Wire Interfaces*/
+#define WIRE_INTERFACES_COUNT 1
+#define PIN_WIRE_SDA 26
+#define PIN_WIRE_SCL 27
+
+// Temperature correction for sensor
+#define AHT10_TEMP_OFFSET -5.0
+
+/*GPS pins*/
+#define HAS_GPS 1
+#define GPS_BAUDRATE 9600
+#define PIN_GPS_RESET 25
+#define PIN_GPS_STANDBY 21
+#define GPS_TX_PIN 20
+#define GPS_RX_PIN 22
+#define GPS_THREAD_INTERVAL 50
+#define PIN_SERIAL1_RX GPS_TX_PIN
+#define PIN_SERIAL1_TX GPS_RX_PIN
+// Button
+#define BUTTON_PIN 12
+#define BUTTON_PIN_ALT (0 + 12)
+// Battery
+#define BATTERY_PIN 5
+#define BATTERY_SENSE_RESOLUTION_BITS 12
+#define BATTERY_SENSE_RESOLUTION 4096.0
+#undef AREF_VOLTAGE
+#define AREF_VOLTAGE 2.4
+#define VBAT_AR_INTERNAL AR_INTERNAL_2_4
+#define ADC_MULTIPLIER (1.75)
+/*SPI Interfaces*/
+#define SPI_INTERFACES_COUNT 1
+#define PIN_SPI_MISO (32 + 15) // P1.15 47
+#define PIN_SPI_MOSI (32 + 14) // P1.14 46
+#define PIN_SPI_SCK (32 + 13) // P1.13 45
+#define PIN_SPI_NSS (32 + 12) // P1.12 44
+/*LORA Interfaces*/
+#define USE_LR1110
+#define LR1110_IRQ_PIN 40
+#define LR1110_NRESET_PIN 42
+#define LR1110_BUSY_PIN 43
+#define LR1110_SPI_NSS_PIN 44
+#define LR1110_SPI_SCK_PIN 45
+#define LR1110_SPI_MOSI_PIN 46
+#define LR1110_SPI_MISO_PIN 47
+#define LR11X0_DIO3_TCXO_VOLTAGE 3.3
+#define LR11X0_DIO_AS_RF_SWITCH
+
+// PCF8563 RTC Module
+#define PCF8563_RTC 0x51
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif