1use core::cell::Cell;
41use kernel::hil::i2c::{self, I2CClient, I2CDevice};
42use kernel::hil::sensors::{NineDof, NineDofClient};
43use kernel::utilities::cells::{OptionalCell, TakeCell};
44use kernel::ErrorCode;
45
46#[allow(dead_code)]
47enum Registers {
48 ChipID = 0x40,
49 DATAxLsb = 0x42,
50 DATAxMsb = 0x43,
51 DATAyLsb = 0x44,
52 DATAyMsb = 0x45,
53 DATAzLsb = 0x46,
54 DATAzMsb = 0x47,
55 RHALLlsb = 0x48,
56 RHALLmsb = 0x49,
57 INTST = 0x4A,
58 CTRL1 = 0x4B,
59 CTRL2 = 0x4C,
60 CTRL3 = 0x4D,
61 CTRL4 = 0x4E,
62 LoThres = 0x4F,
63 HiThres = 0x50,
64 REPXY = 0x51,
65 REPZ = 0x52,
66}
67
68pub struct BMM150<'a, I: I2CDevice> {
69 buffer: TakeCell<'static, [u8]>,
70 i2c: &'a I,
71 ninedof_client: OptionalCell<&'a dyn NineDofClient>,
72 state: Cell<State>,
73}
74
75impl<'a, I: I2CDevice> BMM150<'a, I> {
76 pub fn new(buffer: &'static mut [u8], i2c: &'a I) -> BMM150<'a, I> {
77 BMM150 {
78 buffer: TakeCell::new(buffer),
79 i2c,
80 ninedof_client: OptionalCell::empty(),
81 state: Cell::new(State::Suspend),
82 }
83 }
84
85 pub fn start_measurement(&self) -> Result<(), ErrorCode> {
86 self.buffer
87 .take()
88 .map(|buffer| {
89 self.i2c.enable();
90 match self.state.get() {
91 State::Suspend => {
92 buffer[0] = Registers::CTRL1 as u8;
93 buffer[1] = 0x1_u8;
94
95 if let Err((_error, buffer)) = self.i2c.write(buffer, 2) {
96 self.buffer.replace(buffer);
97 self.i2c.disable();
98 } else {
99 self.state.set(State::PowerOn);
100 }
101 }
102 State::Sleep => {
103 buffer[0] = Registers::CTRL2 as u8;
104 buffer[1] = 0x3A_u8;
105
106 if let Err((_error, buffer)) = self.i2c.write(buffer, 2) {
107 self.buffer.replace(buffer);
108 self.i2c.disable();
109 } else {
110 self.state.set(State::InitializeReading);
111 }
112 }
113 _ => {}
114 }
115 })
116 .ok_or(ErrorCode::FAIL)
117 }
118}
119
120impl<'a, I: i2c::I2CDevice> NineDof<'a> for BMM150<'a, I> {
121 fn set_client(&self, client: &'a dyn NineDofClient) {
122 self.ninedof_client.set(client);
123 }
124
125 fn read_magnetometer(&self) -> Result<(), ErrorCode> {
126 self.start_measurement()
127 }
128}
129
130#[derive(Clone, Copy, Debug)]
131enum State {
132 Suspend,
133 Sleep,
134 PowerOn,
135 InitializeReading,
136 ReadMeasurement,
137 Read,
138}
139
140impl<I: I2CDevice> I2CClient for BMM150<'_, I> {
141 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
142 if let Err(i2c_err) = status {
143 self.state.set(State::Sleep);
144 self.buffer.replace(buffer);
145 self.ninedof_client
146 .map(|client| client.callback(i2c_err as usize, 0, 0));
147 return;
148 }
149
150 match self.state.get() {
151 State::PowerOn => {
152 buffer[0] = Registers::CTRL2 as u8;
153 buffer[1] = 0x3A_u8;
154
155 if let Err((error, buffer)) = self.i2c.write(buffer, 2) {
156 self.buffer.replace(buffer);
157 self.i2c.disable();
158 self.ninedof_client
159 .map(|client| client.callback(error as usize, 0, 0));
160 } else {
161 self.state.set(State::InitializeReading);
162 }
163 }
164 State::InitializeReading => {
165 buffer[0] = Registers::DATAxLsb as u8;
166
167 if let Err((i2c_err, buffer)) = self.i2c.write(buffer, 1) {
168 self.state.set(State::Sleep);
169 self.buffer.replace(buffer);
170 self.ninedof_client
171 .map(|client| client.callback(i2c_err as usize, 0, 0));
172 } else {
173 self.state.set(State::ReadMeasurement);
174 }
175 }
176 State::ReadMeasurement => {
177 if let Err((i2c_err, buffer)) = self.i2c.read(buffer, 8) {
178 self.state.set(State::Sleep);
179 self.buffer.replace(buffer);
180 self.ninedof_client
181 .map(|client| client.callback(i2c_err as usize, 0, 0));
182 } else {
183 self.state.set(State::Read);
184 }
185 }
186 State::Read => {
187 let x_axis = ((buffer[1] as i16) << 5) | ((buffer[0] as i16) >> 3);
188 let y_axis = ((buffer[3] as i16) << 5) | ((buffer[2] as i16) >> 3);
189 let z_axis = ((buffer[5] as i16) << 7) | ((buffer[4] as i16) >> 1);
190
191 self.state.set(State::Sleep);
192 self.buffer.replace(buffer);
193 self.i2c.disable();
194 self.ninedof_client.map(|client| {
195 client.callback(x_axis as usize, y_axis as usize, z_axis as usize)
196 });
197 }
198 State::Sleep => {} State::Suspend => {} }
201 }
202}