capsules_extra/
lps22hb.rs1use core::cell::Cell;
40use kernel::hil::i2c::{self, I2CClient, I2CDevice};
41use kernel::hil::sensors::{PressureClient, PressureDriver};
42use kernel::utilities::cells::{OptionalCell, TakeCell};
43use kernel::ErrorCode;
44
45use capsules_core::driver;
47pub const DRIVER_NUM: usize = driver::NUM::Pressure as usize;
48
49const REGISTER_AUTO_INCREMENT: u8 = 0x80;
52const CTRL_REG1_ONE_SHOT: u8 = 0x00;
53
54#[allow(dead_code)]
55enum Registers {
56 IntCfgReg = 0x0B,
57 ThsPL = 0x0C,
58 ThsPH = 0x0D,
59 WhoAmI = 0x0F,
60 CtrlReg1 = 0x10,
61 CtrlReg2 = 0x11,
62 CtrlReg3 = 0x12,
63 FifoCtrl = 0x14,
64 RefPXl = 0x15,
65 RefPL = 0x16,
66 RefPH = 0x17,
67 RpdsL = 0x18,
68 RpdsH = 0x19,
69 ResConf = 0x1A,
70 IntSourceReg = 0x25,
71 FifoStatus = 0x26,
72 StatusReg = 0x27,
73 PressOutXl = 0x28,
74 PressOutL = 0x29,
75 PressOutH = 0x2A,
76 TempOutL = 0x2B,
77 TempOutH = 0x2C,
78 LpfpRes = 0x33,
79}
80
81pub struct Lps22hb<'a, I: I2CDevice> {
82 buffer: TakeCell<'static, [u8]>,
83 i2c_bus: &'a I,
84 pressure_client: OptionalCell<&'a dyn PressureClient>,
85 pending_pressure: Cell<bool>,
86 state: Cell<State>,
87}
88
89impl<'a, I: I2CDevice> Lps22hb<'a, I> {
90 pub fn new(i2c_bus: &'a I, buffer: &'static mut [u8]) -> Lps22hb<'a, I> {
91 Lps22hb {
92 buffer: TakeCell::new(buffer),
93 i2c_bus,
94 pressure_client: OptionalCell::empty(),
95 pending_pressure: Cell::new(false),
96 state: Cell::new(State::Sleep),
97 }
98 }
99
100 fn start_measurement(&self) -> Result<(), ErrorCode> {
101 self.buffer
102 .take()
103 .map(|buffer| {
104 self.i2c_bus.enable();
105 match self.state.get() {
106 State::Sleep => {
107 buffer[0] = Registers::WhoAmI as u8;
108
109 if let Err((_error, buffer)) = self.i2c_bus.write_read(buffer, 1, 1) {
110 self.buffer.replace(buffer);
111 self.i2c_bus.disable();
112 } else {
113 self.state.set(State::PowerOn);
114 }
115 }
116 State::Idle => {
117 buffer[0] = Registers::CtrlReg2 as u8;
118 buffer[1] = 0x11_u8;
119
120 if let Err((_error, buffer)) = self.i2c_bus.write(buffer, 2) {
121 self.buffer.replace(buffer);
122 self.i2c_bus.disable();
123 } else {
124 self.state.set(State::Status);
125 }
126 }
127 _ => {}
128 }
129 })
130 .ok_or(ErrorCode::FAIL)
131 }
132}
133
134impl<'a, I: I2CDevice> PressureDriver<'a> for Lps22hb<'a, I> {
135 fn set_client(&self, client: &'a dyn PressureClient) {
136 self.pressure_client.set(client);
137 }
138
139 fn read_atmospheric_pressure(&self) -> Result<(), ErrorCode> {
140 if !self.pending_pressure.get() {
141 self.pending_pressure.set(true);
142 self.start_measurement()
143 } else {
144 Err(ErrorCode::BUSY)
145 }
146 }
147}
148
149#[derive(Clone, Copy, PartialEq)]
150pub enum State {
151 Sleep,
152 PowerOn,
153 Idle,
154 ConfOut,
155 Status,
156 ReadMeasurementInit,
157 ReadMeasurement,
158 GotMeasurement,
159}
160
161impl<I: I2CDevice> I2CClient for Lps22hb<'_, I> {
162 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
163 if let Err(i2c_err) = status {
164 self.state.set(State::Idle);
165 self.buffer.replace(buffer);
166 self.pressure_client
167 .map(|client| client.callback(Err(i2c_err.into())));
168 return;
169 }
170
171 match self.state.get() {
172 State::PowerOn => {
173 if buffer[0] == 0xB1 {
174 buffer[0] = Registers::CtrlReg1 as u8;
175 buffer[1] = CTRL_REG1_ONE_SHOT;
176
177 if let Err((i2c_err, buffer)) = self.i2c_bus.write(buffer, 2) {
178 self.state.set(State::Idle);
179 self.buffer.replace(buffer);
180 self.pressure_client
181 .map(|client| client.callback(Err(i2c_err.into())));
182 } else {
183 self.state.set(State::ConfOut);
184 }
185 } else {
186 self.state.set(State::Sleep);
187 }
188 }
189 State::ConfOut => {
190 buffer[0] = Registers::CtrlReg2 as u8;
191 buffer[1] = 0x11_u8;
192
193 if let Err((i2c_err, buffer)) = self.i2c_bus.write(buffer, 2) {
194 self.state.set(State::Idle);
195 self.buffer.replace(buffer);
196 self.pressure_client
197 .map(|client| client.callback(Err(i2c_err.into())));
198 } else {
199 self.state.set(State::Status);
200 }
201 }
202 State::Status => {
203 buffer[0] = Registers::CtrlReg2 as u8;
204
205 if let Err((i2c_err, buffer)) = self.i2c_bus.write_read(buffer, 1, 1) {
206 self.state.set(State::Idle);
207 self.buffer.replace(buffer);
208 self.pressure_client
209 .map(|client| client.callback(Err(i2c_err.into())));
210 } else {
211 self.state.set(State::ReadMeasurementInit);
212 }
213 }
214 State::ReadMeasurementInit => {
215 if buffer[0] == 0x10 {
216 buffer[0] = Registers::PressOutXl as u8 | REGISTER_AUTO_INCREMENT;
217
218 if let Err((i2c_err, buffer)) = self.i2c_bus.write(buffer, 1) {
219 self.state.set(State::Idle);
220 self.buffer.replace(buffer);
221 self.pressure_client
222 .map(|client| client.callback(Err(i2c_err.into())));
223 } else {
224 self.state.set(State::ReadMeasurement);
225 }
226 } else {
227 buffer[0] = Registers::CtrlReg2 as u8;
228
229 if let Err((i2c_err, buffer)) = self.i2c_bus.write_read(buffer, 1, 1) {
230 self.state.set(State::Idle);
231 self.buffer.replace(buffer);
232 self.pressure_client
233 .map(|client| client.callback(Err(i2c_err.into())));
234 } else {
235 self.state.set(State::ReadMeasurementInit);
236 }
237 }
238 }
239 State::ReadMeasurement => {
240 if let Err((i2c_err, buffer)) = self.i2c_bus.read(buffer, 3) {
241 self.state.set(State::Idle);
242 self.buffer.replace(buffer);
243 self.pressure_client
244 .map(|client| client.callback(Err(i2c_err.into())));
245 } else {
246 self.state.set(State::GotMeasurement);
247 }
248 }
249 State::GotMeasurement => {
250 let pressure =
251 (((buffer[2] as u32) << 16) | ((buffer[1] as u32) << 8) | (buffer[0] as u32))
252 / 4096;
253
254 self.buffer.replace(buffer);
255 self.i2c_bus.disable();
256 if self.pending_pressure.get() {
257 self.pending_pressure.set(false);
258 self.pressure_client
259 .map(|client| client.callback(Ok(pressure)));
260 }
261
262 self.state.set(State::Idle);
263 }
264 State::Sleep => {}
265 State::Idle => {}
266 }
267 }
268}