Skyward boardcore
Loading...
Searching...
No Matches
H3LIS331DL.cpp
Go to the documentation of this file.
1/* Copyright (c) 2023 Skyward Experimental Rocketry
2 * Author: Radu Raul
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "H3LIS331DL.h"
24
25namespace Boardcore
26{
27
28H3LIS331DL::H3LIS331DL(SPIBusInterface& spiBus, miosix::GpioPin cs,
32 : spi(spiBus, cs, cfg), odr(odr), bdu(bdu), fs(fs), initialized(false)
33{
35}
36
37H3LIS331DL::H3LIS331DL(SPIBusInterface& spiBus, miosix::GpioPin cs,
41 : H3LIS331DL(spiBus, cs, {}, odr, bdu, fs)
42{
43}
44
46{
47 SPIBusConfig spiConfig;
49 spiConfig.mode = SPI::Mode::MODE_3;
50 spiConfig.byteOrder = SPI::Order::LSB_FIRST;
51 return spiConfig;
52}
53
55{
56 if (initialized)
57 {
59 return false;
60 }
61
62 SPITransaction spiTr(spi);
63
64 uint8_t whoami =
66
67 if (whoami != H3LIS331DLDefs::WHO_AM_I_ID)
68 {
70 LOG_ERR(logger,
71 "Failed init. Cause: INVALID_WHOAMI. Expected Value: "
72 "{:X}. Actual Value: {:X}\n",
74 return false;
75 }
76
77 // We assume everything is okay, if there are issues while writing the
78 // configuration we will set this flag to false
79 initialized = true;
80
81 // CTRL_REG1 initialization
82 {
83 uint8_t ctrlReg1 = 0b0000'0000; // Default: poweroff
84
85 ctrlReg1 = odr | H3LIS331DLDefs::CTRL_REG1_XEN |
88
89 spiTr.writeRegister(H3LIS331DLDefs::Registers::REG_CTRL_REG1, ctrlReg1);
90
91 miosix::delayUs(10);
92
93 uint8_t ctrlReg1OnChip =
95
96 initialized = (ctrlReg1 == ctrlReg1OnChip);
97
98 if (!initialized)
99 {
100 LOG_ERR(logger,
101 "Control Register 1 After init: {:X}, expected "
102 "value:{:X}",
103 ctrlReg1OnChip, ctrlReg1);
104 return false;
105 }
106 }
107
108 {
109 // CTRL_REG4 initialization
110 // CTRL_REG4 controls the BDU (@see H3LIS331DL::BlockDataUpdate) and
111 // the FSR (@see H3LIS331DL::FullScaleRange).
112 uint8_t ctrlReg4 = 0b0000'0000;
113
114 ctrlReg4 = bdu | fs;
115
116 spiTr.writeRegister(H3LIS331DLDefs::Registers::REG_CTRL_REG4, ctrlReg4);
117
118 miosix::delayUs(10);
119
120 uint8_t ctrlReg4OnChip =
122
123 initialized = (ctrlReg4 == ctrlReg4OnChip);
124
125 if (!initialized)
126 {
127 LOG_ERR(logger,
128 "Control Register 1 After init: {:X}, expected "
129 "value:{:X}",
130 ctrlReg4OnChip, ctrlReg4);
131 return false;
132 }
133 }
134
135 return initialized;
136}
137
138bool H3LIS331DL::selfTest() { return true; }
139
141{
142 if (!initialized)
143 {
145 return lastSample;
146 }
147
148 // Timestamp of the last sample
149 uint64_t lastSampleTimestamp = TimestampTimer::getTimestamp();
150
151 float x = 0;
152 float y = 0;
153 float z = 0;
154
155 // Read output data registers (X, Y, Z)
156 {
157 SPITransaction spiTr(spi);
158 uint8_t buff[7];
159
162 buff, 7);
163
164 // The status register that tells if new data is available is the first
165 // byte that was read from the 7 byte read.
166 uint8_t status = buff[0];
167 uint16_t regX = buff[2] << 8 | buff[1];
168 uint16_t regY = buff[4] << 8 | buff[3];
169 uint16_t regZ = buff[6] << 8 | buff[5];
170
171 if (!(status & H3LIS331DLDefs::STATUS_REG_XYZDR))
172 {
174 LOG_ERR(logger, "No new data available.");
175 return lastSample;
176 }
177
178 // Here we get the sensitivity based on the FullScaleRange
179 float sensitivity = H3LIS331DLDefs::SENSITIVITY_VALUES[fs >> 4];
180
181 int16_t xInt = static_cast<int16_t>(regX);
182 float xFloat = static_cast<float>(xInt >> 4);
183 x = xFloat * sensitivity;
184
185 int16_t yInt = static_cast<int16_t>(regY);
186 float yFloat = static_cast<float>(yInt >> 4);
187 y = yFloat * sensitivity;
188
189 int16_t zInt = static_cast<int16_t>(regZ);
190 float zFloat = static_cast<float>(zInt >> 4);
191 z = zFloat * sensitivity;
192 }
193
194 return H3LIS331DLData(lastSampleTimestamp, x, y, z);
195}
196
197} // namespace Boardcore
#define LOG_ERR(logger,...)
SensorErrors lastError
Definition Sensor.h:54
static SPIBusConfig getDefaultSPIConfig()
H3LIS331DL(SPIBusInterface &spiBus, miosix::GpioPin cs, H3LIS331DLDefs::OutputDataRate odr, H3LIS331DLDefs::BlockDataUpdate bdu, H3LIS331DLDefs::FullScaleRange fs)
Creates an instance of an H3LIS331DL sensor.
H3LIS331DLData sampleImpl() override
Samples data from the register.
bool init()
Initializes the H3LIS331DL.
bool selfTest()
This method does nothing as no self test is implemented in the sensor.
Interface for low level access of a SPI bus as a master.
Provides high-level access to the SPI Bus for a single transaction.
constexpr float SENSITIVITY_VALUES[]
Constants for the sensitivity values based on the Full Scale Range.
FullScaleRange
Constants for the FullScale Range.
BlockDataUpdate
Constants for Block Data Update.
constexpr uint8_t CTRL_REG1_ZEN
constexpr uint8_t CTRL_REG1_XEN
constexpr uint8_t AUTOINC_ADDR
make the driver automatically increase the register address when reading multiple bytes with SPI.
constexpr uint8_t CTRL_REG1_YEN
@ STATUS_REG_XYZDR
Data Ready on All Axis.
OutputDataRate
Constants for Output Data Rate configuration.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
@ INVALID_WHOAMI
Definition SensorData.h:40
SPI Bus configuration for a specific slave.
SPI::ClockDivider clockDivider
< Peripheral clock division