Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_Compass/AP_Compass_LSM9DS1.cpp
Views: 1798
#include "AP_Compass_LSM9DS1.h"12#if AP_COMPASS_LSM9DS1_ENABLED34#include <AP_Math/AP_Math.h>5#include <AP_HAL/AP_HAL.h>67#define LSM9DS1M_OFFSET_X_REG_L_M 0x058#define LSM9DS1M_OFFSET_X_REG_H_M 0x069#define LSM9DS1M_OFFSET_Y_REG_L_M 0x0710#define LSM9DS1M_OFFSET_Y_REG_H_M 0x0811#define LSM9DS1M_OFFSET_Z_REG_L_M 0x0912#define LSM9DS1M_OFFSET_Z_REG_H_M 0x0A1314#define LSM9DS1M_WHO_AM_I 0x0F15#define WHO_AM_I_MAG 0x3D1617#define LSM9DS1M_CTRL_REG1_M 0x2018#define LSM9DS1M_TEMP_COMP (0x1 << 7)19#define LSM9DS1M_XY_ULTRA_HIGH (0x3 << 5)20#define LSM9DS1M_80HZ (0x7 << 2)21#define LSM9DS1M_FAST_ODR (0x1 << 1)2223#define LSM9DS1M_CTRL_REG2_M 0x2124#define LSM9DS1M_FS_16G (0x3 << 5)2526#define LSM9DS1M_CTRL_REG3_M 0x2227#define LSM9DS1M_SPI_ENABLE (0x01 << 2)28#define LSM9DS1M_CONTINUOUS_MODE 0x02930#define LSM9DS1M_CTRL_REG4_M 0x2331#define LSM9DS1M_Z_ULTRA_HIGH (0x3 << 2)3233#define LSM9DS1M_CTRL_REG5_M 0x2434#define LSM9DS1M_BDU (0x0 << 6)3536#define LSM9DS1M_STATUS_REG_M 0x273738#define LSM9DS1M_OUT_X_L_M 0x2839#define LSM9DS1M_OUT_X_H_M 0x2940#define LSM9DS1M_OUT_Y_L_M 0x2A41#define LSM9DS1M_OUT_Y_H_M 0x2B42#define LSM9DS1M_OUT_Z_L_M 0x2C43#define LSM9DS1M_OUT_Z_H_M 0x2D44#define LSM9DS1M_INT_CFG_M 0x3045#define LSM9DS1M_INT_SRC_M 0x3146#define LSM9DS1M_INT_THS_L_M 0x3247#define LSM9DS1M_INT_THS_H_M 0x334849extern const AP_HAL::HAL &hal;5051AP_Compass_LSM9DS1::AP_Compass_LSM9DS1(AP_HAL::OwnPtr<AP_HAL::Device> dev,52enum Rotation rotation)53: _dev(std::move(dev))54, _rotation(rotation)55{56}5758AP_Compass_Backend *AP_Compass_LSM9DS1::probe(AP_HAL::OwnPtr<AP_HAL::Device> dev,59enum Rotation rotation)60{61if (!dev) {62return nullptr;63}64AP_Compass_LSM9DS1 *sensor = NEW_NOTHROW AP_Compass_LSM9DS1(std::move(dev), rotation);65if (!sensor || !sensor->init()) {66delete sensor;67return nullptr;68}6970return sensor;71}7273bool AP_Compass_LSM9DS1::init()74{75AP_HAL::Semaphore *bus_sem = _dev->get_semaphore();7677if (!bus_sem) {78DEV_PRINTF("LSM9DS1: Unable to get bus semaphore\n");79return false;80}81bus_sem->take_blocking();8283if (!_check_id()) {84DEV_PRINTF("LSM9DS1: Could not check id\n");85goto errout;86}8788if (!_configure()) {89DEV_PRINTF("LSM9DS1: Could not check id\n");90goto errout;91}9293if (!_set_scale()) {94DEV_PRINTF("LSM9DS1: Could not set scale\n");95goto errout;96}9798//register compass instance99_dev->set_device_type(DEVTYPE_LSM9DS1);100if (!register_compass(_dev->get_bus_id(), _compass_instance)) {101goto errout;102}103set_dev_id(_compass_instance, _dev->get_bus_id());104105set_rotation(_compass_instance, _rotation);106107108_dev->register_periodic_callback(10000, FUNCTOR_BIND_MEMBER(&AP_Compass_LSM9DS1::_update, void));109110bus_sem->give();111112return true;113114errout:115bus_sem->give();116return false;117}118119void AP_Compass_LSM9DS1::_dump_registers()120{121DEV_PRINTF("LSMDS1 registers\n");122for (uint8_t reg = LSM9DS1M_OFFSET_X_REG_L_M; reg <= LSM9DS1M_INT_THS_H_M; reg++) {123DEV_PRINTF("%02x:%02x ", (unsigned)reg, (unsigned)_register_read(reg));124if ((reg - (LSM9DS1M_OFFSET_X_REG_L_M-1)) % 16 == 0) {125DEV_PRINTF("\n");126}127}128DEV_PRINTF("\n");129}130131void AP_Compass_LSM9DS1::_update(void)132{133struct sample_regs regs;134Vector3f raw_field;135136if (!_block_read(LSM9DS1M_STATUS_REG_M, (uint8_t *) ®s, sizeof(regs))) {137return;138}139140if (regs.status & 0x80) {141return;142}143144raw_field = Vector3f(regs.val[0], regs.val[1], regs.val[2]);145146if (is_zero(raw_field.x) && is_zero(raw_field.y) && is_zero(raw_field.z)) {147return;148}149150raw_field *= _scaling;151152accumulate_sample(raw_field, _compass_instance);153}154155void AP_Compass_LSM9DS1::read()156{157drain_accumulated_samples(_compass_instance);158}159160bool AP_Compass_LSM9DS1::_check_id(void)161{162// initially run the bus at low speed163_dev->set_speed(AP_HAL::Device::SPEED_LOW);164165uint8_t value = _register_read(LSM9DS1M_WHO_AM_I);166if (value != WHO_AM_I_MAG) {167DEV_PRINTF("LSM9DS1: unexpected WHOAMI 0x%x\n", (unsigned)value);168return false;169}170171_dev->set_speed(AP_HAL::Device::SPEED_HIGH);172173return true;174}175176bool AP_Compass_LSM9DS1::_configure(void)177{178_register_write(LSM9DS1M_CTRL_REG1_M, LSM9DS1M_TEMP_COMP | LSM9DS1M_XY_ULTRA_HIGH | LSM9DS1M_80HZ | LSM9DS1M_FAST_ODR);179_register_write(LSM9DS1M_CTRL_REG2_M, LSM9DS1M_FS_16G);180_register_write(LSM9DS1M_CTRL_REG3_M, LSM9DS1M_CONTINUOUS_MODE);181_register_write(LSM9DS1M_CTRL_REG4_M, LSM9DS1M_Z_ULTRA_HIGH);182_register_write(LSM9DS1M_CTRL_REG5_M, LSM9DS1M_BDU);183184return true;185}186187bool AP_Compass_LSM9DS1::_set_scale(void)188{189static const uint8_t FS_M_MASK = 0xc;190_register_modify(LSM9DS1M_CTRL_REG2_M, FS_M_MASK, LSM9DS1M_FS_16G);191_scaling = 0.58f;192193return true;194}195196uint8_t AP_Compass_LSM9DS1::_register_read(uint8_t reg)197{198uint8_t val = 0;199200/* set READ bit */201reg |= 0x80;202_dev->read_registers(reg, &val, 1);203204return val;205}206207bool AP_Compass_LSM9DS1::_block_read(uint8_t reg, uint8_t *buf, uint32_t size)208{209/* set !MS bit */210reg |= 0xc0;211return _dev->read_registers(reg, buf, size);212}213214void AP_Compass_LSM9DS1::_register_write(uint8_t reg, uint8_t val)215{216_dev->write_register(reg, val);217}218219void AP_Compass_LSM9DS1::_register_modify(uint8_t reg, uint8_t clearbits, uint8_t setbits)220{221uint8_t val;222223val = _register_read(reg);224val &= ~clearbits;225val |= setbits;226_register_write(reg, val);227}228229#endif230231232