Files
firmware/src/motion/QMI8658Sensor.cpp
T
c308d0aca4 feat: Support Elecrow ThinkNode M9 (#10908)
* thinknode-m9 variant

* move lora to SPI1 device

* enable SDcard

* use HSPI

* BaseUI tft -> HSPI

* buzzer, webdav lib

* fix build issues

* M9 default to MUI, no BT, short ringtone

* add keyboard long-press config

* update variant

* add ThingNode-M9 GPS string

* GPS 115200 baud

* Basic BaseUI support

* Fixup power detection

* Compass and KB fixes for M9

* add timed Lock::lock()

* add SD card

* point device-ui to thinknode m9 draft branch

* trunk fmt

* fix FusionCompass

* Fix t-deck-tft linker arg list overflow in CI

* SDcard/lora fix: SPI1 must not be declared twice in arduino 3.x -> reuse SPI1 defined in FSCommon.cpp

* update battery parameters

* reinit SD card when updating; fix PSRAM size

* update lib versions

* fix wakeup on key press (KB_INT)

* fix default nag_timeout for TFT/MUI devices with buzzer

* increase PSRAM and SD freq

* trunk fmt

* update lovyanGFX 1.2.26

* update device-ui commit reference

* fix screen definition

* remove DONE; maybe a keyword or other used identifier

* fixed CI error nag_timeout

* fix prepareSleep initialization

* trunk fmt

* reduce SD SPI frequency

* update device-ui

* fix SDcard issue

* stage

* fix device-ui commit reference

* fix device-ui commit

* update device-ui commit (fixed keyboard lag)

* fix QMI8658

* trunk fmt

* update .ini meta information, align SD freq

* fix device-ui reference to target (ready to merge)

* device-ui for all other targets

* make the rabbit happy

* trunk fmt

* fixed lock screen

* fix compile error

* SPI lock timeout

* apply device-ui fix

* revert bad RadioLib commit hash in platformio.ini

Co-authored-by: mverch67 <71137295+mverch67@users.noreply.github.com>

* fix wrong commit hash change

* fix fix commit fix

* I love changing random numbers in random files

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-08-17 17:28:33 +00:00

89 lines
3.9 KiB
C++

#include "QMI8658Sensor.h"
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && __has_include(<SensorQMI8658.hpp>)
#include "NodeDB.h"
#include "detect/ScanI2CTwoWire.h"
#include <math.h>
// Accelerometer configuration. 2G full-scale gives the best gravity resolution for the tilt
// compensation that the (future) separate compass module will apply to these samples.
static constexpr SensorQMI8658::AccelRange QMI8658_ACCEL_RANGE = SensorQMI8658::ACC_RANGE_2G;
static constexpr SensorQMI8658::AccelODR QMI8658_ACCEL_ODR = SensorQMI8658::ACC_ODR_125Hz;
// Any-motion slope threshold (in mg) used to wake the screen. Tunable: raise to reduce false wakes,
// lower to make it more sensitive. 200mg (~0.2g) requires a deliberate movement.
static constexpr float QMI8658_ANY_MOTION_THRESHOLD_MG = 200.0f;
static constexpr uint8_t QMI8658_ANY_MOTION_WINDOW = 1;
// Optional board-defined rotation (degrees) applied to the accel X/Y before publishing to the compass
// fusion path, mirroring the ICM42607P driver. Defaults to no rotation.
static constexpr float QMI8658_ACCEL_TO_COMPASS_ROTATION_DEG_VALUE =
#ifdef QMI8658_ACCEL_TO_COMPASS_ROTATION_DEG
QMI8658_ACCEL_TO_COMPASS_ROTATION_DEG;
#else
0.0f;
#endif
QMI8658Sensor::QMI8658Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool QMI8658Sensor::init()
{
LOG_DEBUG("QMI8658 begin on addr 0x%02X (port=%d)", deviceAddress(), devicePort());
TwoWire *wire = ScanI2CTwoWire::fetchI2CBus(device.address);
if (!sensor.begin(*wire, deviceAddress())) {
LOG_DEBUG("QMI8658 init failed");
return false;
}
sensor.configAccelerometer(QMI8658_ACCEL_RANGE, QMI8658_ACCEL_ODR, SensorQMI8658::LPF_MODE_0);
sensor.enableAccelerometer();
// Configure the on-chip any-motion engine so we can wake the screen without a dedicated interrupt pin.
// configMotion() runs alongside normal accel data output (unlike Wake-on-Motion, which halts data), so
// we keep publishing samples for compass fusion while still detecting motion.
wakeOnMotion = config.display.wake_on_tap_or_motion;
if (wakeOnMotion) {
const uint8_t modeCtrl = SensorQMI8658::ANY_MOTION_EN_X | SensorQMI8658::ANY_MOTION_EN_Y | SensorQMI8658::ANY_MOTION_EN_Z;
// No-motion detection is left disabled (unreliable per the SensorLib example); its thresholds/windows
// are still required arguments but are ignored when the mode bits above are clear.
sensor.configMotion(modeCtrl, QMI8658_ANY_MOTION_THRESHOLD_MG, QMI8658_ANY_MOTION_THRESHOLD_MG,
QMI8658_ANY_MOTION_THRESHOLD_MG, QMI8658_ANY_MOTION_WINDOW, /*NoMotion X/Y/Z*/ 0.1f, 0.1f, 0.1f,
/*NoMotionWindow*/ 1, /*SigMotionWaitWindow*/ 1, /*SigMotionConfirmWindow*/ 1);
sensor.enableMotionDetect();
}
LOG_DEBUG("QMI8658 init ok");
return true;
}
int32_t QMI8658Sensor::runOnce()
{
float ax, ay, az;
if (sensor.getAccelerometer(ax, ay, az)) {
if (QMI8658_ACCEL_TO_COMPASS_ROTATION_DEG_VALUE != 0.0f) {
static const float rotRad = QMI8658_ACCEL_TO_COMPASS_ROTATION_DEG_VALUE * DEG_TO_RAD;
static const float cosTheta = cosf(rotRad);
static const float sinTheta = sinf(rotRad);
const float rotatedX = (ax * cosTheta) - (ay * sinTheta);
const float rotatedY = (ax * sinTheta) + (ay * cosTheta);
ax = rotatedX;
ay = rotatedY;
}
// Match the accel sign convention used by the other FusionCompass sensor paths (e.g. ICM42607P).
// The final handedness must be verified against the QMI8658 datasheet and real calibration once the
// separate compass module is wired up; do not hand-tune the signs before then.
publishCompassAccelSample(ax, ay, az);
}
if (wakeOnMotion && (sensor.getStatusRegister() & SensorQMI8658::EVENT_ANY_MOTION)) {
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif