diff --git a/src/shared/sensors/LIS2MDL/LIS2MDL.h b/src/shared/sensors/LIS2MDL/LIS2MDL.h new file mode 100644 index 0000000000000000000000000000000000000000..03110470f3026d02786800505b89677afe2d102a --- /dev/null +++ b/src/shared/sensors/LIS2MDL/LIS2MDL.h @@ -0,0 +1,218 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Giulia Ghirardini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <diagnostic/PrintLogger.h> +#include <drivers/spi/SPIDriver.h> +#include <sensors/Sensor.h> + +#include "LIS2MDLData.h" + +namespace Boardcore +{ + +/** + * Driver for LIS2MDL, a three-axis magnetic sensor. + */ +class LIS2MDL : public Sensor<LIS2MDLData> +{ +public: + /** + * @brief Constants for Output Data Rate configuration. + * + */ + enum ODR : uint8_t + { + ODR_10_HZ = 0x00, //!< 10 Hz + ODR_20_HZ = 0x01, //!< 20 Hz + ODR_50_HZ = 0x02, //!< 50 Hz + ODR_100_HZ = 0x03, //!< 100 Hz + }; + + /** + * @brief Mode of operation constants. + * + */ + enum OperativeMode : uint8_t + { + MD_CONTINUOUS = 0x00, + MD_SINGLE = 0x01, + MD_IDLE0 = 0x02, + MD_IDLE1 = 0x03, + }; + + /** + * @brief Sensor configuration + * + * This struct contains all the settings the user + * is able to modify with the help of the driver. + * They are applied in the constructor of LIS2MDL class + * and on each call of LIS2MDL::applyConfig() + */ + struct Config + { + Config() {} + /** + * @brief Data rate configuration + * + * Default: 10 Hz + * + * @see LIS2MDL::ODR + */ + ODR odr = ODR_10_HZ; + + /** + * @brief Mode of operation of the device + * Default value: 11 - Idle mode 2 + * + * @see LIS2MDL::OperativeMode + */ + OperativeMode deviceMode = MD_IDLE1; + + /** + * Enables temperature sensor. + * Default: true + */ + bool enableTemperature = true; + + /** + * @brief Sets the value of tempDivider. + * + * With the given value you can instruct the driver to update + * the temperature according to a different rate. + * The temperature will be updated only once in `tempDivider` calls + * to sampleImpl(), so for example: + * 2 -> updated half the times, + * 1 -> updated every time. + */ + unsigned temperatureDivider = 1; + + /** + * @brief Enables interrupts + * + * Whether are interrupts enabled respectively on the x, y and z axis. + * If it is set to true on at least one axis, the interrupts will be + * generated otherwise, they will be completely disabled by the driver. + */ + bool enableInterrupt[3] = {false, false, false}; + + /** + * Absolute value of the threshold that triggers the interrupt + * (expressed in gauss). + */ + float threshold = 0; + + /** + * @brief BDU setting + * + * If set to true, the sensor won't update the data until it is read, if + * false the sensor data will be continuously updated. + */ + bool doBlockDataUpdate = false; + }; + + LIS2MDL(SPIBusInterface& bus, miosix::GpioPin pin, + SPIBusConfig spiConfig = {}, Config config = {}); + + bool init() override; + + bool selfTest() override; + + /** + * @brief Overwrites the sensor settings. + * + * Writes a certain config to the sensor registers. This method is + * automatically called in LIS2MDL::init() using as parameter the + * configuration given in the constructor. + * + * This method checks if the values were actually written in the sensor's + * registers and returns false if at least one of them was not as expected. + * + * @param config The configuration to be applied. + * @returns True if the configuration was applied successfully, + * false otherwise. + */ + bool applyConfig(Config config); + +private: + LIS2MDLData sampleImpl() override; + + SPISlave mSlave; + Config mConfig; + + unsigned currDiv; + bool isInitialized; + float mUnit = 0; + + enum Registers : uint8_t + { + OFFSET_X_REG_L = 0x45, + OFFSET_X_REG_H = 0x46, + OFFSET_Y_REG_L = 0x47, + OFFSET_Y_REG_H = 0x48, + OFFSET_Z_REG_L = 0x49, + OFFSET_Z_REG_H = 0x4a, + + WHO_AM_I = 0x4f, + + CFG_REG_A = 0x60, + CFG_REG_B = 0x61, + CFG_REG_C = 0x62, + + INT_CRTL_REG = 0x63, + INT_SOURCE_REG = 0x64, + INT_THS_L_REG = 0x65, + INT_THS_H_REG = 0x66, + STATUS_REG = 0x67, + + OUTX_L_REG = 0x68, + OUTX_H_REG = 0x69, + OUTY_L_REG = 0x6a, + OUTY_H_REG = 0x6b, + OUTZ_L_REG = 0x6c, + OUTZ_H_REG = 0x6d, + + TEMP_OUT_L_REG = 0x6e, + TEMP_OUT_H_REG = 0x6f, + }; + + static constexpr uint32_t WHO_AM_I_VALUE = 0x40; + static constexpr uint32_t CONTINUOS_CONVERSION = 0x0; + + static constexpr float REFERENCE_TEMPERATURE = 25; + static constexpr float LSB_PER_CELSIUS = 8; + static constexpr float LSB_PER_GAUSS_MIN = 0.001395; + static constexpr float LSB_PER_GAUSS_MAX = 0.001605; + + static constexpr uint32_t ENABLE_TEMPERATURE = 0x80; + static constexpr uint32_t ENABLE_SELF_TEST = 0x02; + static constexpr uint32_t ENABLE_BDU = 0x10; + static constexpr uint32_t ENABLE_INT_PIN = 0x01; + static constexpr uint32_t ENABLE_INT_X = 0x80; + static constexpr uint32_t ENABLE_INT_Y = 0x40; + static constexpr uint32_t ENABLE_INT_Z = 0x20; + + PrintLogger logger = Logging::getLogger("lis2mdl"); +}; + +} // namespace Boardcore