mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-21 01:07:51 +00:00
add a .clang-format file (#9154)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user