1use core::cell::Cell;
52use kernel::hil::i2c::{self, I2CClient, I2CDevice};
53use kernel::hil::sensors::{HumidityClient, HumidityDriver, TemperatureClient, TemperatureDriver};
54use kernel::utilities::cells::{OptionalCell, TakeCell};
55use kernel::ErrorCode;
56
57pub struct Hs3003<'a, I: I2CDevice> {
58 buffer: TakeCell<'static, [u8]>,
59 i2c: &'a I,
60 temperature_client: OptionalCell<&'a dyn TemperatureClient>,
61 humidity_client: OptionalCell<&'a dyn HumidityClient>,
62 state: Cell<State>,
63 pending_temperature: Cell<bool>,
64 pending_humidity: Cell<bool>,
65}
66
67impl<'a, I: I2CDevice> Hs3003<'a, I> {
68 pub fn new(i2c: &'a I, buffer: &'static mut [u8]) -> Self {
69 Hs3003 {
70 buffer: TakeCell::new(buffer),
71 i2c,
72 temperature_client: OptionalCell::empty(),
73 humidity_client: OptionalCell::empty(),
74 state: Cell::new(State::Sleep),
75 pending_temperature: Cell::new(false),
76 pending_humidity: Cell::new(false),
77 }
78 }
79
80 pub fn start_reading(&self) -> Result<(), ErrorCode> {
81 self.buffer
82 .take()
83 .map(|buffer| {
84 self.i2c.enable();
85 match self.state.get() {
86 State::Sleep => {
87 if let Err((_error, buffer)) = self.i2c.write(buffer, 1) {
88 self.buffer.replace(buffer);
89 self.i2c.disable();
90 } else {
91 self.state.set(State::InitiateReading);
92 }
93 }
94 _ => {}
95 }
96 })
97 .ok_or(ErrorCode::BUSY)
98 }
99}
100
101impl<'a, I: I2CDevice> TemperatureDriver<'a> for Hs3003<'a, I> {
102 fn set_client(&self, client: &'a dyn TemperatureClient) {
103 self.temperature_client.set(client);
104 }
105
106 fn read_temperature(&self) -> Result<(), ErrorCode> {
107 self.pending_temperature.set(true);
108 if !self.pending_humidity.get() {
109 self.start_reading()
110 } else {
111 Ok(())
112 }
113 }
114}
115
116impl<'a, I: I2CDevice> HumidityDriver<'a> for Hs3003<'a, I> {
117 fn set_client(&self, client: &'a dyn HumidityClient) {
118 self.humidity_client.set(client);
119 }
120
121 fn read_humidity(&self) -> Result<(), ErrorCode> {
122 self.pending_humidity.set(true);
123 if !self.pending_temperature.get() {
124 self.start_reading()
125 } else {
126 Ok(())
127 }
128 }
129}
130
131#[derive(Clone, Copy, Debug)]
132enum State {
133 Sleep,
134 InitiateReading,
135 Read,
136}
137
138impl<I: I2CDevice> I2CClient for Hs3003<'_, I> {
139 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
140 if let Err(i2c_err) = status {
141 self.state.set(State::Sleep);
142 self.buffer.replace(buffer);
143 self.temperature_client
144 .map(|client| client.callback(Err(i2c_err.into())));
145 self.humidity_client.map(|client| client.callback(0));
146 return;
147 }
148
149 match self.state.get() {
150 State::InitiateReading => {
151 if let Err((i2c_err, buffer)) = self.i2c.read(buffer, 4) {
152 self.state.set(State::Sleep);
153 self.buffer.replace(buffer);
154 self.temperature_client
155 .map(|client| client.callback(Err(i2c_err.into())));
156 self.humidity_client.map(|client| client.callback(0));
157 } else {
158 self.state.set(State::Read);
159 }
160 }
161 State::Read => {
162 let humidity_raw = (((buffer[0] & 0x3F) as u16) << 8) | buffer[1] as u16;
163 let humidity = ((humidity_raw as f32 / ((1 << 14) - 1) as f32) * 100.0) as usize;
164
165 let temperature_raw = ((buffer[2] as u16) << 8) | (buffer[3] as u16 >> 2);
166 let temperature = ((((temperature_raw as f32 / ((1 << 14) - 1) as f32) * 165.0)
169 - 40.0)
170 / 10.0) as i32;
171
172 self.buffer.replace(buffer);
173 self.i2c.disable();
174 if self.pending_temperature.get() {
175 self.pending_temperature.set(false);
176 self.temperature_client
177 .map(|client| client.callback(Ok(temperature)));
178 }
179 if self.pending_humidity.get() {
180 self.pending_humidity.set(false);
181 self.humidity_client.map(|client| client.callback(humidity));
182 }
183
184 self.state.set(State::Sleep);
185 }
186 State::Sleep => {} }
188 }
189}