add Thinknode-M1 (#6435)

* ThinkNode M1
* Update Epaper Driver
* Your day isn't complete unless trunk has complained about your formatting at least once.
pull/6354/head
Thomas Göttgens 2025-03-28 21:22:17 +01:00 zatwierdzone przez GitHub
rodzic a2387c79ee
commit 4a12b4eb32
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
13 zmienionych plików z 435 dodań i 14 usunięć

Wyświetl plik

@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "elecrow_eink",
"mcu": "nrf52840",
"variant": "ELECROW-ThinkNode-M1",
"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 eink",
"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": "FIXME",
"vendor": "ELECROW"
}

Wyświetl plik

@ -713,6 +713,9 @@ void Power::readPowerStatus()
const PowerStatus powerStatus2 = PowerStatus(hasBattery, usbPowered, isCharging, batteryVoltageMv, batteryChargePercent);
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d", powerStatus2.getHasUSB(), powerStatus2.getIsCharging(),
powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
#if defined(ELECROW_ThinkNode_M1)
power_num = powerStatus2.getBatteryVoltageMv();
#endif
newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP
if (lastheap != memGet.getFreeHeap()) {
@ -759,6 +762,9 @@ void Power::readPowerStatus()
if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < OCV[NUM_OCV_POINTS - 1]) {
low_voltage_counter++;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
if (low_voltage_counter > 10) {
#ifdef ARCH_NRF52
@ -771,6 +777,9 @@ void Power::readPowerStatus()
}
} else {
low_voltage_counter = 0;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
}
}
}

Wyświetl plik

@ -128,16 +128,24 @@ bool EInkDisplay::connect()
#ifdef PIN_EINK_EN
// backlight power, HIGH is backlight on, LOW is off
pinMode(PIN_EINK_EN, OUTPUT);
#ifdef ELECROW_ThinkNode_M1
digitalWrite(PIN_EINK_EN, LOW);
#else
digitalWrite(PIN_EINK_EN, HIGH);
#endif
#endif
#if defined(TTGO_T_ECHO)
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1)
{
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();
#ifdef ELECROW_ThinkNode_M1
adafruitDisplay->setRotation(4);
#else
adafruitDisplay->setRotation(3);
#endif
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(MESHLINK)

Wyświetl plik

@ -1641,6 +1641,11 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
setScreensaverFrames(einkScreensaver);
#endif
LOG_INFO("Turn off screen");
#ifdef ELECROW_ThinkNode_M1
if (digitalRead(PIN_EINK_EN) == HIGH) {
digitalWrite(PIN_EINK_EN, LOW);
}
#endif
dispdev->displayOff();
#ifdef USE_ST7789
SPI1.end();

Wyświetl plik

@ -262,6 +262,27 @@ void printInfo()
#ifndef PIO_UNIT_TESTING
void setup()
{
// power on peripherals
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
#endif
#ifdef LED_POWER
pinMode(LED_POWER, OUTPUT);
digitalWrite(LED_POWER, HIGH);
#endif
#ifdef POWER_LED
pinMode(POWER_LED, OUTPUT);
digitalWrite(POWER_LED, HIGH);
#endif
#ifdef USER_LED
pinMode(USER_LED, OUTPUT);
digitalWrite(USER_LED, LOW);
#endif
#if defined(T_DECK)
// GPIO10 manages all peripheral power supplies
// Turn on peripheral power immediately after MUC starts.
@ -325,13 +346,6 @@ void setup()
initDeepSleep();
// power on peripherals
#if defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
// digitalWrite(PIN_POWER_EN1, INPUT);
#endif
#if defined(LORA_TCXO_GPIO)
pinMode(LORA_TCXO_GPIO, OUTPUT);
digitalWrite(LORA_TCXO_GPIO, HIGH);
@ -1303,5 +1317,4 @@ void loop()
mainDelay.delay(delayMsec);
}
}
#endif

Wyświetl plik

@ -60,7 +60,7 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK)
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
@ -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) && !defined(MESHLINK)
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@ -214,7 +214,7 @@ int32_t SerialModule::runOnce()
}
}
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@ -416,7 +416,8 @@ uint32_t SerialModule::getBaudRate()
*/
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK)
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;

Wyświetl plik

@ -53,6 +53,8 @@
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN // HW_VENDOR meshtastic_HardwareModel_ThinkNode_M1
#elif defined(NANO_G2_ULTRA)
#define HW_VENDOR meshtastic_HardwareModel_NANO_G2_ULTRA
#elif defined(CANARYONE)

Wyświetl plik

@ -235,6 +235,14 @@ void nrf52InitSemiHosting()
void nrf52Setup()
{
#ifdef USB_CHECK
pinMode(USB_CHECK, INPUT);
#endif
#ifdef ADC_V
pinMode(ADC_V, INPUT);
#endif
uint32_t why = NRF_POWER->RESETREAS;
// per
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
@ -275,9 +283,11 @@ void cpuDeepSleep(uint32_t msecToWake)
Wire.end();
#endif
SPI.end();
#if SPI_INTERFACES_COUNT > 1
SPI1.end();
#endif
// This may cause crashes as debug messages continue to flow.
Serial.end();
#ifdef PIN_SERIAL_RX1
Serial1.end();
#endif
@ -315,6 +325,31 @@ void cpuDeepSleep(uint32_t msecToWake)
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
#endif
#ifdef ELECROW_ThinkNode_M1
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
pinMode(pin, OUTPUT);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
digitalWrite(pin, LOW);
}
for (int pin = 0; pin < 48; pin++) {
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
continue;
}
NRF_GPIO->DIRCLR = (1 << pin);
}
#endif
// Sleepy trackers or sensors can low power "sleep"
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
if (msecToWake != portMAX_DELAY &&
@ -333,6 +368,17 @@ void cpuDeepSleep(uint32_t msecToWake)
// FIXME, use system off mode with ram retention for key state?
// FIXME, use non-init RAM per
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
#ifdef ELECROW_ThinkNode_M1
nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense);
nrf_gpio_cfg_input(PIN_BUTTON2, NRF_GPIO_PIN_PULLUP);
nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
nrf_gpio_cfg_sense_set(PIN_BUTTON2, sense1);
#endif
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");

Wyświetl plik

@ -84,6 +84,11 @@ class Power : private concurrency::OSThread
void setStatusHandler(meshtastic::PowerStatus *handler) { statusHandler = handler; }
const uint16_t OCV[11] = {OCV_ARRAY};
#if defined(ELECROW_ThinkNode_M1)
uint8_t low_voltage_counter_led3;
int power_num = 0;
#endif
protected:
meshtastic::PowerStatus *statusHandler;

Wyświetl plik

@ -228,6 +228,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
}
#ifdef PIN_POWER_EN
digitalWrite(PIN_POWER_EN, LOW);
pinMode(PIN_POWER_EN, INPUT); // power off peripherals
// pinMode(PIN_POWER_EN1, INPUT_PULLDOWN);
#endif

Wyświetl plik

@ -0,0 +1,29 @@
; First prototype eink/nrf52840/sx1262 device
[env:thinknode_m1]
extends = nrf52840_base
board = ThinkNode-M1
board_check = true
debug_tool = jlink
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1
-DELECROW_ThinkNode_M1
-DGPS_POWER_TOGGLE
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DEINK_DISPLAY_MODEL=GxEPD2_154_D67
-DEINK_WIDTH=200
-DEINK_HEIGHT=200
-DUSE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-DEINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted //20
-DEINK_LIMIT_RATE_BACKGROUND_SEC=10 ; Minimum interval between BACKGROUND updates //30
-DEINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates
; -DEINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ELECROW-ThinkNode-M1>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
lewisxhe/PCF8563_Library@^1.0.1
khoih-prog/nRF52_PWM@^1.0.1
;upload_protocol = fs

Wyświetl plik

@ -0,0 +1,44 @@
/*
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 - pins 0 and 1 are hardwired for xtal and should never be enabled
0xff, 0xff, 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_LED3, OUTPUT);
ledOff(PIN_LED3);
}

Wyświetl plik

@ -0,0 +1,205 @@
/*
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_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
// 在PinDescription数组中定义的引脚数
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
#define PIN_LED1 -1
#define PIN_LED2 -1
#define PIN_LED3 -1
// LED
#define POWER_LED (32 + 6) // red
#define LED_POWER (32 + 4)
#define USER_LED (0 + 13) // green
// USB_CHECK
#define USB_CHECK (32 + 3)
#define ADC_V (0 + 8)
#define LED_RED PIN_LED3
#define LED_BLUE PIN_LED1
#define LED_GREEN PIN_LED2
#define LED_BUILTIN LED_BLUE
#define LED_CONN PIN_GREEN
#define LED_STATE_ON 0 // State when LED is lit // LED灯亮时的状态
#define M1_buzzer (0 + 6)
/*
* Buttons
*/
#define PIN_BUTTON2 (32 + 10)
#define PIN_BUTTON1 (32 + 7)
// #define PIN_BUTTON1 (0 + 11)
// #define PIN_BUTTON1 (32 + 7)
// #define BUTTON_CLICK_MS 400
// #define BUTTON_TOUCH_MS 200
/*
* Analog pins
*/
#define PIN_A0 (4) // Battery ADC
#define BATTERY_PIN PIN_A0
static const uint8_t A0 = PIN_A0;
#define ADC_RESOLUTION 14
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
/*Wire Interfaces*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (26)
#define PIN_WIRE_SCL (27)
/* touch sensor, active high */
#define TP_SER_IO (0 + 11)
#define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
/*
External serial flash WP25R1635FZUIL0
*/
// QSPI Pins
#define PIN_QSPI_SCK (32 + 14)
#define PIN_QSPI_CS (32 + 15)
#define PIN_QSPI_IO0 (32 + 12) // MOSI if using two bit interface
#define PIN_QSPI_IO1 (32 + 13) // MISO if using two bit interface
#define PIN_QSPI_IO2 (0 + 7) // WP if using two bit interface (i.e. not used)
#define PIN_QSPI_IO3 (0 + 5) // HOLD if using two bit interface (i.e. not used)
// On-board QSPI Flash
#define EXTERNAL_FLASH_DEVICES MX25R1635F
#define EXTERNAL_FLASH_USE_QSPI
/*
* Lora radio
*/
#define SX126X_POWER_EN (0 + 21)
#define USE_SX1262
#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 20)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
// #define SX1262_DIO3 (0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not
// drive from the main
#define SX126X_BUSY (0 + 17)
#define SX126X_RESET (0 + 25)
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 3.3
#define PIN_EINK_EN (32 + 11) // Note: this is really just backlight power
#define PIN_EINK_CS (0 + 30)
#define PIN_EINK_BUSY (0 + 3)
#define PIN_EINK_DC (0 + 28)
#define PIN_EINK_RES (0 + 2)
#define PIN_EINK_SCLK (0 + 31)
#define PIN_EINK_MOSI (0 + 29) // also called SDI
// Controls power for all peripherals (eink + GPS + LoRa + Sensor)
#define PIN_POWER_EN (0 + 12)
#define USE_EINK
#define PIN_SPI1_MISO (32 + 7)
#define PIN_SPI1_MOSI PIN_EINK_MOSI
#define PIN_SPI1_SCK PIN_EINK_SCLK
/*
* GPS pins
*/
// #define HAS_GPS 1
#define GPS_L76K
#define GPS_BAUDRATE 9600
#define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
// Seems to be missing on this new board
// #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
#define GPS_TX_PIN (32 + 9) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (32 + 8) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_PPS (32 + 1) // GPS开关判断
#define PIN_SERIAL1_RX GPS_TX_PIN
#define PIN_SERIAL1_TX GPS_RX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
// For LORA, spi 0
#define PIN_SPI_MISO (0 + 23)
#define PIN_SPI_MOSI (0 + 22)
#define PIN_SPI_SCK (0 + 19)
#define PIN_PWR_EN (0 + 6)
// To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER
// Battery
// The battery sense is hooked to pin A0 (4)
// it is defined in the anlaolgue pin section of this file
// and has 12 bit resolution
#define BATTERY_SENSE_RESOLUTION_BITS 12
#define BATTERY_SENSE_RESOLUTION 4096.0
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (2.02F)
// #define HAS_RTC 0
// #define HAS_SCREEN 0
#ifdef __cplusplus
}
#endif
#endif