Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_Compass: add IIS2MDC driver #28602

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tools/scripts/build_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ def config_option(self):
Feature('Compass', 'HMC5843', 'AP_COMPASS_HMC5843_ENABLED', 'Enable HMC5843 compasses', 1, None),
Feature('Compass', 'ICM20948', 'AP_COMPASS_ICM20948_ENABLED', 'Enable AK09916 on ICM20948 compasses', 1, "AK09916"),
Feature('Compass', 'IST8308', 'AP_COMPASS_IST8308_ENABLED', 'Enable IST8308 compasses', 1, None),
Feature('Compass', 'IIS2MDC', 'AP_COMPASS_IIS2MDC_ENABLED', 'Enable IIS2MDC compasses', 0, None),
Feature('Compass', 'IST8310', 'AP_COMPASS_IST8310_ENABLED', 'Enable IST8310 compasses', 1, None),
Feature('Compass', 'LIS3MDL', 'AP_COMPASS_LIS3MDL_ENABLED', 'Enable LIS3MDL compasses', 1, None),
Feature('Compass', 'LSM303D', 'AP_COMPASS_LSM303D_ENABLED', 'Enable LSM303D compasses', 1, None),
Expand Down
1 change: 1 addition & 0 deletions Tools/scripts/decode_devid.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def num(s):
0x15 : "DEVTYPE_AK09915",
0x16 : "DEVTYPE_QMC5883P",
0x17 : "DEVTYPE_BMM350",
0x18 : "DEVTYPE_IIS2MDC",
}

imu_types = {
Expand Down
23 changes: 22 additions & 1 deletion libraries/AP_Compass/AP_Compass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "AP_Compass_BMM150.h"
#include "AP_Compass_BMM350.h"
#include "AP_Compass_HMC5843.h"
#include "AP_Compass_IIS2MDC.h"
#include "AP_Compass_IST8308.h"
#include "AP_Compass_IST8310.h"
#include "AP_Compass_LSM303D.h"
Expand Down Expand Up @@ -529,7 +530,7 @@ const AP_Param::GroupInfo Compass::var_info[] = {
// @Param: DISBLMSK
// @DisplayName: Compass disable driver type mask
// @Description: This is a bitmask of driver types to disable. If a driver type is set in this mask then that driver will not try to find a sensor at startup
// @Bitmask: 0:HMC5883,1:LSM303D,2:AK8963,3:BMM150,4:LSM9DS1,5:LIS3MDL,6:AK09916,7:IST8310,8:ICM20948,9:MMC3416,11:DroneCAN,12:QMC5883,14:MAG3110,15:IST8308,16:RM3100,17:MSP,18:ExternalAHRS,19:MMC5XX3,20:QMC5883P,21:BMM350
// @Bitmask: 0:HMC5883,1:LSM303D,2:AK8963,3:BMM150,4:LSM9DS1,5:LIS3MDL,6:AK09916,7:IST8310,8:ICM20948,9:MMC3416,11:DroneCAN,12:QMC5883,14:MAG3110,15:IST8308,16:RM3100,17:MSP,18:ExternalAHRS,19:MMC5XX3,20:QMC5883P,21:BMM350,22:IIS2MDC
// @User: Advanced
AP_GROUPINFO("DISBLMSK", 33, Compass, _driver_type_mask, 0),

Expand Down Expand Up @@ -1171,6 +1172,26 @@ void Compass::_probe_external_i2c_compasses(void)
#endif
#endif // AP_COMPASS_QMC5883P_ENABLED

#if AP_COMPASS_IIS2MDC_ENABLED
//external i2c bus
FOREACH_I2C_EXTERNAL(i) {
ADD_BACKEND(DRIVER_IIS2MDC, AP_Compass_IIS2MDC::probe(GET_I2C_DEVICE(i, HAL_COMPASS_IIS2MDC_I2C_ADDR),
true, HAL_COMPASS_IIS2MDC_ORIENTATION_EXTERNAL));
}

// internal i2c bus
#if !defined(HAL_SKIP_AUTO_INTERNAL_I2C_PROBE)
if (all_external) {
// only probe IIS2MDC on internal if we are treating internals as externals
FOREACH_I2C_INTERNAL(i) {
ADD_BACKEND(DRIVER_IIS2MDC, AP_Compass_IIS2MDC::probe(GET_I2C_DEVICE(i, HAL_COMPASS_IIS2MDC_I2C_ADDR),
all_external,
all_external?HAL_COMPASS_IIS2MDC_ORIENTATION_EXTERNAL:HAL_COMPASS_IIS2MDC_ORIENTATION_INTERNAL));
}
}
#endif
#endif // AP_COMPASS_QMC5883P_ENABLED

#ifndef HAL_BUILD_AP_PERIPH
// AK09916 on ICM20948
#if AP_COMPASS_AK09916_ENABLED && AP_COMPASS_ICM20948_ENABLED
Expand Down
3 changes: 3 additions & 0 deletions libraries/AP_Compass/AP_Compass.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,9 @@ friend class AP_Compass_Backend;
#if AP_COMPASS_BMM350_ENABLED
DRIVER_BMM350 =21,
#endif
#if AP_COMPASS_IIS2MDC_ENABLED
DRIVER_IIS2MDC =22,
#endif
};

bool _driver_enabled(enum DriverType driver_type);
Expand Down
1 change: 1 addition & 0 deletions libraries/AP_Compass/AP_Compass_Backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class AP_Compass_Backend
DEVTYPE_AK09915 = 0x15,
DEVTYPE_QMC5883P = 0x16,
DEVTYPE_BMM350 = 0x17,
DEVTYPE_IIS2MDC = 0x18,
};

#if AP_COMPASS_MSP_ENABLED
Expand Down
171 changes: 171 additions & 0 deletions libraries/AP_Compass/AP_Compass_IIS2MDC.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
*
*/
#include "AP_Compass_config.h"

#if AP_COMPASS_IIS2MDC_ENABLED

#include "AP_Compass_IIS2MDC.h"

// IIS2MDC Registers
#define IIS2MDC_ADDR_CFG_REG_A 0x60
#define IIS2MDC_ADDR_CFG_REG_B 0x61
#define IIS2MDC_ADDR_CFG_REG_C 0x62
#define IIS2MDC_ADDR_STATUS_REG 0x67
#define IIS2MDC_ADDR_OUTX_L_REG 0x68
#define IIS2MDC_ADDR_WHO_AM_I 0x4F

// IIS2MDC Definitions
#define IIS2MDC_WHO_AM_I 0b01000000
#define IIS2MDC_STATUS_REG_READY 0b00001111
// CFG_REG_A
#define COMP_TEMP_EN (1 << 7)
#define MD_CONTINUOUS (0 << 0)
#define ODR_100 ((1 << 3) | (1 << 2))
// CFG_REG_B
#define OFF_CANC (1 << 1)
// CFG_REG_C
#define BDU (1 << 4)

extern const AP_HAL::HAL &hal;

AP_Compass_Backend *AP_Compass_IIS2MDC::probe(AP_HAL::OwnPtr<AP_HAL::I2CDevice> dev,
bool force_external,
enum Rotation rotation)
{
if (!dev) {
return nullptr;
}

AP_Compass_IIS2MDC *sensor = NEW_NOTHROW AP_Compass_IIS2MDC(std::move(dev),force_external,rotation);

if (!sensor || !sensor->init()) {
delete sensor;
return nullptr;
}

return sensor;
}

AP_Compass_IIS2MDC::AP_Compass_IIS2MDC(AP_HAL::OwnPtr<AP_HAL::Device> dev,
bool force_external,
enum Rotation rotation)
: _dev(std::move(dev))
, _rotation(rotation)
, _force_external(force_external)
{
}

bool AP_Compass_IIS2MDC::init()
{
WITH_SEMAPHORE(_dev->get_semaphore());

_dev->set_retries(10);

if (!check_whoami()) {
return false;
}

if (!_dev->write_register(IIS2MDC_ADDR_CFG_REG_A, MD_CONTINUOUS | ODR_100 | COMP_TEMP_EN)) {
return false;
}

if (!_dev->write_register(IIS2MDC_ADDR_CFG_REG_B, OFF_CANC)) {
return false;
}

if (!_dev->write_register(IIS2MDC_ADDR_CFG_REG_C, BDU)) {
return false;
}

// lower retries for run
_dev->set_retries(3);

// register compass instance
_dev->set_device_type(DEVTYPE_IIS2MDC);

if (!register_compass(_dev->get_bus_id(), _instance)) {
return false;
}

set_dev_id(_instance, _dev->get_bus_id());

set_rotation(_instance, _rotation);

if (_force_external) {
set_external(_instance, true);
}

// Enable 100HZ
_dev->register_periodic_callback(10000, FUNCTOR_BIND_MEMBER(&AP_Compass_IIS2MDC::timer, void));

return true;
}

bool AP_Compass_IIS2MDC::check_whoami()
{
uint8_t whoami = 0;
if (!_dev->read_registers(IIS2MDC_ADDR_WHO_AM_I, &whoami, 1)){
return false;
}

return whoami == IIS2MDC_WHO_AM_I;
}

void AP_Compass_IIS2MDC::timer()
{
struct PACKED {
uint8_t xout0;
uint8_t xout1;
uint8_t yout0;
uint8_t yout1;
uint8_t zout0;
uint8_t zout1;
uint8_t tout0;
uint8_t tout1;
} buffer;

const float range_scale = 100.f / 65.535f; // +/- 50,000 milligauss, 16bit

uint8_t status = 0;
if (!_dev->read_registers(IIS2MDC_ADDR_STATUS_REG, &status, 1)) {
return;
}

if (!(status & IIS2MDC_STATUS_REG_READY)) {
return;
}

if (!_dev->read_registers(IIS2MDC_ADDR_OUTX_L_REG, (uint8_t *) &buffer, sizeof(buffer))) {
return;
}

const int16_t x = ((buffer.xout1 << 8) | buffer.xout0);
const int16_t y = ((buffer.yout1 << 8) | buffer.yout0);
const int16_t z = -1 * ((buffer.zout1 << 8) | buffer.zout0);

Vector3f field{ x * range_scale, y * range_scale, z * range_scale };

accumulate_sample(field, _instance);
}

void AP_Compass_IIS2MDC::read()
{
drain_accumulated_samples(_instance);
}

#endif //AP_COMPASS_IIS2MDC_ENABLED
67 changes: 67 additions & 0 deletions libraries/AP_Compass/AP_Compass_IIS2MDC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once

#include "AP_Compass_config.h"

#if AP_COMPASS_IIS2MDC_ENABLED

#include <AP_HAL/AP_HAL.h>
#include <AP_HAL/I2CDevice.h>

#include "AP_Compass.h"
#include "AP_Compass_Backend.h"

#ifndef HAL_COMPASS_IIS2MDC_I2C_ADDR
#define HAL_COMPASS_IIS2MDC_I2C_ADDR 0x1E
#endif

#ifndef HAL_COMPASS_IIS2MDC_ORIENTATION_EXTERNAL
#define HAL_COMPASS_IIS2MDC_ORIENTATION_EXTERNAL ROTATION_NONE
#endif

#ifndef HAL_COMPASS_IIS2MDC_ORIENTATION_INTERNAL
#define HAL_COMPASS_IIS2MDC_ORIENTATION_INTERNAL ROTATION_NONE
#endif

class AP_Compass_IIS2MDC : public AP_Compass_Backend
{
public:
static AP_Compass_Backend *probe(AP_HAL::OwnPtr<AP_HAL::I2CDevice> dev,
bool force_external,
enum Rotation rotation);

void read() override;

static constexpr const char *name = "IIS2MDC";

private:
AP_Compass_IIS2MDC(AP_HAL::OwnPtr<AP_HAL::Device> dev,
bool force_external,
enum Rotation rotation);

bool check_whoami();
void timer();
bool init();

AP_HAL::OwnPtr<AP_HAL::Device> _dev;

enum Rotation _rotation;
uint8_t _instance;
bool _force_external;
};

#endif // AP_COMPASS_IIS2MDC_ENABLED
4 changes: 4 additions & 0 deletions libraries/AP_Compass/AP_Compass_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@
#define AP_COMPASS_ICM20948_ENABLED AP_COMPASS_I2C_BACKEND_DEFAULT_ENABLED
#endif

#ifndef AP_COMPASS_IIS2MDC_ENABLED
#define AP_COMPASS_IIS2MDC_ENABLED 0
#endif

#ifndef AP_COMPASS_IST8308_ENABLED
#define AP_COMPASS_IST8308_ENABLED AP_COMPASS_I2C_BACKEND_DEFAULT_ENABLED
#endif
Expand Down
Loading