refactor(io): unique_ptr ownership for motion sensors and I2C keyboard (#11458)

* refactor(io): unique_ptr ownership for motion sensors and I2C keyboard

- AccelerometerThread / MagnetometerThread: the owned MotionSensor
  becomes unique_ptr, removing the manual delete/null bookkeeping in
  clean(). Deletion behavior is unchanged (MotionSensor's destructor is
  virtual).

- KbI2cBase: the TCA keyboard was a reference member bound to an
  anonymous heap allocation - ownership was invisible and nothing could
  ever free it. It becomes unique_ptr with an out-of-line destructor
  (the base type is only forward-declared in the header).

- GeoCoord::pointAtDistance returned shared_ptr with no shared
  ownership anywhere (and no callers); return by value instead.

No behavior change.

* fix(io): make TCA8418KeyboardBase destructor public for unique_ptr ownership

* refactor(gps): delete dead pointAtDistance instead of converting it

Per review: zero callers in this repo or device-ui, and the math was
wrong at both ends (rangeMetersToRadians multiplies meters by 1852,
treating meters as nautical miles). Remove it, its now-unused helper,
and the <memory> include the old shared_ptr signature pulled in.
This commit is contained in:
Ben Meadors
2026-08-14 09:33:39 +00:00
committed by GitHub
parent a661fd8cd4
commit 5e54262fe1
7 changed files with 44 additions and 74 deletions
-35
View File
@@ -521,41 +521,6 @@ float GeoCoord::bearing(double lat1, double lon1, double lat2, double lon2)
return atan2(y, x);
}
/**
* Ported from http://www.edwilliams.org/avform147.htm#Intro
* @brief Convert from meters to range in radians on a great circle
* @param range_meters
* The range in meters
* @return range in radians on a great circle
*/
float GeoCoord::rangeMetersToRadians(double range_meters)
{
// 1 nm is 1852 meters
double distance_nm = range_meters * 1852;
return (PI / (180 * 60)) * distance_nm;
}
/**
* Create a new point based on the passed-in point
* Ported from http://www.edwilliams.org/avform147.htm#LL
* @param bearing
* The bearing in radians
* @param range_meters
* range in meters
* @return GeoCoord object of point at bearing and range from initial point
*/
std::shared_ptr<GeoCoord> GeoCoord::pointAtDistance(double bearing, double range_meters)
{
double range_radians = rangeMetersToRadians(range_meters);
double lat1 = this->getLatitude() * 1e-7;
double lon1 = this->getLongitude() * 1e-7;
double lat = asin(sin(lat1) * cos(range_radians) + cos(lat1) * sin(range_radians) * cos(bearing));
double dlon = atan2(sin(bearing) * sin(range_radians) * cos(lat1), cos(range_radians) - sin(lat1) * sin(lat));
double lon = fmod(lon1 - dlon + PI, 2 * PI) - PI;
return std::make_shared<GeoCoord>(double(lat), double(lon), this->getAltitude());
}
/**
* Convert bearing to degrees
* @param bearing
-5
View File
@@ -4,7 +4,6 @@
#include <cstdint>
#include <cstring>
#include <math.h>
#include <memory>
#include <stdexcept>
#include <stdint.h>
#include <string>
@@ -103,7 +102,6 @@ class GeoCoord
static void convertWGS84ToOSGB36(const double lat, const double lon, double &osgb_Latitude, double &osgb_Longitude);
static float latLongToMeter(double lat_a, double lng_a, double lat_b, double lng_b);
static float bearing(double lat1, double lon1, double lat2, double lon2);
static float rangeMetersToRadians(double range_meters);
static unsigned int bearingToDegrees(const char *bearing);
static const char *degreesToBearing(unsigned int degrees);
@@ -112,9 +110,6 @@ class GeoCoord
static double toRadians(double deg);
static double toDegrees(double r);
// Point to point conversions
std::shared_ptr<GeoCoord> pointAtDistance(double bearing, double range);
// Lat lon alt getters
int32_t getLatitude() const { return _latitude; }
int32_t getLongitude() const { return _longitude; }
+3 -2
View File
@@ -52,6 +52,9 @@ class TCA8418KeyboardBase
virtual bool hasEvent(void) const;
virtual char dequeueEvent(void);
// Public so owners (KbI2cBase's unique_ptr) can destroy through the base
virtual ~TCA8418KeyboardBase() {}
protected:
enum KeyState { Init, Idle, Held, Busy };
@@ -132,8 +135,6 @@ class TCA8418KeyboardBase
virtual void queueEvent(char);
virtual ~TCA8418KeyboardBase() {}
protected:
// Set the size of the keypad matrix
// All other rows and columns are set as inputs.
+15 -13
View File
@@ -21,20 +21,22 @@ extern uint8_t kb_model;
KbI2cBase::KbI2cBase(const char *name)
: concurrency::OSThread(name),
#if defined(T_DECK_PRO)
TCAKeyboard(*(new TDeckProKeyboard()))
TCAKeyboard(new TDeckProKeyboard())
#elif defined(T_LORA_PAGER)
TCAKeyboard(*(new TLoraPagerKeyboard()))
TCAKeyboard(new TLoraPagerKeyboard())
#elif defined(M5STACK_CARDPUTER_ADV)
TCAKeyboard(*(new CardputerKeyboard()))
TCAKeyboard(new CardputerKeyboard())
#elif defined(HACKADAY_COMMUNICATOR)
TCAKeyboard(*(new HackadayCommunicatorKeyboard()))
TCAKeyboard(new HackadayCommunicatorKeyboard())
#else
TCAKeyboard(*(new TCA8418Keyboard()))
TCAKeyboard(new TCA8418Keyboard())
#endif
{
this->_originName = name;
}
KbI2cBase::~KbI2cBase() = default;
uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t length)
{
uint8_t readflag = 0;
@@ -70,7 +72,7 @@ int32_t KbI2cBase::runOnce()
MPRkeyboard.begin(MPR121_KB_ADDR, i2cBus);
}
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, i2cBus);
TCAKeyboard->begin(TCA8418_KB_ADDR, i2cBus);
}
break;
#endif
@@ -85,7 +87,7 @@ int32_t KbI2cBase::runOnce()
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
}
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire);
TCAKeyboard->begin(TCA8418_KB_ADDR, &Wire);
}
break;
case ScanI2C::NO_I2C:
@@ -259,10 +261,10 @@ int32_t KbI2cBase::runOnce()
break;
}
case 0x84: { // Adafruit TCA8418
TCAKeyboard.trigger();
TCAKeyboard->trigger();
InputEvent e = {};
while (TCAKeyboard.hasEvent()) {
char nextEvent = TCAKeyboard.dequeueEvent();
while (TCAKeyboard->hasEvent()) {
char nextEvent = TCAKeyboard->dequeueEvent();
e.inputEvent = INPUT_BROKER_ANYKEY;
e.kbchar = 0x00;
e.source = this->_originName;
@@ -361,9 +363,9 @@ int32_t KbI2cBase::runOnce()
// LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
this->notifyObservers(&e);
}
TCAKeyboard.trigger();
TCAKeyboard->trigger();
}
TCAKeyboard.clearInt();
TCAKeyboard->clearInt();
break;
}
case 0x02: {
@@ -553,6 +555,6 @@ int32_t KbI2cBase::runOnce()
void KbI2cBase::toggleBacklight(bool on)
{
#if defined(T_LORA_PAGER)
TCAKeyboard.setBacklight(on);
TCAKeyboard->setBacklight(on);
#endif
}
+6 -1
View File
@@ -6,12 +6,17 @@
#include "Wire.h"
#include "concurrency/OSThread.h"
#include <memory>
class TCA8418KeyboardBase;
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit KbI2cBase(const char *name);
// Out-of-line: TCA8418KeyboardBase is only forward-declared here, so the unique_ptr
// deleter must be instantiated in the .cpp where the type is complete
~KbI2cBase();
void toggleBacklight(bool on);
protected:
@@ -24,6 +29,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
BBQ10Keyboard Q10keyboard;
MPR121Keyboard MPRkeyboard;
TCA8418KeyboardBase &TCAKeyboard;
std::unique_ptr<TCA8418KeyboardBase> TCAKeyboard;
bool is_sym = false;
};
+15 -14
View File
@@ -21,6 +21,8 @@
#include "LSM6DS3Sensor.h"
#include "MPU6050Sensor.h"
#include "MotionSensor.h"
#include <memory>
#ifdef HAS_QMA6100P
#include "QMA6100PSensor.h"
#endif
@@ -33,7 +35,7 @@ extern ScanI2C::DeviceAddress accelerometer_found;
class AccelerometerThread : public concurrency::OSThread
{
private:
MotionSensor *sensor = nullptr;
std::unique_ptr<MotionSensor> sensor;
bool isInitialised = false;
public:
@@ -93,56 +95,56 @@ class AccelerometerThread : public concurrency::OSThread
switch (device.type) {
#ifdef HAS_BMA423
case ScanI2C::DeviceType::BMA423:
sensor = new BMA423Sensor(device);
sensor.reset(new BMA423Sensor(device));
break;
#endif
#if __has_include(<Adafruit_MPU6050.h>)
case ScanI2C::DeviceType::MPU6050:
sensor = new MPU6050Sensor(device);
sensor.reset(new MPU6050Sensor(device));
break;
#endif
case ScanI2C::DeviceType::BMX160:
sensor = new BMX160Sensor(device);
sensor.reset(new BMX160Sensor(device));
break;
#if __has_include(<Adafruit_LIS3DH.h>)
case ScanI2C::DeviceType::LIS3DH:
case ScanI2C::DeviceType::SC7A20:
sensor = new LIS3DHSensor(device);
sensor.reset(new LIS3DHSensor(device));
break;
#endif
#if __has_include(<Adafruit_LSM6DS3TRC.h>)
case ScanI2C::DeviceType::LSM6DS3:
sensor = new LSM6DS3Sensor(device);
sensor.reset(new LSM6DS3Sensor(device));
break;
#endif
#ifdef HAS_STK8XXX
case ScanI2C::DeviceType::STK8BAXX:
sensor = new STK8XXXSensor(device);
sensor.reset(new STK8XXXSensor(device));
break;
#endif
#if __has_include(<ICM_20948.h>)
case ScanI2C::DeviceType::ICM20948:
sensor = new ICM20948Sensor(device);
sensor.reset(new ICM20948Sensor(device));
break;
#endif
#if __has_include(<ICM42670P.h>)
case ScanI2C::DeviceType::ICM42607P:
sensor = new ICM42607PSensor(device);
sensor.reset(new ICM42607PSensor(device));
break;
#endif
#if __has_include(<DFRobot_BMM150.h>)
case ScanI2C::DeviceType::BMM150:
sensor = new BMM150Sensor(device);
sensor.reset(new BMM150Sensor(device));
break;
#endif
#ifdef HAS_BMI270
case ScanI2C::DeviceType::BMI270:
sensor = new BMI270Sensor(device);
sensor.reset(new BMI270Sensor(device));
break;
#endif
#ifdef HAS_QMA6100P
case ScanI2C::DeviceType::QMA6100P:
sensor = new QMA6100PSensor(device);
sensor.reset(new QMA6100PSensor(device));
break;
#endif
default:
@@ -185,8 +187,7 @@ class AccelerometerThread : public concurrency::OSThread
void clean()
{
isInitialised = false;
delete sensor;
sensor = nullptr;
sensor.reset();
}
};
+5 -4
View File
@@ -10,12 +10,14 @@
#include "MMC5983MASensor.h"
#include "MotionSensor.h"
#include <memory>
extern ScanI2C::DeviceAddress magnetometer_found;
class MagnetometerThread : public concurrency::OSThread
{
private:
MotionSensor *sensor = nullptr;
std::unique_ptr<MotionSensor> sensor;
ScanI2C::FoundDevice device;
bool isInitialised = false;
@@ -69,7 +71,7 @@ class MagnetometerThread : public concurrency::OSThread
switch (device.type) {
#if __has_include(<SparkFun_MMC5983MA_Arduino_Library.h>)
case ScanI2C::DeviceType::MMC5983MA:
sensor = new MMC5983MASensor(device);
sensor.reset(new MMC5983MASensor(device));
break;
#endif
default:
@@ -106,8 +108,7 @@ class MagnetometerThread : public concurrency::OSThread
void clean()
{
isInitialised = false;
delete sensor;
sensor = nullptr;
sensor.reset();
}
};