Merge remote-tracking branch 'upstream/dev' into keymindCascade
# Conflicts: # examples/companion_radio/NodePrefs.h
This commit is contained in:
commit
6fafcc67a7
16 files changed
+960
-8
No files matched your search
@@ -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": "nrf52.cfg"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Seeed SenseCAP MeshTracker 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"
|
||||
}
|
||||
@@ -317,6 +317,9 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
file.read((uint8_t *)&_prefs.radio_fem_rxgain, sizeof(_prefs.radio_fem_rxgain)); // 122
|
||||
file.read((uint8_t *)&_prefs.radio_fem_rxgain_override,
|
||||
sizeof(_prefs.radio_fem_rxgain_override)); // 123
|
||||
if (file.available() >= (int)sizeof(_prefs.vibe_quiet)) {
|
||||
file.read((uint8_t *)&_prefs.vibe_quiet, sizeof(_prefs.vibe_quiet)); // 124
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
@@ -364,6 +367,8 @@ bool DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
||||
success = success && file.write((uint8_t *)&_prefs.radio_fem_rxgain, sizeof(_prefs.radio_fem_rxgain)) == sizeof(_prefs.radio_fem_rxgain); // 122
|
||||
success = success && file.write((uint8_t *)&_prefs.radio_fem_rxgain_override,
|
||||
sizeof(_prefs.radio_fem_rxgain_override)) == sizeof(_prefs.radio_fem_rxgain_override); // 123
|
||||
success = success && file.write((uint8_t *)&_prefs.vibe_quiet,
|
||||
sizeof(_prefs.vibe_quiet)) == sizeof(_prefs.vibe_quiet); // 124
|
||||
|
||||
#if defined(NRF52_PLATFORM)
|
||||
success = file.commit(success);
|
||||
|
||||
@@ -346,7 +346,7 @@ float MyMesh::getAirtimeBudgetFactor() const {
|
||||
}
|
||||
|
||||
bool MyMesh::getCADEnabled() const {
|
||||
return true; // hardware CAD before TX (no CLI toggle on companion; enabled by default)
|
||||
return true; // tuned branch behavior: hardware CAD before every companion TX
|
||||
}
|
||||
|
||||
int MyMesh::getInterferenceThreshold() const {
|
||||
@@ -1309,6 +1309,7 @@ void MyMesh::begin(bool has_display) {
|
||||
_prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, -9, MAX_LORA_TX_POWER);
|
||||
_prefs.multi_acks = constrain(_prefs.multi_acks, 0, 1);
|
||||
_prefs.manual_add_contacts = constrain(_prefs.manual_add_contacts, 0, 1);
|
||||
_prefs.vibe_quiet = constrain(_prefs.vibe_quiet, 0, 1);
|
||||
_prefs.gps_enabled = constrain(_prefs.gps_enabled, 0, 1); // Ensure boolean 0 or 1
|
||||
_prefs.gps_interval = constrain(_prefs.gps_interval, 0, 86400); // Max 24 hours
|
||||
_prefs.autoadd_config &= AUTO_ADD_OVERWRITE_OLDEST | AUTO_ADD_CHAT | AUTO_ADD_REPEATER | AUTO_ADD_ROOM_SERVER | AUTO_ADD_SENSOR;
|
||||
|
||||
@@ -36,6 +36,7 @@ struct NodePrefs { // persisted to file
|
||||
char default_scope_name[31];
|
||||
uint8_t default_scope_key[16];
|
||||
uint8_t radio_fem_rxgain_override; // 1 once the user overrides the build default
|
||||
uint8_t vibe_quiet; // haptic quiet mode; appended for prefs compatibility
|
||||
|
||||
// Keep the upstream repeat API while retaining the existing binary prefs
|
||||
// layout used by this branch.
|
||||
|
||||
@@ -6,12 +6,19 @@
|
||||
#define AUTO_OFF_MILLIS 15000 // 15 seconds
|
||||
#define BOOT_SCREEN_MILLIS 3000 // 3 seconds
|
||||
|
||||
#ifdef PIN_STATUS_LED
|
||||
#if defined(PIN_STATUS_LED) || defined(PIN_STATUS_LED_R)
|
||||
#define LED_ON_MILLIS 20
|
||||
#define LED_ON_MSG_MILLIS 200
|
||||
#define LED_CYCLE_MILLIS 4000
|
||||
#endif
|
||||
|
||||
#if defined(PIN_STATUS_LED_R) && defined(PIN_STATUS_LED_G) && defined(PIN_STATUS_LED_B)
|
||||
#define STATUS_LED_RGB 1
|
||||
#ifndef LOW_BATT_MILLIVOLTS
|
||||
#define LOW_BATT_MILLIVOLTS 3500
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USER_BTN_PRESSED
|
||||
#define USER_BTN_PRESSED LOW
|
||||
#endif
|
||||
@@ -60,6 +67,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
||||
buzzer.startup();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DRV2605
|
||||
vibration.begin();
|
||||
vibration.quiet(_node_prefs->vibe_quiet);
|
||||
#endif
|
||||
|
||||
// Initialize digital button if available
|
||||
#ifdef PIN_USER_BTN
|
||||
_userButton = new Button(PIN_USER_BTN, USER_BTN_PRESSED);
|
||||
@@ -144,6 +156,10 @@ void UITask::clearMsgPreview() {
|
||||
void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) {
|
||||
_msgcount = msgcount;
|
||||
|
||||
#ifdef HAS_DRV2605
|
||||
vibration.trigger(); // vibrate even while the app is connected (honors quiet + cooldown)
|
||||
#endif
|
||||
|
||||
if (path_len == 0xFF) {
|
||||
sprintf(_origin, "(F) %s", from_name);
|
||||
} else {
|
||||
@@ -274,8 +290,118 @@ void UITask::renderCurrScreen() {
|
||||
_need_refresh = false;
|
||||
}
|
||||
|
||||
#ifdef STATUS_LED_RGB
|
||||
static void statusLedWrite(uint8_t r, uint8_t g, uint8_t b) {
|
||||
analogWrite(PIN_STATUS_LED_R, r);
|
||||
analogWrite(PIN_STATUS_LED_G, g);
|
||||
analogWrite(PIN_STATUS_LED_B, b);
|
||||
}
|
||||
|
||||
static void statusLedWheel(uint8_t pos) { // smooth hue sweep, 0..255
|
||||
if (pos < 85) {
|
||||
statusLedWrite(255 - pos * 3, pos * 3, 0);
|
||||
} else if (pos < 170) {
|
||||
pos -= 85;
|
||||
statusLedWrite(0, 255 - pos * 3, pos * 3);
|
||||
} else {
|
||||
pos -= 170;
|
||||
statusLedWrite(pos * 3, 0, 255 - pos * 3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void UITask::userLedHandler() {
|
||||
#ifdef PIN_STATUS_LED
|
||||
#ifdef STATUS_LED_RGB
|
||||
static bool booted = false;
|
||||
static bool flourish_active = false;
|
||||
static unsigned long flourish_until = 0;
|
||||
static int prev_msgcount = 0;
|
||||
static int state = 0;
|
||||
static unsigned long next_change = 0;
|
||||
static int last_increment = 0;
|
||||
static unsigned long next_batt_check = 0;
|
||||
static bool low_batt = false;
|
||||
|
||||
unsigned long cur_time = millis();
|
||||
|
||||
if (!booted) { // color sweep on boot
|
||||
booted = true;
|
||||
flourish_until = cur_time + 1200;
|
||||
flourish_active = true;
|
||||
}
|
||||
if (_msgcount > prev_msgcount) { // color sweep when a new message arrives
|
||||
flourish_until = cur_time + 800;
|
||||
flourish_active = true;
|
||||
}
|
||||
prev_msgcount = _msgcount;
|
||||
|
||||
if (flourish_active) {
|
||||
if (cur_time < flourish_until) {
|
||||
statusLedWheel((cur_time % 1200) * 255 / 1200);
|
||||
return;
|
||||
}
|
||||
statusLedWrite(0, 0, 0);
|
||||
flourish_active = false;
|
||||
state = 0;
|
||||
next_change = cur_time;
|
||||
}
|
||||
|
||||
if (cur_time > next_batt_check) { // battery reads are not free, keep them rare
|
||||
low_batt = _board->getBattMilliVolts() < LOW_BATT_MILLIVOLTS;
|
||||
next_batt_check = cur_time + 60000;
|
||||
}
|
||||
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
// charge status display while docked (skipped when messages are waiting,
|
||||
// so the unread indication is never masked)
|
||||
static unsigned long next_pwr_check = 0;
|
||||
static bool ext_powered = false, ext_charging = false;
|
||||
if (cur_time > next_pwr_check) {
|
||||
ext_powered = _board->isExternalPowered();
|
||||
bool chrg = digitalRead(EXT_CHRG_DETECT) == LOW;
|
||||
#ifdef EXT_CHRG_DONE
|
||||
if (digitalRead(EXT_CHRG_DONE) == LOW) chrg = false; // charge-done wins
|
||||
#endif
|
||||
ext_charging = ext_powered && chrg;
|
||||
next_pwr_check = cur_time + 1000;
|
||||
}
|
||||
if (ext_powered && _msgcount == 0) {
|
||||
if (ext_charging) {
|
||||
// amber breathing while charging
|
||||
int ph = cur_time % 2000;
|
||||
int v = ph < 1000 ? ph : 2000 - ph;
|
||||
uint8_t lvl = (uint8_t)(v * 255 / 1000);
|
||||
statusLedWrite(lvl, (uint8_t)(lvl * 35 / 100), 0);
|
||||
} else {
|
||||
statusLedWrite(0, 40, 0); // dim solid green: charge complete
|
||||
}
|
||||
state = 0;
|
||||
next_change = cur_time;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cur_time > next_change) {
|
||||
if (state == 0) {
|
||||
state = 1;
|
||||
last_increment = (_msgcount > 0) ? LED_ON_MSG_MILLIS : LED_ON_MILLIS;
|
||||
next_change = cur_time + last_increment;
|
||||
if (low_batt) {
|
||||
statusLedWrite(255, 0, 0); // red: battery low
|
||||
} else if (_msgcount > 0) {
|
||||
statusLedWrite(255, 90, 0); // amber: unread messages
|
||||
} else if (_connected) {
|
||||
statusLedWrite(0, 0, 255); // blue: app connected
|
||||
} else {
|
||||
statusLedWrite(0, 255, 0); // green: heartbeat
|
||||
}
|
||||
} else {
|
||||
state = 0;
|
||||
next_change = cur_time + LED_CYCLE_MILLIS - last_increment;
|
||||
statusLedWrite(0, 0, 0);
|
||||
}
|
||||
}
|
||||
#elif defined(PIN_STATUS_LED)
|
||||
static int state = 0;
|
||||
static int next_change = 0;
|
||||
static int last_increment = 0;
|
||||
@@ -420,8 +546,26 @@ void UITask::handleButtonDoublePress() {
|
||||
|
||||
void UITask::handleButtonTriplePress() {
|
||||
MESH_DEBUG_PRINTLN("UITask: triple press triggered");
|
||||
// Toggle buzzer quiet mode
|
||||
#ifdef PIN_BUZZER
|
||||
#if defined(PIN_BUZZER) && defined(HAS_DRV2605)
|
||||
// cycle alert modes: Buzz+Vibe -> Buzz only -> Vibe only -> Silent
|
||||
int mode = (_node_prefs->buzzer_quiet ? 2 : 0) | (_node_prefs->vibe_quiet ? 1 : 0);
|
||||
mode = (mode + 1) & 3;
|
||||
_node_prefs->buzzer_quiet = (mode & 2) ? 1 : 0;
|
||||
_node_prefs->vibe_quiet = (mode & 1) ? 1 : 0;
|
||||
buzzer.quiet(_node_prefs->buzzer_quiet);
|
||||
vibration.quiet(_node_prefs->vibe_quiet);
|
||||
// audible/tactile confirmation of the new mode (no screen on some boards)
|
||||
if (!_node_prefs->buzzer_quiet) notify(UIEventType::ack);
|
||||
if (!_node_prefs->vibe_quiet) vibration.trigger(true);
|
||||
switch (mode) {
|
||||
case 0: sprintf(_alert, "Alerts: Buzz+Vibe"); break;
|
||||
case 1: sprintf(_alert, "Alerts: Buzz only"); break;
|
||||
case 2: sprintf(_alert, "Alerts: Vibe only"); break;
|
||||
default: sprintf(_alert, "Alerts: Silent"); break;
|
||||
}
|
||||
the_mesh.savePrefs();
|
||||
_need_refresh = true;
|
||||
#elif defined(PIN_BUZZER)
|
||||
if (buzzer.isQuiet()) {
|
||||
buzzer.quiet(false);
|
||||
notify(UIEventType::ack);
|
||||
@@ -433,7 +577,7 @@ void UITask::handleButtonTriplePress() {
|
||||
_node_prefs->buzzer_quiet = buzzer.isQuiet();
|
||||
the_mesh.savePrefs();
|
||||
_need_refresh = true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void UITask::handleButtonQuadruplePress() {
|
||||
|
||||
@@ -14,11 +14,18 @@
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
#ifdef HAS_DRV2605
|
||||
#include <helpers/ui/DRV2605Vibration.h>
|
||||
#endif
|
||||
|
||||
class UITask : public AbstractUITask {
|
||||
DisplayDriver* _display;
|
||||
SensorManager* _sensors;
|
||||
#ifdef PIN_BUZZER
|
||||
genericBuzzer buzzer;
|
||||
#endif
|
||||
#ifdef HAS_DRV2605
|
||||
DRV2605Vibration vibration;
|
||||
#endif
|
||||
unsigned long _next_refresh, _auto_off;
|
||||
NodePrefs* _node_prefs;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifdef HAS_DRV2605
|
||||
|
||||
#include "DRV2605Vibration.h"
|
||||
#include <Wire.h>
|
||||
|
||||
void DRV2605Vibration::begin() {
|
||||
#ifdef PIN_DRV_EN
|
||||
pinMode(PIN_DRV_EN, OUTPUT);
|
||||
digitalWrite(PIN_DRV_EN, HIGH); // power up the haptic driver
|
||||
delay(10);
|
||||
#endif
|
||||
if (!drv.begin(&Wire)) {
|
||||
return; // no haptic driver found, stay silent
|
||||
}
|
||||
#ifdef DRV2605_USE_LRA
|
||||
// LRA mode: 4x brake factor, medium loop gain, back-EMF gain 2
|
||||
drv.writeRegister8(DRV2605_REG_FEEDBACK, 0xB6);
|
||||
#endif
|
||||
drv.selectLibrary(1);
|
||||
drv.setMode(DRV2605_MODE_INTTRIG);
|
||||
_ready = true;
|
||||
}
|
||||
|
||||
void DRV2605Vibration::trigger(bool force) {
|
||||
if (!_ready || _quiet) return;
|
||||
unsigned long now = millis();
|
||||
if (!force && _last_trigger != 0 && now - _last_trigger < VIBRATION_TIMEOUT) return;
|
||||
_last_trigger = now;
|
||||
drv.setWaveform(0, DRV2605_EFFECT);
|
||||
drv.setWaveform(1, 0); // pause
|
||||
drv.setWaveform(2, DRV2605_EFFECT);
|
||||
drv.setWaveform(3, 0); // end of sequence
|
||||
drv.go();
|
||||
}
|
||||
|
||||
void DRV2605Vibration::loop() {
|
||||
}
|
||||
|
||||
bool DRV2605Vibration::isVibrating() {
|
||||
return false; // effects are short, treat as instantaneous
|
||||
}
|
||||
|
||||
void DRV2605Vibration::stop() {
|
||||
if (_ready) drv.stop();
|
||||
}
|
||||
|
||||
#endif // ifdef HAS_DRV2605
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef HAS_DRV2605
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Adafruit_DRV2605.h>
|
||||
|
||||
/*
|
||||
* Vibration control class for boards where the motor is behind a
|
||||
* DRV2605 haptic driver on I2C (e.g. Seeed SenseCAP MeshTracker X1).
|
||||
* Same interface as GenericVibration.
|
||||
*/
|
||||
|
||||
#ifndef VIBRATION_TIMEOUT
|
||||
#define VIBRATION_TIMEOUT 5000 // cooldown between vibrations
|
||||
#endif
|
||||
|
||||
#ifndef DRV2605_EFFECT
|
||||
#define DRV2605_EFFECT 16 // "1000 ms alert" from the DRV2605 effect library
|
||||
#endif
|
||||
|
||||
class DRV2605Vibration {
|
||||
public:
|
||||
void begin(); // power up and init the DRV2605
|
||||
void trigger(bool force = false); // trigger vibration; force skips the cooldown
|
||||
void loop(); // no-op, the DRV2605 plays effects autonomously
|
||||
bool isVibrating();
|
||||
void stop(); // stop vibration immediately
|
||||
void quiet(bool q) { _quiet = q; }
|
||||
bool isQuiet() const { return _quiet; }
|
||||
|
||||
private:
|
||||
Adafruit_DRV2605 drv;
|
||||
bool _ready = false;
|
||||
bool _quiet = false;
|
||||
unsigned long _last_trigger = 0;
|
||||
};
|
||||
|
||||
#endif // ifdef HAS_DRV2605
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "MeshTrackerX1Board.h"
|
||||
|
||||
void MeshTrackerX1Board::begin() {
|
||||
NRF52BoardDCDC::begin();
|
||||
btn_prev_state = LOW; // button is active HIGH
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
pinMode(BATTERY_PIN, INPUT);
|
||||
pinMode(BUTTON_PIN, INPUT_PULLDOWN);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
|
||||
Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
|
||||
#endif
|
||||
|
||||
Wire.begin();
|
||||
|
||||
delay(10); // give lr2021 some time to power up
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
class MeshTrackerX1Board : public NRF52BoardDCDC {
|
||||
protected:
|
||||
uint8_t btn_prev_state;
|
||||
|
||||
public:
|
||||
MeshTrackerX1Board() : NRF52Board("X1_OTA") {}
|
||||
void begin();
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
#ifdef BATTERY_PIN
|
||||
#ifdef PIN_BAT_ADC_EN
|
||||
digitalWrite(PIN_BAT_ADC_EN, HIGH);
|
||||
#endif
|
||||
analogReference(AR_INTERNAL_3_0);
|
||||
analogReadResolution(12);
|
||||
delay(10);
|
||||
float volts = (analogRead(BATTERY_PIN) * ADC_MULTIPLIER * AREF_VOLTAGE) / 4096;
|
||||
|
||||
analogReference(AR_DEFAULT); // put back to default
|
||||
analogReadResolution(10);
|
||||
|
||||
return volts * 1000;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return "Seeed SenseCAP MeshTracker X1";
|
||||
}
|
||||
|
||||
int buttonStateChanged() {
|
||||
#ifdef BUTTON_PIN
|
||||
uint8_t v = digitalRead(BUTTON_PIN);
|
||||
if (v != btn_prev_state) {
|
||||
btn_prev_state = v;
|
||||
return (v == USER_BTN_PRESSED) ? 1 : -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void powerOff() override {
|
||||
#ifdef HAS_GPS
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, LOW);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_DRV_EN
|
||||
digitalWrite(PIN_DRV_EN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_BAT_ADC_EN
|
||||
digitalWrite(PIN_BAT_ADC_EN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_3V3_EN
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
#endif
|
||||
|
||||
// set led on and wait for button release before poweroff
|
||||
#ifdef LED_PIN
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN
|
||||
while(digitalRead(BUTTON_PIN));
|
||||
#endif
|
||||
#ifdef LED_PIN
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
|
||||
#endif
|
||||
|
||||
sd_power_system_off();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
[MeshTracker_X1]
|
||||
extends = nrf52_base
|
||||
board = seeed-mesh-tracker-x1
|
||||
board_build.ldscript = boards/nrf52840_s140_v7.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
|
||||
-I variants/meshtracker_x1
|
||||
-I src/helpers/ui
|
||||
-D MESH_TRACKER_X1
|
||||
-D PIN_USER_BTN=6
|
||||
-D USER_BTN_PRESSED=HIGH
|
||||
-D PIN_STATUS_LED=24
|
||||
-D PIN_STATUS_LED_R=3 ; P0.3 red
|
||||
-D PIN_STATUS_LED_G=24 ; P0.24 green
|
||||
-D PIN_STATUS_LED_B=28 ; P0.28 blue
|
||||
-D RADIO_CLASS=CustomLR2021
|
||||
-D USE_LR2021
|
||||
-D WRAPPER_CLASS=CustomLR2021Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D P_LORA_BUSY=7 ; P0.7
|
||||
-D P_LORA_SCLK=11 ; P0.11
|
||||
-D P_LORA_NSS=12 ; P0.12
|
||||
-D P_LORA_DIO_1=33 ; P1.1
|
||||
-D P_LORA_MISO=40 ; P1.8
|
||||
-D P_LORA_MOSI=41 ; P1.9
|
||||
-D P_LORA_RESET=42 ; P1.10
|
||||
-D LR2021_IRQ_DIO=8 ; P1.1 is connected to LR2021 DIO8
|
||||
-D LR2021_TCXO_VOLTAGE=1.6f
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<../variants/meshtracker_x1>
|
||||
lib_deps = ${nrf52_base.lib_deps}
|
||||
https://github.com/adafruit/Adafruit_SPA06_003/archive/refs/tags/1.0.2.zip
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
|
||||
[env:MeshTracker_X1_repeater]
|
||||
extends = MeshTracker_X1
|
||||
build_flags = ${MeshTracker_X1.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ADVERT_NAME='"MeshTracker X1 Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${MeshTracker_X1.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps = ${MeshTracker_X1.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
|
||||
[env:MeshTracker_X1_room_server]
|
||||
extends = MeshTracker_X1
|
||||
build_flags = ${MeshTracker_X1.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ADVERT_NAME='"MeshTracker X1 Room"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${MeshTracker_X1.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps = ${MeshTracker_X1.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
|
||||
[env:MeshTracker_X1_companion_radio_usb]
|
||||
extends = MeshTracker_X1
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${MeshTracker_X1.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D PIN_BUZZER=25
|
||||
-D HAS_DRV2605=1
|
||||
-D DRV2605_USE_LRA=1
|
||||
-D ENABLE_USB_INTERFACE
|
||||
build_src_filter = ${MeshTracker_X1.build_src_filter}
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<helpers/ui/DRV2605Vibration.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${MeshTracker_X1.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit DRV2605 Library @ ^1.2.4
|
||||
|
||||
[env:MeshTracker_X1_companion_radio_ble]
|
||||
extends = MeshTracker_X1
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${MeshTracker_X1.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_TX_POWER=0
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D PIN_BUZZER=25
|
||||
-D HAS_DRV2605=1
|
||||
-D DRV2605_USE_LRA=1
|
||||
-D ADVERT_NAME='"@@MAC"'
|
||||
build_src_filter = ${MeshTracker_X1.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<helpers/ui/DRV2605Vibration.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${MeshTracker_X1.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit DRV2605 Library @ ^1.2.4
|
||||
@@ -0,0 +1,132 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
|
||||
MeshTrackerX1Board board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock rtc_clock;
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
||||
MeshTrackerX1SensorManager sensors = MeshTrackerX1SensorManager(nmea);
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
NullDisplayDriver display;
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
return radio.std_init(&SPI);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::start_gps() {
|
||||
gps_active = true;
|
||||
// this init sequence comes from seeed examples and deals with all gps pins
|
||||
pinMode(GPS_EN, OUTPUT);
|
||||
digitalWrite(GPS_EN, HIGH);
|
||||
delay(10);
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
delay(10);
|
||||
|
||||
pinMode(GPS_RESET, OUTPUT);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
delay(10);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::sleep_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, HIGH); // keep RTC alive for faster fix on wake
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::stop_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
bool MeshTrackerX1SensorManager::begin() {
|
||||
// init GPS
|
||||
Serial1.begin(GPS_BAUD_RATE);
|
||||
|
||||
// init SPA06-003 barometer
|
||||
baro_ok = spa06.begin(SPA06_003_DEFAULT_ADDR, &Wire) || spa06.begin(0x76, &Wire);
|
||||
if (baro_ok) {
|
||||
spa06.setPressureOversampling(SPA06_003_OVERSAMPLE_8);
|
||||
spa06.setTemperatureOversampling(SPA06_003_OVERSAMPLE_8);
|
||||
// 1 Hz continuous keeps reads non-blocking at minimal power cost
|
||||
spa06.setPressureMeasureRate(SPA06_003_RATE_1);
|
||||
spa06.setTemperatureMeasureRate(SPA06_003_RATE_1);
|
||||
spa06.setMeasurementMode(SPA06_003_MEAS_CONTINUOUS_BOTH);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeshTrackerX1SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
|
||||
if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission?
|
||||
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
|
||||
}
|
||||
if (requester_permissions & TELEM_PERM_ENVIRONMENT && baro_ok) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, spa06.readTemperature());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, spa06.readPressure());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::loop() {
|
||||
static long next_gps_update = 0;
|
||||
|
||||
|
||||
_nmea->loop();
|
||||
|
||||
if (millis() > next_gps_update) {
|
||||
if (gps_active && _nmea->isValid()) {
|
||||
node_lat = ((double)_nmea->getLatitude())/1000000.;
|
||||
node_lon = ((double)_nmea->getLongitude())/1000000.;
|
||||
node_altitude = ((double)_nmea->getAltitude()) / 1000.0;
|
||||
}
|
||||
next_gps_update = millis() + 1000;
|
||||
}
|
||||
}
|
||||
|
||||
int MeshTrackerX1SensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch)
|
||||
|
||||
const char* MeshTrackerX1SensorManager::getSettingName(int i) const {
|
||||
return i == 0 ? "gps" : NULL;
|
||||
}
|
||||
const char* MeshTrackerX1SensorManager::getSettingValue(int i) const {
|
||||
if (i == 0) {
|
||||
return gps_active ? "1" : "0";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
bool MeshTrackerX1SensorManager::setSettingValue(const char* name, const char* value) {
|
||||
if (strcmp(name, "gps") == 0) {
|
||||
if (strcmp(value, "0") == 0) {
|
||||
sleep_gps(); // sleep for faster fix !
|
||||
} else {
|
||||
start_gps();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false; // not supported
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include "MeshTrackerX1Board.h"
|
||||
#include <helpers/radiolib/CustomLR2021Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <Adafruit_SPA06_003.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include "NullDisplayDriver.h"
|
||||
#endif
|
||||
|
||||
class MeshTrackerX1SensorManager: public SensorManager {
|
||||
bool gps_active = false;
|
||||
bool baro_ok = false;
|
||||
Adafruit_SPA06_003 spa06;
|
||||
LocationProvider * _nmea;
|
||||
|
||||
void start_gps();
|
||||
void sleep_gps();
|
||||
void stop_gps();
|
||||
public:
|
||||
MeshTrackerX1SensorManager(LocationProvider &nmea): _nmea(&nmea) { }
|
||||
bool begin() override;
|
||||
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
|
||||
void loop() override;
|
||||
int getNumSettings() const override;
|
||||
const char* getSettingName(int i) const override;
|
||||
const char* getSettingValue(int i) const override;
|
||||
bool setSettingValue(const char* name, const char* value) override;
|
||||
LocationProvider* getLocationProvider() { return _nmea; }
|
||||
};
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern NullDisplayDriver display;
|
||||
#endif
|
||||
|
||||
extern MeshTrackerX1Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern VolatileRTCClock rtc_clock;
|
||||
extern MeshTrackerX1SensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* variant.cpp - Seeed SenseCAP MeshTracker X1 (nRF52840 + Semtech LR2021)
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[PINS_COUNT + 1] =
|
||||
{
|
||||
0, // P0.00
|
||||
1, // P0.01
|
||||
2, // P0.02, AIN0 BATTERY_PIN
|
||||
3, // P0.03, LED_RED
|
||||
4, // P0.04, AIN2 VCC_ADC
|
||||
5, // P0.05, AIN3 EXT_PWR_DETECT
|
||||
6, // P0.06, PIN_BUTTON1
|
||||
7, // P0.07, LORA_BUSY
|
||||
8, // P0.08, GPS_RESET
|
||||
9, // P0.09, PIN_RTC_EN
|
||||
10, // P0.10
|
||||
11, // P0.11, PIN_SPI_SCK
|
||||
12, // P0.12, PIN_SPI_NSS
|
||||
13, // P0.13, PIN_SERIAL1_TX
|
||||
14, // P0.14, PIN_SERIAL1_RX
|
||||
15, // P0.15
|
||||
16, // P0.16, PIN_SERIAL2_TX
|
||||
17, // P0.17, PIN_SERIAL2_RX
|
||||
18, // P0.18
|
||||
19, // P0.19
|
||||
20, // P0.20
|
||||
21, // P0.21
|
||||
22, // P0.22
|
||||
23, // P0.23
|
||||
24, // P0.24, LED_GREEN
|
||||
25, // P0.25, BUZZER_PIN
|
||||
26, // P0.26
|
||||
27, // P0.27
|
||||
28, // P0.28, LED_BLUE
|
||||
29, // P0.29, GPS_RTC_INT
|
||||
30, // P0.30, GPS_SLEEP_INT
|
||||
31, // P0.31
|
||||
32, // P1.00
|
||||
33, // P1.01, LORA_DIO_1 (LR2021 DIO8 IRQ)
|
||||
34, // P1.02
|
||||
35, // P1.03, EXT_CHRG_DETECT
|
||||
36, // P1.04, CHARGE_DONE
|
||||
37, // P1.05, PIN_DRV_EN
|
||||
38, // P1.06, PIN_BAT_ADC_EN
|
||||
39, // P1.07, PIN_3V3_EN
|
||||
40, // P1.08, PIN_SPI_MISO
|
||||
41, // P1.09, PIN_SPI_MOSI
|
||||
42, // P1.10, LORA_RESET
|
||||
43, // P1.11, GPS_EN
|
||||
44, // P1.12
|
||||
45, // P1.13, GPS_VRTC_EN
|
||||
46, // P1.14, PIN_WIRE_SCL
|
||||
47, // P1.15, PIN_WIRE_SDA
|
||||
255, // NRFX_SPIM_PIN_NOT_USED
|
||||
};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
pinMode(BATTERY_PIN, INPUT);
|
||||
pinMode(EXT_CHRG_DETECT, INPUT_PULLUP);
|
||||
pinMode(EXT_CHRG_DONE, INPUT_PULLUP);
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
pinMode(PIN_BUTTON1, INPUT_PULLDOWN);
|
||||
|
||||
pinMode(PIN_3V3_EN, OUTPUT);
|
||||
digitalWrite(PIN_3V3_EN, HIGH);
|
||||
|
||||
pinMode(PIN_BAT_ADC_EN, OUTPUT);
|
||||
digitalWrite(PIN_BAT_ADC_EN, HIGH);
|
||||
|
||||
pinMode(PIN_RTC_EN, OUTPUT);
|
||||
digitalWrite(PIN_RTC_EN, LOW);
|
||||
|
||||
pinMode(PIN_DRV_EN, OUTPUT);
|
||||
digitalWrite(PIN_DRV_EN, LOW);
|
||||
|
||||
pinMode(LED_RED, OUTPUT);
|
||||
digitalWrite(LED_RED, LOW);
|
||||
|
||||
pinMode(LED_GREEN, OUTPUT);
|
||||
digitalWrite(LED_GREEN, LOW);
|
||||
|
||||
pinMode(LED_BLUE, OUTPUT);
|
||||
digitalWrite(LED_BLUE, LOW);
|
||||
|
||||
pinMode(GPS_EN, OUTPUT);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
|
||||
pinMode(GPS_RESET, OUTPUT);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
|
||||
pinMode(BUZZER_PIN, INPUT_PULLDOWN);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* variant.h - Seeed SenseCAP MeshTracker X1 (nRF52840 + Semtech LR2021)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency clock source
|
||||
|
||||
#define USE_LFXO // 32.768 kHz crystal oscillator
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Power
|
||||
|
||||
#define NRF_APM // detect usb power
|
||||
#define PIN_3V3_EN (39) // P1.7 Power to sensors
|
||||
#define PIN_BAT_ADC_EN (38) // P1.6 Power to battery ADC divider
|
||||
#define PIN_RTC_EN (9) // P0.9 Power to RTC
|
||||
|
||||
#define BATTERY_PIN (2) // P0.2/AIN0
|
||||
#define BATTERY_IMMUTABLE
|
||||
#define ADC_MULTIPLIER (2.0F)
|
||||
|
||||
#define EXT_CHRG_DETECT (35) // P1.3, LOW while charging
|
||||
#define EXT_CHRG_DONE (36) // P1.4, LOW when charge complete
|
||||
#define EXT_PWR_DETECT (5) // P0.5
|
||||
|
||||
#define ADC_RESOLUTION (14)
|
||||
#define BATTERY_SENSE_RES (12)
|
||||
|
||||
#define AREF_VOLTAGE (3.0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (6)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UART pin definition
|
||||
|
||||
#define PIN_SERIAL1_RX (14) // P0.14 (GPS)
|
||||
#define PIN_SERIAL1_TX (13) // P0.13 (GPS)
|
||||
|
||||
#define PIN_SERIAL2_RX (17) // P0.17
|
||||
#define PIN_SERIAL2_TX (16) // P0.16
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C pin definition
|
||||
|
||||
#define HAS_WIRE (1)
|
||||
#define WIRE_INTERFACES_COUNT (1)
|
||||
|
||||
#define PIN_WIRE_SDA (47) // P1.15
|
||||
#define PIN_WIRE_SCL (46) // P1.14
|
||||
#define I2C_NO_RESCAN
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI pin definition
|
||||
|
||||
#define SPI_INTERFACES_COUNT (1)
|
||||
|
||||
#define PIN_SPI_MISO (40) // P1.8
|
||||
#define PIN_SPI_MOSI (41) // P1.9
|
||||
#define PIN_SPI_SCK (11) // P0.11
|
||||
#define PIN_SPI_NSS (12) // P0.12
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin LEDs (RGB)
|
||||
|
||||
#define LED_BUILTIN (-1)
|
||||
#define LED_RED (3) // P0.3
|
||||
#define LED_GREEN (24) // P0.24
|
||||
#define LED_BLUE (28) // P0.28
|
||||
#define LED_PIN LED_GREEN
|
||||
|
||||
#define LED_STATE_ON HIGH
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin buttons
|
||||
|
||||
#define PIN_BUTTON1 (6) // P0.6, active HIGH (internal pull-down)
|
||||
#define BUTTON_PIN PIN_BUTTON1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LR2021
|
||||
|
||||
#define LORA_DIO_1 (33) // P1.1, IRQ line (LR2021 DIO8)
|
||||
#define LORA_NSS (PIN_SPI_NSS) // P0.12
|
||||
#define LORA_RESET (42) // P1.10
|
||||
#define LORA_BUSY (7) // P0.7
|
||||
#define LORA_SCLK (PIN_SPI_SCK) // P0.11
|
||||
#define LORA_MISO (PIN_SPI_MISO) // P1.8
|
||||
#define LORA_MOSI (PIN_SPI_MOSI) // P1.9
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GPS (Airoha, dual-band L1+L5)
|
||||
|
||||
#define HAS_GPS 1
|
||||
#define GPS_RX_PIN PIN_SERIAL1_RX
|
||||
#define GPS_TX_PIN PIN_SERIAL1_TX
|
||||
#define GPS_BAUD_RATE (115200)
|
||||
|
||||
#define GPS_EN (43) // P1.11, active HIGH
|
||||
#define GPS_RESET (8) // P0.8, active HIGH
|
||||
|
||||
#define GPS_VRTC_EN (45) // P1.13
|
||||
#define GPS_SLEEP_INT (30) // P0.30
|
||||
#define GPS_RTC_INT (29) // P0.29
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Haptic driver (DRV2605 on I2C)
|
||||
|
||||
#define PIN_DRV_EN (37) // P1.5, power to haptic driver
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Buzzer
|
||||
|
||||
#define BUZZER_PIN (25) // P0.25, pwm output
|
||||
@@ -85,7 +85,6 @@ build_flags =
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
|
||||
-D QSPIFLASH=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${ThinkNode_M6.build_src_filter}
|
||||
@@ -107,7 +106,6 @@ build_flags =
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D QSPIFLASH=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
|
||||
-D ENABLE_USB_INTERFACE
|
||||
|
||||
Reference in new issue
Block a user