// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include #include #include #include // ALS31300 magnetometer driver namespace drivers::als31300 { // Note: this device returns 32-bit register values in MSB order using whole_reg_t = uint32_t; // ALS31300 always talks 4 bytes constexpr auto I2C_ADDRESS = 0x64; // base ALS31300 register struct. struct base_reg { virtual operator whole_reg_t() const = 0; }; // REGISTER DEFINITIONS // there is no 0x01 register // -------- constexpr auto CONF_REG = 0x02; struct conf_reg : base_reg { conf_reg(whole_reg_t whole_reg); operator whole_reg_t() const override; uint8_t user_eeprom : 5; bool int_latch_enable : 1; bool channel_X_en : 1; bool channel_Y_en : 1; bool channel_Z_en : 1; bool I2C_threshold : 1; uint8_t slave_addr : 7; bool disable_slave_ADC : 1; bool I2C_CRC_en : 1; uint8_t hall_mode : 2; uint8_t bandwidth : 3; uint8_t RESERVED : 8; }; constexpr auto CONF_REG_LATCH_disabled = 0b0; constexpr auto CONF_REG_LATCH_enabled = 0b1; constexpr auto CONF_REG_CHANNEL_disabled = 0b0; constexpr auto CONF_REG_CHANNEL_enabled = 0b1; constexpr auto CONF_REG_I2C_THRES_3v0 = 0b0; constexpr auto CONF_REG_I2C_THRES_1v8 = 0b1; // -------- constexpr auto INT_REG = 0x03; struct int_reg : base_reg { int_reg(whole_reg_t whole_reg); operator whole_reg_t() const override; uint8_t int_X_threshold : 6; uint8_t int_Y_threshold : 6; uint8_t int_Z_threshold : 6; bool int_X_en : 1; bool int_Y_en : 1; bool int_Z_en : 1; bool int_eeprom_en : 1; bool int_eeprom_status : 1; bool int_mode : 1; bool int_threshold_signed : 1; uint8_t RESERVED : 7; }; constexpr auto INT_REG_INT_CHANNEL_disabled = 0b0; constexpr auto INT_REG_INT_CHANNEL_enabled = 0b1; constexpr auto INT_REG_INT_MODE_threshold = 0b0; constexpr auto INT_REG_INT_MODE_delta = 0b1; constexpr auto INT_REG_THRESHOLD_absolute = 0b0; constexpr auto INT_REG_THRESHOLD_signed = 0b1; constexpr auto INT_REG_INT_EEPROM_disable = 0b0; constexpr auto INT_REG_INT_EEPROM_enable = 0b1; // -------- constexpr auto PWR_REG = 0x27; struct pwr_reg : base_reg { pwr_reg(whole_reg_t whole_reg); operator whole_reg_t() const override; uint8_t sleep : 2; uint8_t I2C_loop_mode : 2; uint8_t count_max_LP_mode : 3; uint32_t RESERVED : 25; }; constexpr auto PWR_REG_SLEEP_MODE_active = 0b00; constexpr auto PWR_REG_SLEEP_MODE_sleep = 0b01; constexpr auto PWR_REG_SLEEP_MODE_LPDCM = 0b10; // Low-Power Duty Cycle Mode constexpr auto PWR_REG_LOOP_MODE_single = 0b00; constexpr auto PWR_REG_LOOP_MODE_fast_loop = 0b01; constexpr auto PWR_REG_LOOP_MODE_full_loop = 0b10; enum PWR_REG_SLEEP_MODE { active = PWR_REG_SLEEP_MODE_active, sleep = PWR_REG_SLEEP_MODE_sleep, periodic_active = PWR_REG_SLEEP_MODE_LPDCM, }; constexpr auto PWR_ON_DELAY_MS = 1; // spec'd as 600µs at most // -------- constexpr auto MEASUREMENTS_MSB_REG = 0x28; struct measurements_MSB_reg : base_reg { measurements_MSB_reg(whole_reg_t whole_reg); operator whole_reg_t() const override; uint8_t temperature_MSB : 6; bool int_flag : 1; bool new_data_flag : 1; uint8_t Z_MSB : 8; uint8_t Y_MSB : 8; uint8_t X_MSB : 8; }; constexpr auto MEAS_REG_NEW_DATA_not_avail = 0b0; constexpr auto MEAS_REG_NEW_DATA_available = 0b1; // -------- constexpr auto MEASUREMENTS_LSB_REG = 0x29; struct measurements_LSB_reg : base_reg { measurements_LSB_reg(whole_reg_t whole_reg); operator whole_reg_t() const override; uint8_t temperature_LSB : 6; uint8_t hall_mode_status : 2; uint8_t Z_LSB : 4; uint8_t Y_LSB : 4; uint8_t X_LSB : 4; bool int_eeprom_write_pending : 1; uint16_t RESERVED : 11; }; float temperature_convert(uint16_t raw_temperature); // NOTE: device sensitivity HW fixed at 4 LSB/Gauss == 0.4 LSB/mT // All measurements are supposed to be raw 4 LSB/Gauss. No need to introduce fractions constexpr auto MEASUREMENTS_REG_bitlength_full_scale = 12; int16_t measurement_sign_convert(uint16_t raw_measurement, uint8_t bit_length = MEASUREMENTS_REG_bitlength_full_scale); // -------- constexpr uint8_t CUSTOMER_ACCESS_REG = 0x35; constexpr whole_reg_t CUSTOMER_ACCESS_REG_code = 0x2C413534; // -------- /// give eeprom registers time to complete WRITE constexpr inline std::array EEPROM_REGS = {CONF_REG, INT_REG, CUSTOMER_ACCESS_REG}; using std::chrono_literals::operator""ms; constexpr auto EEPROM_REG_WRITE_DELAY_MS = 60ms; // docs say 50ms, +10ms for good measure ///////////////////// } // namespace drivers::als31300