add a .clang-format file (#9154)

This commit is contained in:
Jorropo
2026-01-03 21:19:24 +01:00
committed by GitHub
parent abab6ce815
commit 0d11331d18
771 changed files with 77752 additions and 83184 deletions

View File

@@ -26,139 +26,127 @@
extern ScanI2C::DeviceAddress accelerometer_found;
class AccelerometerThread : public concurrency::OSThread
{
private:
MotionSensor *sensor = nullptr;
bool isInitialised = false;
class AccelerometerThread : public concurrency::OSThread {
private:
MotionSensor *sensor = nullptr;
bool isInitialised = false;
public:
explicit AccelerometerThread(ScanI2C::FoundDevice foundDevice) : OSThread("Accelerometer")
{
device = foundDevice;
init();
public:
explicit AccelerometerThread(ScanI2C::FoundDevice foundDevice) : OSThread("Accelerometer") {
device = foundDevice;
init();
}
explicit AccelerometerThread(ScanI2C::DeviceType type) : AccelerometerThread(ScanI2C::FoundDevice{type, accelerometer_found}) {}
void start() {
init();
setIntervalFromNow(0);
};
void calibrate(uint16_t forSeconds) {
if (sensor) {
sensor->calibrate(forSeconds);
}
}
protected:
int32_t runOnce() override {
// Assume we should not keep the board awake
canSleep = true;
if (isInitialised)
return sensor->runOnce();
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
private:
ScanI2C::FoundDevice device;
void init() {
if (isInitialised)
return;
if (device.address.port == ScanI2C::I2CPort::NO_I2C || device.address.address == 0 || device.type == ScanI2C::NONE) {
LOG_DEBUG("AccelerometerThread Disable due to no sensors found");
disable();
return;
}
explicit AccelerometerThread(ScanI2C::DeviceType type) : AccelerometerThread(ScanI2C::FoundDevice{type, accelerometer_found})
{
}
void start()
{
init();
setIntervalFromNow(0);
};
void calibrate(uint16_t forSeconds)
{
if (sensor) {
sensor->calibrate(forSeconds);
}
}
protected:
int32_t runOnce() override
{
// Assume we should not keep the board awake
canSleep = true;
if (isInitialised)
return sensor->runOnce();
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
private:
ScanI2C::FoundDevice device;
void init()
{
if (isInitialised)
return;
if (device.address.port == ScanI2C::I2CPort::NO_I2C || device.address.address == 0 || device.type == ScanI2C::NONE) {
LOG_DEBUG("AccelerometerThread Disable due to no sensors found");
disable();
return;
}
switch (device.type) {
switch (device.type) {
#ifdef HAS_BMA423
case ScanI2C::DeviceType::BMA423:
sensor = new BMA423Sensor(device);
break;
case ScanI2C::DeviceType::BMA423:
sensor = new BMA423Sensor(device);
break;
#endif
case ScanI2C::DeviceType::MPU6050:
sensor = new MPU6050Sensor(device);
break;
case ScanI2C::DeviceType::BMX160:
sensor = new BMX160Sensor(device);
break;
case ScanI2C::DeviceType::LIS3DH:
sensor = new LIS3DHSensor(device);
break;
case ScanI2C::DeviceType::LSM6DS3:
sensor = new LSM6DS3Sensor(device);
break;
case ScanI2C::DeviceType::MPU6050:
sensor = new MPU6050Sensor(device);
break;
case ScanI2C::DeviceType::BMX160:
sensor = new BMX160Sensor(device);
break;
case ScanI2C::DeviceType::LIS3DH:
sensor = new LIS3DHSensor(device);
break;
case ScanI2C::DeviceType::LSM6DS3:
sensor = new LSM6DS3Sensor(device);
break;
#ifdef HAS_STK8XXX
case ScanI2C::DeviceType::STK8BAXX:
sensor = new STK8XXXSensor(device);
break;
case ScanI2C::DeviceType::STK8BAXX:
sensor = new STK8XXXSensor(device);
break;
#endif
case ScanI2C::DeviceType::ICM20948:
sensor = new ICM20948Sensor(device);
break;
case ScanI2C::DeviceType::BMM150:
sensor = new BMM150Sensor(device);
break;
case ScanI2C::DeviceType::ICM20948:
sensor = new ICM20948Sensor(device);
break;
case ScanI2C::DeviceType::BMM150:
sensor = new BMM150Sensor(device);
break;
#ifdef HAS_QMA6100P
case ScanI2C::DeviceType::QMA6100P:
sensor = new QMA6100PSensor(device);
break;
case ScanI2C::DeviceType::QMA6100P:
sensor = new QMA6100PSensor(device);
break;
#endif
default:
disable();
return;
}
isInitialised = sensor->init();
if (!isInitialised) {
clean();
}
LOG_DEBUG("AccelerometerThread::init %s", isInitialised ? "ok" : "failed");
default:
disable();
return;
}
// Copy constructor (not implemented / included to avoid cppcheck warnings)
AccelerometerThread(const AccelerometerThread &other) : OSThread::OSThread("Accelerometer") { this->copy(other); }
// Destructor (included to avoid cppcheck warnings)
virtual ~AccelerometerThread() { clean(); }
// Copy assignment (not implemented / included to avoid cppcheck warnings)
AccelerometerThread &operator=(const AccelerometerThread &other)
{
this->copy(other);
return *this;
isInitialised = sensor->init();
if (!isInitialised) {
clean();
}
LOG_DEBUG("AccelerometerThread::init %s", isInitialised ? "ok" : "failed");
}
// Take a very shallow copy (does not copy OSThread state nor the sensor object)
// If for some reason this is ever used, make sure to call init() after any copy
void copy(const AccelerometerThread &other)
{
if (this != &other) {
clean();
this->device = ScanI2C::FoundDevice(other.device.type,
ScanI2C::DeviceAddress(other.device.address.port, other.device.address.address));
}
}
// Copy constructor (not implemented / included to avoid cppcheck warnings)
AccelerometerThread(const AccelerometerThread &other) : OSThread::OSThread("Accelerometer") { this->copy(other); }
// Cleanup resources
void clean()
{
isInitialised = false;
delete sensor;
sensor = nullptr;
// Destructor (included to avoid cppcheck warnings)
virtual ~AccelerometerThread() { clean(); }
// Copy assignment (not implemented / included to avoid cppcheck warnings)
AccelerometerThread &operator=(const AccelerometerThread &other) {
this->copy(other);
return *this;
}
// Take a very shallow copy (does not copy OSThread state nor the sensor object)
// If for some reason this is ever used, make sure to call init() after any copy
void copy(const AccelerometerThread &other) {
if (this != &other) {
clean();
this->device = ScanI2C::FoundDevice(other.device.type, ScanI2C::DeviceAddress(other.device.address.port, other.device.address.address));
}
}
// Cleanup resources
void clean() {
isInitialised = false;
delete sensor;
sensor = nullptr;
}
};
#endif

View File

@@ -4,57 +4,55 @@
BMA423Sensor::BMA423Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool BMA423Sensor::init()
{
if (sensor.begin(Wire, deviceAddress())) {
sensor.configAccelerometer(sensor.RANGE_2G, sensor.ODR_100HZ, sensor.BW_NORMAL_AVG4, sensor.PERF_CONTINUOUS_MODE);
sensor.enableAccelerometer();
sensor.configInterrupt();
bool BMA423Sensor::init() {
if (sensor.begin(Wire, deviceAddress())) {
sensor.configAccelerometer(sensor.RANGE_2G, sensor.ODR_100HZ, sensor.BW_NORMAL_AVG4, sensor.PERF_CONTINUOUS_MODE);
sensor.enableAccelerometer();
sensor.configInterrupt();
#ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
#endif
#ifdef T_WATCH_S3
// Need to raise the wrist function, need to set the correct axis
sensor.setRemapAxes(sensor.REMAP_TOP_LAYER_RIGHT_CORNER);
// Need to raise the wrist function, need to set the correct axis
sensor.setRemapAxes(sensor.REMAP_TOP_LAYER_RIGHT_CORNER);
#else
sensor.setRemapAxes(sensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
sensor.setRemapAxes(sensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
#endif
// sensor.enableFeature(sensor.FEATURE_STEP_CNTR, true);
sensor.enableFeature(sensor.FEATURE_TILT, true);
sensor.enableFeature(sensor.FEATURE_WAKEUP, true);
// sensor.resetPedometer();
// sensor.enableFeature(sensor.FEATURE_STEP_CNTR, true);
sensor.enableFeature(sensor.FEATURE_TILT, true);
sensor.enableFeature(sensor.FEATURE_WAKEUP, true);
// sensor.resetPedometer();
// Turn on feature interrupt
sensor.enablePedometerIRQ();
sensor.enableTiltIRQ();
// Turn on feature interrupt
sensor.enablePedometerIRQ();
sensor.enableTiltIRQ();
// It corresponds to isDoubleClick interrupt
sensor.enableWakeupIRQ();
LOG_DEBUG("BMA423 init ok");
return true;
}
LOG_DEBUG("BMA423 init failed");
return false;
// It corresponds to isDoubleClick interrupt
sensor.enableWakeupIRQ();
LOG_DEBUG("BMA423 init ok");
return true;
}
LOG_DEBUG("BMA423 init failed");
return false;
}
int32_t BMA423Sensor::runOnce()
{
if (sensor.readIrqStatus()) {
if (sensor.isTilt() || sensor.isDoubleTap()) {
wakeScreen();
return 500;
}
int32_t BMA423Sensor::runOnce() {
if (sensor.readIrqStatus()) {
if (sensor.isTilt() || sensor.isDoubleTap()) {
wakeScreen();
return 500;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif

View File

@@ -9,16 +9,15 @@
#include <SensorBMA423.hpp>
#include <Wire.h>
class BMA423Sensor : public MotionSensor
{
private:
SensorBMA423 sensor;
volatile bool BMA_IRQ = false;
class BMA423Sensor : public MotionSensor {
private:
SensorBMA423 sensor;
volatile bool BMA_IRQ = false;
public:
explicit BMA423Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
public:
explicit BMA423Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
};
#endif

View File

@@ -12,39 +12,37 @@ volatile static bool BMM150_IRQ = false;
BMM150Sensor::BMM150Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool BMM150Sensor::init()
{
// Initialise the sensor
sensor = BMM150Singleton::GetInstance(device);
return sensor->init(device);
bool BMM150Sensor::init() {
// Initialise the sensor
sensor = BMM150Singleton::GetInstance(device);
return sensor->init(device);
}
int32_t BMM150Sensor::runOnce()
{
int32_t BMM150Sensor::runOnce() {
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
float heading = sensor->getCompassDegree();
float heading = sensor->getCompassDegree();
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
#endif
return MOTION_SENSOR_CHECK_INTERVAL_MS;
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
// ----------------------------------------------------------------------
@@ -52,17 +50,16 @@ int32_t BMM150Sensor::runOnce()
// ----------------------------------------------------------------------
// Get a singleton wrapper for an Sparkfun BMM_150_I2C
BMM150Singleton *BMM150Singleton::GetInstance(ScanI2C::FoundDevice device)
{
BMM150Singleton *BMM150Singleton::GetInstance(ScanI2C::FoundDevice device) {
#if defined(WIRE_INTERFACES_COUNT) && (WIRE_INTERFACES_COUNT > 1)
TwoWire &bus = (device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
TwoWire &bus = (device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
TwoWire &bus = Wire; // fallback if only one I2C interface
TwoWire &bus = Wire; // fallback if only one I2C interface
#endif
if (pinstance == nullptr) {
pinstance = new BMM150Singleton(&bus, device.address.address);
}
return pinstance;
if (pinstance == nullptr) {
pinstance = new BMM150Singleton(&bus, device.address.address);
}
return pinstance;
}
BMM150Singleton::~BMM150Singleton() {}
@@ -71,23 +68,22 @@ BMM150Singleton *BMM150Singleton::pinstance{nullptr};
// Initialise the BMM150 Sensor
// https://github.com/DFRobot/DFRobot_BMM150/blob/master/examples/getGeomagneticData/getGeomagneticData.ino
bool BMM150Singleton::init(ScanI2C::FoundDevice device)
{
bool BMM150Singleton::init(ScanI2C::FoundDevice device) {
// startup
LOG_DEBUG("BMM150 begin on addr 0x%02X (port=%d)", device.address.address, device.address.port);
uint8_t status = begin();
if (status != 0) {
LOG_DEBUG("BMM150 init error %u", status);
return false;
}
// startup
LOG_DEBUG("BMM150 begin on addr 0x%02X (port=%d)", device.address.address, device.address.port);
uint8_t status = begin();
if (status != 0) {
LOG_DEBUG("BMM150 init error %u", status);
return false;
}
// SW reset to make sure the device starts in a known state
setOperationMode(BMM150_POWERMODE_NORMAL);
setPresetMode(BMM150_PRESETMODE_LOWPOWER);
setRate(BMM150_DATA_RATE_02HZ);
setMeasurementXYZ();
return true;
// SW reset to make sure the device starts in a known state
setOperationMode(BMM150_POWERMODE_NORMAL);
setPresetMode(BMM150_PRESETMODE_LOWPOWER);
setRate(BMM150_DATA_RATE_02HZ);
setMeasurementXYZ();
return true;
}
#endif

View File

@@ -13,43 +13,41 @@
extern ScanI2C::DeviceAddress accelerometer_found;
// Singleton wrapper
class BMM150Singleton : public DFRobot_BMM150_I2C
{
private:
static BMM150Singleton *pinstance;
class BMM150Singleton : public DFRobot_BMM150_I2C {
private:
static BMM150Singleton *pinstance;
protected:
BMM150Singleton(TwoWire *tw, uint8_t addr) : DFRobot_BMM150_I2C(tw, addr) {}
~BMM150Singleton();
protected:
BMM150Singleton(TwoWire *tw, uint8_t addr) : DFRobot_BMM150_I2C(tw, addr) {}
~BMM150Singleton();
public:
// Create a singleton instance (not thread safe)
static BMM150Singleton *GetInstance(ScanI2C::FoundDevice device);
public:
// Create a singleton instance (not thread safe)
static BMM150Singleton *GetInstance(ScanI2C::FoundDevice device);
// Singletons should not be cloneable.
BMM150Singleton(BMM150Singleton &other) = delete;
// Singletons should not be cloneable.
BMM150Singleton(BMM150Singleton &other) = delete;
// Singletons should not be assignable.
void operator=(const BMM150Singleton &) = delete;
// Singletons should not be assignable.
void operator=(const BMM150Singleton &) = delete;
// Initialise the motion sensor singleton for normal operation
bool init(ScanI2C::FoundDevice device);
// Initialise the motion sensor singleton for normal operation
bool init(ScanI2C::FoundDevice device);
};
class BMM150Sensor : public MotionSensor
{
private:
BMM150Singleton *sensor = nullptr;
bool showingScreen = false;
class BMM150Sensor : public MotionSensor {
private:
BMM150Singleton *sensor = nullptr;
bool showingScreen = false;
public:
explicit BMM150Sensor(ScanI2C::FoundDevice foundDevice);
public:
explicit BMM150Sensor(ScanI2C::FoundDevice foundDevice);
// Initialise the motion sensor
virtual bool init() override;
// Initialise the motion sensor
virtual bool init() override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
};
#endif

View File

@@ -11,123 +11,120 @@ BMX160Sensor::BMX160Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::Mot
extern graphics::Screen *screen;
#endif
bool BMX160Sensor::init()
{
if (sensor.begin()) {
// set output data rate
sensor.ODR_Config(BMX160_ACCEL_ODR_100HZ, BMX160_GYRO_ODR_100HZ);
LOG_DEBUG("BMX160 init ok");
return true;
}
LOG_DEBUG("BMX160 init failed");
return false;
bool BMX160Sensor::init() {
if (sensor.begin()) {
// set output data rate
sensor.ODR_Config(BMX160_ACCEL_ODR_100HZ, BMX160_GYRO_ODR_100HZ);
LOG_DEBUG("BMX160 init ok");
return true;
}
LOG_DEBUG("BMX160 init failed");
return false;
}
int32_t BMX160Sensor::runOnce()
{
int32_t BMX160Sensor::runOnce() {
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
sBmx160SensorData_t magAccel;
sBmx160SensorData_t gAccel;
sBmx160SensorData_t magAccel;
sBmx160SensorData_t gAccel;
/* Get a new sensor event */
sensor.getAllData(&magAccel, NULL, &gAccel);
/* Get a new sensor event */
sensor.getAllData(&magAccel, NULL, &gAccel);
if (doCalibration) {
if (doCalibration) {
if (!showingScreen) {
powerFSM.trigger(EVENT_PRESS); // keep screen alive during calibration
showingScreen = true;
if (screen)
screen->startAlert((FrameCallback)drawFrameCalibration);
}
if (magAccel.x > highestX)
highestX = magAccel.x;
if (magAccel.x < lowestX)
lowestX = magAccel.x;
if (magAccel.y > highestY)
highestY = magAccel.y;
if (magAccel.y < lowestY)
lowestY = magAccel.y;
if (magAccel.z > highestZ)
highestZ = magAccel.z;
if (magAccel.z < lowestZ)
lowestZ = magAccel.z;
uint32_t now = millis();
if (now > endCalibrationAt) {
doCalibration = false;
endCalibrationAt = 0;
showingScreen = false;
if (screen)
screen->endAlert();
}
// LOG_DEBUG("BMX160 min_x: %.4f, max_X: %.4f, min_Y: %.4f, max_Y: %.4f, min_Z: %.4f, max_Z: %.4f", lowestX, highestX,
// lowestY, highestY, lowestZ, highestZ);
if (!showingScreen) {
powerFSM.trigger(EVENT_PRESS); // keep screen alive during calibration
showingScreen = true;
if (screen)
screen->startAlert((FrameCallback)drawFrameCalibration);
}
int highestRealX = highestX - (highestX + lowestX) / 2;
if (magAccel.x > highestX)
highestX = magAccel.x;
if (magAccel.x < lowestX)
lowestX = magAccel.x;
if (magAccel.y > highestY)
highestY = magAccel.y;
if (magAccel.y < lowestY)
lowestY = magAccel.y;
if (magAccel.z > highestZ)
highestZ = magAccel.z;
if (magAccel.z < lowestZ)
lowestZ = magAccel.z;
magAccel.x -= (highestX + lowestX) / 2;
magAccel.y -= (highestY + lowestY) / 2;
magAccel.z -= (highestZ + lowestZ) / 2;
FusionVector ga, ma;
ga.axis.x = -gAccel.x; // default location for the BMX160 is on the rear of the board
ga.axis.y = -gAccel.y;
ga.axis.z = gAccel.z;
ma.axis.x = -magAccel.x;
ma.axis.y = -magAccel.y;
ma.axis.z = magAccel.z * 3;
// If we're set to one of the inverted positions
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
uint32_t now = millis();
if (now > endCalibrationAt) {
doCalibration = false;
endCalibrationAt = 0;
showingScreen = false;
if (screen)
screen->endAlert();
}
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
// LOG_DEBUG("BMX160 min_x: %.4f, max_X: %.4f, min_Y: %.4f, max_Y: %.4f, min_Z: %.4f, max_Z: %.4f", lowestX,
// highestX, lowestY, highestY, lowestZ, highestZ);
}
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
int highestRealX = highestX - (highestX + lowestX) / 2;
magAccel.x -= (highestX + lowestX) / 2;
magAccel.y -= (highestY + lowestY) / 2;
magAccel.z -= (highestZ + lowestZ) / 2;
FusionVector ga, ma;
ga.axis.x = -gAccel.x; // default location for the BMX160 is on the rear of the board
ga.axis.y = -gAccel.y;
ga.axis.z = gAccel.z;
ma.axis.x = -magAccel.x;
ma.axis.y = -magAccel.y;
ma.axis.z = magAccel.z * 3;
// If we're set to one of the inverted positions
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
}
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
#endif
return MOTION_SENSOR_CHECK_INTERVAL_MS;
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
void BMX160Sensor::calibrate(uint16_t forSeconds)
{
void BMX160Sensor::calibrate(uint16_t forSeconds) {
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
sBmx160SensorData_t magAccel;
sBmx160SensorData_t gAccel;
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
sensor.getAllData(&magAccel, NULL, &gAccel);
highestX = magAccel.x, lowestX = magAccel.x;
highestY = magAccel.y, lowestY = magAccel.y;
highestZ = magAccel.z, lowestZ = magAccel.z;
sBmx160SensorData_t magAccel;
sBmx160SensorData_t gAccel;
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
sensor.getAllData(&magAccel, NULL, &gAccel);
highestX = magAccel.x, lowestX = magAccel.x;
highestY = magAccel.y, lowestY = magAccel.y;
highestZ = magAccel.z, lowestZ = magAccel.z;
doCalibration = true;
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
endCalibrationAt = millis() + calibrateFor;
if (screen)
screen->setEndCalibration(endCalibrationAt);
doCalibration = true;
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
endCalibrationAt = millis() + calibrateFor;
if (screen)
screen->setEndCalibration(endCalibrationAt);
#endif
}

View File

@@ -12,27 +12,25 @@
#include "Fusion/Fusion.h"
#include <Rak_BMX160.h>
class BMX160Sensor : public MotionSensor
{
private:
RAK_BMX160 sensor;
bool showingScreen = false;
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
class BMX160Sensor : public MotionSensor {
private:
RAK_BMX160 sensor;
bool showingScreen = false;
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
public:
explicit BMX160Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
virtual void calibrate(uint16_t forSeconds) override;
public:
explicit BMX160Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
virtual void calibrate(uint16_t forSeconds) override;
};
#else
// Stub
class BMX160Sensor : public MotionSensor
{
public:
explicit BMX160Sensor(ScanI2C::FoundDevice foundDevice);
class BMX160Sensor : public MotionSensor {
public:
explicit BMX160Sensor(ScanI2C::FoundDevice foundDevice);
};
#endif

View File

@@ -11,186 +11,180 @@ extern graphics::Screen *screen;
volatile static bool ICM20948_IRQ = false;
// Interrupt service routine
void ICM20948SetInterrupt()
{
ICM20948_IRQ = true;
}
void ICM20948SetInterrupt() { ICM20948_IRQ = true; }
ICM20948Sensor::ICM20948Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool ICM20948Sensor::init()
{
// Initialise the sensor
sensor = ICM20948Singleton::GetInstance();
if (!sensor->init(device))
return false;
bool ICM20948Sensor::init() {
// Initialise the sensor
sensor = ICM20948Singleton::GetInstance();
if (!sensor->init(device))
return false;
// Enable simple Wake on Motion
return sensor->setWakeOnMotion();
// Enable simple Wake on Motion
return sensor->setWakeOnMotion();
}
#ifdef ICM_20948_INT_PIN
int32_t ICM20948Sensor::runOnce()
{
// Wake on motion using hardware interrupts - this is the most efficient way to check for motion
if (ICM20948_IRQ) {
ICM20948_IRQ = false;
sensor->clearInterrupts();
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
int32_t ICM20948Sensor::runOnce() {
// Wake on motion using hardware interrupts - this is the most efficient way to check for motion
if (ICM20948_IRQ) {
ICM20948_IRQ = false;
sensor->clearInterrupts();
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#else
int32_t ICM20948Sensor::runOnce()
{
int32_t ICM20948Sensor::runOnce() {
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
#if defined(MUZI_BASE) // temporarily gated to single device due to feature freeze
if (screen && !screen->isScreenOn() && !config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
if (!isAsleep) {
LOG_DEBUG("sleeping IMU");
sensor->sleep(true);
isAsleep = true;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
if (isAsleep) {
sensor->sleep(false);
isAsleep = false;
}
#endif
float magX = 0, magY = 0, magZ = 0;
if (sensor->dataReady()) {
sensor->getAGMT();
magX = sensor->agmt.mag.axes.x;
magY = sensor->agmt.mag.axes.y;
magZ = sensor->agmt.mag.axes.z;
}
if (doCalibration) {
if (!showingScreen) {
powerFSM.trigger(EVENT_PRESS); // keep screen alive during calibration
showingScreen = true;
if (screen)
screen->startAlert((FrameCallback)drawFrameCalibration);
}
if (magX > highestX)
highestX = magX;
if (magX < lowestX)
lowestX = magX;
if (magY > highestY)
highestY = magY;
if (magY < lowestY)
lowestY = magY;
if (magZ > highestZ)
highestZ = magZ;
if (magZ < lowestZ)
lowestZ = magZ;
uint32_t now = millis();
if (now > endCalibrationAt) {
doCalibration = false;
endCalibrationAt = 0;
showingScreen = false;
if (screen)
screen->endAlert();
}
// LOG_DEBUG("ICM20948 min_x: %.4f, max_X: %.4f, min_Y: %.4f, max_Y: %.4f, min_Z: %.4f, max_Z: %.4f", lowestX, highestX,
// lowestY, highestY, lowestZ, highestZ);
}
magX -= (highestX + lowestX) / 2;
magY -= (highestY + lowestY) / 2;
magZ -= (highestZ + lowestZ) / 2;
FusionVector ga, ma;
ga.axis.x = (sensor->agmt.acc.axes.x);
ga.axis.y = -(sensor->agmt.acc.axes.y);
ga.axis.z = -(sensor->agmt.acc.axes.z);
ma.axis.x = magX;
ma.axis.y = magY;
ma.axis.z = magZ;
// If we're set to one of the inverted positions
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
}
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
#endif
// Wake on motion using polling - this is not as efficient as using hardware interrupt pin (see above)
auto status = sensor->setBank(0);
if (sensor->status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 isWakeOnMotion failed to set bank - %s", sensor->statusString());
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
ICM_20948_INT_STATUS_t int_stat;
status = sensor->read(AGB0_REG_INT_STATUS, (uint8_t *)&int_stat, sizeof(ICM_20948_INT_STATUS_t));
if (status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 isWakeOnMotion failed to read interrupts - %s", sensor->statusString());
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
if (int_stat.WOM_INT != 0) {
// Wake up!
wakeScreen();
if (screen && !screen->isScreenOn() && !config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
if (!isAsleep) {
LOG_DEBUG("sleeping IMU");
sensor->sleep(true);
isAsleep = true;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
if (isAsleep) {
sensor->sleep(false);
isAsleep = false;
}
#endif
float magX = 0, magY = 0, magZ = 0;
if (sensor->dataReady()) {
sensor->getAGMT();
magX = sensor->agmt.mag.axes.x;
magY = sensor->agmt.mag.axes.y;
magZ = sensor->agmt.mag.axes.z;
}
if (doCalibration) {
if (!showingScreen) {
powerFSM.trigger(EVENT_PRESS); // keep screen alive during calibration
showingScreen = true;
if (screen)
screen->startAlert((FrameCallback)drawFrameCalibration);
}
if (magX > highestX)
highestX = magX;
if (magX < lowestX)
lowestX = magX;
if (magY > highestY)
highestY = magY;
if (magY < lowestY)
lowestY = magY;
if (magZ > highestZ)
highestZ = magZ;
if (magZ < lowestZ)
lowestZ = magZ;
uint32_t now = millis();
if (now > endCalibrationAt) {
doCalibration = false;
endCalibrationAt = 0;
showingScreen = false;
if (screen)
screen->endAlert();
}
// LOG_DEBUG("ICM20948 min_x: %.4f, max_X: %.4f, min_Y: %.4f, max_Y: %.4f, min_Z: %.4f, max_Z: %.4f", lowestX,
// highestX,
// lowestY, highestY, lowestZ, highestZ);
}
magX -= (highestX + lowestX) / 2;
magY -= (highestY + lowestY) / 2;
magZ -= (highestZ + lowestZ) / 2;
FusionVector ga, ma;
ga.axis.x = (sensor->agmt.acc.axes.x);
ga.axis.y = -(sensor->agmt.acc.axes.y);
ga.axis.z = -(sensor->agmt.acc.axes.z);
ma.axis.x = magX;
ma.axis.y = magY;
ma.axis.z = magZ;
// If we're set to one of the inverted positions
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
}
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
switch (config.display.compass_orientation) {
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
heading += 90;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
heading += 180;
break;
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
heading += 270;
break;
}
if (screen)
screen->setHeading(heading);
#endif
// Wake on motion using polling - this is not as efficient as using hardware interrupt pin (see above)
auto status = sensor->setBank(0);
if (sensor->status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 isWakeOnMotion failed to set bank - %s", sensor->statusString());
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
ICM_20948_INT_STATUS_t int_stat;
status = sensor->read(AGB0_REG_INT_STATUS, (uint8_t *)&int_stat, sizeof(ICM_20948_INT_STATUS_t));
if (status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 isWakeOnMotion failed to read interrupts - %s", sensor->statusString());
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
if (int_stat.WOM_INT != 0) {
// Wake up!
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif
void ICM20948Sensor::calibrate(uint16_t forSeconds)
{
void ICM20948Sensor::calibrate(uint16_t forSeconds) {
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
LOG_DEBUG("Old calibration data: highestX = %f, lowestX = %f, highestY = %f, lowestY = %f, highestZ = %f, lowestZ = %f",
highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
if (sensor->dataReady()) {
sensor->getAGMT();
highestX = sensor->agmt.mag.axes.x;
lowestX = sensor->agmt.mag.axes.x;
highestY = sensor->agmt.mag.axes.y;
lowestY = sensor->agmt.mag.axes.y;
highestZ = sensor->agmt.mag.axes.z;
lowestZ = sensor->agmt.mag.axes.z;
} else {
highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
}
LOG_DEBUG("Old calibration data: highestX = %f, lowestX = %f, highestY = %f, lowestY = %f, highestZ = %f, lowestZ = %f", highestX, lowestX,
highestY, lowestY, highestZ, lowestZ);
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
if (sensor->dataReady()) {
sensor->getAGMT();
highestX = sensor->agmt.mag.axes.x;
lowestX = sensor->agmt.mag.axes.x;
highestY = sensor->agmt.mag.axes.y;
lowestY = sensor->agmt.mag.axes.y;
highestZ = sensor->agmt.mag.axes.z;
lowestZ = sensor->agmt.mag.axes.z;
} else {
highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
}
doCalibration = true;
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
endCalibrationAt = millis() + calibrateFor;
if (screen)
screen->setEndCalibration(endCalibrationAt);
doCalibration = true;
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
endCalibrationAt = millis() + calibrateFor;
if (screen)
screen->setEndCalibration(endCalibrationAt);
#endif
}
// ----------------------------------------------------------------------
@@ -198,12 +192,11 @@ void ICM20948Sensor::calibrate(uint16_t forSeconds)
// ----------------------------------------------------------------------
// Get a singleton wrapper for an Sparkfun ICM_20948_I2C
ICM20948Singleton *ICM20948Singleton::GetInstance()
{
if (pinstance == nullptr) {
pinstance = new ICM20948Singleton();
}
return pinstance;
ICM20948Singleton *ICM20948Singleton::GetInstance() {
if (pinstance == nullptr) {
pinstance = new ICM20948Singleton();
}
return pinstance;
}
ICM20948Singleton::ICM20948Singleton() {}
@@ -213,114 +206,109 @@ ICM20948Singleton::~ICM20948Singleton() {}
ICM20948Singleton *ICM20948Singleton::pinstance{nullptr};
// Initialise the ICM20948 Sensor
bool ICM20948Singleton::init(ScanI2C::FoundDevice device)
{
bool ICM20948Singleton::init(ScanI2C::FoundDevice device) {
#ifdef ICM_20948_DEBUG
// Set ICM_20948_DEBUG to enable helpful debug messages on Serial
enableDebugging();
// Set ICM_20948_DEBUG to enable helpful debug messages on Serial
enableDebugging();
#endif
// startup
// startup
#if defined(WIRE_INTERFACES_COUNT) && (WIRE_INTERFACES_COUNT > 1)
TwoWire &bus = (device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
TwoWire &bus = (device.address.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else
TwoWire &bus = Wire; // fallback if only one I2C interface
TwoWire &bus = Wire; // fallback if only one I2C interface
#endif
bool bAddr = (device.address.address == 0x69);
delay(100);
bool bAddr = (device.address.address == 0x69);
delay(100);
LOG_DEBUG("ICM20948 begin on addr 0x%02X (port=%d, bAddr=%d)", device.address.address, device.address.port, bAddr);
LOG_DEBUG("ICM20948 begin on addr 0x%02X (port=%d, bAddr=%d)", device.address.address, device.address.port, bAddr);
ICM_20948_Status_e status = begin(bus, bAddr);
if (status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init begin - %s", statusString());
return false;
}
ICM_20948_Status_e status = begin(bus, bAddr);
if (status != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init begin - %s", statusString());
return false;
}
// SW reset to make sure the device starts in a known state
if (swReset() != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init reset - %s", statusString());
return false;
}
delay(200);
// SW reset to make sure the device starts in a known state
if (swReset() != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init reset - %s", statusString());
return false;
}
delay(200);
// Now wake the sensor up
if (sleep(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init wake - %s", statusString());
return false;
}
// Now wake the sensor up
if (sleep(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init wake - %s", statusString());
return false;
}
if (lowPower(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init high power - %s", statusString());
return false;
}
if (lowPower(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init high power - %s", statusString());
return false;
}
if (startupMagnetometer(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init magnetometer - %s", statusString());
return false;
}
if (startupMagnetometer(false) != ICM_20948_Stat_Ok) {
LOG_DEBUG("ICM20948 init magnetometer - %s", statusString());
return false;
}
#ifdef ICM_20948_INT_PIN
// Active low
cfgIntActiveLow(true);
LOG_DEBUG("ICM20948 init set cfgIntActiveLow - %s", statusString());
// Active low
cfgIntActiveLow(true);
LOG_DEBUG("ICM20948 init set cfgIntActiveLow - %s", statusString());
// Push-pull
cfgIntOpenDrain(false);
LOG_DEBUG("ICM20948 init set cfgIntOpenDrain - %s", statusString());
// Push-pull
cfgIntOpenDrain(false);
LOG_DEBUG("ICM20948 init set cfgIntOpenDrain - %s", statusString());
// If enabled, *ANY* read will clear the INT_STATUS register.
cfgIntAnyReadToClear(true);
LOG_DEBUG("ICM20948 init set cfgIntAnyReadToClear - %s", statusString());
// If enabled, *ANY* read will clear the INT_STATUS register.
cfgIntAnyReadToClear(true);
LOG_DEBUG("ICM20948 init set cfgIntAnyReadToClear - %s", statusString());
// Latch the interrupt until cleared
cfgIntLatch(true);
LOG_DEBUG("ICM20948 init set cfgIntLatch - %s", statusString());
// Latch the interrupt until cleared
cfgIntLatch(true);
LOG_DEBUG("ICM20948 init set cfgIntLatch - %s", statusString());
// Set up an interrupt pin with an internal pullup for active low
pinMode(ICM_20948_INT_PIN, INPUT_PULLUP);
// Set up an interrupt pin with an internal pullup for active low
pinMode(ICM_20948_INT_PIN, INPUT_PULLUP);
// Set up an interrupt service routine
attachInterrupt(ICM_20948_INT_PIN, ICM20948SetInterrupt, FALLING);
// Set up an interrupt service routine
attachInterrupt(ICM_20948_INT_PIN, ICM20948SetInterrupt, FALLING);
#endif
return true;
return true;
}
#ifdef ICM_20948_DMP_IS_ENABLED
// Stub
bool ICM20948Sensor::initDMP()
{
bool ICM20948Sensor::initDMP() { return false; }
#endif
bool ICM20948Singleton::setWakeOnMotion() {
// Set WoM threshold in milli G's
auto status = WOMThreshold(ICM_20948_WOM_THRESHOLD);
if (status != ICM_20948_Stat_Ok)
return false;
}
#endif
bool ICM20948Singleton::setWakeOnMotion()
{
// Set WoM threshold in milli G's
auto status = WOMThreshold(ICM_20948_WOM_THRESHOLD);
if (status != ICM_20948_Stat_Ok)
return false;
// Enable WoM Logic mode 1 = Compare the current sample with the previous sample
status = WOMLogic(true, 1);
LOG_DEBUG("ICM20948 init set WOMLogic - %s", statusString());
if (status != ICM_20948_Stat_Ok)
return false;
// Enable interrupts on WakeOnMotion
status = intEnableWOM(true);
LOG_DEBUG("ICM20948 init set intEnableWOM - %s", statusString());
return status == ICM_20948_Stat_Ok;
// Clear any current interrupts
ICM20948_IRQ = false;
clearInterrupts();
return true;
// Enable WoM Logic mode 1 = Compare the current sample with the previous sample
status = WOMLogic(true, 1);
LOG_DEBUG("ICM20948 init set WOMLogic - %s", statusString());
if (status != ICM_20948_Stat_Ok)
return false;
// Enable interrupts on WakeOnMotion
status = intEnableWOM(true);
LOG_DEBUG("ICM20948 init set intEnableWOM - %s", statusString());
return status == ICM_20948_Stat_Ok;
// Clear any current interrupts
ICM20948_IRQ = false;
clearInterrupts();
return true;
}
#endif

View File

@@ -46,59 +46,56 @@
extern ScanI2C::DeviceAddress accelerometer_found;
// Singleton wrapper for the Sparkfun ICM_20948_I2C class
class ICM20948Singleton : public ICM_20948_I2C
{
private:
static ICM20948Singleton *pinstance;
class ICM20948Singleton : public ICM_20948_I2C {
private:
static ICM20948Singleton *pinstance;
protected:
ICM20948Singleton();
~ICM20948Singleton();
protected:
ICM20948Singleton();
~ICM20948Singleton();
public:
// Create a singleton instance (not thread safe)
static ICM20948Singleton *GetInstance();
public:
// Create a singleton instance (not thread safe)
static ICM20948Singleton *GetInstance();
// Singletons should not be cloneable.
ICM20948Singleton(ICM20948Singleton &other) = delete;
// Singletons should not be cloneable.
ICM20948Singleton(ICM20948Singleton &other) = delete;
// Singletons should not be assignable.
void operator=(const ICM20948Singleton &) = delete;
// Singletons should not be assignable.
void operator=(const ICM20948Singleton &) = delete;
// Initialise the motion sensor singleton for normal operation
bool init(ScanI2C::FoundDevice device);
// 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();
// Enable Wake on Motion interrupts (sensor must be initialised first)
bool setWakeOnMotion();
#ifdef ICM_20948_DMP_IS_ENABLED
// Initialise the motion sensor singleton for digital motion processing
bool initDMP();
// Initialise the motion sensor singleton for digital motion processing
bool initDMP();
#endif
};
class ICM20948Sensor : public MotionSensor
{
private:
ICM20948Singleton *sensor = nullptr;
bool showingScreen = false;
class ICM20948Sensor : public MotionSensor {
private:
ICM20948Singleton *sensor = nullptr;
bool showingScreen = false;
#ifdef MUZI_BASE
bool isAsleep = false;
float highestX = 449.000000, lowestX = -140.000000, highestY = 422.000000, lowestY = -232.000000, highestZ = 749.000000,
lowestZ = 98.000000;
bool isAsleep = false;
float highestX = 449.000000, lowestX = -140.000000, highestY = 422.000000, lowestY = -232.000000, highestZ = 749.000000, lowestZ = 98.000000;
#else
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
#endif
public:
explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice);
public:
explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice);
// Initialise the motion sensor
virtual bool init() override;
// Initialise the motion sensor
virtual bool init() override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
virtual void calibrate(uint16_t forSeconds) override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
virtual void calibrate(uint16_t forSeconds) override;
};
#endif

View File

@@ -5,33 +5,31 @@
LIS3DHSensor::LIS3DHSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool LIS3DHSensor::init()
{
if (sensor.begin(deviceAddress())) {
sensor.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive
sensor.setClick(config.device.double_tap_as_button_press ? 2 : 1, MOTION_SENSOR_CHECK_INTERVAL_MS);
LOG_DEBUG("LIS3DH init ok");
return true;
}
LOG_DEBUG("LIS3DH init failed");
return false;
bool LIS3DHSensor::init() {
if (sensor.begin(deviceAddress())) {
sensor.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive
sensor.setClick(config.device.double_tap_as_button_press ? 2 : 1, MOTION_SENSOR_CHECK_INTERVAL_MS);
LOG_DEBUG("LIS3DH init ok");
return true;
}
LOG_DEBUG("LIS3DH init failed");
return false;
}
int32_t LIS3DHSensor::runOnce()
{
if (sensor.getClick() > 0) {
uint8_t click = sensor.getClick();
if (!config.device.double_tap_as_button_press && config.display.wake_on_tap_or_motion) {
wakeScreen();
}
if (config.device.double_tap_as_button_press && (click & 0x20)) {
buttonPress();
return 500;
}
int32_t LIS3DHSensor::runOnce() {
if (sensor.getClick() > 0) {
uint8_t click = sensor.getClick();
if (!config.device.double_tap_as_button_press && config.display.wake_on_tap_or_motion) {
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
if (config.device.double_tap_as_button_press && (click & 0x20)) {
buttonPress();
return 500;
}
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif

View File

@@ -8,15 +8,14 @@
#include <Adafruit_LIS3DH.h>
class LIS3DHSensor : public MotionSensor
{
private:
Adafruit_LIS3DH sensor;
class LIS3DHSensor : public MotionSensor {
private:
Adafruit_LIS3DH sensor;
public:
explicit LIS3DHSensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
public:
explicit LIS3DHSensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
};
#endif

View File

@@ -5,30 +5,28 @@
LSM6DS3Sensor::LSM6DS3Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool LSM6DS3Sensor::init()
{
if (sensor.begin_I2C(deviceAddress())) {
bool LSM6DS3Sensor::init() {
if (sensor.begin_I2C(deviceAddress())) {
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
sensor.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
sensor.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
// Duration is number of occurrences needed to trigger, higher threshold is less sensitive
sensor.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
// Duration is number of occurrences needed to trigger, higher threshold is less sensitive
sensor.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
LOG_DEBUG("LSM6DS3 init ok");
return true;
}
LOG_DEBUG("LSM6DS3 init failed");
return false;
LOG_DEBUG("LSM6DS3 init ok");
return true;
}
LOG_DEBUG("LSM6DS3 init failed");
return false;
}
int32_t LSM6DS3Sensor::runOnce()
{
if (sensor.shake()) {
wakeScreen();
return 500;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
int32_t LSM6DS3Sensor::runOnce() {
if (sensor.shake()) {
wakeScreen();
return 500;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif

View File

@@ -12,15 +12,14 @@
#include <Adafruit_LSM6DS3TRC.h>
class LSM6DS3Sensor : public MotionSensor
{
private:
Adafruit_LSM6DS3TRC sensor;
class LSM6DS3Sensor : public MotionSensor {
private:
Adafruit_LSM6DS3TRC sensor;
public:
explicit LSM6DS3Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
public:
explicit LSM6DS3Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
};
#endif

View File

@@ -4,28 +4,26 @@
MPU6050Sensor::MPU6050Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool MPU6050Sensor::init()
{
if (sensor.begin(deviceAddress())) {
// setup motion detection
sensor.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
sensor.setMotionDetectionThreshold(1);
sensor.setMotionDetectionDuration(20);
sensor.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
sensor.setInterruptPinPolarity(true);
LOG_DEBUG("MPU6050 init ok");
return true;
}
LOG_DEBUG("MPU6050 init failed");
return false;
bool MPU6050Sensor::init() {
if (sensor.begin(deviceAddress())) {
// setup motion detection
sensor.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
sensor.setMotionDetectionThreshold(1);
sensor.setMotionDetectionDuration(20);
sensor.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
sensor.setInterruptPinPolarity(true);
LOG_DEBUG("MPU6050 init ok");
return true;
}
LOG_DEBUG("MPU6050 init failed");
return false;
}
int32_t MPU6050Sensor::runOnce()
{
if (sensor.getMotionInterruptStatus()) {
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
int32_t MPU6050Sensor::runOnce() {
if (sensor.getMotionInterruptStatus()) {
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif

View File

@@ -8,15 +8,14 @@
#include <Adafruit_MPU6050.h>
class MPU6050Sensor : public MotionSensor
{
private:
Adafruit_MPU6050 sensor;
class MPU6050Sensor : public MotionSensor {
private:
Adafruit_MPU6050 sensor;
public:
explicit MPU6050Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
public:
explicit MPU6050Sensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
};
#endif

View File

@@ -8,76 +8,63 @@ char timeRemainingBuffer[12];
// screen is defined in main.cpp
extern graphics::Screen *screen;
MotionSensor::MotionSensor(ScanI2C::FoundDevice foundDevice)
{
device.address.address = foundDevice.address.address;
device.address.port = foundDevice.address.port;
device.type = foundDevice.type;
LOG_DEBUG("Motion MotionSensor port: %s address: 0x%x type: %d", devicePort() == ScanI2C::I2CPort::WIRE1 ? "Wire1" : "Wire",
(uint8_t)deviceAddress(), deviceType());
MotionSensor::MotionSensor(ScanI2C::FoundDevice foundDevice) {
device.address.address = foundDevice.address.address;
device.address.port = foundDevice.address.port;
device.type = foundDevice.type;
LOG_DEBUG("Motion MotionSensor port: %s address: 0x%x type: %d", devicePort() == ScanI2C::I2CPort::WIRE1 ? "Wire1" : "Wire",
(uint8_t)deviceAddress(), deviceType());
}
ScanI2C::DeviceType MotionSensor::deviceType()
{
return device.type;
}
ScanI2C::DeviceType MotionSensor::deviceType() { return device.type; }
uint8_t MotionSensor::deviceAddress()
{
return device.address.address;
}
uint8_t MotionSensor::deviceAddress() { return device.address.address; }
ScanI2C::I2CPort MotionSensor::devicePort()
{
return device.address.port;
}
ScanI2C::I2CPort MotionSensor::devicePort() { return device.address.port; }
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
void MotionSensor::drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
if (screen == nullptr)
return;
// int x_offset = display->width() / 2;
// int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
display->drawString(x, y, "Calibrating\nCompass");
void MotionSensor::drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
if (screen == nullptr)
return;
// int x_offset = display->width() / 2;
// int y_offset = display->height() <= 80 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
display->drawString(x, y, "Calibrating\nCompass");
uint8_t timeRemaining = (screen->getEndCalibration() - millis()) / 1000;
sprintf(timeRemainingBuffer, "( %02d )", timeRemaining);
display->setFont(FONT_SMALL);
display->drawString(x, y + 40, timeRemainingBuffer);
uint8_t timeRemaining = (screen->getEndCalibration() - millis()) / 1000;
sprintf(timeRemainingBuffer, "( %02d )", timeRemaining);
display->setFont(FONT_SMALL);
display->drawString(x, y + 40, timeRemainingBuffer);
int16_t compassX = 0, compassY = 0;
uint16_t compassDiam = graphics::CompassRenderer::getCompassDiam(display->getWidth(), display->getHeight());
int16_t compassX = 0, compassY = 0;
uint16_t compassDiam = graphics::CompassRenderer::getCompassDiam(display->getWidth(), display->getHeight());
// coordinates for the center of the compass/circle
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + display->getHeight() / 2;
} else {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
}
display->drawCircle(compassX, compassY, compassDiam / 2);
graphics::CompassRenderer::drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180, (compassDiam / 2));
// coordinates for the center of the compass/circle
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + display->getHeight() / 2;
} else {
compassX = x + display->getWidth() - compassDiam / 2 - 5;
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
}
display->drawCircle(compassX, compassY, compassDiam / 2);
graphics::CompassRenderer::drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180, (compassDiam / 2));
}
#endif
#if !MESHTASTIC_EXCLUDE_POWER_FSM
void MotionSensor::wakeScreen()
{
if (powerFSM.getState() == &stateDARK) {
LOG_DEBUG("Motion wakeScreen detected");
if (config.display.wake_on_tap_or_motion)
powerFSM.trigger(EVENT_INPUT);
}
void MotionSensor::wakeScreen() {
if (powerFSM.getState() == &stateDARK) {
LOG_DEBUG("Motion wakeScreen detected");
if (config.display.wake_on_tap_or_motion)
powerFSM.trigger(EVENT_INPUT);
}
}
void MotionSensor::buttonPress()
{
LOG_DEBUG("Motion buttonPress detected");
powerFSM.trigger(EVENT_PRESS);
void MotionSensor::buttonPress() {
LOG_DEBUG("Motion buttonPress detected");
powerFSM.trigger(EVENT_PRESS);
}
#else

View File

@@ -17,48 +17,47 @@
#include "Wire.h"
// Base class for motion processing
class MotionSensor
{
public:
explicit MotionSensor(ScanI2C::FoundDevice foundDevice);
virtual ~MotionSensor(){};
class MotionSensor {
public:
explicit MotionSensor(ScanI2C::FoundDevice foundDevice);
virtual ~MotionSensor(){};
// Get the device type
ScanI2C::DeviceType deviceType();
// Get the device type
ScanI2C::DeviceType deviceType();
// Get the device address
uint8_t deviceAddress();
// Get the device address
uint8_t deviceAddress();
// Get the device port
ScanI2C::I2CPort devicePort();
// Get the device port
ScanI2C::I2CPort devicePort();
// Initialise the motion sensor
inline virtual bool init() { return false; };
// Initialise the motion sensor
inline virtual bool init() { return false; };
// The method that will be called each time our sensor gets a chance to run
// Returns the desired period for next invocation (or RUN_SAME for no change)
// Refer to /src/concurrency/OSThread.h for more information
inline virtual int32_t runOnce() { return MOTION_SENSOR_CHECK_INTERVAL_MS; };
// The method that will be called each time our sensor gets a chance to run
// Returns the desired period for next invocation (or RUN_SAME for no change)
// Refer to /src/concurrency/OSThread.h for more information
inline virtual int32_t runOnce() { return MOTION_SENSOR_CHECK_INTERVAL_MS; };
virtual void calibrate(uint16_t forSeconds){};
virtual void calibrate(uint16_t forSeconds){};
protected:
// Turn on the screen when a tap or motion is detected
virtual void wakeScreen();
protected:
// Turn on the screen when a tap or motion is detected
virtual void wakeScreen();
// Register a button press when a double-tap is detected
virtual void buttonPress();
// Register a button press when a double-tap is detected
virtual void buttonPress();
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
// draw an OLED frame (currently only used by the RAK4631 BMX160 sensor)
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// draw an OLED frame (currently only used by the RAK4631 BMX160 sensor)
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#endif
ScanI2C::FoundDevice device;
ScanI2C::FoundDevice device;
// Do calibration if true
bool doCalibration = false;
uint32_t endCalibrationAt = 0;
// Do calibration if true
bool doCalibration = false;
uint32_t endCalibrationAt = 0;
};
#endif

View File

@@ -6,53 +6,47 @@
volatile static bool QMA6100P_IRQ = false;
// Interrupt service routine
void QMA6100PSetInterrupt()
{
QMA6100P_IRQ = true;
}
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;
bool QMA6100PSensor::init() {
// Initialise the sensor
sensor = QMA6100PSingleton::GetInstance();
if (!sensor->init(device))
return false;
// Enable simple Wake on Motion
return sensor->setWakeOnMotion();
// 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;
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)
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("QMA6100PS isWakeOnMotion failed to read interrupts");
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
if ((tempVal & 7) != 0) {
// Wake up!
wakeScreen();
}
uint8_t tempVal;
if (!sensor->readRegisterRegion(SFE_QMA6100P_INT_ST0, &tempVal, 1)) {
LOG_DEBUG("QMA6100PS 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
@@ -62,12 +56,11 @@ int32_t QMA6100PSensor::runOnce()
// ----------------------------------------------------------------------
// Get a singleton wrapper for an Sparkfun QMA_6100P_I2C
QMA6100PSingleton *QMA6100PSingleton::GetInstance()
{
if (pinstance == nullptr) {
pinstance = new QMA6100PSingleton();
}
return pinstance;
QMA6100PSingleton *QMA6100PSingleton::GetInstance() {
if (pinstance == nullptr) {
pinstance = new QMA6100PSingleton();
}
return pinstance;
}
QMA6100PSingleton::QMA6100PSingleton() {}
@@ -77,107 +70,105 @@ QMA6100PSingleton::~QMA6100PSingleton() {}
QMA6100PSingleton *QMA6100PSingleton::pinstance{nullptr};
// Initialise the QMA6100P Sensor
bool QMA6100PSingleton::init(ScanI2C::FoundDevice device)
{
bool QMA6100PSingleton::init(ScanI2C::FoundDevice device) {
// startup
#ifdef Wire1
bool status = begin(device.address.address, device.address.port == ScanI2C::I2CPort::WIRE1 ? &Wire1 : &Wire);
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);
// check chip id
bool status = begin(device.address.address, &Wire);
#endif
if (status != true) {
LOG_WARN("QMA6100P init begin failed");
return false;
}
delay(20);
// SW reset to make sure the device starts in a known state
if (softwareReset() != true) {
LOG_WARN("QMA6100P init reset failed");
return false;
}
delay(20);
// Set range
if (!setRange(QMA_6100P_MPU_ACCEL_SCALE)) {
LOG_WARN("QMA6100P init range failed");
return false;
}
// set active mode
if (!enableAccel()) {
LOG_WARN("ERROR QMA6100P active mode set failed");
}
// set calibrateoffsets
if (!calibrateOffsets()) {
LOG_WARN("ERROR QMA6100P calibration failed");
}
if (status != true) {
LOG_WARN("QMA6100P init begin failed");
return false;
}
delay(20);
// SW reset to make sure the device starts in a known state
if (softwareReset() != true) {
LOG_WARN("QMA6100P init reset failed");
return false;
}
delay(20);
// Set range
if (!setRange(QMA_6100P_MPU_ACCEL_SCALE)) {
LOG_WARN("QMA6100P init range failed");
return false;
}
// set active mode
if (!enableAccel()) {
LOG_WARN("ERROR QMA6100P active mode set failed");
}
// set calibrateoffsets
if (!calibrateOffsets()) {
LOG_WARN("ERROR QMA6100P calibration failed");
}
#ifdef QMA_6100P_INT_PIN
// Active low & Open Drain
uint8_t tempVal;
if (!readRegisterRegion(SFE_QMA6100P_INTPINT_CONF, &tempVal, 1)) {
LOG_WARN("QMA6100P init failed to read interrupt pin config");
return false;
}
// Active low & Open Drain
uint8_t tempVal;
if (!readRegisterRegion(SFE_QMA6100P_INTPINT_CONF, &tempVal, 1)) {
LOG_WARN("QMA6100P init failed to read interrupt pin config");
return false;
}
tempVal |= 0b00000010; // Active low & Open Drain
tempVal |= 0b00000010; // Active low & Open Drain
if (!writeRegisterByte(SFE_QMA6100P_INTPINT_CONF, tempVal)) {
LOG_WARN("QMA6100P init failed to write interrupt pin config");
return false;
}
if (!writeRegisterByte(SFE_QMA6100P_INTPINT_CONF, tempVal)) {
LOG_WARN("QMA6100P 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("QMA6100P init failed to read interrupt config");
return false;
}
// Latch until cleared, all reads clear the latch
if (!readRegisterRegion(SFE_QMA6100P_INT_CFG, &tempVal, 1)) {
LOG_WARN("QMA6100P init failed to read interrupt config");
return false;
}
tempVal |= 0b10000001; // Latch until cleared, INT_RD_CLR1
tempVal |= 0b10000001; // Latch until cleared, INT_RD_CLR1
if (!writeRegisterByte(SFE_QMA6100P_INT_CFG, tempVal)) {
LOG_WARN("QMA6100P 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);
if (!writeRegisterByte(SFE_QMA6100P_INT_CFG, tempVal)) {
LOG_WARN("QMA6100P 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);
// Set up an interrupt service routine
attachInterrupt(QMA_6100P_INT_PIN, QMA6100PSetInterrupt, FALLING);
#endif
return true;
return true;
}
bool QMA6100PSingleton::setWakeOnMotion()
{
// Enable 'Any Motion' interrupt
if (!writeRegisterByte(SFE_QMA6100P_INT_EN2, 0b00000111)) {
LOG_WARN("QMA6100P :setWakeOnMotion failed to write interrupt enable");
return false;
}
bool QMA6100PSingleton::setWakeOnMotion() {
// Enable 'Any Motion' interrupt
if (!writeRegisterByte(SFE_QMA6100P_INT_EN2, 0b00000111)) {
LOG_WARN("QMA6100P :setWakeOnMotion failed to write interrupt enable");
return false;
}
// Set 'Significant Motion' interrupt map to INT1
uint8_t tempVal;
// Set 'Significant Motion' interrupt map to INT1
uint8_t tempVal;
if (!readRegisterRegion(SFE_QMA6100P_INT_MAP1, &tempVal, 1)) {
LOG_WARN("QMA6100P setWakeOnMotion failed to read interrupt map");
return false;
}
if (!readRegisterRegion(SFE_QMA6100P_INT_MAP1, &tempVal, 1)) {
LOG_WARN("QMA6100P 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;
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("QMA6100P setWakeOnMotion failed to write interrupt map");
return false;
}
if (!writeRegisterByte(SFE_QMA6100P_INT_MAP1, tempVal)) {
LOG_WARN("QMA6100P setWakeOnMotion failed to write interrupt map");
return false;
}
// Clear any current interrupts
QMA6100P_IRQ = false;
return true;
// Clear any current interrupts
QMA6100P_IRQ = false;
return true;
}
#endif

View File

@@ -17,45 +17,43 @@
extern ScanI2C::DeviceAddress accelerometer_found;
// Singleton wrapper for the Sparkfun QMA_6100P_I2C class
class QMA6100PSingleton : public QMA6100P
{
private:
static QMA6100PSingleton *pinstance;
class QMA6100PSingleton : public QMA6100P {
private:
static QMA6100PSingleton *pinstance;
protected:
QMA6100PSingleton();
~QMA6100PSingleton();
protected:
QMA6100PSingleton();
~QMA6100PSingleton();
public:
// Create a singleton instance (not thread safe)
static QMA6100PSingleton *GetInstance();
public:
// Create a singleton instance (not thread safe)
static QMA6100PSingleton *GetInstance();
// Singletons should not be cloneable.
QMA6100PSingleton(QMA6100PSingleton &other) = delete;
// Singletons should not be cloneable.
QMA6100PSingleton(QMA6100PSingleton &other) = delete;
// Singletons should not be assignable.
void operator=(const QMA6100PSingleton &) = delete;
// Singletons should not be assignable.
void operator=(const QMA6100PSingleton &) = delete;
// Initialise the motion sensor singleton for normal operation
bool init(ScanI2C::FoundDevice device);
// 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();
// Enable Wake on Motion interrupts (sensor must be initialised first)
bool setWakeOnMotion();
};
class QMA6100PSensor : public MotionSensor
{
private:
QMA6100PSingleton *sensor = nullptr;
class QMA6100PSensor : public MotionSensor {
private:
QMA6100PSingleton *sensor = nullptr;
public:
explicit QMA6100PSensor(ScanI2C::FoundDevice foundDevice);
public:
explicit QMA6100PSensor(ScanI2C::FoundDevice foundDevice);
// Initialise the motion sensor
virtual bool init() override;
// Initialise the motion sensor
virtual bool init() override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
// Called each time our sensor gets a chance to run
virtual int32_t runOnce() override;
};
#endif

View File

@@ -8,31 +8,29 @@ STK8XXXSensor::STK8XXXSensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::M
volatile static bool STK_IRQ;
bool STK8XXXSensor::init()
{
if (sensor.STK8xxx_Initialization(STK8xxx_VAL_RANGE_2G)) {
STK_IRQ = false;
sensor.STK8xxx_Anymotion_init();
pinMode(STK8XXX_INT, INPUT_PULLUP);
attachInterrupt(
digitalPinToInterrupt(STK8XXX_INT), [] { STK_IRQ = true; }, RISING);
bool STK8XXXSensor::init() {
if (sensor.STK8xxx_Initialization(STK8xxx_VAL_RANGE_2G)) {
STK_IRQ = false;
sensor.STK8xxx_Anymotion_init();
pinMode(STK8XXX_INT, INPUT_PULLUP);
attachInterrupt(
digitalPinToInterrupt(STK8XXX_INT), [] { STK_IRQ = true; }, RISING);
LOG_DEBUG("STK8XXX init ok");
return true;
}
LOG_DEBUG("STK8XXX init failed");
return false;
LOG_DEBUG("STK8XXX init ok");
return true;
}
LOG_DEBUG("STK8XXX init failed");
return false;
}
int32_t STK8XXXSensor::runOnce()
{
if (STK_IRQ) {
STK_IRQ = false;
if (config.display.wake_on_tap_or_motion) {
wakeScreen();
}
int32_t STK8XXXSensor::runOnce() {
if (STK_IRQ) {
STK_IRQ = false;
if (config.display.wake_on_tap_or_motion) {
wakeScreen();
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
return MOTION_SENSOR_CHECK_INTERVAL_MS;
}
#endif

View File

@@ -10,24 +10,22 @@
#include <stk8baxx.h>
class STK8XXXSensor : public MotionSensor
{
private:
STK8xxx sensor;
class STK8XXXSensor : public MotionSensor {
private:
STK8xxx sensor;
public:
explicit STK8XXXSensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
public:
explicit STK8XXXSensor(ScanI2C::FoundDevice foundDevice);
virtual bool init() override;
virtual int32_t runOnce() override;
};
#else
// Stub
class STK8XXXSensor : public MotionSensor
{
public:
explicit STK8XXXSensor(ScanI2C::FoundDevice foundDevice);
class STK8XXXSensor : public MotionSensor {
public:
explicit STK8XXXSensor(ScanI2C::FoundDevice foundDevice);
};
#endif