GCC Code Coverage Report


Directory: ./
File: firmware/hw_layer/sensors/lps25.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 15.0% 6 0 40
Functions: 33.3% 1 0 3
Branches: 11.1% 2 0 18
Decisions: 13.3% 2 - 15

Line Branch Decision Exec Source
1 /**
2 * @file lps25.cpp
3 * @brief Driver for the ST LPS25HB pressure sensor
4 *
5 * At the moment uses bit-banged I2C driver
6 *
7 * @date February 6, 2020
8 * @author Matthew Kennedy, (c) 2020
9 */
10
11 #include "pch.h"
12
13 #include "lps25.h"
14
15 static constexpr uint8_t addr = 0x5C;
16 static constexpr uint8_t expectedWhoAmILps22 = 0xB1;
17 static constexpr uint8_t expectedWhoAmILps25 = 0xBD;
18
19 // Control register 1
20 #define LPS_CR1_PD (1 << 7)
21 #define LPS_CR1_ODR_25hz (4 << 4)
22 #define LPS_CR1_BDU (1 << 2)
23
24 // Status register flags
25 #define LPS_SR_P_DA (1 << 1) // Pressure data available
26
27 #define REG_WhoAmI 0x0F
28
29 // register address different on LPS22 vs LPS25
30 #define REG_Cr1_Lps22 0x10
31 #define REG_Cr1_Lps25 0x20
32 #define REG_Status 0x27
33 #define REG_PressureOutXl 0x28
34 #define REG_PressureOutL 0x29
35 #define REG_PressureOutH 0x2A
36
37 2 bool Lps25::init(brain_pin_e scl, brain_pin_e sda) {
38
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
2 if (!m_i2c.init(scl, sda)) {
39 return false;
40 }
41
42 // Read ident register
43 2 auto whoAmI = m_i2c.readRegister(addr, REG_WhoAmI);
44
45
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 switch (whoAmI)
46 {
47 case expectedWhoAmILps22:
48 m_type = Type::Lps22;
49 break;
50 case expectedWhoAmILps25:
51 m_type = Type::Lps25;
52 break;
53
1/1
✓ Decision 'true' taken 2 times.
2 default:
54 // chip not detected
55 2 return false;
56 }
57
58 uint8_t cr1 =
59 LPS_CR1_ODR_25hz | // 25hz update rate
60 // TODO: should bdu be set?
61 LPS_CR1_BDU; // Output registers update only when read
62
63 if (m_type == Type::Lps25) {
64 // Set to active mode
65 // this bit must be 0 on LPS22
66 cr1 |= LPS_CR1_PD;
67 }
68
69 // Set the control registers
70 m_i2c.writeRegister(addr, regCr1(), cr1);
71
72 m_hasInit = true;
73 return true;
74 }
75
76 expected<float> Lps25::readPressureKpa() {
77 if (!m_hasInit) {
78 return unexpected;
79 }
80
81 uint8_t buffer[4];
82 // Sequential multi-byte reads need to set the high bit of the
83 // register address to enable multi-byte read
84 constexpr uint8_t readAddr = REG_Status | 0x80;
85 m_i2c.writeRead(addr, &readAddr, 1, buffer, 4);
86
87 // First check the status reg to check if there are data available
88 bool hasPressure = buffer[0] & LPS_SR_P_DA;
89
90 if (!hasPressure) {
91 return unexpected;
92 }
93
94 // Glue the 3 bytes back in to a 24 bit integer
95 uint32_t counts = buffer[3] << 16 | buffer[2] << 8 | buffer[1];
96
97 // 4096 counts per hectopascal
98 // = 40960 counts per kilopascal
99 constexpr float ratio = 1 / 40960.0f;
100
101 float kilopascal = counts * ratio;
102
103 // Sensor limits are 26-126 kPa
104 // The highest ever barometric pressure measured was only 108.3 kPa
105 // The pressure at the highest altitude road (Khardung La, India/Tibet) is at 5600 meters,
106 // which should have a nominal barometric pressure of around 50 kPa
107 // Anything outside that range is not a place we expect your engine to run, so we assume
108 // some sensing problem (sealed ECU case and high temperature?)
109 if (kilopascal > 120 || kilopascal < 50) {
110 return unexpected;
111 }
112
113 return kilopascal;
114 }
115
116 uint8_t Lps25::regCr1() const {
117 switch (m_type)
118 {
119 case Type::Lps22:
120 return REG_Cr1_Lps22;
121 case Type::Lps25:
122 default:
123 return REG_Cr1_Lps25;
124 }
125 }
126