mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-08 14:12:05 +00:00
Merge branch 'master' into apollo
This commit is contained in:
commit
7a3f30f99e
@ -20,6 +20,7 @@ Lora:
|
|||||||
# CS: 0
|
# CS: 0
|
||||||
# IRQ: 10
|
# IRQ: 10
|
||||||
# Busy: 11
|
# Busy: 11
|
||||||
|
# DIO2_AS_RF_SWITCH: true
|
||||||
# spidev: spidev0.1
|
# spidev: spidev0.1
|
||||||
|
|
||||||
# Module: RF95 # Adafruit RFM9x
|
# Module: RF95 # Adafruit RFM9x
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Meshtastic Native Daemon
|
Description=Meshtastic Native Daemon
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
|
StartLimitInterval=200
|
||||||
|
StartLimitBurst=5
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/usr/sbin/meshtasticd
|
ExecStart=/usr/sbin/meshtasticd
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
|
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
|
||||||
mkdir /etc/meshtasticd
|
mkdir -p /etc/meshtasticd
|
||||||
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||||
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||||
else
|
else
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e22381a3c6bbdd428f127ed8c0aa0a37789c3907
|
Subproject commit 7960241ccdd6b262a11b79523857037f755ab847
|
@ -360,7 +360,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
/**
|
/**
|
||||||
* return true if there is a battery installed in this unit
|
* return true if there is a battery installed in this unit
|
||||||
*/
|
*/
|
||||||
|
// if we have a integrated device with a battery, we can assume that the battery is always connected
|
||||||
|
#ifdef BATTERY_IMMUTABLE
|
||||||
|
virtual bool isBatteryConnect() override { return true; }
|
||||||
|
#else
|
||||||
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
|
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
||||||
/// in power
|
/// in power
|
||||||
|
@ -51,9 +51,9 @@ class RedirectablePrint : public Print
|
|||||||
protected:
|
protected:
|
||||||
/// Subclasses can override if they need to change how we format over the serial port
|
/// Subclasses can override if they need to change how we format over the serial port
|
||||||
virtual void log_to_serial(const char *logLevel, const char *format, va_list arg);
|
virtual void log_to_serial(const char *logLevel, const char *format, va_list arg);
|
||||||
|
meshtastic_LogRecord_Level getLogLevel(const char *logLevel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void log_to_syslog(const char *logLevel, const char *format, va_list arg);
|
void log_to_syslog(const char *logLevel, const char *format, va_list arg);
|
||||||
void log_to_ble(const char *logLevel, const char *format, va_list arg);
|
void log_to_ble(const char *logLevel, const char *format, va_list arg);
|
||||||
meshtastic_LogRecord_Level getLogLevel(const char *logLevel);
|
|
||||||
};
|
};
|
@ -99,25 +99,7 @@ bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
|||||||
void SerialConsole::log_to_serial(const char *logLevel, const char *format, va_list arg)
|
void SerialConsole::log_to_serial(const char *logLevel, const char *format, va_list arg)
|
||||||
{
|
{
|
||||||
if (usingProtobufs && config.security.debug_log_api_enabled) {
|
if (usingProtobufs && config.security.debug_log_api_enabled) {
|
||||||
meshtastic_LogRecord_Level ll = meshtastic_LogRecord_Level_UNSET; // default to unset
|
meshtastic_LogRecord_Level ll = RedirectablePrint::getLogLevel(logLevel);
|
||||||
switch (logLevel[0]) {
|
|
||||||
case 'D':
|
|
||||||
ll = meshtastic_LogRecord_Level_DEBUG;
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
ll = meshtastic_LogRecord_Level_INFO;
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
ll = meshtastic_LogRecord_Level_WARNING;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
ll = meshtastic_LogRecord_Level_ERROR;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
ll = meshtastic_LogRecord_Level_CRITICAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto thread = concurrency::OSThread::currentThread;
|
auto thread = concurrency::OSThread::currentThread;
|
||||||
emitLogRecord(ll, thread ? thread->ThreadName.c_str() : "", format, arg);
|
emitLogRecord(ll, thread ? thread->ThreadName.c_str() : "", format, arg);
|
||||||
} else
|
} else
|
||||||
|
@ -55,6 +55,18 @@ void playBeep()
|
|||||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void playGPSEnableBeep()
|
||||||
|
{
|
||||||
|
ToneDuration melody[] = {{NOTE_C3, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}, {NOTE_CS4, DURATION_1_4}};
|
||||||
|
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||||
|
}
|
||||||
|
|
||||||
|
void playGPSDisableBeep()
|
||||||
|
{
|
||||||
|
ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}, {NOTE_C3, DURATION_1_4}};
|
||||||
|
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||||
|
}
|
||||||
|
|
||||||
void playStartMelody()
|
void playStartMelody()
|
||||||
{
|
{
|
||||||
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8}, {NOTE_CS4, DURATION_1_4}};
|
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8}, {NOTE_CS4, DURATION_1_4}};
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
void playBeep();
|
void playBeep();
|
||||||
void playStartMelody();
|
void playStartMelody();
|
||||||
void playShutdownMelody();
|
void playShutdownMelody();
|
||||||
|
void playGPSEnableBeep();
|
||||||
|
void playGPSDisableBeep();
|
@ -114,6 +114,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define CARDKB_ADDR 0x5F
|
#define CARDKB_ADDR 0x5F
|
||||||
#define TDECK_KB_ADDR 0x55
|
#define TDECK_KB_ADDR 0x55
|
||||||
#define BBQ10_KB_ADDR 0x1F
|
#define BBQ10_KB_ADDR 0x1F
|
||||||
|
#define MPR121_KB_ADDR 0x5A
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// SENSOR
|
// SENSOR
|
||||||
@ -135,6 +136,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define LPS22HB_ADDR_ALT 0x5D
|
#define LPS22HB_ADDR_ALT 0x5D
|
||||||
#define SHT31_4x_ADDR 0x44
|
#define SHT31_4x_ADDR 0x44
|
||||||
#define PMSA0031_ADDR 0x12
|
#define PMSA0031_ADDR 0x12
|
||||||
|
#define QMA6100P_ADDR 0x12
|
||||||
#define AHT10_ADDR 0x38
|
#define AHT10_ADDR 0x38
|
||||||
#define RCWL9620_ADDR 0x57
|
#define RCWL9620_ADDR 0x57
|
||||||
#define VEML7700_ADDR 0x10
|
#define VEML7700_ADDR 0x10
|
||||||
|
@ -31,14 +31,14 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
|||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||||
{
|
{
|
||||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004};
|
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB};
|
||||||
return firstOfOrNONE(4, types);
|
return firstOfOrNONE(5, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||||
{
|
{
|
||||||
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948};
|
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948, QMA6100P};
|
||||||
return firstOfOrNONE(7, types);
|
return firstOfOrNONE(8, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
|
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
|
||||||
|
@ -39,6 +39,7 @@ class ScanI2C
|
|||||||
QMC5883L,
|
QMC5883L,
|
||||||
HMC5883L,
|
HMC5883L,
|
||||||
PMSA0031,
|
PMSA0031,
|
||||||
|
QMA6100P,
|
||||||
MPU6050,
|
MPU6050,
|
||||||
LIS3DH,
|
LIS3DH,
|
||||||
BMA423,
|
BMA423,
|
||||||
@ -61,7 +62,8 @@ class ScanI2C
|
|||||||
STK8BAXX,
|
STK8BAXX,
|
||||||
ICM20948,
|
ICM20948,
|
||||||
MAX30102,
|
MAX30102,
|
||||||
TPS65233
|
TPS65233,
|
||||||
|
MPR121KB
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
// typedef uint8_t DeviceAddress;
|
// typedef uint8_t DeviceAddress;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||||
#include "main.h" // atecc
|
#include "main.h" // atecc
|
||||||
|
#include "meshUtils.h" // vformat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||||
@ -172,7 +173,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (addr.address = 1; addr.address < 127; addr.address++) {
|
// We only need to scan 112 addresses, the rest is reserved for special purposes
|
||||||
|
// 0x00 General Call
|
||||||
|
// 0x01 CBUS addresses
|
||||||
|
// 0x02 Reserved for different bus formats
|
||||||
|
// 0x03 Reserved for future purposes
|
||||||
|
// 0x04-0x07 High Speed Master Code
|
||||||
|
// 0x78-0x7B 10-bit slave addressing
|
||||||
|
// 0x7C-0x7F Reserved for future purposes
|
||||||
|
|
||||||
|
for (addr.address = 8; addr.address < 120; addr.address++) {
|
||||||
if (asize != 0) {
|
if (asize != 0) {
|
||||||
if (!in_array(address, asize, addr.address))
|
if (!in_array(address, asize, addr.address))
|
||||||
continue;
|
continue;
|
||||||
@ -243,6 +253,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
|
|
||||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found");
|
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found");
|
||||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found");
|
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found");
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found");
|
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found");
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found");
|
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found");
|
||||||
@ -393,7 +404,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
|
|
||||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found")
|
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found")
|
||||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found")
|
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found")
|
||||||
|
#ifdef HAS_QMA6100P
|
||||||
|
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P accelerometer found")
|
||||||
|
#else
|
||||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found")
|
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found")
|
||||||
|
#endif
|
||||||
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found");
|
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found");
|
||||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found");
|
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found");
|
||||||
@ -408,7 +423,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
#ifdef HAS_TPS65233
|
#ifdef HAS_TPS65233
|
||||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found");
|
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found");
|
||||||
#endif
|
#endif
|
||||||
SCAN_SIMPLE_CASE(MLX90614_ADDR_DEF, MLX90614, "MLX90614 IR temp sensor found");
|
|
||||||
|
case MLX90614_ADDR_DEF:
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1);
|
||||||
|
if (registerValue == 0x5a) {
|
||||||
|
type = MLX90614;
|
||||||
|
LOG_INFO("MLX90614 IR temp sensor found");
|
||||||
|
} else {
|
||||||
|
type = MPR121KB;
|
||||||
|
LOG_INFO("MPR121KB keyboard found");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ICM20948_ADDR: // same as BMX160_ADDR
|
case ICM20948_ADDR: // same as BMX160_ADDR
|
||||||
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
|
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
#if 0
|
|
||||||
// Turn off for now
|
|
||||||
uint32_t axpDebugRead()
|
|
||||||
{
|
|
||||||
axp.debugCharging();
|
|
||||||
LOG_DEBUG("vbus current %f", axp.getVbusCurrent());
|
|
||||||
LOG_DEBUG("charge current %f", axp.getBattChargeCurrent());
|
|
||||||
LOG_DEBUG("bat voltage %f", axp.getBattVoltage());
|
|
||||||
LOG_DEBUG("batt pct %d", axp.getBattPercentage());
|
|
||||||
LOG_DEBUG("is battery connected %d", axp.isBatteryConnect());
|
|
||||||
LOG_DEBUG("is USB connected %d", axp.isVBUSPlug());
|
|
||||||
LOG_DEBUG("is charging %d", axp.isChargeing());
|
|
||||||
|
|
||||||
return 30 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
Periodic axpDebugOutput(axpDebugRead);
|
|
||||||
axpDebugOutput.setup();
|
|
||||||
#endif
|
|
@ -7,6 +7,7 @@
|
|||||||
#include "PowerMon.h"
|
#include "PowerMon.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "Throttle.h"
|
#include "Throttle.h"
|
||||||
|
#include "buzz.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
|
|
||||||
#include "main.h" // pmu_found
|
#include "main.h" // pmu_found
|
||||||
@ -266,6 +267,9 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
|||||||
uint32_t startTime = millis();
|
uint32_t startTime = millis();
|
||||||
const char frame_errors[] = "More than 100 frame errors";
|
const char frame_errors[] = "More than 100 frame errors";
|
||||||
int sCounter = 0;
|
int sCounter = 0;
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
std::string debugmsg = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int j = 2; j < 6; j++) {
|
for (int j = 2; j < 6; j++) {
|
||||||
buf[8] += buf[j];
|
buf[8] += buf[j];
|
||||||
@ -291,20 +295,24 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
|||||||
if (b == frame_errors[sCounter]) {
|
if (b == frame_errors[sCounter]) {
|
||||||
sCounter++;
|
sCounter++;
|
||||||
if (sCounter == 26) {
|
if (sCounter == 26) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
|
||||||
|
LOG_DEBUG(debugmsg.c_str());
|
||||||
|
#endif
|
||||||
return GNSS_RESPONSE_FRAME_ERRORS;
|
return GNSS_RESPONSE_FRAME_ERRORS;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sCounter = 0;
|
sCounter = 0;
|
||||||
}
|
}
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
LOG_DEBUG("%02X", b);
|
debugmsg += vformat("%02X", b);
|
||||||
#endif
|
#endif
|
||||||
if (b == buf[ack]) {
|
if (b == buf[ack]) {
|
||||||
ack++;
|
ack++;
|
||||||
} else {
|
} else {
|
||||||
if (ack == 3 && b == 0x00) { // UBX-ACK-NAK message
|
if (ack == 3 && b == 0x00) { // UBX-ACK-NAK message
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
LOG_DEBUG("");
|
LOG_DEBUG(debugmsg.c_str());
|
||||||
#endif
|
#endif
|
||||||
LOG_WARN("Got NAK for class %02X message %02X", class_id, msg_id);
|
LOG_WARN("Got NAK for class %02X message %02X", class_id, msg_id);
|
||||||
return GNSS_RESPONSE_NAK; // NAK received
|
return GNSS_RESPONSE_NAK; // NAK received
|
||||||
@ -314,7 +322,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
LOG_DEBUG("");
|
LOG_DEBUG(debugmsg.c_str());
|
||||||
LOG_WARN("No response for class %02X message %02X", class_id, msg_id);
|
LOG_WARN("No response for class %02X message %02X", class_id, msg_id);
|
||||||
#endif
|
#endif
|
||||||
return GNSS_RESPONSE_NONE; // No response received within timeout
|
return GNSS_RESPONSE_NONE; // No response received within timeout
|
||||||
@ -1623,6 +1631,9 @@ bool GPS::whileActive()
|
|||||||
{
|
{
|
||||||
unsigned int charsInBuf = 0;
|
unsigned int charsInBuf = 0;
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
std::string debugmsg = "";
|
||||||
|
#endif
|
||||||
if (powerState != GPS_ACTIVE) {
|
if (powerState != GPS_ACTIVE) {
|
||||||
clearBuffer();
|
clearBuffer();
|
||||||
return false;
|
return false;
|
||||||
@ -1640,7 +1651,7 @@ bool GPS::whileActive()
|
|||||||
int c = _serial_gps->read();
|
int c = _serial_gps->read();
|
||||||
UBXscratch[charsInBuf] = c;
|
UBXscratch[charsInBuf] = c;
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
LOG_DEBUG("%c", c);
|
debugmsg += vformat("%c", (c >= 32 && c <= 126) ? c : '.');
|
||||||
#endif
|
#endif
|
||||||
isValid |= reader.encode(c);
|
isValid |= reader.encode(c);
|
||||||
if (charsInBuf > sizeof(UBXscratch) - 10 || c == '\r') {
|
if (charsInBuf > sizeof(UBXscratch) - 10 || c == '\r') {
|
||||||
@ -1652,6 +1663,9 @@ bool GPS::whileActive()
|
|||||||
charsInBuf++;
|
charsInBuf++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG(debugmsg.c_str());
|
||||||
|
#endif
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
void GPS::enable()
|
void GPS::enable()
|
||||||
@ -1680,6 +1694,7 @@ void GPS::toggleGpsMode()
|
|||||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
|
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
|
||||||
LOG_INFO("User toggled GpsMode. Now DISABLED.");
|
LOG_INFO("User toggled GpsMode. Now DISABLED.");
|
||||||
|
playGPSDisableBeep();
|
||||||
#ifdef GNSS_AIROHA
|
#ifdef GNSS_AIROHA
|
||||||
if (powerState == GPS_ACTIVE) {
|
if (powerState == GPS_ACTIVE) {
|
||||||
LOG_DEBUG("User power Off GPS");
|
LOG_DEBUG("User power Off GPS");
|
||||||
@ -1690,6 +1705,7 @@ void GPS::toggleGpsMode()
|
|||||||
} else if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_DISABLED) {
|
} else if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_DISABLED) {
|
||||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
|
||||||
LOG_INFO("User toggled GpsMode. Now ENABLED");
|
LOG_INFO("User toggled GpsMode. Now ENABLED");
|
||||||
|
playGPSEnableBeep();
|
||||||
enable();
|
enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class GPS : private concurrency::OSThread
|
|||||||
uint8_t fixType = 0; // fix type from GPGSA
|
uint8_t fixType = 0; // fix type from GPGSA
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
const int serialSpeeds[6] = {9600, 4800, 38400, 57600, 115200, 9600};
|
const int serialSpeeds[6] = {9600, 115200, 38400, 4800, 57600, 9600};
|
||||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||||
uint32_t rx_gpio = 0;
|
uint32_t rx_gpio = 0;
|
||||||
uint32_t tx_gpio = 0;
|
uint32_t tx_gpio = 0;
|
||||||
|
430
src/input/MPR121Keyboard.cpp
Normal file
430
src/input/MPR121Keyboard.cpp
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
// Based on the BBQ10 Keyboard
|
||||||
|
|
||||||
|
#include "MPR121Keyboard.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define _MPR121_REG_KEY 0x5a
|
||||||
|
|
||||||
|
#define _MPR121_REG_TOUCH_STATUS 0x00
|
||||||
|
#define _MPR121_REG_ELECTRODE_FILTERED_DATA
|
||||||
|
#define _MPR121_REG_BASELINE_VALUE 0x1E
|
||||||
|
|
||||||
|
// Baseline filters
|
||||||
|
#define _MPR121_REG_MAX_HALF_DELTA_RISING 0x2B
|
||||||
|
#define _MPR121_REG_NOISE_HALF_DELTA_RISING 0x2C
|
||||||
|
#define _MPR121_REG_NOISE_COUNT_LIMIT_RISING 0x2D
|
||||||
|
#define _MPR121_REG_FILTER_DELAY_COUNT_RISING 0x2E
|
||||||
|
#define _MPR121_REG_MAX_HALF_DELTA_FALLING 0x2F
|
||||||
|
#define _MPR121_REG_NOISE_HALF_DELTA_FALLING 0x30
|
||||||
|
#define _MPR121_REG_NOISE_COUNT_LIMIT_FALLING 0x31
|
||||||
|
#define _MPR121_REG_FILTER_DELAY_COUNT_FALLING 0x32
|
||||||
|
#define _MPR121_REG_NOISE_HALF_DELTA_TOUCHED 0x33
|
||||||
|
#define _MPR121_REG_NOISE_COUNT_LIMIT_TOUCHED 0x34
|
||||||
|
#define _MPR121_REG_FILTER_DELAY_COUNT_TOUCHED 0x35
|
||||||
|
|
||||||
|
#define _MPR121_REG_TOUCH_THRESHOLD 0x41 // First input, +2 for subsequent
|
||||||
|
#define _MPR121_REG_RELEASE_THRESHOLD 0x42 // First input, +2 for subsequent
|
||||||
|
#define _MPR121_REG_DEBOUNCE 0x5B
|
||||||
|
#define _MPR121_REG_CONFIG1 0x5C
|
||||||
|
#define _MPR121_REG_CONFIG2 0x5D
|
||||||
|
#define _MPR121_REG_ELECTRODE_CONFIG 0x5E
|
||||||
|
#define _MPR121_REG_SOFT_RESET 0x80
|
||||||
|
|
||||||
|
#define _KEY_MASK 0x0FFF // Key mask for the first 12 bits
|
||||||
|
#define _NUM_KEYS 12
|
||||||
|
|
||||||
|
#define ECR_CALIBRATION_TRACK_FROM_ZERO (0 << 6)
|
||||||
|
#define ECR_CALIBRATION_LOCK (1 << 6)
|
||||||
|
#define ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER (2 << 6) // Recommended Typical Mode
|
||||||
|
#define ECR_CALIBRATION_TRACK_FROM_FULL_FILTER (3 << 6)
|
||||||
|
#define ECR_PROXIMITY_DETECTION_OFF (0 << 0) // Not using proximity detection
|
||||||
|
#define ECR_TOUCH_DETECTION_12CH (12 << 0) // Using all 12 channels
|
||||||
|
|
||||||
|
#define MPR121_NONE 0x00
|
||||||
|
#define MPR121_REBOOT 0x90
|
||||||
|
#define MPR121_LEFT 0xb4
|
||||||
|
#define MPR121_UP 0xb5
|
||||||
|
#define MPR121_DOWN 0xb6
|
||||||
|
#define MPR121_RIGHT 0xb7
|
||||||
|
#define MPR121_ESC 0x1b
|
||||||
|
#define MPR121_BSP 0x08
|
||||||
|
#define MPR121_SELECT 0x0d
|
||||||
|
|
||||||
|
#define MPR121_FN_ON 0xf1
|
||||||
|
#define MPR121_FN_OFF 0xf2
|
||||||
|
|
||||||
|
#define LONG_PRESS_THRESHOLD 2000
|
||||||
|
#define MULTI_TAP_THRESHOLD 2000
|
||||||
|
|
||||||
|
uint8_t TapMod[12] = {1, 2, 1, 13, 7, 7, 7, 7, 7, 9, 7, 9}; // Num chars per key, Modulus for rotating through characters
|
||||||
|
|
||||||
|
unsigned char MPR121_TapMap[12][13] = {{MPR121_BSP},
|
||||||
|
{'0', ' '},
|
||||||
|
{MPR121_SELECT},
|
||||||
|
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'},
|
||||||
|
{'2', 'a', 'b', 'c', 'A', 'B', 'C'},
|
||||||
|
{'3', 'd', 'e', 'f', 'D', 'E', 'F'},
|
||||||
|
{'4', 'g', 'h', 'i', 'G', 'H', 'I'},
|
||||||
|
{'5', 'j', 'k', 'l', 'J', 'K', 'L'},
|
||||||
|
{'6', 'm', 'n', 'o', 'M', 'N', 'O'},
|
||||||
|
{'7', 'p', 'q', 'r', 's', 'P', 'Q', 'R', 'S'},
|
||||||
|
{'8', 't', 'u', 'v', 'T', 'U', 'V'},
|
||||||
|
{'9', 'w', 'x', 'y', 'z', 'W', 'X', 'Y', 'Z'}};
|
||||||
|
|
||||||
|
unsigned char MPR121_LongPressMap[12] = {MPR121_ESC, ' ', MPR121_NONE, MPR121_NONE, MPR121_UP, MPR121_NONE,
|
||||||
|
MPR121_LEFT, MPR121_NONE, MPR121_RIGHT, MPR121_NONE, MPR121_DOWN, MPR121_NONE};
|
||||||
|
|
||||||
|
// Translation map from left to right, top to bottom layout to a more convenient layout to manufacture, matching the
|
||||||
|
// https://www.amazon.com.au/Capacitive-Sensitive-Sensitivity-Replacement-Traditional/dp/B0CTJD5KW9/ref=pd_ci_mcx_mh_mcx_views_0_title?th=1
|
||||||
|
/*uint8_t MPR121_KeyMap[12] = {
|
||||||
|
9, 6, 3, 0,
|
||||||
|
10, 7, 4, 1,
|
||||||
|
11, 8, 5, 2
|
||||||
|
};*/
|
||||||
|
// Rotated Layout
|
||||||
|
uint8_t MPR121_KeyMap[12] = {2, 5, 8, 11, 1, 4, 7, 10, 0, 3, 6, 9};
|
||||||
|
|
||||||
|
MPR121Keyboard::MPR121Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
|
||||||
|
{
|
||||||
|
// LOG_DEBUG("MPR121 @ %02x\n", m_addr);
|
||||||
|
state = Init;
|
||||||
|
last_key = -1;
|
||||||
|
last_tap = 0L;
|
||||||
|
char_idx = 0;
|
||||||
|
queue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::begin(uint8_t addr, TwoWire *wire)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = wire;
|
||||||
|
|
||||||
|
m_wire->begin();
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = nullptr;
|
||||||
|
writeCallback = w;
|
||||||
|
readCallback = r;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::reset()
|
||||||
|
{
|
||||||
|
LOG_DEBUG("MPR121 Resetting...");
|
||||||
|
// Trigger a MPR121 Soft Reset
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(_MPR121_REG_SOFT_RESET);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
uint8_t data = 0;
|
||||||
|
writeCallback(m_addr, _MPR121_REG_SOFT_RESET, &data, 0);
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
// Reset Electrode Configuration to 0x00, Stop Mode
|
||||||
|
writeRegister(_MPR121_REG_ELECTRODE_CONFIG, 0x00);
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
LOG_DEBUG("MPR121 Configuring");
|
||||||
|
// Set touch release thresholds
|
||||||
|
for (uint8_t i = 0; i < 12; i++) {
|
||||||
|
// Set touch threshold
|
||||||
|
writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 15);
|
||||||
|
delay(20);
|
||||||
|
// Set release threshold
|
||||||
|
writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 7);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
// Configure filtering and baseline registers
|
||||||
|
writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x01);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_MAX_HALF_DELTA_FALLING, 0x01);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_HALF_DELTA_RISING, 0x01);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_HALF_DELTA_FALLING, 0x05);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_HALF_DELTA_TOUCHED, 0x00);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x0e);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_FALLING, 0x01);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_TOUCHED, 0x00);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_RISING, 0x00);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_FALLING, 0x00);
|
||||||
|
delay(20);
|
||||||
|
writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_TOUCHED, 0x00);
|
||||||
|
delay(20);
|
||||||
|
// Set Debounce to 0x02
|
||||||
|
writeRegister(_MPR121_REG_DEBOUNCE, 0x00);
|
||||||
|
delay(20);
|
||||||
|
// Set Filter1 itterations and discharge current 6x and 16uA respectively (0x10)
|
||||||
|
writeRegister(_MPR121_REG_CONFIG1, 0x10);
|
||||||
|
delay(20);
|
||||||
|
// Set CDT to 0.5us, Filter2 itterations to 4x, and Sample interval = 0 (0x20)
|
||||||
|
writeRegister(_MPR121_REG_CONFIG2, 0x20);
|
||||||
|
delay(20);
|
||||||
|
// Enter run mode by Seting partial filter calibration tracking, disable proximity detection, enable 12 channels
|
||||||
|
writeRegister(_MPR121_REG_ELECTRODE_CONFIG,
|
||||||
|
ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
|
||||||
|
delay(100);
|
||||||
|
LOG_DEBUG("MPR121 Running");
|
||||||
|
state = Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT_PULLUP);
|
||||||
|
::attachInterrupt(digitalPinToInterrupt(pin), func, RISING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::detachInterrupt(uint8_t pin) const
|
||||||
|
{
|
||||||
|
::detachInterrupt(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MPR121Keyboard::status() const
|
||||||
|
{
|
||||||
|
return readRegister16(_MPR121_REG_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MPR121Keyboard::keyCount() const
|
||||||
|
{
|
||||||
|
// Read the key register
|
||||||
|
uint16_t keyRegister = readRegister16(_MPR121_REG_KEY);
|
||||||
|
return keyCount(keyRegister);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MPR121Keyboard::keyCount(uint16_t value) const
|
||||||
|
{
|
||||||
|
// Mask the first 12 bits
|
||||||
|
uint16_t buttonState = value & _KEY_MASK;
|
||||||
|
|
||||||
|
// Count how many bits are set to 1 (i.e., how many buttons are pressed)
|
||||||
|
uint8_t numButtonsPressed = 0;
|
||||||
|
for (uint8_t i = 0; i < 12; ++i) {
|
||||||
|
if (buttonState & (1 << i)) {
|
||||||
|
numButtonsPressed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numButtonsPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MPR121Keyboard::hasEvent()
|
||||||
|
{
|
||||||
|
return queue.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::queueEvent(char next)
|
||||||
|
{
|
||||||
|
if (next == MPR121_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queue.concat(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
char MPR121Keyboard::dequeueEvent()
|
||||||
|
{
|
||||||
|
if (queue.length() < 1) {
|
||||||
|
return MPR121_NONE;
|
||||||
|
}
|
||||||
|
char next = queue.charAt(0);
|
||||||
|
queue.remove(0, 1);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::trigger()
|
||||||
|
{
|
||||||
|
// Intended to fire in response to an interrupt from the MPR121 or a longpress callback
|
||||||
|
// Only functional if not in Init state
|
||||||
|
if (state != Init) {
|
||||||
|
// Read the key register
|
||||||
|
uint16_t keyRegister = readRegister16(_MPR121_REG_KEY);
|
||||||
|
uint8_t keysPressed = keyCount(keyRegister);
|
||||||
|
if (keysPressed == 0) {
|
||||||
|
// No buttons pressed
|
||||||
|
if (state == Held)
|
||||||
|
released();
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keysPressed == 1) {
|
||||||
|
// No buttons pressed
|
||||||
|
if (state == Held || state == HeldLong)
|
||||||
|
held(keyRegister);
|
||||||
|
if (state == Idle)
|
||||||
|
pressed(keyRegister);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keysPressed > 1) {
|
||||||
|
// Multipress
|
||||||
|
state = Busy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::pressed(uint16_t keyRegister)
|
||||||
|
{
|
||||||
|
if (state == Init || state == Busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keyCount(keyRegister) != 1) {
|
||||||
|
LOG_DEBUG("Multipress");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("Pressed");
|
||||||
|
}
|
||||||
|
uint16_t buttonState = keyRegister & _KEY_MASK;
|
||||||
|
uint8_t next_pin = 0;
|
||||||
|
for (uint8_t i = 0; i < 12; ++i) {
|
||||||
|
if (buttonState & (1 << i)) {
|
||||||
|
next_pin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t next_key = MPR121_KeyMap[next_pin];
|
||||||
|
LOG_DEBUG("MPR121 Pin: %i Key: %i", next_pin, next_key);
|
||||||
|
uint32_t now = millis();
|
||||||
|
int32_t tap_interval = now - last_tap;
|
||||||
|
if (tap_interval < 0) {
|
||||||
|
// long running, millis has overflowed.
|
||||||
|
last_tap = 0;
|
||||||
|
state = Busy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (next_key != last_key || tap_interval > MULTI_TAP_THRESHOLD) {
|
||||||
|
char_idx = 0;
|
||||||
|
} else {
|
||||||
|
char_idx += 1;
|
||||||
|
}
|
||||||
|
last_key = next_key;
|
||||||
|
last_tap = now;
|
||||||
|
state = Held;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::held(uint16_t keyRegister)
|
||||||
|
{
|
||||||
|
if (state == Init || state == Busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keyCount(keyRegister) != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Held");
|
||||||
|
uint16_t buttonState = keyRegister & _KEY_MASK;
|
||||||
|
uint8_t next_key = 0;
|
||||||
|
for (uint8_t i = 0; i < 12; ++i) {
|
||||||
|
if (buttonState & (1 << i)) {
|
||||||
|
next_key = MPR121_KeyMap[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t now = millis();
|
||||||
|
int32_t held_interval = now - last_tap;
|
||||||
|
if (held_interval < 0 || next_key != last_key) {
|
||||||
|
// long running, millis has overflowed, or a key has been switched quickly...
|
||||||
|
last_tap = 0;
|
||||||
|
state = Busy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (held_interval > LONG_PRESS_THRESHOLD) {
|
||||||
|
// Set state to heldlong, send a longpress, and reset the timer...
|
||||||
|
state = HeldLong; // heldlong will allow this function to still fire, but prevent a "release"
|
||||||
|
queueEvent(MPR121_LongPressMap[last_key]);
|
||||||
|
last_tap = now;
|
||||||
|
LOG_DEBUG("Long Press Key: %i Map: %i", last_key, MPR121_LongPressMap[last_key]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::released()
|
||||||
|
{
|
||||||
|
if (state != Held) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// would clear longpress callback... later.
|
||||||
|
if (last_key < 0 || last_key > _NUM_KEYS) { // reset to idle if last_key out of bounds
|
||||||
|
last_key = -1;
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Released");
|
||||||
|
if (char_idx > 0 && TapMod[last_key] > 1) {
|
||||||
|
queueEvent(MPR121_BSP);
|
||||||
|
LOG_DEBUG("Multi Press, Backspace");
|
||||||
|
}
|
||||||
|
queueEvent(MPR121_TapMap[last_key][(char_idx % TapMod[last_key])]);
|
||||||
|
LOG_DEBUG("Key Press: %i Index:%i if %i Map: %i", last_key, char_idx, TapMod[last_key],
|
||||||
|
MPR121_TapMap[last_key][(char_idx % TapMod[last_key])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MPR121Keyboard::readRegister8(uint8_t reg) const
|
||||||
|
{
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)1);
|
||||||
|
if (m_wire->available() < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
uint8_t data;
|
||||||
|
readCallback(m_addr, reg, &data, 1);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MPR121Keyboard::readRegister16(uint8_t reg) const
|
||||||
|
{
|
||||||
|
uint8_t data[2] = {0};
|
||||||
|
// uint8_t low = 0, high = 0;
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)2);
|
||||||
|
if (m_wire->available() < 2)
|
||||||
|
return 0;
|
||||||
|
data[0] = m_wire->read();
|
||||||
|
data[1] = m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
readCallback(m_addr, reg, data, 2);
|
||||||
|
}
|
||||||
|
return (data[1] << 8) | data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPR121Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t data[2];
|
||||||
|
data[0] = reg;
|
||||||
|
data[1] = value;
|
||||||
|
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(data, sizeof(uint8_t) * 2);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||||
|
}
|
||||||
|
}
|
56
src/input/MPR121Keyboard.h
Normal file
56
src/input/MPR121Keyboard.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Based on the BBQ10 Keyboard
|
||||||
|
|
||||||
|
#include "concurrency/NotifiedWorkerThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <main.h>
|
||||||
|
|
||||||
|
class MPR121Keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
enum MPR121States { Init = 0, Idle, Held, HeldLong, Busy };
|
||||||
|
|
||||||
|
MPR121States state;
|
||||||
|
|
||||||
|
int8_t last_key;
|
||||||
|
uint32_t last_tap;
|
||||||
|
uint8_t char_idx;
|
||||||
|
|
||||||
|
String queue;
|
||||||
|
|
||||||
|
MPR121Keyboard();
|
||||||
|
|
||||||
|
void begin(uint8_t addr = MPR121_KB_ADDR, TwoWire *wire = &Wire);
|
||||||
|
|
||||||
|
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = MPR121_KB_ADDR);
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
|
||||||
|
void attachInterrupt(uint8_t pin, void (*func)(void)) const;
|
||||||
|
void detachInterrupt(uint8_t pin) const;
|
||||||
|
|
||||||
|
void trigger(void);
|
||||||
|
void pressed(uint16_t value);
|
||||||
|
void held(uint16_t value);
|
||||||
|
void released(void);
|
||||||
|
|
||||||
|
uint8_t status(void) const;
|
||||||
|
uint8_t keyCount(void) const;
|
||||||
|
uint8_t keyCount(uint16_t value) const;
|
||||||
|
|
||||||
|
bool hasEvent(void);
|
||||||
|
char dequeueEvent(void);
|
||||||
|
void queueEvent(char);
|
||||||
|
|
||||||
|
uint8_t readRegister8(uint8_t reg) const;
|
||||||
|
uint16_t readRegister16(uint8_t reg) const;
|
||||||
|
void writeRegister(uint8_t reg, uint8_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TwoWire *m_wire;
|
||||||
|
uint8_t m_addr;
|
||||||
|
i2c_com_fptr_t readCallback;
|
||||||
|
i2c_com_fptr_t writeCallback;
|
||||||
|
};
|
@ -9,11 +9,11 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
|||||||
|
|
||||||
void CardKbI2cImpl::init()
|
void CardKbI2cImpl::init()
|
||||||
{
|
{
|
||||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO)
|
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
|
||||||
if (cardkb_found.address == 0x00) {
|
if (cardkb_found.address == 0x00) {
|
||||||
LOG_DEBUG("Rescanning for I2C keyboard");
|
LOG_DEBUG("Rescanning for I2C keyboard");
|
||||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR};
|
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR};
|
||||||
uint8_t i2caddr_asize = 3;
|
uint8_t i2caddr_asize = 4;
|
||||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||||
|
|
||||||
#if WIRE_INTERFACES_COUNT == 2
|
#if WIRE_INTERFACES_COUNT == 2
|
||||||
@ -39,12 +39,17 @@ void CardKbI2cImpl::init()
|
|||||||
// assign an arbitrary value to distinguish from other models
|
// assign an arbitrary value to distinguish from other models
|
||||||
kb_model = 0x11;
|
kb_model = 0x11;
|
||||||
break;
|
break;
|
||||||
|
case ScanI2C::DeviceType::MPR121KB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x37;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// use this as default since it's also just zero
|
// use this as default since it's also just zero
|
||||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||||
kb_model = 0x00;
|
kb_model = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
|
||||||
if (cardkb_found.address == 0x00) {
|
if (cardkb_found.address == 0x00) {
|
||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
|
@ -40,6 +40,9 @@ int32_t KbI2cBase::runOnce()
|
|||||||
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
|
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
|
||||||
Q10keyboard.setBacklight(0);
|
Q10keyboard.setBacklight(0);
|
||||||
}
|
}
|
||||||
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case ScanI2C::WIRE:
|
case ScanI2C::WIRE:
|
||||||
@ -49,6 +52,9 @@ int32_t KbI2cBase::runOnce()
|
|||||||
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);
|
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);
|
||||||
Q10keyboard.setBacklight(0);
|
Q10keyboard.setBacklight(0);
|
||||||
}
|
}
|
||||||
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ScanI2C::NO_I2C:
|
case ScanI2C::NO_I2C:
|
||||||
default:
|
default:
|
||||||
@ -157,6 +163,69 @@ int32_t KbI2cBase::runOnce()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0x37: { // MPR121
|
||||||
|
MPRkeyboard.trigger();
|
||||||
|
InputEvent e;
|
||||||
|
|
||||||
|
while (MPRkeyboard.hasEvent()) {
|
||||||
|
char nextEvent = MPRkeyboard.dequeueEvent();
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
e.source = this->_originName;
|
||||||
|
switch (nextEvent) {
|
||||||
|
case 0x00: // MPR121_NONE
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x90: // MPR121_REBOOT
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_REBOOT;
|
||||||
|
break;
|
||||||
|
case 0xb4: // MPR121_LEFT
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case 0xb5: // MPR121_UP
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case 0xb6: // MPR121_DOWN
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case 0xb7: // MPR121_RIGHT
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case 0x1b: // MPR121_ESC
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||||
|
e.kbchar = 0x1b;
|
||||||
|
break;
|
||||||
|
case 0x08: // MPR121_BSP
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||||
|
e.kbchar = 0x08;
|
||||||
|
break;
|
||||||
|
case 0x0d: // MPR121_SELECT
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
|
e.kbchar = 0x0d;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (nextEvent > 127) {
|
||||||
|
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = nextEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
LOG_DEBUG("MP121 Notifying: %i Char: %i", e.inputEvent, e.kbchar);
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0x02: {
|
case 0x02: {
|
||||||
// RAK14004
|
// RAK14004
|
||||||
uint8_t rDataBuf[8] = {0};
|
uint8_t rDataBuf[8] = {0};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "BBQ10Keyboard.h"
|
#include "BBQ10Keyboard.h"
|
||||||
#include "InputBroker.h"
|
#include "InputBroker.h"
|
||||||
|
#include "MPR121Keyboard.h"
|
||||||
#include "Wire.h"
|
#include "Wire.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
@ -19,5 +20,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
|||||||
TwoWire *i2cBus = 0;
|
TwoWire *i2cBus = 0;
|
||||||
|
|
||||||
BBQ10Keyboard Q10keyboard;
|
BBQ10Keyboard Q10keyboard;
|
||||||
|
MPR121Keyboard MPRkeyboard;
|
||||||
bool is_sym = false;
|
bool is_sym = false;
|
||||||
};
|
};
|
@ -27,7 +27,6 @@
|
|||||||
#include "detect/ScanI2CTwoWire.h"
|
#include "detect/ScanI2CTwoWire.h"
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#endif
|
#endif
|
||||||
#include "detect/axpDebug.h"
|
|
||||||
#include "detect/einkScan.h"
|
#include "detect/einkScan.h"
|
||||||
#include "gps/RTC.h"
|
#include "gps/RTC.h"
|
||||||
#include "graphics/RAKled.h"
|
#include "graphics/RAKled.h"
|
||||||
@ -524,6 +523,10 @@ void setup()
|
|||||||
// assign an arbitrary value to distinguish from other models
|
// assign an arbitrary value to distinguish from other models
|
||||||
kb_model = 0x11;
|
kb_model = 0x11;
|
||||||
break;
|
break;
|
||||||
|
case ScanI2C::DeviceType::MPR121KB:
|
||||||
|
// assign an arbitrary value to distinguish from other models
|
||||||
|
kb_model = 0x37;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// use this as default since it's also just zero
|
// use this as default since it's also just zero
|
||||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type);
|
||||||
|
@ -117,13 +117,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
|||||||
static const uint8_t defaultpsk0[] = USERPREFS_CHANNEL_0_PSK;
|
static const uint8_t defaultpsk0[] = USERPREFS_CHANNEL_0_PSK;
|
||||||
memcpy(channelSettings.psk.bytes, defaultpsk0, sizeof(defaultpsk0));
|
memcpy(channelSettings.psk.bytes, defaultpsk0, sizeof(defaultpsk0));
|
||||||
channelSettings.psk.size = sizeof(defaultpsk0);
|
channelSettings.psk.size = sizeof(defaultpsk0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_0_NAME
|
#ifdef USERPREFS_CHANNEL_0_NAME
|
||||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_0_NAME);
|
strcpy(channelSettings.name, USERPREFS_CHANNEL_0_NAME);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_0_PRECISION
|
#ifdef USERPREFS_CHANNEL_0_PRECISION
|
||||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_0_PRECISION;
|
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_0_PRECISION;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_0_UPLINK_ENABLED
|
||||||
|
channelSettings.uplink_enabled = USERPREFS_CHANNEL_0_UPLINK_ENABLED;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_0_DOWNLINK_ENABLED
|
||||||
|
channelSettings.downlink_enabled = USERPREFS_CHANNEL_0_DOWNLINK_ENABLED;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
@ -131,13 +136,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
|||||||
static const uint8_t defaultpsk1[] = USERPREFS_CHANNEL_1_PSK;
|
static const uint8_t defaultpsk1[] = USERPREFS_CHANNEL_1_PSK;
|
||||||
memcpy(channelSettings.psk.bytes, defaultpsk1, sizeof(defaultpsk1));
|
memcpy(channelSettings.psk.bytes, defaultpsk1, sizeof(defaultpsk1));
|
||||||
channelSettings.psk.size = sizeof(defaultpsk1);
|
channelSettings.psk.size = sizeof(defaultpsk1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_1_NAME
|
#ifdef USERPREFS_CHANNEL_1_NAME
|
||||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_1_NAME);
|
strcpy(channelSettings.name, USERPREFS_CHANNEL_1_NAME);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_1_PRECISION
|
#ifdef USERPREFS_CHANNEL_1_PRECISION
|
||||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_1_PRECISION;
|
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_1_PRECISION;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_1_UPLINK_ENABLED
|
||||||
|
channelSettings.uplink_enabled = USERPREFS_CHANNEL_1_UPLINK_ENABLED;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_1_DOWNLINK_ENABLED
|
||||||
|
channelSettings.downlink_enabled = USERPREFS_CHANNEL_1_DOWNLINK_ENABLED;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -145,13 +155,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
|||||||
static const uint8_t defaultpsk2[] = USERPREFS_CHANNEL_2_PSK;
|
static const uint8_t defaultpsk2[] = USERPREFS_CHANNEL_2_PSK;
|
||||||
memcpy(channelSettings.psk.bytes, defaultpsk2, sizeof(defaultpsk2));
|
memcpy(channelSettings.psk.bytes, defaultpsk2, sizeof(defaultpsk2));
|
||||||
channelSettings.psk.size = sizeof(defaultpsk2);
|
channelSettings.psk.size = sizeof(defaultpsk2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_2_NAME
|
#ifdef USERPREFS_CHANNEL_2_NAME
|
||||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_2_NAME);
|
strcpy(channelSettings.name, USERPREFS_CHANNEL_2_NAME);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USERPREFS_CHANNEL_2_PRECISION
|
#ifdef USERPREFS_CHANNEL_2_PRECISION
|
||||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_2_PRECISION;
|
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_2_PRECISION;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_2_UPLINK_ENABLED
|
||||||
|
channelSettings.uplink_enabled = USERPREFS_CHANNEL_2_UPLINK_ENABLED;
|
||||||
|
#endif
|
||||||
|
#ifdef USERPREFS_CHANNEL_2_DOWNLINK_ENABLED
|
||||||
|
channelSettings.downlink_enabled = USERPREFS_CHANNEL_2_DOWNLINK_ENABLED;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -43,6 +43,15 @@ uint32_t Default::getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t d
|
|||||||
return getConfiguredOrDefaultMs(configured, defaultValue) * congestionScalingCoefficient(numOnlineNodes);
|
return getConfiguredOrDefaultMs(configured, defaultValue) * congestionScalingCoefficient(numOnlineNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Default::getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue)
|
||||||
|
{
|
||||||
|
// If zero, intervals should be coalesced later by getConfiguredOrDefault... methods
|
||||||
|
if (configured == 0)
|
||||||
|
return configured;
|
||||||
|
|
||||||
|
return configured < minValue ? minValue : configured;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Default::getConfiguredOrDefaultHopLimit(uint8_t configured)
|
uint8_t Default::getConfiguredOrDefaultHopLimit(uint8_t configured)
|
||||||
{
|
{
|
||||||
#if USERPREFS_EVENT_MODE
|
#if USERPREFS_EVENT_MODE
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
#define THIRTY_SECONDS_MS 30 * 1000
|
#define THIRTY_SECONDS_MS 30 * 1000
|
||||||
#define FIVE_SECONDS_MS 5 * 1000
|
#define FIVE_SECONDS_MS 5 * 1000
|
||||||
|
|
||||||
|
#define min_default_telemetry_interval_secs 30 * 60
|
||||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||||
#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 30 * 60)
|
#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60)
|
||||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||||
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
||||||
@ -35,6 +36,7 @@ class Default
|
|||||||
static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue);
|
static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue);
|
||||||
static uint32_t getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t defaultValue, uint32_t numOnlineNodes);
|
static uint32_t getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t defaultValue, uint32_t numOnlineNodes);
|
||||||
static uint8_t getConfiguredOrDefaultHopLimit(uint8_t configured);
|
static uint8_t getConfiguredOrDefaultHopLimit(uint8_t configured);
|
||||||
|
static uint32_t getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float congestionScalingCoefficient(int numOnlineNodes)
|
static float congestionScalingCoefficient(int numOnlineNodes)
|
||||||
|
@ -44,7 +44,7 @@ bool FloodingRouter::isRebroadcaster()
|
|||||||
void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
|
void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
|
||||||
{
|
{
|
||||||
bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
|
bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
|
||||||
if (isAckorReply && !isToUs(p) && p->to != NODENUM_BROADCAST) {
|
if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) {
|
||||||
// do not flood direct message that is ACKed or replied to
|
// do not flood direct message that is ACKed or replied to
|
||||||
LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast.");
|
LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast.");
|
||||||
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
|
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
|
||||||
|
@ -67,8 +67,10 @@ template <typename T> bool LR11x0Interface<T>::init()
|
|||||||
power = LR1110_MAX_POWER;
|
power = LR1110_MAX_POWER;
|
||||||
|
|
||||||
if ((power > LR1120_MAX_POWER) &&
|
if ((power > LR1120_MAX_POWER) &&
|
||||||
(config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) // clamp again if wide freq range
|
(config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { // clamp again if wide freq range
|
||||||
power = LR1120_MAX_POWER;
|
power = LR1120_MAX_POWER;
|
||||||
|
preambleLength = 12; // 12 is the default for operation above 2GHz
|
||||||
|
}
|
||||||
|
|
||||||
limitPower();
|
limitPower();
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
|
|||||||
|
|
||||||
// Was this message directed to us specifically? Will be false if we are sniffing someone elses packets
|
// Was this message directed to us specifically? Will be false if we are sniffing someone elses packets
|
||||||
auto ourNodeNum = nodeDB->getNodeNum();
|
auto ourNodeNum = nodeDB->getNodeNum();
|
||||||
bool toUs = mp.to == NODENUM_BROADCAST || isToUs(&mp);
|
bool toUs = isBroadcast(mp.to) || isToUs(&mp);
|
||||||
|
|
||||||
for (auto i = modules->begin(); i != modules->end(); ++i) {
|
for (auto i = modules->begin(); i != modules->end(); ++i) {
|
||||||
auto &pi = **i;
|
auto &pi = **i;
|
||||||
|
@ -58,3 +58,5 @@ bool isToUs(const meshtastic_MeshPacket *p);
|
|||||||
|
|
||||||
/* Some clients might not properly set priority, therefore we fix it here. */
|
/* Some clients might not properly set priority, therefore we fix it here. */
|
||||||
void fixPriority(meshtastic_MeshPacket *p);
|
void fixPriority(meshtastic_MeshPacket *p);
|
||||||
|
|
||||||
|
bool isBroadcast(uint32_t dest);
|
@ -34,7 +34,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "modules/StoreForwardModule.h"
|
#include "modules/StoreForwardModule.h"
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
|
#include <esp_efuse.h>
|
||||||
|
#include <esp_efuse_table.h>
|
||||||
#include <nvs_flash.h>
|
#include <nvs_flash.h>
|
||||||
|
#include <soc/efuse_reg.h>
|
||||||
|
#include <soc/soc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
@ -109,6 +113,43 @@ NodeDB::NodeDB()
|
|||||||
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
||||||
|
|
||||||
int saveWhat = 0;
|
int saveWhat = 0;
|
||||||
|
bool hasUniqueId = false;
|
||||||
|
// Get device unique id
|
||||||
|
#if defined(ARCH_ESP32) && defined(ESP_EFUSE_OPTIONAL_UNIQUE_ID)
|
||||||
|
uint32_t unique_id[4];
|
||||||
|
// ESP32 factory burns a unique id in efuse for S2+ series and evidently C3+ series
|
||||||
|
// This is used for HMACs in the esp-rainmaker AIOT platform and seems to be a good choice for us
|
||||||
|
esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_OPTIONAL_UNIQUE_ID, unique_id, sizeof(unique_id) * 8);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
memcpy(myNodeInfo.device_id.bytes, unique_id, sizeof(unique_id));
|
||||||
|
myNodeInfo.device_id.size = 16;
|
||||||
|
hasUniqueId = true;
|
||||||
|
} else {
|
||||||
|
LOG_WARN("Failed to read unique id from efuse");
|
||||||
|
}
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
|
// Nordic applies a FIPS compliant Random ID to each chip at the factory
|
||||||
|
// We concatenate the device address to the Random ID to create a unique ID for now
|
||||||
|
// This will likely utilize a crypto module in the future
|
||||||
|
uint64_t device_id_start = ((uint64_t)NRF_FICR->DEVICEID[1] << 32) | NRF_FICR->DEVICEID[0];
|
||||||
|
uint64_t device_id_end = ((uint64_t)NRF_FICR->DEVICEADDR[1] << 32) | NRF_FICR->DEVICEADDR[0];
|
||||||
|
memcpy(myNodeInfo.device_id.bytes, &device_id_start, sizeof(device_id_start));
|
||||||
|
memcpy(myNodeInfo.device_id.bytes + sizeof(device_id_start), &device_id_end, sizeof(device_id_end));
|
||||||
|
myNodeInfo.device_id.size = 16;
|
||||||
|
hasUniqueId = true;
|
||||||
|
#else
|
||||||
|
// FIXME - implement for other platforms
|
||||||
|
#endif
|
||||||
|
// Uncomment below to print the device id
|
||||||
|
// if (hasUniqueId) {
|
||||||
|
// std::string deviceIdHex;
|
||||||
|
// for (size_t i = 0; i < myNodeInfo.device_id.size; ++i) {
|
||||||
|
// char buf[3];
|
||||||
|
// snprintf(buf, sizeof(buf), "%02X", myNodeInfo.device_id.bytes[i]);
|
||||||
|
// deviceIdHex += buf;
|
||||||
|
// }
|
||||||
|
// LOG_DEBUG("Device ID (HEX): %s", deviceIdHex.c_str());
|
||||||
|
// }
|
||||||
|
|
||||||
// likewise - we always want the app requirements to come from the running appload
|
// likewise - we always want the app requirements to come from the running appload
|
||||||
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
||||||
@ -171,6 +212,22 @@ NodeDB::NodeDB()
|
|||||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);
|
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);
|
||||||
|
|
||||||
|
// If we are setup to broadcast on the default channel, ensure that the telemetry intervals are coerced to the minimum value
|
||||||
|
// of 30 minutes or more
|
||||||
|
if (channels.isDefaultChannel(channels.getPrimaryIndex())) {
|
||||||
|
LOG_DEBUG("Coercing telemetry to min of 30 minutes on defaults");
|
||||||
|
moduleConfig.telemetry.device_update_interval = Default::getConfiguredOrMinimumValue(
|
||||||
|
moduleConfig.telemetry.device_update_interval, min_default_telemetry_interval_secs);
|
||||||
|
moduleConfig.telemetry.environment_update_interval = Default::getConfiguredOrMinimumValue(
|
||||||
|
moduleConfig.telemetry.environment_update_interval, min_default_telemetry_interval_secs);
|
||||||
|
moduleConfig.telemetry.air_quality_interval = Default::getConfiguredOrMinimumValue(
|
||||||
|
moduleConfig.telemetry.air_quality_interval, min_default_telemetry_interval_secs);
|
||||||
|
moduleConfig.telemetry.power_update_interval = Default::getConfiguredOrMinimumValue(
|
||||||
|
moduleConfig.telemetry.power_update_interval, min_default_telemetry_interval_secs);
|
||||||
|
moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue(
|
||||||
|
moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs);
|
||||||
|
}
|
||||||
|
|
||||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||||
saveWhat |= SEGMENT_DEVICESTATE;
|
saveWhat |= SEGMENT_DEVICESTATE;
|
||||||
if (configCRC != crc32Buffer(&config, sizeof(config)))
|
if (configCRC != crc32Buffer(&config, sizeof(config)))
|
||||||
@ -206,6 +263,11 @@ bool isToUs(const meshtastic_MeshPacket *p)
|
|||||||
return p->to == nodeDB->getNodeNum();
|
return p->to == nodeDB->getNodeNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isBroadcast(uint32_t dest)
|
||||||
|
{
|
||||||
|
return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA;
|
||||||
|
}
|
||||||
|
|
||||||
bool NodeDB::resetRadioConfig(bool factory_reset)
|
bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||||
{
|
{
|
||||||
bool didFactoryReset = false;
|
bool didFactoryReset = false;
|
||||||
|
@ -467,7 +467,10 @@ void RadioLibInterface::setStandby()
|
|||||||
void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||||
{
|
{
|
||||||
printPacket("Starting low level send", txp);
|
printPacket("Starting low level send", txp);
|
||||||
if (disabled || !config.lora.tx_enabled) {
|
if (txp->to == NODENUM_BROADCAST_NO_LORA) {
|
||||||
|
LOG_DEBUG("Drop Tx packet because dest is broadcast no-lora");
|
||||||
|
packetPool.release(txp);
|
||||||
|
} else if (disabled || !config.lora.tx_enabled) {
|
||||||
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
|
LOG_WARN("Drop Tx packet because LoRa Tx disabled");
|
||||||
packetPool.release(txp);
|
packetPool.release(txp);
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,7 +181,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
} else {
|
} else {
|
||||||
// If we are sending a broadcast, we also treat it as if we just received it ourself
|
// If we are sending a broadcast, we also treat it as if we just received it ourself
|
||||||
// this allows local apps (and PCs) to see broadcasts sourced locally
|
// this allows local apps (and PCs) to see broadcasts sourced locally
|
||||||
if (p->to == NODENUM_BROADCAST) {
|
if (isBroadcast(p->to)) {
|
||||||
handleReceived(p, src);
|
handleReceived(p, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
|||||||
// assert
|
// assert
|
||||||
|
|
||||||
// Never set the want_ack flag on broadcast packets sent over the air.
|
// Never set the want_ack flag on broadcast packets sent over the air.
|
||||||
if (p->to == NODENUM_BROADCAST)
|
if (isBroadcast(p->to))
|
||||||
p->want_ack = false;
|
p->want_ack = false;
|
||||||
|
|
||||||
// Up until this point we might have been using 0 for the from address (if it started with the phone), but when we send over
|
// Up until this point we might have been using 0 for the from address (if it started with the phone), but when we send over
|
||||||
@ -328,7 +328,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
|
|||||||
memcpy(ScratchEncrypted, p->encrypted.bytes, rawSize);
|
memcpy(ScratchEncrypted, p->encrypted.bytes, rawSize);
|
||||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||||
// Attempt PKI decryption first
|
// Attempt PKI decryption first
|
||||||
if (p->channel == 0 && isToUs(p) && p->to > 0 && p->to != NODENUM_BROADCAST && nodeDB->getMeshNode(p->from) != nullptr &&
|
if (p->channel == 0 && isToUs(p) && p->to > 0 && !isBroadcast(p->to) && nodeDB->getMeshNode(p->from) != nullptr &&
|
||||||
nodeDB->getMeshNode(p->from)->user.public_key.size > 0 && nodeDB->getMeshNode(p->to)->user.public_key.size > 0 &&
|
nodeDB->getMeshNode(p->from)->user.public_key.size > 0 && nodeDB->getMeshNode(p->to)->user.public_key.size > 0 &&
|
||||||
rawSize > MESHTASTIC_PKC_OVERHEAD) {
|
rawSize > MESHTASTIC_PKC_OVERHEAD) {
|
||||||
LOG_DEBUG("Attempting PKI decryption");
|
LOG_DEBUG("Attempting PKI decryption");
|
||||||
@ -493,7 +493,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
|||||||
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
|
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
|
||||||
!(p->pki_encrypted != true && p->channel > 0) &&
|
!(p->pki_encrypted != true && p->channel > 0) &&
|
||||||
// Check for valid keys and single node destination
|
// Check for valid keys and single node destination
|
||||||
config.security.private_key.size == 32 && p->to != NODENUM_BROADCAST && node != nullptr &&
|
config.security.private_key.size == 32 && !isBroadcast(p->to) && node != nullptr &&
|
||||||
// Check for a known public key for the destination
|
// Check for a known public key for the destination
|
||||||
(node->user.public_key.size == 32) &&
|
(node->user.public_key.size == 32) &&
|
||||||
// Some portnums either make no sense to send with PKC
|
// Some portnums either make no sense to send with PKC
|
||||||
@ -615,7 +615,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||||
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to
|
// Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to
|
||||||
// us (because we would be able to decrypt it)
|
// us (because we would be able to decrypt it)
|
||||||
if (!decoded && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && p->to != NODENUM_BROADCAST && !isToUs(p))
|
if (!decoded && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && !isBroadcast(p->to) && !isToUs(p))
|
||||||
p_encrypted->pki_encrypted = true;
|
p_encrypted->pki_encrypted = true;
|
||||||
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
|
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
|
||||||
if ((decoded || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled && !isFromUs(p) && mqtt)
|
if ((decoded || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled && !isFromUs(p) && mqtt)
|
||||||
|
@ -75,7 +75,10 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
|
|||||||
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */
|
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */
|
||||||
meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY = 3,
|
meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY = 3,
|
||||||
/* Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. */
|
/* Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. */
|
||||||
meshtastic_Config_DeviceConfig_RebroadcastMode_NONE = 4
|
meshtastic_Config_DeviceConfig_RebroadcastMode_NONE = 4,
|
||||||
|
/* Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc.
|
||||||
|
Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. */
|
||||||
|
meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY = 5
|
||||||
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
||||||
|
|
||||||
/* Bit field of boolean configuration options, indicating which optional
|
/* Bit field of boolean configuration options, indicating which optional
|
||||||
@ -587,8 +590,8 @@ extern "C" {
|
|||||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_TAK_TRACKER+1))
|
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_TAK_TRACKER+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_NONE
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_NONE+1))
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
||||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
||||||
|
@ -765,6 +765,7 @@ typedef struct _meshtastic_NodeInfo {
|
|||||||
bool is_favorite;
|
bool is_favorite;
|
||||||
} meshtastic_NodeInfo;
|
} meshtastic_NodeInfo;
|
||||||
|
|
||||||
|
typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t;
|
||||||
/* Unique local debugging info for this node
|
/* Unique local debugging info for this node
|
||||||
Note: we don't include position or the user info, because that will come in the
|
Note: we don't include position or the user info, because that will come in the
|
||||||
Sent to the phone in response to WantNodes. */
|
Sent to the phone in response to WantNodes. */
|
||||||
@ -778,6 +779,8 @@ typedef struct _meshtastic_MyNodeInfo {
|
|||||||
/* The minimum app version that can talk to this device.
|
/* The minimum app version that can talk to this device.
|
||||||
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
|
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
|
||||||
uint32_t min_app_version;
|
uint32_t min_app_version;
|
||||||
|
/* Unique hardware identifier for this device */
|
||||||
|
meshtastic_MyNodeInfo_device_id_t device_id;
|
||||||
} meshtastic_MyNodeInfo;
|
} meshtastic_MyNodeInfo;
|
||||||
|
|
||||||
/* Debug output from the device.
|
/* Debug output from the device.
|
||||||
@ -1112,7 +1115,7 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
|
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
|
||||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
|
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0}
|
||||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
|
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}}
|
||||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||||
@ -1137,7 +1140,7 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
|
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0}
|
||||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
|
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0}
|
||||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
|
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}}
|
||||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||||
@ -1244,6 +1247,7 @@ extern "C" {
|
|||||||
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
||||||
#define meshtastic_MyNodeInfo_reboot_count_tag 8
|
#define meshtastic_MyNodeInfo_reboot_count_tag 8
|
||||||
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
||||||
|
#define meshtastic_MyNodeInfo_device_id_tag 12
|
||||||
#define meshtastic_LogRecord_message_tag 1
|
#define meshtastic_LogRecord_message_tag 1
|
||||||
#define meshtastic_LogRecord_time_tag 2
|
#define meshtastic_LogRecord_time_tag 2
|
||||||
#define meshtastic_LogRecord_source_tag 3
|
#define meshtastic_LogRecord_source_tag 3
|
||||||
@ -1446,7 +1450,8 @@ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10)
|
|||||||
#define meshtastic_MyNodeInfo_FIELDLIST(X, a) \
|
#define meshtastic_MyNodeInfo_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11)
|
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \
|
||||||
|
X(a, STATIC, SINGULAR, BYTES, device_id, 12)
|
||||||
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
||||||
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
||||||
|
|
||||||
@ -1669,7 +1674,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
|||||||
#define meshtastic_LogRecord_size 426
|
#define meshtastic_LogRecord_size 426
|
||||||
#define meshtastic_MeshPacket_size 367
|
#define meshtastic_MeshPacket_size 367
|
||||||
#define meshtastic_MqttClientProxyMessage_size 501
|
#define meshtastic_MqttClientProxyMessage_size 501
|
||||||
#define meshtastic_MyNodeInfo_size 18
|
#define meshtastic_MyNodeInfo_size 36
|
||||||
#define meshtastic_NeighborInfo_size 258
|
#define meshtastic_NeighborInfo_size 258
|
||||||
#define meshtastic_Neighbor_size 22
|
#define meshtastic_Neighbor_size 22
|
||||||
#define meshtastic_NodeInfo_size 317
|
#define meshtastic_NodeInfo_size 317
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
/* Canned message module configuration. */
|
/* Canned message module configuration. */
|
||||||
typedef struct _meshtastic_RTTTLConfig {
|
typedef struct _meshtastic_RTTTLConfig {
|
||||||
/* Ringtone for PWM Buzzer in RTTTL Format. */
|
/* Ringtone for PWM Buzzer in RTTTL Format. */
|
||||||
char ringtone[230];
|
char ringtone[231];
|
||||||
} meshtastic_RTTTLConfig;
|
} meshtastic_RTTTLConfig;
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ extern const pb_msgdesc_t meshtastic_RTTTLConfig_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_RTTTL_PB_H_MAX_SIZE meshtastic_RTTTLConfig_size
|
#define MESHTASTIC_MESHTASTIC_RTTTL_PB_H_MAX_SIZE meshtastic_RTTTLConfig_size
|
||||||
#define meshtastic_RTTTLConfig_size 232
|
#define meshtastic_RTTTLConfig_size 233
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -122,7 +122,7 @@ Will be used for broadcast.
|
|||||||
int32_t NeighborInfoModule::runOnce()
|
int32_t NeighborInfoModule::runOnce()
|
||||||
{
|
{
|
||||||
if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
|
if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
|
||||||
sendNeighborInfo(NODENUM_BROADCAST, false);
|
sendNeighborInfo(NODENUM_BROADCAST_NO_LORA, false);
|
||||||
}
|
}
|
||||||
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
|||||||
|
|
||||||
bool hasChanged = nodeDB->updateUser(getFrom(&mp), p, mp.channel);
|
bool hasChanged = nodeDB->updateUser(getFrom(&mp), p, mp.channel);
|
||||||
|
|
||||||
bool wasBroadcast = mp.to == NODENUM_BROADCAST;
|
bool wasBroadcast = isBroadcast(mp.to);
|
||||||
|
|
||||||
// Show new nodes on LCD screen
|
// Show new nodes on LCD screen
|
||||||
if (wasBroadcast) {
|
if (wasBroadcast) {
|
||||||
|
@ -10,11 +10,7 @@ RoutingModule *routingModule;
|
|||||||
|
|
||||||
bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Routing *r)
|
bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Routing *r)
|
||||||
{
|
{
|
||||||
printPacket("Routing sniffing", &mp);
|
bool maybePKI = mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && mp.channel == 0 && !isBroadcast(mp.to);
|
||||||
router->sniffReceived(&mp, r);
|
|
||||||
|
|
||||||
bool maybePKI =
|
|
||||||
mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && mp.channel == 0 && mp.to != NODENUM_BROADCAST;
|
|
||||||
// Beginning of logic whether to drop the packet based on Rebroadcast mode
|
// Beginning of logic whether to drop the packet based on Rebroadcast mode
|
||||||
if (mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag &&
|
if (mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag &&
|
||||||
(config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY ||
|
(config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY ||
|
||||||
@ -26,9 +22,12 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printPacket("Routing sniffing", &mp);
|
||||||
|
router->sniffReceived(&mp, r);
|
||||||
|
|
||||||
// FIXME - move this to a non promsicious PhoneAPI module?
|
// FIXME - move this to a non promsicious PhoneAPI module?
|
||||||
// Note: we are careful not to send back packets that started with the phone back to the phone
|
// Note: we are careful not to send back packets that started with the phone back to the phone
|
||||||
if ((mp.to == NODENUM_BROADCAST || isToUs(&mp)) && (mp.from != 0)) {
|
if ((isBroadcast(mp.to) || isToUs(&mp)) && (mp.from != 0)) {
|
||||||
printPacket("Delivering rx packet", &mp);
|
printPacket("Delivering rx packet", &mp);
|
||||||
service->handleFromRadio(&mp);
|
service->handleFromRadio(&mp);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ int32_t AirQualityTelemetryModule::runOnce()
|
|||||||
if (moduleConfig.telemetry.air_quality_enabled) {
|
if (moduleConfig.telemetry.air_quality_enabled) {
|
||||||
LOG_INFO("Air quality Telemetry: Initializing");
|
LOG_INFO("Air quality Telemetry: Initializing");
|
||||||
if (!aqi.begin_I2C()) {
|
if (!aqi.begin_I2C()) {
|
||||||
|
#ifndef I2C_NO_RESCAN
|
||||||
LOG_WARN("Could not establish i2c connection to AQI sensor. Rescanning...");
|
LOG_WARN("Could not establish i2c connection to AQI sensor. Rescanning...");
|
||||||
// rescan for late arriving sensors. AQI Module starts about 10 seconds into the boot so this is plenty.
|
// rescan for late arriving sensors. AQI Module starts about 10 seconds into the boot so this is plenty.
|
||||||
uint8_t i2caddr_scan[] = {PMSA0031_ADDR};
|
uint8_t i2caddr_scan[] = {PMSA0031_ADDR};
|
||||||
@ -51,6 +52,7 @@ int32_t AirQualityTelemetryModule::runOnce()
|
|||||||
i2cScanner->fetchI2CBus(found.address);
|
i2cScanner->fetchI2CBus(found.address);
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return disable();
|
return disable();
|
||||||
}
|
}
|
||||||
return 1000;
|
return 1000;
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
#include "LSM6DS3Sensor.h"
|
#include "LSM6DS3Sensor.h"
|
||||||
#include "MPU6050Sensor.h"
|
#include "MPU6050Sensor.h"
|
||||||
#include "MotionSensor.h"
|
#include "MotionSensor.h"
|
||||||
|
#ifdef HAS_QMA6100P
|
||||||
|
#include "QMA6100PSensor.h"
|
||||||
|
#endif
|
||||||
#include "STK8XXXSensor.h"
|
#include "STK8XXXSensor.h"
|
||||||
|
|
||||||
extern ScanI2C::DeviceAddress accelerometer_found;
|
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||||
@ -97,6 +100,11 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
case ScanI2C::DeviceType::ICM20948:
|
case ScanI2C::DeviceType::ICM20948:
|
||||||
sensor = new ICM20948Sensor(device);
|
sensor = new ICM20948Sensor(device);
|
||||||
break;
|
break;
|
||||||
|
#ifdef HAS_QMA6100P
|
||||||
|
case ScanI2C::DeviceType::QMA6100P:
|
||||||
|
sensor = new QMA6100PSensor(device);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "LIS3DHSensor.h"
|
#include "LIS3DHSensor.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
|
||||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "LSM6DS3Sensor.h"
|
#include "LSM6DS3Sensor.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
|
||||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "../graphics/Screen.h"
|
#include "../graphics/Screen.h"
|
||||||
#include "../graphics/ScreenFonts.h"
|
#include "../graphics/ScreenFonts.h"
|
||||||
#include "../power.h"
|
#include "../power.h"
|
||||||
|
#include "Wire.h"
|
||||||
|
|
||||||
// Base class for motion processing
|
// Base class for motion processing
|
||||||
class MotionSensor
|
class MotionSensor
|
||||||
|
183
src/motion/QMA6100PSensor.cpp
Normal file
183
src/motion/QMA6100PSensor.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#include "QMA6100PSensor.h"
|
||||||
|
|
||||||
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && HAS_QMA6100P
|
||||||
|
|
||||||
|
// Flag when an interrupt has been detected
|
||||||
|
volatile static bool QMA6100P_IRQ = false;
|
||||||
|
|
||||||
|
// Interrupt service routine
|
||||||
|
void QMA6100PSetInterrupt()
|
||||||
|
{
|
||||||
|
QMA6100P_IRQ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMA6100PSensor::QMA6100PSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
|
||||||
|
|
||||||
|
bool QMA6100PSensor::init()
|
||||||
|
{
|
||||||
|
// Initialise the sensor
|
||||||
|
sensor = QMA6100PSingleton::GetInstance();
|
||||||
|
if (!sensor->init(device))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Enable simple Wake on Motion
|
||||||
|
return sensor->setWakeOnMotion();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef QMA_6100P_INT_PIN
|
||||||
|
|
||||||
|
int32_t QMA6100PSensor::runOnce()
|
||||||
|
{
|
||||||
|
// Wake on motion using hardware interrupts - this is the most efficient way to check for motion
|
||||||
|
if (QMA6100P_IRQ) {
|
||||||
|
QMA6100P_IRQ = false;
|
||||||
|
wakeScreen();
|
||||||
|
}
|
||||||
|
return MOTION_SENSOR_CHECK_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int32_t QMA6100PSensor::runOnce()
|
||||||
|
{
|
||||||
|
// Wake on motion using polling - this is not as efficient as using hardware interrupt pin (see above)
|
||||||
|
|
||||||
|
uint8_t tempVal;
|
||||||
|
if (!sensor->readRegisterRegion(SFE_QMA6100P_INT_ST0, &tempVal, 1)) {
|
||||||
|
LOG_DEBUG("QMA6100PSensor::isWakeOnMotion failed to read interrupts");
|
||||||
|
return MOTION_SENSOR_CHECK_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tempVal & 7) != 0) {
|
||||||
|
// Wake up!
|
||||||
|
wakeScreen();
|
||||||
|
}
|
||||||
|
return MOTION_SENSOR_CHECK_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// QMA6100PSingleton
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get a singleton wrapper for an Sparkfun QMA_6100P_I2C
|
||||||
|
QMA6100PSingleton *QMA6100PSingleton::GetInstance()
|
||||||
|
{
|
||||||
|
if (pinstance == nullptr) {
|
||||||
|
pinstance = new QMA6100PSingleton();
|
||||||
|
}
|
||||||
|
return pinstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMA6100PSingleton::QMA6100PSingleton() {}
|
||||||
|
|
||||||
|
QMA6100PSingleton::~QMA6100PSingleton() {}
|
||||||
|
|
||||||
|
QMA6100PSingleton *QMA6100PSingleton::pinstance{nullptr};
|
||||||
|
|
||||||
|
// Initialise the QMA6100P Sensor
|
||||||
|
bool QMA6100PSingleton::init(ScanI2C::FoundDevice device)
|
||||||
|
{
|
||||||
|
|
||||||
|
// startup
|
||||||
|
#ifdef Wire1
|
||||||
|
bool status = begin(device.address.address, device.address.port == ScanI2C::I2CPort::WIRE1 ? &Wire1 : &Wire);
|
||||||
|
#else
|
||||||
|
// check chip id
|
||||||
|
bool status = begin(device.address.address, &Wire);
|
||||||
|
#endif
|
||||||
|
if (status != true) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init begin failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delay(20);
|
||||||
|
// SW reset to make sure the device starts in a known state
|
||||||
|
if (softwareReset() != true) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init reset failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delay(20);
|
||||||
|
// Set range
|
||||||
|
if (!setRange(QMA_6100P_MPU_ACCEL_SCALE)) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init range failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// set active mode
|
||||||
|
if (!enableAccel()) {
|
||||||
|
LOG_WARN("ERROR :QMA6100PSensor::active mode set failed");
|
||||||
|
}
|
||||||
|
// set calibrateoffsets
|
||||||
|
if (!calibrateOffsets()) {
|
||||||
|
LOG_WARN("ERROR :QMA6100PSensor:: calibration failed");
|
||||||
|
}
|
||||||
|
#ifdef QMA_6100P_INT_PIN
|
||||||
|
|
||||||
|
// Active low & Open Drain
|
||||||
|
uint8_t tempVal;
|
||||||
|
if (!readRegisterRegion(SFE_QMA6100P_INTPINT_CONF, &tempVal, 1)) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init failed to read interrupt pin config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempVal |= 0b00000010; // Active low & Open Drain
|
||||||
|
|
||||||
|
if (!writeRegisterByte(SFE_QMA6100P_INTPINT_CONF, tempVal)) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init failed to write interrupt pin config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Latch until cleared, all reads clear the latch
|
||||||
|
if (!readRegisterRegion(SFE_QMA6100P_INT_CFG, &tempVal, 1)) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init failed to read interrupt config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempVal |= 0b10000001; // Latch until cleared, INT_RD_CLR1
|
||||||
|
|
||||||
|
if (!writeRegisterByte(SFE_QMA6100P_INT_CFG, tempVal)) {
|
||||||
|
LOG_WARN("QMA6100PSensor::init failed to write interrupt config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Set up an interrupt pin with an internal pullup for active low
|
||||||
|
pinMode(QMA_6100P_INT_PIN, INPUT_PULLUP);
|
||||||
|
|
||||||
|
// Set up an interrupt service routine
|
||||||
|
attachInterrupt(QMA_6100P_INT_PIN, QMA6100PSetInterrupt, FALLING);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMA6100PSingleton::setWakeOnMotion()
|
||||||
|
{
|
||||||
|
// Enable 'Any Motion' interrupt
|
||||||
|
if (!writeRegisterByte(SFE_QMA6100P_INT_EN2, 0b00000111)) {
|
||||||
|
LOG_WARN("QMA6100PSingleton::setWakeOnMotion failed to write interrupt enable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set 'Significant Motion' interrupt map to INT1
|
||||||
|
uint8_t tempVal;
|
||||||
|
|
||||||
|
if (!readRegisterRegion(SFE_QMA6100P_INT_MAP1, &tempVal, 1)) {
|
||||||
|
LOG_WARN("QMA6100PSingleton::setWakeOnMotion failed to read interrupt map");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfe_qma6100p_int_map1_bitfield_t int_map1;
|
||||||
|
int_map1.all = tempVal;
|
||||||
|
int_map1.bits.int1_any_mot = 1; // any motion interrupt to INT1
|
||||||
|
tempVal = int_map1.all;
|
||||||
|
|
||||||
|
if (!writeRegisterByte(SFE_QMA6100P_INT_MAP1, tempVal)) {
|
||||||
|
LOG_WARN("QMA6100PSingleton::setWakeOnMotion failed to write interrupt map");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any current interrupts
|
||||||
|
QMA6100P_IRQ = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
63
src/motion/QMA6100PSensor.h
Normal file
63
src/motion/QMA6100PSensor.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _QMA_6100P_SENSOR_H_
|
||||||
|
#define _QMA_6100P_SENSOR_H_
|
||||||
|
|
||||||
|
#include "MotionSensor.h"
|
||||||
|
|
||||||
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && HAS_QMA6100P
|
||||||
|
|
||||||
|
#include <QMA6100P.h>
|
||||||
|
|
||||||
|
// Set the default accelerometer scale - gpm2, gpm4, gpm8, gpm16
|
||||||
|
#ifndef QMA_6100P_MPU_ACCEL_SCALE
|
||||||
|
#define QMA_6100P_MPU_ACCEL_SCALE SFE_QMA6100P_RANGE32G
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The I2C address of the Accelerometer (if found) from main.cpp
|
||||||
|
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||||
|
|
||||||
|
// Singleton wrapper for the Sparkfun QMA_6100P_I2C class
|
||||||
|
class QMA6100PSingleton : public QMA6100P
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static QMA6100PSingleton *pinstance;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QMA6100PSingleton();
|
||||||
|
~QMA6100PSingleton();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Create a singleton instance (not thread safe)
|
||||||
|
static QMA6100PSingleton *GetInstance();
|
||||||
|
|
||||||
|
// Singletons should not be cloneable.
|
||||||
|
QMA6100PSingleton(QMA6100PSingleton &other) = delete;
|
||||||
|
|
||||||
|
// Singletons should not be assignable.
|
||||||
|
void operator=(const QMA6100PSingleton &) = delete;
|
||||||
|
|
||||||
|
// Initialise the motion sensor singleton for normal operation
|
||||||
|
bool init(ScanI2C::FoundDevice device);
|
||||||
|
|
||||||
|
// Enable Wake on Motion interrupts (sensor must be initialised first)
|
||||||
|
bool setWakeOnMotion();
|
||||||
|
};
|
||||||
|
|
||||||
|
class QMA6100PSensor : public MotionSensor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QMA6100PSingleton *sensor = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit QMA6100PSensor(ScanI2C::FoundDevice foundDevice);
|
||||||
|
|
||||||
|
// Initialise the motion sensor
|
||||||
|
virtual bool init() override;
|
||||||
|
|
||||||
|
// Called each time our sensor gets a chance to run
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -706,22 +706,48 @@ bool MQTT::isValidJsonEnvelope(JSONObject &json)
|
|||||||
|
|
||||||
bool MQTT::isPrivateIpAddress(const char address[])
|
bool MQTT::isPrivateIpAddress(const char address[])
|
||||||
{
|
{
|
||||||
// Min. length like 10.0.0.0, max like 192.168.255.255
|
// Min. length like 10.0.0.0 (8), max like 192.168.255.255:65535 (21)
|
||||||
size_t length = strlen(address);
|
size_t length = strlen(address);
|
||||||
if (length < 8 || length > 15) {
|
if (length < 8 || length > 21) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the address contains only digits and dots.
|
// Ensure the address contains only digits and dots and maybe a colon.
|
||||||
|
// Some limited validation is done.
|
||||||
// Even if it's not a valid IP address, we will know it's not a domain.
|
// Even if it's not a valid IP address, we will know it's not a domain.
|
||||||
for (int i = 0; i < length; i++) {
|
bool hasColon = false;
|
||||||
if (!isdigit(address[i]) && address[i] != '.') {
|
int numDots = 0;
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
if (!isdigit(address[i]) && address[i] != '.' && address[i] != ':') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dots can't be the first character, immediately follow another dot,
|
||||||
|
// occur more than 3 times, or occur after a colon.
|
||||||
|
if (address[i] == '.') {
|
||||||
|
if (++numDots > 3 || i == 0 || address[i - 1] == '.' || hasColon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There can only be a single colon, and it can only occur after 3 dots
|
||||||
|
else if (address[i] == ':') {
|
||||||
|
if (hasColon || numDots < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasColon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final validation for IPv4 address and port format.
|
||||||
|
// Note that the values of octets haven't been tested, only the address format.
|
||||||
|
if (numDots != 3) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the easy ones first.
|
// Check the easy ones first.
|
||||||
if (strcmp(address, "127.0.0.1") == 0 || strncmp(address, "10.", 3) == 0 || strncmp(address, "192.168", 7) == 0) {
|
if (strcmp(address, "127.0.0.1") == 0 || strncmp(address, "10.", 3) == 0 || strncmp(address, "192.168", 7) == 0 ||
|
||||||
|
strncmp(address, "169.254", 7) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,26 +166,6 @@ void esp32Setup()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Turn off for now
|
|
||||||
|
|
||||||
uint32_t axpDebugRead()
|
|
||||||
{
|
|
||||||
axp.debugCharging();
|
|
||||||
LOG_DEBUG("vbus current %f", axp.getVbusCurrent());
|
|
||||||
LOG_DEBUG("charge current %f", axp.getBattChargeCurrent());
|
|
||||||
LOG_DEBUG("bat voltage %f", axp.getBattVoltage());
|
|
||||||
LOG_DEBUG("batt pct %d", axp.getBattPercentage());
|
|
||||||
LOG_DEBUG("is battery connected %d", axp.isBatteryConnect());
|
|
||||||
LOG_DEBUG("is USB connected %d", axp.isVBUSPlug());
|
|
||||||
LOG_DEBUG("is charging %d", axp.isChargeing());
|
|
||||||
|
|
||||||
return 30 * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
Periodic axpDebugOutput(axpDebugRead);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// loop code specific to ESP32 targets
|
/// loop code specific to ESP32 targets
|
||||||
void esp32Loop()
|
void esp32Loop()
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
*/
|
*/
|
||||||
// #define USERPREFS_CHANNEL_0_NAME "DEFCONnect"
|
// #define USERPREFS_CHANNEL_0_NAME "DEFCONnect"
|
||||||
// #define USERPREFS_CHANNEL_0_PRECISION 14
|
// #define USERPREFS_CHANNEL_0_PRECISION 14
|
||||||
|
// #define USERPREFS_CHANNEL_0_UPLINK_ENABLED true
|
||||||
|
// #define USERPREFS_CHANNEL_0_DOWNLINK_ENABLED true
|
||||||
/*
|
/*
|
||||||
#define USERPREFS_CHANNEL_1_PSK \
|
#define USERPREFS_CHANNEL_1_PSK \
|
||||||
{ \
|
{ \
|
||||||
@ -35,6 +37,8 @@
|
|||||||
*/
|
*/
|
||||||
// #define USERPREFS_CHANNEL_1_NAME "REPLACEME"
|
// #define USERPREFS_CHANNEL_1_NAME "REPLACEME"
|
||||||
// #define USERPREFS_CHANNEL_1_PRECISION 14
|
// #define USERPREFS_CHANNEL_1_PRECISION 14
|
||||||
|
// #define USERPREFS_CHANNEL_1_UPLINK_ENABLED true
|
||||||
|
// #define USERPREFS_CHANNEL_1_DOWNLINK_ENABLED true
|
||||||
/*
|
/*
|
||||||
#define USERPREFS_CHANNEL_2_PSK \
|
#define USERPREFS_CHANNEL_2_PSK \
|
||||||
{ \
|
{ \
|
||||||
@ -44,6 +48,8 @@
|
|||||||
*/
|
*/
|
||||||
// #define USERPREFS_CHANNEL_2_NAME "REPLACEME"
|
// #define USERPREFS_CHANNEL_2_NAME "REPLACEME"
|
||||||
// #define USERPREFS_CHANNEL_2_PRECISION 14
|
// #define USERPREFS_CHANNEL_2_PRECISION 14
|
||||||
|
// #define USERPREFS_CHANNEL_2_UPLINK_ENABLED true
|
||||||
|
// #define USERPREFS_CHANNEL_2_DOWNLINK_ENABLED true
|
||||||
|
|
||||||
// #define USERPREFS_CONFIG_OWNER_LONG_NAME "My Long Name"
|
// #define USERPREFS_CONFIG_OWNER_LONG_NAME "My Long Name"
|
||||||
// #define USERPREFS_CONFIG_OWNER_SHORT_NAME "MLN"
|
// #define USERPREFS_CONFIG_OWNER_SHORT_NAME "MLN"
|
||||||
|
@ -34,4 +34,4 @@
|
|||||||
#define SX128X_TXEN 26
|
#define SX128X_TXEN 26
|
||||||
#define SX128X_RXEN 27
|
#define SX128X_RXEN 27
|
||||||
#define SX128X_RESET LORA_RESET
|
#define SX128X_RESET LORA_RESET
|
||||||
#define SX128X_MAX_POWER 13
|
#define SX128X_MAX_POWER 3
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[env:heltec-v2_1]
|
[env:heltec-v2_1]
|
||||||
|
board_level = extra
|
||||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = heltec_wifi_lora_32_V2
|
board = heltec_wifi_lora_32_V2
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[env:heltec-v2_0]
|
[env:heltec-v2_0]
|
||||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||||
|
board_level = extra
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = heltec_wifi_lora_32_V2
|
board = heltec_wifi_lora_32_V2
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -55,6 +55,6 @@
|
|||||||
#define SX126X_BUSY LORA_BUSY
|
#define SX126X_BUSY LORA_BUSY
|
||||||
#define SX126X_RESET LORA_RESET
|
#define SX126X_RESET LORA_RESET
|
||||||
#define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL
|
#define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL
|
||||||
#define SX126X_POWER_EN LORA_DIO4 // Antenna switch !CTRL via GPIO17
|
#define SX126X_RXEN LORA_DIO4 // Antenna switch !CTRL via GPIO17
|
||||||
// #define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
// #define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
#endif
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
[env:tlora-v1]
|
[env:tlora-v1]
|
||||||
|
board_level = extra
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[env:tlora_v1_3]
|
[env:tlora_v1_3]
|
||||||
|
board_level = extra
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[env:tlora-v2]
|
[env:tlora-v2]
|
||||||
|
board_level = extra
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-lora32-v1
|
board = ttgo-lora32-v1
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
; tracker-t1000-e v0.9.1
|
|
||||||
[env:tracker-t1000-e]
|
[env:tracker-t1000-e]
|
||||||
extends = nrf52840_base
|
extends = nrf52840_base
|
||||||
board = tracker-t1000-e
|
board = tracker-t1000-e
|
||||||
; board_level = extra
|
|
||||||
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/tracker-t1000-e -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DTRACKER_T1000_E
|
build_flags = ${nrf52840_base.build_flags} -Ivariants/tracker-t1000-e -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DTRACKER_T1000_E
|
||||||
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
|
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
|
||||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
-DGPS_POWER_TOGGLE
|
||||||
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/tracker-t1000-e>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/tracker-t1000-e>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
|
https://github.com/meshtastic/QMA6100P_Arduino_Library.git#14c900b8b2e4feaac5007a7e41e0c1b7f0841136
|
||||||
debug_tool = jlink
|
debug_tool = jlink
|
||||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||||
upload_protocol = nrfutil
|
upload_protocol = nrfutil
|
||||||
|
@ -40,7 +40,7 @@ void initVariant()
|
|||||||
digitalWrite(PIN_3V3_EN, HIGH);
|
digitalWrite(PIN_3V3_EN, HIGH);
|
||||||
|
|
||||||
pinMode(PIN_3V3_ACC_EN, OUTPUT);
|
pinMode(PIN_3V3_ACC_EN, OUTPUT);
|
||||||
digitalWrite(PIN_3V3_ACC_EN, LOW);
|
digitalWrite(PIN_3V3_ACC_EN, HIGH);
|
||||||
|
|
||||||
pinMode(BUZZER_EN_PIN, OUTPUT);
|
pinMode(BUZZER_EN_PIN, OUTPUT);
|
||||||
digitalWrite(BUZZER_EN_PIN, HIGH);
|
digitalWrite(BUZZER_EN_PIN, HIGH);
|
||||||
|
@ -52,7 +52,7 @@ extern "C" {
|
|||||||
#define LED_BLUE -1 // Actually green
|
#define LED_BLUE -1 // Actually green
|
||||||
#define LED_STATE_ON 1 // State when LED is lit
|
#define LED_STATE_ON 1 // State when LED is lit
|
||||||
|
|
||||||
#define BUTTON_PIN (0 + 6) // P0.6
|
#define BUTTON_PIN (0 + 6) // P0.06
|
||||||
#define BUTTON_ACTIVE_LOW false
|
#define BUTTON_ACTIVE_LOW false
|
||||||
#define BUTTON_ACTIVE_PULLUP false
|
#define BUTTON_ACTIVE_PULLUP false
|
||||||
#define BUTTON_SENSE_TYPE 0x6
|
#define BUTTON_SENSE_TYPE 0x6
|
||||||
@ -61,9 +61,11 @@ extern "C" {
|
|||||||
|
|
||||||
#define WIRE_INTERFACES_COUNT 1
|
#define WIRE_INTERFACES_COUNT 1
|
||||||
|
|
||||||
// unused pins
|
#define PIN_WIRE_SDA (0 + 26) // P0.26
|
||||||
#define PIN_WIRE_SDA (0 + 9) // P0.26
|
#define PIN_WIRE_SCL (0 + 27) // P0.27
|
||||||
#define PIN_WIRE_SCL (0 + 10) // P0.27
|
#define I2C_NO_RESCAN // I2C is a bit finicky, don't scan too much
|
||||||
|
#define HAS_QMA6100P // very rare beast, only on this board.
|
||||||
|
#define QMA_6100P_INT_PIN (32 + 2) // P1.02
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serial interfaces
|
* Serial interfaces
|
||||||
@ -116,14 +118,22 @@ extern "C" {
|
|||||||
#define PIN_GPS_RESET (32 + 15) // P1.15
|
#define PIN_GPS_RESET (32 + 15) // P1.15
|
||||||
#define GPS_RESET_MODE HIGH
|
#define GPS_RESET_MODE HIGH
|
||||||
|
|
||||||
#define GPS_VRTC_EN (0 + 8) // P0.8, awlays high
|
#define GPS_VRTC_EN (0 + 8) // P0.8, always high
|
||||||
#define GPS_SLEEP_INT (32 + 12) // P1.12, awlays high
|
#define GPS_SLEEP_INT (32 + 12) // P1.12, always high
|
||||||
#define GPS_RTC_INT (0 + 15) // P0.15, normal is LOW, wake by HIGH
|
#define GPS_RTC_INT (0 + 15) // P0.15, normal is LOW, wake by HIGH
|
||||||
#define GPS_RESETB_OUT (32 + 14) // P1.14, awlays input pull_up
|
#define GPS_RESETB_OUT (32 + 14) // P1.14, always input pull_up
|
||||||
|
|
||||||
#define GPS_FIX_HOLD_TIME 15000 // ms
|
#define GPS_FIX_HOLD_TIME 15000 // ms
|
||||||
#define BATTERY_PIN 2
|
#define BATTERY_PIN 2 // P0.02/AIN0, BAT_ADC
|
||||||
|
#define BATTERY_IMMUTABLE
|
||||||
#define ADC_MULTIPLIER (2.0F)
|
#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 ADC_RESOLUTION 14
|
||||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||||
@ -133,13 +143,13 @@ extern "C" {
|
|||||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||||
|
|
||||||
// Buzzer
|
// Buzzer
|
||||||
#define BUZZER_EN_PIN (32 + 5) // P1.05, awlays high
|
#define BUZZER_EN_PIN (32 + 5) // P1.05, always high
|
||||||
#define PIN_BUZZER (0 + 25) // P0.25, pwm output
|
#define PIN_BUZZER (0 + 25) // P0.25, pwm output
|
||||||
|
|
||||||
#define T1000X_SENSOR_EN
|
#define T1000X_SENSOR_EN
|
||||||
#define T1000X_VCC_PIN (0 + 4) // P0.4
|
#define T1000X_VCC_PIN (0 + 4) // P0.4
|
||||||
#define T1000X_NTC_PIN (0 + 31) // P0.31
|
#define T1000X_NTC_PIN (0 + 31) // P0.31/AIN7
|
||||||
#define T1000X_LUX_PIN (0 + 29) // P0.29
|
#define T1000X_LUX_PIN (0 + 29) // P0.29/AIN5
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[VERSION]
|
[VERSION]
|
||||||
major = 2
|
major = 2
|
||||||
minor = 5
|
minor = 5
|
||||||
build = 7
|
build = 9
|
||||||
|
Loading…
Reference in New Issue
Block a user