~aleteoryx/muditaos

ref: fcfd5c90a2f8cdf956349652f49bda56be54cab8 muditaos/module-bsp/board/rt1051/bsp/magnetometer/ALS31300.hpp -rw-r--r-- 5.2 KiB
fcfd5c90 — Lefucjusz [MOS-303] GCC11 build fix 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// 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 <array>
#include <cstdint>
#include <cstring>
#include <chrono>

// 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<std::uint8_t, 3> 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