1use core::cell::Cell;
29use kernel::hil;
30use kernel::hil::gpio;
31use kernel::hil::i2c::{Error, I2CClient, I2CDevice};
32use kernel::utilities::cells::{OptionalCell, TakeCell};
33use kernel::ErrorCode;
34
35pub const BUF_LEN: usize = 6;
37
38#[allow(dead_code)]
39enum Registers {
40 Status = 0x00,
41 OutXMsb = 0x01,
42 OutXLsb = 0x02,
43 OutYMsb = 0x03,
44 OutYLsb = 0x04,
45 OutZMsb = 0x05,
46 OutZLsb = 0x06,
47 FSetup = 0x09,
48 TrigCfg = 0x0a,
49 Sysmod = 0x0b,
50 IntSource = 0x0c,
51 WhoAmI = 0x0d,
52 XyzDataCfg = 0x0e,
53 HpFilterCutoff = 0x0f,
54 PlStatus = 0x10,
55 PlCfg = 0x11,
56 PlCount = 0x12,
57 PlBfZcomp = 0x13,
58 PlThsReg = 0x14,
59 AFfmtCfg = 0x15,
60 AFfmtSrc = 0x16,
61 AFfmtThs = 0x17,
62 AFfmtCount = 0x18,
63 TransientCfg = 0x1d,
64 TransientSrc = 0x1e,
65 TransientThs = 0x1f,
66 TransientCount = 0x20,
67 PulseCfg = 0x21,
68 PulseSrc = 0x22,
69 PulseThsx = 0x23,
70 PulseThsy = 0x24,
71 PulseThsz = 0x25,
72 PulseTmlt = 0x26,
73 PulseLtcy = 0x27,
74 PulseWind = 0x28,
75 AslpCount = 0x29,
76 CtrlReg1 = 0x2a,
77 CtrlReg2 = 0x2b,
78 CtrlReg3 = 0x2c,
79 CtrlReg4 = 0x2d,
80 CtrlReg5 = 0x2e,
81 OffX = 0x2f,
82 OffY = 0x30,
83 OffZ = 0x31,
84 MDrStatus = 0x32,
85 MOutXMsb = 0x33,
86 MOutXLsb = 0x34,
87 MOutYMsb = 0x35,
88 MOutYLsb = 0x36,
89 MOutZMsb = 0x37,
90 MOutZLsb = 0x38,
91 CmpXMsb = 0x39,
92 CmpXLsb = 0x3a,
93 CmpYMsb = 0x3b,
94 CmpYLsb = 0x3c,
95 CmpZMsb = 0x3d,
96 CmpZLsb = 0x3e,
97 MOffXMsb = 0x3f,
98 MOffXLsb = 0x40,
99 MOffYMsb = 0x41,
100 MOffYLsb = 0x42,
101 MOffZMsb = 0x43,
102 MOffZLsb = 0x44,
103 MaxXMsb = 0x45,
104 MaxXLsb = 0x46,
105 MaxYMsb = 0x47,
106 MaxYLsb = 0x48,
107 MaxZMsb = 0x49,
108 MaxZLsb = 0x4a,
109 MinXMsb = 0x4b,
110 MinXLsb = 0x4c,
111 MinYMsb = 0x4d,
112 MinYLsb = 0x4e,
113 MinZMsb = 0x4f,
114 MinZLsb = 0x50,
115 Temp = 0x51,
116 MThsCfg = 0x52,
117 MThsSrc = 0x53,
118 MThsXMsb = 0x54,
119 MThsXLsb = 0x55,
120 MThsYMsb = 0x56,
121 MThsYLsb = 0x57,
122 MThsZMsb = 0x58,
123 MThsZLsb = 0x59,
124 MThsCount = 0x5a,
125 MCtrlReg1 = 0x5b,
126 MCtrlReg2 = 0x5c,
127 MCtrlReg3 = 0x5d,
128 MIntSrc = 0x5e,
129 AVecmCfg = 0x5f,
130 AVecmThsMsb = 0x60,
131 AVecmThsLsb = 0x61,
132 AVecmCnt = 0x62,
133 AVecmInitxMsb = 0x63,
134 AVecmInitxLsb = 0x64,
135 AVecmInityMsb = 0x65,
136 AVecmInityLsb = 0x66,
137 AVecmInitzMsb = 0x67,
138 AVecmInitzLsb = 0x68,
139 MVecmCfg = 0x69,
140 MVecmThsMsb = 0x6a,
141 MVecmThsLsb = 0x6b,
142 MVecmCnt = 0x6c,
143 MVecmInitxMsb = 0x6d,
144 MVecmInitxLsb = 0x6e,
145 MVecmInityMsb = 0x6f,
146 MVecmInityLsb = 0x70,
147 MVecmInitzMsb = 0x71,
148 MVecmInitzLsb = 0x72,
149 AFfmtThsXMsb = 0x73,
150 AFfmtThsXLsb = 0x74,
151 AFfmtThsYMsb = 0x75,
152 AFfmtThsYLsb = 0x76,
153 AFfmtThsZMsb = 0x77,
154 AFfmtThsZLsb = 0x78,
155}
156
157#[derive(Clone, Copy, PartialEq)]
158enum State {
159 Disabled,
161
162 ReadAccelSetup,
164
165 ReadAccelWait,
167
168 ReadAccelWaiting,
170
171 ReadAccelReading,
173
174 ReadAccelDeactivating(i16, i16, i16),
176
177 ReadMagStart,
179
180 ReadMagValues,
182}
183
184pub struct Fxos8700cq<'a> {
185 i2c: &'a dyn I2CDevice,
186 interrupt_pin1: &'a dyn gpio::InterruptPin<'a>,
187 state: Cell<State>,
188 buffer: TakeCell<'static, [u8]>,
189 callback: OptionalCell<&'a dyn hil::sensors::NineDofClient>,
190}
191
192impl<'a> Fxos8700cq<'a> {
193 pub fn new(
194 i2c: &'a dyn I2CDevice,
195 interrupt_pin1: &'a dyn gpio::InterruptPin<'a>,
196 buffer: &'static mut [u8],
197 ) -> Fxos8700cq<'a> {
198 Fxos8700cq {
199 i2c,
200 interrupt_pin1,
201 state: Cell::new(State::Disabled),
202 buffer: TakeCell::new(buffer),
203 callback: OptionalCell::empty(),
204 }
205 }
206
207 fn start_read_accel(&self) -> Result<(), ErrorCode> {
208 if self.state.get() == State::Disabled {
209 self.interrupt_pin1.make_input(); self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
211 self.i2c.enable();
212 buf[0] = Registers::CtrlReg4 as u8;
214 buf[1] = 1; buf[2] = 1; if let Err((error, buf)) = self.i2c.write(buf, 3) {
218 self.buffer.replace(buf);
219 self.i2c.disable();
220 Err(error.into())
221 } else {
222 self.state.set(State::ReadAccelSetup);
223 Ok(())
224 }
225 })
226 } else {
227 Err(ErrorCode::BUSY)
228 }
229 }
230
231 fn start_read_magnetometer(&self) -> Result<(), ErrorCode> {
232 if self.state.get() == State::Disabled {
233 self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
234 self.i2c.enable();
235 buf[0] = Registers::MCtrlReg1 as u8;
237 buf[1] = 0b00100011;
239
240 if let Err((error, buf)) = self.i2c.write(buf, 2) {
241 self.buffer.replace(buf);
242 self.i2c.disable();
243 Err(error.into())
244 } else {
245 self.state.set(State::ReadMagStart);
246 Ok(())
247 }
248 })
249 } else {
250 Err(ErrorCode::BUSY)
251 }
252 }
253}
254
255impl gpio::Client for Fxos8700cq<'_> {
256 fn fired(&self) {
257 self.buffer.take().map(|buffer| {
258 self.interrupt_pin1.disable_interrupts();
259
260 self.i2c.enable();
262 buffer[0] = Registers::OutXMsb as u8;
263
264 if let Err((_error, buffer)) = self.i2c.write_read(buffer, 1, 6) {
269 self.buffer.replace(buffer);
270 self.i2c.disable();
271 } else {
272 self.state.set(State::ReadAccelReading);
273 }
274 });
275 }
276}
277
278impl I2CClient for Fxos8700cq<'_> {
279 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), Error>) {
280 if status != Ok(()) {
286 self.state.set(State::Disabled);
287 self.buffer.replace(buffer);
288 self.callback.map(|cb| {
289 cb.callback(0, 0, 0);
290 });
291 return;
292 }
293 match self.state.get() {
294 State::ReadAccelSetup => {
295 self.interrupt_pin1
297 .enable_interrupts(gpio::InterruptEdge::FallingEdge);
298
299 buffer[0] = Registers::CtrlReg1 as u8;
301 buffer[1] = 1;
302
303 if let Err((_error, buffer)) = self.i2c.write(buffer, 2) {
306 self.state.set(State::Disabled);
307 self.buffer.replace(buffer);
308 self.callback.map(|cb| {
309 cb.callback(0, 0, 0);
310 });
311 } else {
312 self.state.set(State::ReadAccelWait);
313 }
314 }
315 State::ReadAccelWait => {
316 if !self.interrupt_pin1.read() {
317 self.interrupt_pin1.disable_interrupts();
319 buffer[0] = Registers::OutXMsb as u8;
320
321 if let Err((_error, buffer)) = self.i2c.write_read(buffer, 1, 6) {
324 self.state.set(State::Disabled);
325 self.buffer.replace(buffer);
326 self.callback.map(|cb| {
327 cb.callback(0, 0, 0);
328 });
329 } else {
330 self.state.set(State::ReadAccelReading);
331 }
332 } else {
333 self.buffer.replace(buffer);
335 self.i2c.disable();
336 self.state.set(State::ReadAccelWaiting);
337 }
338 }
339 State::ReadAccelReading => {
340 let x = (((buffer[0] as i16) << 8) | buffer[1] as i16) >> 2;
341 let y = (((buffer[2] as i16) << 8) | buffer[3] as i16) >> 2;
342 let z = (((buffer[4] as i16) << 8) | buffer[5] as i16) >> 2;
343
344 let x = ((x as isize) * 244) / 1000;
345 let y = ((y as isize) * 244) / 1000;
346 let z = ((z as isize) * 244) / 1000;
347
348 buffer[0] = Registers::CtrlReg1 as u8;
350 buffer[1] = 0; if let Err((_error, buffer)) = self.i2c.write(buffer, 2) {
355 self.state.set(State::Disabled);
356 self.buffer.replace(buffer);
357 self.callback.map(|cb| {
358 cb.callback(0, 0, 0);
359 });
360 } else {
361 self.state
362 .set(State::ReadAccelDeactivating(x as i16, y as i16, z as i16));
363 }
364 }
365 State::ReadAccelDeactivating(x, y, z) => {
366 self.i2c.disable();
367 self.state.set(State::Disabled);
368 self.buffer.replace(buffer);
369 self.callback.map(|cb| {
370 cb.callback(x as usize, y as usize, z as usize);
371 });
372 }
373 State::ReadMagStart => {
374 buffer[0] = Registers::MOutXMsb as u8;
376 self.state.set(State::ReadMagValues);
377
378 if let Err((_error, buffer)) = self.i2c.write_read(buffer, 1, 6) {
381 self.state.set(State::Disabled);
382 self.buffer.replace(buffer);
383 self.callback.map(|cb| {
384 cb.callback(0, 0, 0);
385 });
386 }
387 }
388 State::ReadMagValues => {
389 let x = (((buffer[0] as u16) << 8) | buffer[1] as u16) as i16;
390 let y = (((buffer[2] as u16) << 8) | buffer[3] as u16) as i16;
391 let z = (((buffer[4] as u16) << 8) | buffer[5] as u16) as i16;
392
393 self.i2c.disable();
396 self.state.set(State::Disabled);
397 self.buffer.replace(buffer);
398
399 self.callback
400 .map(|cb| cb.callback(x as usize, y as usize, z as usize));
401 }
402 _ => {}
403 }
404 }
405}
406
407impl<'a> hil::sensors::NineDof<'a> for Fxos8700cq<'a> {
408 fn set_client(&self, client: &'a dyn hil::sensors::NineDofClient) {
409 self.callback.set(client);
410 }
411
412 fn read_accelerometer(&self) -> Result<(), ErrorCode> {
413 self.start_read_accel()
414 }
415
416 fn read_magnetometer(&self) -> Result<(), ErrorCode> {
417 self.start_read_magnetometer()
418 }
419}