Add Heltec mesh node t1 (#10416)

* add heltec-mesh-node-t1

* fixed low power

* Update the sensor enumeration values.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix memory leak in ICM42607PSensor

* fix  ST7735_MISO  error

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Quency-D
2026-05-29 12:47:09 -05:00
committed by GitHub
co-authored by GitHub Ben Meadors Copilot Autofix powered by AI
parent d3c7f05baa
commit 60303968bb
20 changed files with 829 additions and 15 deletions
+54
View File
@@ -0,0 +1,54 @@
{
"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"],
["0x2886", "0x1667"]
],
"usb_product": "HT-n5262",
"mcu": "nrf52840",
"variant": "heltec_mesh_node_t1",
"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": "Heltec Mesh Node T1",
"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": "https://heltec.org",
"vendor": "Heltec"
}
+4
View File
@@ -186,12 +186,16 @@ lib_deps =
https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/archive/refs/tags/v1.1.2.zip https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/archive/refs/tags/v1.1.2.zip
# renovate: datasource=github-tags depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/SparkFun_ICM-20948_ArduinoLibrary # renovate: datasource=github-tags depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/SparkFun_ICM-20948_ArduinoLibrary
https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/archive/refs/tags/v1.3.2.zip https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary/archive/refs/tags/v1.3.2.zip
# renovate: datasource=github-tags depName=TDK InvenSense ICM42670P packageName=tdk-invn-oss/motion.arduino.ICM42670P
https://github.com/tdk-invn-oss/motion.arduino.ICM42670P/archive/refs/tags/1.0.8.zip
# renovate: datasource=github-tags depName=Adafruit LTR390 Library packageName=adafruit/Adafruit_LTR390 # renovate: datasource=github-tags depName=Adafruit LTR390 Library packageName=adafruit/Adafruit_LTR390
https://github.com/adafruit/Adafruit_LTR390/archive/refs/tags/1.1.2.zip https://github.com/adafruit/Adafruit_LTR390/archive/refs/tags/1.1.2.zip
# renovate: datasource=github-tags depName=Adafruit PCT2075 packageName=adafruit/Adafruit_PCT2075 # renovate: datasource=github-tags depName=Adafruit PCT2075 packageName=adafruit/Adafruit_PCT2075
https://github.com/adafruit/Adafruit_PCT2075/archive/refs/tags/1.0.6.zip https://github.com/adafruit/Adafruit_PCT2075/archive/refs/tags/1.0.6.zip
# renovate: datasource=github-tags depName=DFRobot_BMM150 packageName=dfrobot/DFRobot_BMM150 # renovate: datasource=github-tags depName=DFRobot_BMM150 packageName=dfrobot/DFRobot_BMM150
https://github.com/DFRobot/DFRobot_BMM150/archive/refs/tags/V1.0.0.zip https://github.com/DFRobot/DFRobot_BMM150/archive/refs/tags/V1.0.0.zip
# renovate: datasource=github-tags depName=SparkFun MMC5983MA Magnetometer packageName=sparkfun/SparkFun_MMC5983MA_Magnetometer_Arduino_Library
https://github.com/sparkfun/SparkFun_MMC5983MA_Magnetometer_Arduino_Library/archive/refs/tags/v1.1.4.zip
# renovate: datasource=github-tags depName=Adafruit_TSL2561 packageName=adafruit/Adafruit_TSL2561 # renovate: datasource=github-tags depName=Adafruit_TSL2561 packageName=adafruit/Adafruit_TSL2561
https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip https://github.com/adafruit/Adafruit_TSL2561/archive/refs/tags/1.1.3.zip
# renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE # renovate: datasource=github-tags depName=BH1750_WE packageName=wollewald/BH1750_WE
+3
View File
@@ -243,6 +243,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define QMI8658_ADDR 0x6B #define QMI8658_ADDR 0x6B
#define QMC5883L_ADDR 0x0D #define QMC5883L_ADDR 0x0D
#define HMC5883L_ADDR 0x1E #define HMC5883L_ADDR 0x1E
#define MMC5983MA_ADDR 0x30
#define SHTC3_ADDR 0x70 #define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C #define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D #define LPS22HB_ADDR_ALT 0x5D
@@ -292,6 +293,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DA217_ADDR 0x26 #define DA217_ADDR 0x26
#define BMI270_ADDR 0x68 #define BMI270_ADDR 0x68
#define BMI270_ADDR_ALT 0x69 #define BMI270_ADDR_ALT 0x69
#define ICM42607P_ADDR 0x68
#define ICM42607P_ADDR_ALT 0x69
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// LED // LED
+9 -2
View File
@@ -37,8 +37,15 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{ {
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948, QMA6100P, BMM150, BMI270}; ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX,
return firstOfOrNONE(10, types); ICM20948, QMA6100P, BMM150, BMI270, ICM42607P};
return firstOfOrNONE(11, types);
}
ScanI2C::FoundDevice ScanI2C::firstMagnetometer() const
{
ScanI2C::DeviceType types[] = {MMC5983MA};
return firstOfOrNONE(1, types);
} }
ScanI2C::FoundDevice ScanI2C::firstAQI() const ScanI2C::FoundDevice ScanI2C::firstAQI() const
+4
View File
@@ -41,6 +41,7 @@ class ScanI2C
QMI8658, QMI8658,
QMC5883L, QMC5883L,
HMC5883L, HMC5883L,
MMC5983MA,
PMSA003I, PMSA003I,
QMA6100P, QMA6100P,
MPU6050, MPU6050,
@@ -65,6 +66,7 @@ class ScanI2C
FT6336U, FT6336U,
STK8BAXX, STK8BAXX,
ICM20948, ICM20948,
ICM42607P,
SCD4X, SCD4X,
MAX30102, MAX30102,
TPS65233, TPS65233,
@@ -149,6 +151,8 @@ class ScanI2C
FoundDevice firstAccelerometer() const; FoundDevice firstAccelerometer() const;
FoundDevice firstMagnetometer() const;
FoundDevice firstAQI() const; FoundDevice firstAQI() const;
FoundDevice firstRGBLED() const; FoundDevice firstRGBLED() const;
+20 -5
View File
@@ -360,9 +360,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address); SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
#ifdef HAS_NCP5623 #ifdef HAS_NCP5623
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address); SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
#endif
#ifdef HAS_LP5562
SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address);
#endif #endif
case XPOWERS_AXP192_AXP2101_ADDRESS: case XPOWERS_AXP192_AXP2101_ADDRESS:
// Do we have the axp2101/192 or the TCA8418 // Do we have the axp2101/192 or the TCA8418
@@ -600,6 +597,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#else #else
SCAN_SIMPLE_CASE(PMSA003I_ADDR, PMSA003I, "PMSA003I", (uint8_t)addr.address) SCAN_SIMPLE_CASE(PMSA003I_ADDR, PMSA003I, "PMSA003I", (uint8_t)addr.address)
#endif #endif
case MMC5983MA_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x2F), 1);
if (registerValue == 0x30) {
type = MMC5983MA;
logFoundDevice("MMC5983MA", (uint8_t)addr.address);
#ifdef HAS_LP5562
} else {
type = LP5562;
logFoundDevice("LP5562", (uint8_t)addr.address);
#endif
}
break;
case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2); registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333 if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
@@ -754,8 +763,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
} }
break; break;
case ICM20948_ADDR: // same as BMX160_ADDR, BMI270_ADDR_ALT, and SEN5X_ADDR case ICM20948_ADDR: // same as BMX160_ADDR, BMI270_ADDR_ALT, ICM42607P_ADDR_ALT, and SEN5X_ADDR
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR, BMI270_ADDR case ICM20948_ADDR_ALT: // same as MPU6050_ADDR, BMI270_ADDR, and ICM42607P_ADDR
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
#ifdef HAS_ICM20948 #ifdef HAS_ICM20948
type = ICM20948; type = ICM20948;
@@ -775,6 +784,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("BMX160", (uint8_t)addr.address); logFoundDevice("BMX160", (uint8_t)addr.address);
break; break;
} else { } else {
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x75), 1); // WHO_AM_I
if (registerValue == 0x60) {
type = ICM42607P;
logFoundDevice("ICM-42607-P", (uint8_t)addr.address);
break;
}
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR
String prod = ""; String prod = "";
prod = readSEN5xProductName(i2cBus, addr.address); prod = readSEN5xProductName(i2cBus, addr.address);
+12 -8
View File
@@ -1458,7 +1458,8 @@ void TFTDisplay::sendCommand(uint8_t com)
digitalWrite(portduino_config.displayBacklight.pin, TFT_BACKLIGHT_ON); digitalWrite(portduino_config.displayBacklight.pin, TFT_BACKLIGHT_ON);
#elif defined(HACKADAY_COMMUNICATOR) #elif defined(HACKADAY_COMMUNICATOR)
tft->displayOn(); tft->displayOn();
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) && !defined(HELTEC_MESH_NODE_T096) #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) && !defined(HELTEC_MESH_NODE_T096) && \
!defined(HELTEC_MESH_NODE_T1)
tft->wakeup(); tft->wakeup();
tft->powerSaveOff(); tft->powerSaveOff();
#endif #endif
@@ -1469,7 +1470,7 @@ void TFTDisplay::sendCommand(uint8_t com)
#ifdef UNPHONE #ifdef UNPHONE
unphone.backlight(true); // using unPhone library unphone.backlight(true); // using unPhone library
#endif #endif
#if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) #if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) || defined(HELTEC_MESH_NODE_T1)
#elif !defined(M5STACK) && !defined(ST7789_CS) && \ #elif !defined(M5STACK) && !defined(ST7789_CS) && \
!defined(HACKADAY_COMMUNICATOR) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function !defined(HACKADAY_COMMUNICATOR) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function
tft->setBrightness(172); tft->setBrightness(172);
@@ -1485,7 +1486,8 @@ void TFTDisplay::sendCommand(uint8_t com)
digitalWrite(portduino_config.displayBacklight.pin, !TFT_BACKLIGHT_ON); digitalWrite(portduino_config.displayBacklight.pin, !TFT_BACKLIGHT_ON);
#elif defined(HACKADAY_COMMUNICATOR) #elif defined(HACKADAY_COMMUNICATOR)
tft->displayOff(); tft->displayOff();
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) && !defined(HELTEC_MESH_NODE_T096) #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) && !defined(HELTEC_MESH_NODE_T096) && \
!defined(HELTEC_MESH_NODE_T1)
tft->sleep(); tft->sleep();
tft->powerSaveOn(); tft->powerSaveOn();
#endif #endif
@@ -1496,7 +1498,7 @@ void TFTDisplay::sendCommand(uint8_t com)
#ifdef UNPHONE #ifdef UNPHONE
unphone.backlight(false); // using unPhone library unphone.backlight(false); // using unPhone library
#endif #endif
#if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) #if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) || defined(HELTEC_MESH_NODE_T1)
#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) #elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR)
tft->setBrightness(0); tft->setBrightness(0);
#endif #endif
@@ -1511,7 +1513,7 @@ void TFTDisplay::sendCommand(uint8_t com)
void TFTDisplay::setDisplayBrightness(uint8_t _brightness) void TFTDisplay::setDisplayBrightness(uint8_t _brightness)
{ {
#if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) #if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) || defined(HELTEC_MESH_NODE_T1)
// todo // todo
#elif !defined(HACKADAY_COMMUNICATOR) #elif !defined(HACKADAY_COMMUNICATOR)
tft->setBrightness(_brightness); tft->setBrightness(_brightness);
@@ -1531,7 +1533,8 @@ bool TFTDisplay::hasTouch(void)
{ {
#ifdef RAK14014 #ifdef RAK14014
return true; return true;
#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) && !defined(HELTEC_MESH_NODE_T096) #elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) && !defined(HELTEC_MESH_NODE_T096) && \
!defined(HELTEC_MESH_NODE_T1)
return tft->touch() != nullptr; return tft->touch() != nullptr;
#else #else
return false; return false;
@@ -1550,7 +1553,8 @@ bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
} else { } else {
return false; return false;
} }
#elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) && !defined(HELTEC_MESH_NODE_T096) #elif !defined(M5STACK) && !defined(HACKADAY_COMMUNICATOR) && !defined(HELTEC_MESH_NODE_T096) && \
!defined(HELTEC_MESH_NODE_T1)
return tft->getTouch(x, y); return tft->getTouch(x, y);
#else #else
return false; return false;
@@ -1567,7 +1571,7 @@ bool TFTDisplay::connect()
{ {
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
LOG_INFO("Do TFT init"); LOG_INFO("Do TFT init");
#if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) #if defined(RAK14014) || defined(HELTEC_MESH_NODE_T096) || defined(HELTEC_MESH_NODE_T1)
tft = new TFT_eSPI; tft = new TFT_eSPI;
#elif defined(HACKADAY_COMMUNICATOR) #elif defined(HACKADAY_COMMUNICATOR)
bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, 38 /* SCK */, 21 /* MOSI */, GFX_NOT_DEFINED /* MISO */, HSPI /* spi_num */); bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, 38 /* SCK */, 21 /* MOSI */, GFX_NOT_DEFINED /* MISO */, HSPI /* spi_num */);
+5
View File
@@ -1333,6 +1333,11 @@ void menuHandler::positionBaseMenu()
if (accelerometerThread) { if (accelerometerThread) {
accelerometerThread->calibrate(30); accelerometerThread->calibrate(30);
} }
#endif
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && !MESHTASTIC_EXCLUDE_MAGNETOMETER
if (magnetometerThread) {
magnetometerThread->calibrate(30);
}
#endif #endif
break; break;
case PositionAction::GPSSmartPosition: case PositionAction::GPSSmartPosition:
+23
View File
@@ -136,6 +136,10 @@ void printPartitionTable()
#include "motion/AccelerometerThread.h" #include "motion/AccelerometerThread.h"
AccelerometerThread *accelerometerThread = nullptr; AccelerometerThread *accelerometerThread = nullptr;
#endif #endif
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && !MESHTASTIC_EXCLUDE_MAGNETOMETER
#include "motion/MagnetometerThread.h"
MagnetometerThread *magnetometerThread = nullptr;
#endif
#ifdef HAS_I2S #ifdef HAS_I2S
#include "AudioThread.h" #include "AudioThread.h"
@@ -206,6 +210,8 @@ bool osk_found = false;
ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE; ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE;
// The I2C address of the Accelerometer (if found) // The I2C address of the Accelerometer (if found)
ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE; ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
// The I2C address of the Magnetometer (if found)
ScanI2C::DeviceAddress magnetometer_found = ScanI2C::ADDRESS_NONE;
// The I2C address of the RGB LED (if found) // The I2C address of the RGB LED (if found)
ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE); ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE);
/// The I2C address of our Air Quality Indicator (if found) /// The I2C address of our Air Quality Indicator (if found)
@@ -431,6 +437,11 @@ void setup()
digitalWrite(VEXT_ENABLE, VEXT_ON_VALUE); // turn on the display power digitalWrite(VEXT_ENABLE, VEXT_ON_VALUE); // turn on the display power
#endif #endif
#if defined(PIN_SENSOR_EN)
pinMode(PIN_SENSOR_EN, OUTPUT);
digitalWrite(PIN_SENSOR_EN, PIN_SENSOR_EN_ACTIVE); // turn on sensor power
#endif
#if defined(BIAS_T_ENABLE) #if defined(BIAS_T_ENABLE)
pinMode(BIAS_T_ENABLE, OUTPUT); pinMode(BIAS_T_ENABLE, OUTPUT);
digitalWrite(BIAS_T_ENABLE, BIAS_T_VALUE); // turn on 5V for GPS Antenna digitalWrite(BIAS_T_ENABLE, BIAS_T_VALUE); // turn on 5V for GPS Antenna
@@ -671,6 +682,11 @@ void setup()
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found; accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
LOG_DEBUG("acc_info = %i", acc_info.type); LOG_DEBUG("acc_info = %i", acc_info.type);
#endif #endif
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_MAGNETOMETER
auto mag_info = i2cScanner->firstMagnetometer();
magnetometer_found = mag_info.type != ScanI2C::DeviceType::NONE ? mag_info.address : magnetometer_found;
LOG_DEBUG("mag_info = %i", mag_info.type);
#endif
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA226, meshtastic_TelemetrySensorType_INA226); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA226, meshtastic_TelemetrySensorType_INA226);
@@ -683,6 +699,8 @@ void setup()
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MMC5983MA, meshtastic_TelemetrySensorType_MMC5983MA);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM42607P, meshtastic_TelemetrySensorType_ICM42607P);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102);
@@ -766,6 +784,11 @@ void setup()
accelerometerThread = new AccelerometerThread(acc_info.type); accelerometerThread = new AccelerometerThread(acc_info.type);
} }
#endif #endif
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_MAGNETOMETER
if (mag_info.type != ScanI2C::DeviceType::NONE) {
magnetometerThread = new MagnetometerThread(mag_info.type);
}
#endif
#if defined(HAS_NEOPIXEL) || defined(UNPHONE) || defined(RGBLED_RED) #if defined(HAS_NEOPIXEL) || defined(UNPHONE) || defined(RGBLED_RED)
ambientLightingThread = new AmbientLightingThread(ScanI2C::DeviceType::NONE); ambientLightingThread = new AmbientLightingThread(ScanI2C::DeviceType::NONE);
+5
View File
@@ -39,6 +39,7 @@ extern bool kb_found;
extern bool osk_found; extern bool osk_found;
extern ScanI2C::DeviceAddress rtc_found; extern ScanI2C::DeviceAddress rtc_found;
extern ScanI2C::DeviceAddress accelerometer_found; extern ScanI2C::DeviceAddress accelerometer_found;
extern ScanI2C::DeviceAddress magnetometer_found;
extern ScanI2C::FoundDevice rgb_found; extern ScanI2C::FoundDevice rgb_found;
extern ScanI2C::DeviceAddress aqi_found; extern ScanI2C::DeviceAddress aqi_found;
@@ -73,6 +74,10 @@ extern graphics::Screen *screen;
#include "motion/AccelerometerThread.h" #include "motion/AccelerometerThread.h"
extern AccelerometerThread *accelerometerThread; extern AccelerometerThread *accelerometerThread;
#endif #endif
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && !MESHTASTIC_EXCLUDE_MAGNETOMETER
#include "motion/MagnetometerThread.h"
extern MagnetometerThread *magnetometerThread;
#endif
extern bool isVibrating; extern bool isVibrating;
+4
View File
@@ -15,6 +15,7 @@
#endif #endif
#include "BMM150Sensor.h" #include "BMM150Sensor.h"
#include "BMX160Sensor.h" #include "BMX160Sensor.h"
#include "ICM42607PSensor.h"
#include "ICM20948Sensor.h" #include "ICM20948Sensor.h"
#include "LIS3DHSensor.h" #include "LIS3DHSensor.h"
#include "LSM6DS3Sensor.h" #include "LSM6DS3Sensor.h"
@@ -111,6 +112,9 @@ class AccelerometerThread : public concurrency::OSThread
case ScanI2C::DeviceType::ICM20948: case ScanI2C::DeviceType::ICM20948:
sensor = new ICM20948Sensor(device); sensor = new ICM20948Sensor(device);
break; break;
case ScanI2C::DeviceType::ICM42607P:
sensor = new ICM42607PSensor(device);
break;
case ScanI2C::DeviceType::BMM150: case ScanI2C::DeviceType::BMM150:
sensor = new BMM150Sensor(device); sensor = new BMM150Sensor(device);
break; break;
+98
View File
@@ -0,0 +1,98 @@
#include "ICM42607PSensor.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<ICM42670P.h>)
#include "detect/ScanI2CTwoWire.h"
#include <ICM42670P.h>
static constexpr uint16_t ICM42607P_ACCEL_ODR_HZ = 50;
static constexpr uint16_t ICM42607P_ACCEL_FSR_G = 2;
static constexpr float ICM42607P_COUNTS_PER_G = 32768.0f / ICM42607P_ACCEL_FSR_G;
#ifdef ICM_42607P_INT_PIN
volatile static bool ICM42607P_IRQ = false;
void ICM42607PSetInterrupt()
{
ICM42607P_IRQ = true;
}
#endif
ICM42607PSensor::ICM42607PSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice)
{
wire = ScanI2CTwoWire::fetchI2CBus(foundDevice.address);
}
ICM42607PSensor::~ICM42607PSensor() = default;
bool ICM42607PSensor::init()
{
bool addressLsb = deviceAddress() == ICM42607P_ADDR_ALT;
LOG_DEBUG("ICM-42607-P begin on addr 0x%02X (port=%d)", deviceAddress(), devicePort());
sensor.reset();
auto newSensor = std::make_unique<ICM42670>(*wire, addressLsb);
int status = newSensor->begin();
// ICM42670P library returns -3 for ICM42607P because WHO_AM_I differs; the register map is compatible.
if (status != 0 && status != -3) {
LOG_DEBUG("ICM-42607-P init error %d", status);
return false;
}
status = newSensor->startAccel(ICM42607P_ACCEL_ODR_HZ, ICM42607P_ACCEL_FSR_G);
if (status != 0) {
LOG_DEBUG("ICM-42607-P accel start error %d", status);
return false;
}
#ifdef ICM_42607P_INT_PIN
ICM42607P_IRQ = false;
status = newSensor->startWakeOnMotion(ICM_42607P_INT_PIN, ICM42607PSetInterrupt);
if (status != 0) {
LOG_DEBUG("ICM-42607-P wake-on-motion start error %d", status);
return false;
}
LOG_DEBUG("ICM-42607-P wake-on-motion interrupt ok pin=%d", ICM_42607P_INT_PIN);
#endif
sensor = std::move(newSensor);
LOG_DEBUG("ICM-42607-P init ok");
return true;
}
int32_t ICM42607PSensor::runOnce()
{
#ifdef ICM_42607P_INT_PIN
if (ICM42607P_IRQ) {
ICM42607P_IRQ = false;
LOG_DEBUG("ICM-42607-P motion interrupt");
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
#else
int16_t x = 0;
int16_t y = 0;
int16_t z = 0;
inv_imu_sensor_event_t event = {};
if (sensor == nullptr || sensor->getDataFromRegisters(event) != 0) {
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
// getDataFromRegisters() fills accel[] but does not set sensor_mask in this library version.
if (event.accel[0] == 0 && event.accel[1] == 0 && event.accel[2] == 0) {
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
x = event.accel[0];
y = event.accel[1];
z = event.accel[2];
// LOG_DEBUG("ICM-42607-P accel read x=%.3fg y=%.3fg z=%.3fg", (float)x / ICM42607P_COUNTS_PER_G,
// (float)y / ICM42607P_COUNTS_PER_G, (float)z / ICM42607P_COUNTS_PER_G);
return MOTION_SENSOR_CHECK_INTERVAL_MS;
#endif
}
#endif
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#ifndef _ICM42607P_SENSOR_H_
#define _ICM42607P_SENSOR_H_
#include "MotionSensor.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<ICM42670P.h>)
#include <memory>
class ICM42670;
class ICM42607PSensor : public MotionSensor
{
private:
std::unique_ptr<ICM42670> sensor;
TwoWire *wire = nullptr;
public:
explicit ICM42607PSensor(ScanI2C::FoundDevice foundDevice);
~ICM42607PSensor() override;
virtual bool init() override;
virtual int32_t runOnce() override;
};
#endif
#endif
+115
View File
@@ -0,0 +1,115 @@
#include "MMC5983MASensor.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SparkFun_MMC5983MA_Arduino_Library.h>)
#include "detect/ScanI2CTwoWire.h"
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
extern graphics::Screen *screen;
#endif
static constexpr float MMC5983MA_ZERO_FIELD = 131072.0f;
static constexpr float MMC5983MA_COUNTS_PER_GAUSS = 16384.0f;
static constexpr uint16_t MMC5983MA_CONTINUOUS_FREQUENCY_HZ = 10;
static constexpr float MMC5983MA_HEADING_OFFSET_DEG = 180.0f;
MMC5983MASensor::MMC5983MASensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool MMC5983MASensor::init()
{
LOG_DEBUG("MMC5983MA begin on addr 0x%02X (port=%d)", device.address.address, device.address.port);
TwoWire *wire = ScanI2CTwoWire::fetchI2CBus(device.address);
if (!sensor.begin(*wire)) {
LOG_DEBUG("MMC5983MA init error");
return false;
}
sensor.softReset();
sensor.setFilterBandwidth(100);
sensor.performSetOperation();
sensor.enableAutomaticSetReset();
continuousMode = sensor.setContinuousModeFrequency(MMC5983MA_CONTINUOUS_FREQUENCY_HZ);
continuousMode &= sensor.enableContinuousMode();
if (!continuousMode) {
LOG_DEBUG("MMC5983MA continuous mode failed, using single-shot reads");
sensor.disableContinuousMode();
}
loadMagnetometerCalibration(compassCalibrationFileName, highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
return true;
}
bool MMC5983MASensor::readMagnetometer(float &xGauss, float &yGauss, float &zGauss)
{
uint32_t rawX = 0;
uint32_t rawY = 0;
uint32_t rawZ = 0;
if (!(continuousMode ? sensor.readFieldsXYZ(&rawX, &rawY, &rawZ) : sensor.getMeasurementXYZ(&rawX, &rawY, &rawZ))) {
LOG_DEBUG("MMC5983MA read failed");
return false;
}
xGauss = ((float)rawX - MMC5983MA_ZERO_FIELD) / MMC5983MA_COUNTS_PER_GAUSS;
yGauss = ((float)rawY - MMC5983MA_ZERO_FIELD) / MMC5983MA_COUNTS_PER_GAUSS;
zGauss = ((float)rawZ - MMC5983MA_ZERO_FIELD) / MMC5983MA_COUNTS_PER_GAUSS;
return true;
}
int32_t MMC5983MASensor::runOnce()
{
float magX = 0, magY = 0, magZ = 0;
if (!readMagnetometer(magX, magY, magZ)) {
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
if (doCalibration) {
beginCalibrationDisplay(showingScreen);
updateCalibrationExtrema(magX, magY, magZ, highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
finishCalibrationIfExpired(showingScreen, compassCalibrationFileName, highestX, lowestX, highestY, lowestY, highestZ,
lowestZ);
}
#endif
magX -= (highestX + lowestX) / 2;
magY -= (highestY + lowestY) / 2;
magZ -= (highestZ + lowestZ) / 2;
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
float heading = atan2f(magY, magX) * RAD_TO_DEG + MMC5983MA_HEADING_OFFSET_DEG;
if (heading < 0.0f) {
heading += 360.0f;
} else if (heading >= 360.0f) {
heading -= 360.0f;
}
heading = applyCompassOrientation(heading);
if (screen) {
screen->setHeading(heading);
}
#endif
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
void MMC5983MASensor::calibrate(uint16_t forSeconds)
{
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
float xGauss = 0.0f;
float yGauss = 0.0f;
float zGauss = 0.0f;
LOG_DEBUG("MMC5983MA calibration started for %is", forSeconds);
if (readMagnetometer(xGauss, yGauss, zGauss)) {
seedCalibrationExtrema(xGauss, yGauss, zGauss, highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
} else {
seedCalibrationExtrema(0.0f, 0.0f, 0.0f, highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
}
startCalibrationWindow(forSeconds);
#endif
}
#endif
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#ifndef _MMC5983MA_SENSOR_H_
#define _MMC5983MA_SENSOR_H_
#include "MotionSensor.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SparkFun_MMC5983MA_Arduino_Library.h>)
#include <SparkFun_MMC5983MA_Arduino_Library.h>
class MMC5983MASensor : public MotionSensor
{
private:
SFE_MMC5983MA sensor;
bool continuousMode = false;
bool showingScreen = false;
static constexpr const char *compassCalibrationFileName = "/prefs/compass_mmc5983ma.dat";
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
bool readMagnetometer(float &xGauss, float &yGauss, float &zGauss);
public:
explicit MMC5983MASensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
virtual void calibrate(uint16_t forSeconds) override;
};
#endif
#endif
+115
View File
@@ -0,0 +1,115 @@
#pragma once
#ifndef _MAGNETOMETER_THREAD_H_
#define _MAGNETOMETER_THREAD_H_
#include "configuration.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && !MESHTASTIC_EXCLUDE_MAGNETOMETER
#include "../concurrency/OSThread.h"
#include "MMC5983MASensor.h"
#include "MotionSensor.h"
extern ScanI2C::DeviceAddress magnetometer_found;
class MagnetometerThread : public concurrency::OSThread
{
private:
MotionSensor *sensor = nullptr;
ScanI2C::FoundDevice device;
bool isInitialised = false;
public:
explicit MagnetometerThread(ScanI2C::FoundDevice foundDevice) : OSThread("Magnetometer")
{
device = foundDevice;
init();
}
explicit MagnetometerThread(ScanI2C::DeviceType type) : MagnetometerThread(ScanI2C::FoundDevice{type, magnetometer_found}) {}
void start()
{
init();
setIntervalFromNow(0);
};
void calibrate(uint16_t forSeconds)
{
if (sensor) {
sensor->calibrate(forSeconds);
setIntervalFromNow(0);
}
}
protected:
int32_t runOnce() override
{
canSleep = true;
if (isInitialised) {
return sensor->runOnce();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
private:
void init()
{
if (isInitialised) {
return;
}
if (device.address.port == ScanI2C::I2CPort::NO_I2C || device.address.address == 0 || device.type == ScanI2C::NONE) {
LOG_DEBUG("MagnetometerThread Disable due to no sensors found");
disable();
return;
}
switch (device.type) {
case ScanI2C::DeviceType::MMC5983MA:
sensor = new MMC5983MASensor(device);
break;
default:
disable();
return;
}
isInitialised = sensor->init();
if (!isInitialised) {
clean();
}
LOG_DEBUG("MagnetometerThread::init %s", isInitialised ? "ok" : "failed");
}
MagnetometerThread(const MagnetometerThread &other) : OSThread::OSThread("Magnetometer") { this->copy(other); }
virtual ~MagnetometerThread() { clean(); }
MagnetometerThread &operator=(const MagnetometerThread &other)
{
this->copy(other);
return *this;
}
void copy(const MagnetometerThread &other)
{
if (this != &other) {
clean();
this->device = ScanI2C::FoundDevice(other.device.type,
ScanI2C::DeviceAddress(other.device.address.port, other.device.address.address));
}
}
void clean()
{
isInitialised = false;
delete sensor;
sensor = nullptr;
}
};
#endif
#endif
+2
View File
@@ -117,6 +117,8 @@
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW #define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#elif defined(HELTEC_T114) #elif defined(HELTEC_T114)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T114 #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T114
#elif defined(HELTEC_MESH_NODE_T1)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_NODE_T1
#elif defined(MESHLINK) #elif defined(MESHLINK)
#define HW_VENDOR meshtastic_HardwareModel_MESHLINK #define HW_VENDOR meshtastic_HardwareModel_MESHLINK
#elif defined(SEEED_XIAO_NRF52840_KIT) #elif defined(SEEED_XIAO_NRF52840_KIT)
@@ -0,0 +1,35 @@
; Heltec Mesh Node T1 nRF52840/SX1262 device
[env:heltec-mesh-node-t1]
custom_meshtastic_hw_model = 133
custom_meshtastic_hw_model_slug = HELTEC_MESH_NODE_T1
custom_meshtastic_architecture = nrf52840
custom_meshtastic_actively_supported = true
custom_meshtastic_support_level = 1
custom_meshtastic_display_name = Heltec Mesh Node T1
custom_meshtastic_images = heltec-mesh-node-t1.svg
custom_meshtastic_tags = Heltec
extends = nrf52840_base
board = heltec_mesh_node_t1
board_level = pr
debug_tool = jlink
build_flags = ${nrf52840_base.build_flags}
-Ivariants/nrf52840/heltec_mesh_node_t1
-DHELTEC_MESH_NODE_T1
-DUSE_TFTDISPLAY
-DUSER_SETUP_LOADED
-DST7735_DRIVER
-DST7735_REDTAB160x80
-D TFT_SPI_PORT=SPI1
-D TFT_CS=ST7735_CS
-D TFT_DC=ST7735_RS
-D TFT_RST=ST7735_RESET
-D TFT_BL=ST7735_BL
-D TFT_BACKLIGHT_ON=LOW
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_node_t1>
lib_deps =
${nrf52840_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1
bodmer/TFT_eSPI@2.5.43
@@ -0,0 +1,85 @@
/*
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()
{
pinMode(PIN_BUZZER_VOLTAGE_MULTIPLIER_1, OUTPUT);
pinMode(PIN_BUZZER_VOLTAGE_MULTIPLIER_2, OUTPUT);
digitalWrite(PIN_BUZZER_VOLTAGE_MULTIPLIER_1, HIGH);
digitalWrite(PIN_BUZZER_VOLTAGE_MULTIPLIER_2, HIGH);
}
void variant_shutdown()
{
nrf_gpio_cfg_default(ST7735_CS);
nrf_gpio_cfg_default(ST7735_RS);
nrf_gpio_cfg_default(ST7735_SDA);
nrf_gpio_cfg_default(ST7735_SCK);
nrf_gpio_cfg_default(ST7735_RESET);
nrf_gpio_cfg_default(ST7735_BL);
nrf_gpio_cfg_default(VTFT_CTRL);
nrf_gpio_cfg_default(PIN_WIRE_SDA);
nrf_gpio_cfg_default(PIN_WIRE_SCL);
nrf_gpio_cfg_default(SX126X_CS);
nrf_gpio_cfg_default(SX126X_DIO1);
nrf_gpio_cfg_default(SX126X_BUSY);
nrf_gpio_cfg_default(SX126X_RESET);
nrf_gpio_cfg_default(PIN_SPI_MISO);
nrf_gpio_cfg_default(PIN_SPI_MOSI);
nrf_gpio_cfg_default(PIN_SPI_SCK);
// nrf_gpio_cfg_default(PIN_SPI1_MISO);// ST7735 doesn't support MISO, so we don't configure it at all
nrf_gpio_cfg_default(PIN_SPI1_MOSI);
nrf_gpio_cfg_default(PIN_SPI1_SCK);
nrf_gpio_cfg_default(PIN_GPS_RESET);
nrf_gpio_cfg_default(PIN_GPS_EN);
nrf_gpio_cfg_default(PIN_GPS_PPS);
nrf_gpio_cfg_default(GPS_TX_PIN);
nrf_gpio_cfg_default(GPS_RX_PIN);
nrf_gpio_cfg_default(PIN_BUZZER_VOLTAGE_MULTIPLIER_1);
nrf_gpio_cfg_default(PIN_BUZZER_VOLTAGE_MULTIPLIER_2);
pinMode(PIN_BUZZER, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
pinMode(PIN_SENSOR_EN, OUTPUT);
digitalWrite(PIN_SENSOR_EN, !PIN_SENSOR_EN_ACTIVE); // Turn off sensor power
pinMode(PIN_LED1, OUTPUT);
digitalWrite(PIN_LED1, HIGH);
}
@@ -0,0 +1,177 @@
/*
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_HELTEC_MESH_NODE_T1_
#define _VARIANT_HELTEC_MESH_NODE_T1_
/** 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
#define ST7735_CS (0 + 12)
#define ST7735_RS (0 + 22) // DC
#define ST7735_SDA (0 + 24)
#define ST7735_SCK (32 + 0)
#define ST7735_RESET (0 + 20)
#define ST7735_MISO -1
#define ST7735_BUSY -1
#define ST7735_BL (0 + 15)
#define VTFT_CTRL (0 + 13) // Active HIGH, powers the ST7735 display
#define SPI_FREQUENCY 80000000
#define SPI_READ_FREQUENCY 16000000
#define SCREEN_ROTATE
#define TFT_HEIGHT 160
#define TFT_WIDTH 80
#define TFT_OFFSET_X 24
#define TFT_OFFSET_Y 0
#define TFT_INVERT false
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
#define DISPLAY_FORCE_SMALL_FONTS
// 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)
// LEDs
#define PIN_LED1 (0 + 16)
#define LED_BLUE PIN_LED1 // fake for bluefruit library
#define LED_GREEN PIN_LED1
#define LED_STATE_ON 0 // State when LED is lit
/*
* Buttons
*/
#define PIN_BUTTON1 (32 + 10)
#define PIN_BUTTON2 (0 + 14)
/*
No longer populated on PCB
*/
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
/*
* I2C
*/
#define WIRE_INTERFACES_COUNT 1
// I2C bus 1
#define PIN_WIRE_SDA (32 + 3)
#define PIN_WIRE_SCL (0 + 10)
#define PIN_SENSOR_EN (32 + 6) // Power control pin for sensors
#define PIN_SENSOR_EN_ACTIVE LOW // Power control active state
// #define ICM_42607P_INT_PIN (32 + 1) // ICM42607P INT1, Arduino pin 33 / nRF P1.01
// #define ICM_42607P_INT2_PIN (32 + 7) // ICM42607P INT2, Arduino pin 39 / nRF P1.07
/*
* Lora radio
*/
#define USE_SX1262
#define SX126X_CS (32 + 11) // FIXME - we really should define LORA_CS instead
#define LORA_CS SX126X_CS
#define SX126X_DIO1 (0 + 31)
#define SX126X_BUSY (0 + 29)
#define SX126X_RESET (0 + 2)
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
// For LORA, spi 0
#define PIN_SPI_MISO (0 + 3)
#define PIN_SPI_MOSI (32 + 14)
#define PIN_SPI_SCK (32 + 13)
#define PIN_SPI1_MISO ST7735_MISO
#define PIN_SPI1_MOSI ST7735_SDA
#define PIN_SPI1_SCK ST7735_SCK
/*
* GPS pins
*/
#define GPS_UC6580
#define GPS_BAUDRATE 115200
#define PIN_GPS_RESET (0 + 26)
#define GPS_RESET_MODE LOW
#define PIN_GPS_EN (0 + 4)
#define GPS_EN_ACTIVE LOW
#define PERIPHERAL_WARMUP_MS 1000 // Make sure I2C QuickLink has stable power before continuing
#define PIN_GPS_PPS (32 + 9) // Pulse per second input from the GPS
#define GPS_TX_PIN (0 + 7)
#define GPS_RX_PIN (0 + 8)
#define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX GPS_RX_PIN
#define PIN_SERIAL1_TX GPS_TX_PIN
#define PIN_BUZZER (0 + 9)
#define PIN_BUZZER_VOLTAGE_MULTIPLIER_1 (32 + 2)
#define PIN_BUZZER_VOLTAGE_MULTIPLIER_2 (32 + 5)
#define ADC_CTRL 11
#define ADC_CTRL_ENABLED HIGH
#define BATTERY_PIN 5
#define ADC_RESOLUTION 14
#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 (4.916F)
// nrf52840 AIN3 = Pin 5
// commented out due to power leakage of 2.9mA in shutdown state see reported issue #8801
#define BATTERY_LPCOMP_INPUT NRF_LPCOMP_INPUT_3
// We have AIN3 with a VBAT divider so AIN3 = VBAT * (100/490)
// We have the device going deep sleep under 3.1V, which is AIN3 = 0.63V
// So we can wake up when VBAT>=VDD is restored to 3.3V, where AIN3 = 0.67V
// Ratio 0.67/3.3 = 0.20, so we can pick a bit higher, 2/8 VDD, which means
// VBAT=4.04V
#define BATTERY_LPCOMP_THRESHOLD NRF_LPCOMP_REF_SUPPLY_2_8
#define HAS_RTC 0
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif