From 7509c1a6dd0d2c27e156ae8d696ed4cd6a0b722c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Thu, 2 Jul 2026 14:39:52 +0200 Subject: [PATCH] Seeed Tracker X1 Support (#10834) * Seeed Tracker X1 Support * silence CPPCheck * fix macro order regression and adapt stm32hal for new radiolib * STM32 is a radiolib upstream fix ( https://github.com/jgromes/RadioLib/issues/1825 ) * fix STM32 regression * Seeed Tracker X1 Support * silence CPPCheck * fix macro order regression and adapt stm32hal for new radiolib * STM32 is a radiolib upstream fix ( https://github.com/jgromes/RadioLib/issues/1825 ) * fix STM32 regression * address copilot OCD * Split behavior only when the two LEDs are on distinct pins. * bring naming in line with the other seeed devices * update env name to fit convention too * guarantee evaluation order * Guard sensor readings against null values, make sensor use less power --- boards/mesh-tracker-x1.json | 60 ++++++ platformio.ini | 4 +- src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 6 +- src/main.cpp | 11 ++ src/modules/ExternalNotificationModule.cpp | 49 +++-- src/modules/ExternalNotificationModule.h | 1 + src/modules/StatusLEDModule.cpp | 16 ++ .../Telemetry/EnvironmentTelemetry.cpp | 11 +- src/modules/Telemetry/Sensor/SPA06Sensor.cpp | 60 ++++++ src/modules/Telemetry/Sensor/SPA06Sensor.h | 22 +++ src/platform/nrf52/architecture.h | 2 + src/sleep.cpp | 8 +- .../seeed_mesh_tracker_X1/platformio.ini | 33 ++++ .../nrf52840/seeed_mesh_tracker_X1/rfswitch.h | 9 + .../seeed_mesh_tracker_X1/variant.cpp | 71 ++++++++ .../nrf52840/seeed_mesh_tracker_X1/variant.h | 172 ++++++++++++++++++ 17 files changed, 514 insertions(+), 22 deletions(-) create mode 100644 boards/mesh-tracker-x1.json create mode 100644 src/modules/Telemetry/Sensor/SPA06Sensor.cpp create mode 100644 src/modules/Telemetry/Sensor/SPA06Sensor.h create mode 100644 variants/nrf52840/seeed_mesh_tracker_X1/platformio.ini create mode 100644 variants/nrf52840/seeed_mesh_tracker_X1/rfswitch.h create mode 100644 variants/nrf52840/seeed_mesh_tracker_X1/variant.cpp create mode 100644 variants/nrf52840/seeed_mesh_tracker_X1/variant.h diff --git a/boards/mesh-tracker-x1.json b/boards/mesh-tracker-x1.json new file mode 100644 index 000000000..5a7dce86b --- /dev/null +++ b/boards/mesh-tracker-x1.json @@ -0,0 +1,60 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v7.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x8029"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"], + ["0x239A", "0x802A"], + ["0x2886", "0x0057"] + ], + "usb_product": "X1-BOOT", + "mcu": "nrf52840", + "variant": "Seeed_Mesh-Tracker-X1", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "7.3.0", + "sd_fwid": "0x0123" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Seeed Mesh Tracker X1", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/SenseCAP-MeshTracker-X1-for-Meshtastic-p-6793.html", + "vendor": "Seeed Studio" +} diff --git a/platformio.ini b/platformio.ini index 6b0183713..32a5d9d3e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -122,7 +122,7 @@ lib_deps = [radiolib_base] lib_deps = # renovate: datasource=github-tags depName=RadioLib packageName=jgromes/RadioLib - https://github.com/jgromes/RadioLib/archive/afe72ae46a343e15e3cac7f26ac585c7f98bffe5.zip + https://github.com/jgromes/RadioLib/archive/10e7925db2727e1f5c1c796191905d0a7d955eec.zip [device-ui_base] lib_deps = @@ -210,6 +210,8 @@ lib_deps = https://github.com/Sensirion/arduino-i2c-scd30/archive/1.1.1.zip # renovate: datasource=github-tags depName=arduino-sht packageName=sensirion/arduino-sht https://github.com/Sensirion/arduino-sht/archive/refs/tags/v1.2.6.zip + # renovate: datasource=github-tags depName=SPA06_003 packageName=adafruit/Adafruit_SPA06_003 + https://github.com/adafruit/Adafruit_SPA06_003/archive/refs/tags/1.0.2.zip ; Common environmental sensor libraries (not included in native / portduino) [environmental_extra_common] diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 2333601f7..3dcbe3c6a 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -101,6 +101,7 @@ class ScanI2C ADS1115, IIS2MDCTR, ISM330DHCX, + SPA06, } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 3db497dc2..ff4f9b890 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -441,8 +441,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) logFoundDevice("DPS310", (uint8_t)addr.address); type = DPS310; break; + case 0x11: + logFoundDevice("SPA06-003", (uint8_t)addr.address); + type = SPA06; + break; } - if (type == DPS310) { + if (type == DPS310 || type == SPA06) { break; } default: diff --git a/src/main.cpp b/src/main.cpp index d1739b0d0..8f2a737e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -874,6 +874,17 @@ void setup() delay(10); #endif drv.begin(); + + // Bits Field Value Meaning + // 7 N_ERM_LRA 1 LRA mode (vs 0 = ERM) + // 6:4 FB_BRAKE_FACTOR 3 4× brake factor + // 3:2 LOOP_GAIN 1 medium loop gain + // 1:0 BEMF_GAIN 2 back-EMF gain + +#if defined(DRV2605_USE_LRA) + drv.writeRegister8(DRV2605_REG_FEEDBACK, 0xB6); +#endif + drv.selectLibrary(1); // I2C trigger by sending 'go' command drv.setMode(DRV2605_MODE_INTTRIG); diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 8a98e86df..a6757e04b 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -127,7 +127,10 @@ int32_t ExternalNotificationModule::runOnce() #endif #ifdef HAS_DRV2605 - drv.go(); + // Only trigger DRV2605 if vibration alerts are enabled + if (moduleConfig.external_notification.alert_message_vibra || moduleConfig.external_notification.alert_bell_vibra) { + drv.go(); + } #endif } @@ -144,7 +147,7 @@ int32_t ExternalNotificationModule::runOnce() } #endif // now let the PWM buzzer play - if (moduleConfig.external_notification.use_pwm && config.device.buzzer_gpio && canBuzz()) { + if (moduleConfig.external_notification.use_pwm && config.device.buzzer_gpio && canBuzz() && buzzerShouldAlert) { if (rtttl::isPlaying()) { rtttl::play(); } else if (isNagging && (nagCycleCutoff >= millis())) { @@ -225,9 +228,18 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on) #endif #ifdef HAS_DRV2605 + // Only trigger DRV2605 when setting vibration motor + bool shouldTriggerDRV = false; if (on) { + if (index == 1 && + (moduleConfig.external_notification.alert_message_vibra || moduleConfig.external_notification.alert_bell_vibra)) { + shouldTriggerDRV = true; + } + } + + if (shouldTriggerDRV) { drv.go(); - } else { + } else if (!on && index == 1) { drv.stop(); } #endif @@ -266,6 +278,7 @@ void ExternalNotificationModule::stopNow() // Prevent the state machine from immediately re-triggering outputs after a manual stop. isNagging = false; + buzzerShouldAlert = false; nagCycleCutoff = UINT32_MAX; #ifdef HAS_I2S @@ -404,8 +417,10 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP // Alert GPIO Buzzer when receiving a bell = alertBellBuzzer: true // Alert GPIO Buzzer when receiving a message = alertMessageBuzzer: true - const bool buzzerShouldAlert = canBuzz() && ((moduleConfig.external_notification.alert_bell_buzzer && containsBell) || - (moduleConfig.external_notification.alert_message_buzzer && !is_muted)); + // If you are already buzzing, keep going + buzzerShouldAlert = + buzzerShouldAlert || (canBuzz() && ((moduleConfig.external_notification.alert_bell_buzzer && containsBell) || + (moduleConfig.external_notification.alert_message_buzzer && !is_muted))); if (genericShouldAlert || vibraShouldAlert || buzzerShouldAlert) { nagCycleCutoff = millis() + (moduleConfig.external_notification.nag_timeout @@ -422,6 +437,18 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP if (vibraShouldAlert) { LOG_INFO("externalNotificationModule - Vibra alert"); +#ifdef HAS_DRV2605 + // Set DRV2605 waveform when vibration alert is triggered + drv.setWaveform(0, 16); // Long buzzer 100% + drv.setWaveform(1, 0); // Pause + drv.setWaveform(2, 16); + drv.setWaveform(3, 0); + drv.setWaveform(4, 16); + drv.setWaveform(5, 0); + drv.setWaveform(6, 16); + drv.setWaveform(7, 0); + drv.go(); +#endif setExternalState(1, true); } @@ -431,18 +458,6 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP LOG_INFO("Message buzzer was suppressed because buzzer mode DIRECT_MSG_ONLY"); } else { // Buzz if buzzer mode is not in DIRECT_MSG_ONLY or is DM to us -#ifdef HAS_DRV2605 - drv.setWaveform(0, 16); // Long buzzer 100% - drv.setWaveform(1, 0); // Pause - drv.setWaveform(2, 16); - drv.setWaveform(3, 0); - drv.setWaveform(4, 16); - drv.setWaveform(5, 0); - drv.setWaveform(6, 16); - drv.setWaveform(7, 0); - drv.go(); -#endif - if (moduleConfig.external_notification.use_i2s_as_buzzer) { #ifdef HAS_I2S audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone)); diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index 8781c1ca8..03eac036b 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -90,6 +90,7 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: bool isNagging = false; bool isSilenced = false; + bool buzzerShouldAlert = false; virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, diff --git a/src/modules/StatusLEDModule.cpp b/src/modules/StatusLEDModule.cpp index 353317d25..5c6f84942 100644 --- a/src/modules/StatusLEDModule.cpp +++ b/src/modules/StatusLEDModule.cpp @@ -215,9 +215,25 @@ int32_t StatusLEDModule::runOnce() #ifdef PCA_LED_ENABLE io.digitalWrite(PCA_LED_ENABLE, CHARGE_LED_state); #endif + #ifdef LED_POWER +#ifdef LED_POWER_CRITICAL + if (LED_POWER != LED_POWER_CRITICAL) { + if (power_state == critical) { + digitalWrite(LED_POWER, 0); + digitalWrite(LED_POWER_CRITICAL, CHARGE_LED_state); + } else { + digitalWrite(LED_POWER, CHARGE_LED_state); + digitalWrite(LED_POWER_CRITICAL, 0); + } + } else { + digitalWrite(LED_POWER, CHARGE_LED_state); + } +#else digitalWrite(LED_POWER, CHARGE_LED_state); #endif +#endif + #ifdef LED_PAIRING digitalWrite(LED_PAIRING, PAIRING_LED_state); #endif diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 1d599b8e8..eafa056c6 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -119,6 +119,10 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c #include "Sensor/T1000xSensor.h" #endif +#if __has_include() +#include "Sensor/SPA06Sensor.h" +#endif + #ifdef SENSECAP_INDICATOR #include "Sensor/IndicatorSensor.h" #endif @@ -167,12 +171,15 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner) // Not a real I2C device, uses UART addSensor(i2cScanner, ScanI2C::DeviceType::NONE); #endif - addSensor(i2cScanner, ScanI2C::DeviceType::RCWL9620); - addSensor(i2cScanner, ScanI2C::DeviceType::CGRADSENS); +#if HAS_SPA06 && __has_include() + addSensor(i2cScanner, ScanI2C::DeviceType::SPA06); +#endif #endif #endif #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL + addSensor(i2cScanner, ScanI2C::DeviceType::RCWL9620); + addSensor(i2cScanner, ScanI2C::DeviceType::CGRADSENS); #if __has_include() addSensor(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK); #endif diff --git a/src/modules/Telemetry/Sensor/SPA06Sensor.cpp b/src/modules/Telemetry/Sensor/SPA06Sensor.cpp new file mode 100644 index 000000000..052e3f8eb --- /dev/null +++ b/src/modules/Telemetry/Sensor/SPA06Sensor.cpp @@ -0,0 +1,60 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "SPA06Sensor.h" +#include "TelemetrySensor.h" +#include + +SPA06Sensor::SPA06Sensor() + : TelemetrySensor(meshtastic_TelemetrySensorType_SPA06, "SPA06"), spa_temp(nullptr), spa_pressure(nullptr) +{ +} + +bool SPA06Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) +{ + LOG_INFO("Init sensor: %s", sensorName); + status = spa06.begin(dev->address.address, bus); + if (!status) { + return status; + } + // Set moderate precision for faster sampling + spa06.setPressureOversampling(SPA06_003_OVERSAMPLE_8); // 8x oversampling + spa06.setTemperatureOversampling(SPA06_003_OVERSAMPLE_8); // 8x oversampling + + // Set measurement rate. 1 Hz is ample for telemetry (polled every tens of seconds) + // and draws far less power than 32 Hz, while staying in continuous mode so getMetrics() + // remains non-blocking (fresh data always available). + spa06.setPressureMeasureRate(SPA06_003_RATE_1); // 1 Hz + spa06.setTemperatureMeasureRate(SPA06_003_RATE_1); // 1 Hz + spa06.setMeasurementMode(SPA06_003_MEAS_CONTINUOUS_BOTH); + + spa_temp = spa06.getTemperatureSensor(); + spa_pressure = spa06.getPressureSensor(); + + initI2CSensor(); + return status; +} + +bool SPA06Sensor::getMetrics(meshtastic_Telemetry *measurement) +{ + if (!spa_temp || !spa_pressure) { + return false; + } + + sensors_event_t temp, press; + + if (!spa_temp->getEvent(&temp) || !spa_pressure->getEvent(&press)) { + LOG_DEBUG("SPA06 getEvents no data"); + return false; + } + + measurement->variant.environment_metrics.has_temperature = true; + measurement->variant.environment_metrics.has_barometric_pressure = true; + measurement->variant.environment_metrics.temperature = temp.temperature; + measurement->variant.environment_metrics.barometric_pressure = press.pressure; + + return true; +} +#endif diff --git a/src/modules/Telemetry/Sensor/SPA06Sensor.h b/src/modules/Telemetry/Sensor/SPA06Sensor.h new file mode 100644 index 000000000..01aadb5cf --- /dev/null +++ b/src/modules/Telemetry/Sensor/SPA06Sensor.h @@ -0,0 +1,22 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include + +class SPA06Sensor : public TelemetrySensor +{ + private: + Adafruit_SPA06_003 spa06; + Adafruit_Sensor *spa_temp; + Adafruit_Sensor *spa_pressure; + + public: + SPA06Sensor(); + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; + virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override; +}; + +#endif diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 3f14e6fa0..600fb8192 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -113,6 +113,8 @@ #define HW_VENDOR meshtastic_HardwareModel_WIO_WM1110 #elif defined(TRACKER_T1000_E) #define HW_VENDOR meshtastic_HardwareModel_TRACKER_T1000_E +#elif defined(MESH_TRACKER_X1) +#define HW_VENDOR meshtastic_HardwareModel_MESH_TRACKER_X1 #elif defined(ME25LS01_4Y10TD) #define HW_VENDOR meshtastic_HardwareModel_ME25LS01_4Y10TD #elif defined(MS24SF1) diff --git a/src/sleep.cpp b/src/sleep.cpp index 626fc4e11..86d226d3a 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -266,20 +266,26 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN digitalWrite(SDCARD_CS, LOW); #endif -#ifdef TRACKER_T1000_E +#if defined(TRACKER_T1000_E) || defined(MESH_TRACKER_X1) #ifdef GNSS_AIROHA digitalWrite(GPS_VRTC_EN, LOW); digitalWrite(PIN_GPS_RESET, LOW); digitalWrite(GPS_SLEEP_INT, LOW); digitalWrite(GPS_RTC_INT, LOW); +#ifdef GPS_RESETB_OUT pinMode(GPS_RESETB_OUT, OUTPUT); digitalWrite(GPS_RESETB_OUT, LOW); #endif +#endif #ifdef BUZZER_EN_PIN digitalWrite(BUZZER_EN_PIN, LOW); #endif +#ifdef PIN_DRV_EN + digitalWrite(PIN_DRV_EN, LOW); +#endif + #ifdef PIN_3V3_EN digitalWrite(PIN_3V3_EN, LOW); #endif diff --git a/variants/nrf52840/seeed_mesh_tracker_X1/platformio.ini b/variants/nrf52840/seeed_mesh_tracker_X1/platformio.ini new file mode 100644 index 000000000..e12fbfd9a --- /dev/null +++ b/variants/nrf52840/seeed_mesh_tracker_X1/platformio.ini @@ -0,0 +1,33 @@ +[env:seeed_mesh_tracker_X1] +custom_meshtastic_support_level = 1 +custom_meshtastic_images = seeed-mesh-tracker-x1.svg +custom_meshtastic_tags = Seeed +custom_meshtastic_hw_model = 128 +custom_meshtastic_hw_model_slug = MESH_TRACKER_X1 +custom_meshtastic_architecture = nrf52840 +custom_meshtastic_display_name = Seeed SenseCAP Mesh-Tracker-X1 +custom_meshtastic_actively_supported = true + +extends = nrf52840_base +board = mesh-tracker-x1 +board_level = pr +build_flags = ${nrf52840_base.build_flags} + -Ivariants/nrf52840/seeed_mesh_tracker_X1 + -Isrc/platform/nrf52/softdevice + -Isrc/platform/nrf52/softdevice/nrf52 + -DMESH_TRACKER_X1 + -DCONFIG_NFCT_PINS_AS_GPIOS=1 + -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL=1 + -DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -DMESHTASTIC_EXCLUDE_SCREEN=1 + -DMESHTASTIC_EXCLUDE_DETECTIONSENSOR=1 + -DMESHTASTIC_EXCLUDE_WIFI=1 +board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/seeed_mesh_tracker_X1> +lib_deps = + ${nrf52840_base.lib_deps} + adafruit/Adafruit DRV2605 Library@1.2.4 + +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +upload_protocol = nrfutil diff --git a/variants/nrf52840/seeed_mesh_tracker_X1/rfswitch.h b/variants/nrf52840/seeed_mesh_tracker_X1/rfswitch.h new file mode 100644 index 000000000..a007b3780 --- /dev/null +++ b/variants/nrf52840/seeed_mesh_tracker_X1/rfswitch.h @@ -0,0 +1,9 @@ +#include "RadioLib.h" +#include "nrf.h" + +static const uint32_t lr2021_rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t lr2021_rfswitch_table[] = { + {LR2021::MODE_STBY, {}}, {LR2021::MODE_RX, {}}, {LR2021::MODE_TX, {}}, + {LR2021::MODE_RX_HF, {}}, {LR2021::MODE_TX_HF, {}}, END_OF_MODE_TABLE, +}; diff --git a/variants/nrf52840/seeed_mesh_tracker_X1/variant.cpp b/variants/nrf52840/seeed_mesh_tracker_X1/variant.cpp new file mode 100644 index 000000000..2ad8b92b8 --- /dev/null +++ b/variants/nrf52840/seeed_mesh_tracker_X1/variant.cpp @@ -0,0 +1,71 @@ +/* + 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 "DebugConfiguration.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(PIN_3V3_EN, OUTPUT); + digitalWrite(PIN_3V3_EN, HIGH); + + pinMode(PIN_BAT_ADC_EN, OUTPUT); + digitalWrite(PIN_BAT_ADC_EN, HIGH); + + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, LOW); + + pinMode(PIN_LED2, OUTPUT); + digitalWrite(PIN_LED2, LOW); + + pinMode(PIN_LED3, OUTPUT); + digitalWrite(PIN_LED3, LOW); + + pinMode(PIN_DRV_EN, OUTPUT); + digitalWrite(PIN_DRV_EN, LOW); + + pinMode(PIN_RTC_EN, OUTPUT); + digitalWrite(PIN_RTC_EN, LOW); + + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, LOW); + + pinMode(GPS_VRTC_EN, OUTPUT); + digitalWrite(GPS_VRTC_EN, HIGH); + + pinMode(PIN_GPS_RESET, OUTPUT); + digitalWrite(PIN_GPS_RESET, LOW); + + pinMode(GPS_SLEEP_INT, OUTPUT); + digitalWrite(GPS_SLEEP_INT, HIGH); + + pinMode(GPS_RTC_INT, OUTPUT); + digitalWrite(GPS_RTC_INT, LOW); +} diff --git a/variants/nrf52840/seeed_mesh_tracker_X1/variant.h b/variants/nrf52840/seeed_mesh_tracker_X1/variant.h new file mode 100644 index 000000000..b9882d719 --- /dev/null +++ b/variants/nrf52840/seeed_mesh_tracker_X1/variant.h @@ -0,0 +1,172 @@ +/* + 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_MESH_TRACKER_X1_ +#define _VARIANT_MESH_TRACKER_X1_ + +/** 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 +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (6) +#define NUM_ANALOG_OUTPUTS (0) + +// Use the native nrf52 usb power detection +#define NRF_APM + +// PIN_3V3_EN use in deep sleep , as power pin. +#define PIN_3V3_EN (32 + 7) // P1.7, Power to Sensors +#define PIN_BAT_ADC_EN (32 + 6) // P1.6, Power to battery ADC +#define PIN_RTC_EN (0 + 9) // P0.9, Power to RTC + +#define PIN_LED1 (0 + 3) // P0.3, red led +#define PIN_LED2 (0 + 24) // P0.24, green led +#define PIN_LED3 (0 + 28) // P0.28, blue led +#define LED_POWER PIN_LED2 +#define LED_RED PIN_LED1 +#define LED_BLUE -1 // Actually green +#define LED_STATE_ON 1 // State when LED is lit +#define LED_POWER_CRITICAL LED_RED // red LED doubles as the low-battery/critical indicator + +// ARCH_NRF52 auto define HAS_BUTTON 1 +#define HAS_BUTTON 1 +#define BUTTON_PIN (0 + 6) // P0.06 +#define BUTTON_ACTIVE_LOW false +#define BUTTON_ACTIVE_PULLUP false +#define BUTTON_SENSE_TYPE 0x5 // enable input pull-down + +/**************** Sensor *******************/ + +#define HAS_WIRE 1 +#define WIRE_INTERFACES_COUNT 1 // have 1 I2C interface, Wire + +#define PIN_WIRE_SDA (32 + 15) // P1.15 +#define PIN_WIRE_SCL (32 + 14) // P1.14 +#define I2C_NO_RESCAN // I2C is a bit finicky, don't scan too much + +#define HAS_DRV2605 1 // haptic driver +#define DRV2605_USE_LRA +#define PIN_DRV_EN (32 + 5) // P1.05, Power to haptic driver + +#define HAS_SPA06 1 + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (0 + 14) // P0.14 +#define PIN_SERIAL1_TX (0 + 13) // P0.13 + +#define PIN_SERIAL2_RX (0 + 17) // P0.17 +#define PIN_SERIAL2_TX (0 + 16) // P0.16 + +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (32 + 8) // P1.08 +#define PIN_SPI_MOSI (32 + 9) // P1.09 +#define PIN_SPI_SCK (0 + 11) // P0.11 +#define PIN_SPI_NSS (0 + 12) // P0.12 + +#define LORA_RESET (32 + 10) // P1.10 // RST +#define LORA_DIO1 (32 + 1) // P1.01 // IRQ +#define LORA_DIO2 (0 + 7) // P0.07 // BUSY +#define LORA_SCK PIN_SPI_SCK +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_CS PIN_SPI_NSS + +// supported modules list +#define USE_LR2021 +#define IRQ_DIO_NUM 8 + +#define LR2021_IRQ_PIN LORA_DIO1 +#define LR2021_NRESET_PIN LORA_RESET +#define LR2021_BUSY_PIN LORA_DIO2 +#define LR2021_SPI_NSS_PIN LORA_CS +#define LR2021_SPI_SCK_PIN LORA_SCK +#define LR2021_SPI_MOSI_PIN LORA_MOSI +#define LR2021_SPI_MISO_PIN LORA_MISO + +#define LR2021_DIO3_TCXO_VOLTAGE 1.6 +// #define LR2021_DIO_AS_RF_SWITCH + +// GPS +#define HAS_GPS 1 +#define GNSS_AIROHA +#define GPS_RX_PIN PIN_SERIAL1_RX +#define GPS_TX_PIN PIN_SERIAL1_TX + +#define GPS_BAUDRATE 115200 +#define GPS_PROBETRIES 8 + +#define PIN_GPS_EN (32 + 11) // P1.11 +#define GPS_EN_ACTIVE HIGH + +#define PIN_GPS_RESET (0 + 8) // P0.8 +#define GPS_RESET_MODE HIGH + +#define GPS_VRTC_EN (32 + 13) // P1.13, always high +#define GPS_SLEEP_INT (0 + 30) // P0.30, always high +#define GPS_RTC_INT (0 + 29) // P0.29, normal is LOW, wake by HIGH + +#define BATTERY_PIN 2 // P0.02/AIN0, BAT_ADC +#define BATTERY_IMMUTABLE +#define ADC_MULTIPLIER (2.0F) +// P0.04/AIN2 is VCC_ADC, P0.05/AIN3 is CHARGER_DET, P1.03 is CHARGE_STA, P1.04 is CHARGE_DONE + +#define EXT_CHRG_DETECT (32 + 3) // P1.03 +#define EXT_CHRG_DETECT_VALUE LOW +// #define EXT_IS_CHRGD (32 + 4) // P1.04 +// #define EXT_IS_CHRGD_VALUE LOW +#define EXT_PWR_DETECT (0 + 5) // P0.05 + +#define ADC_RESOLUTION 14 +#define BATTERY_SENSE_RESOLUTION_BITS 12 + +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 + +#define OCV_ARRAY 4290, 4118, 4002, 3889, 3798, 3728, 3677, 3643, 3594, 3500, 3100 + +// Buzzer +#define PIN_BUZZER (0 + 25) // P0.25, pwm output + +#define HAS_SCREEN 0 + +#ifdef __cplusplus +} +#endif +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif // _VARIANT_MESH_TRACKER_X1_