capsules_extra/
hs3003.rs
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 if let State::Sleep = self.state.get() {
86 if let Err((_error, buffer)) = self.i2c.write(buffer, 1) {
87 self.buffer.replace(buffer);
88 self.i2c.disable();
89 } else {
90 self.state.set(State::InitiateReading);
91 }
92 }
93 })
94 .ok_or(ErrorCode::BUSY)
95 }
96}
97
98impl<'a, I: I2CDevice> TemperatureDriver<'a> for Hs3003<'a, I> {
99 fn set_client(&self, client: &'a dyn TemperatureClient) {
100 self.temperature_client.set(client);
101 }
102
103 fn read_temperature(&self) -> Result<(), ErrorCode> {
104 self.pending_temperature.set(true);
105 if !self.pending_humidity.get() {
106 self.start_reading()
107 } else {
108 Ok(())
109 }
110 }
111}
112
113impl<'a, I: I2CDevice> HumidityDriver<'a> for Hs3003<'a, I> {
114 fn set_client(&self, client: &'a dyn HumidityClient) {
115 self.humidity_client.set(client);
116 }
117
118 fn read_humidity(&self) -> Result<(), ErrorCode> {
119 self.pending_humidity.set(true);
120 if !self.pending_temperature.get() {
121 self.start_reading()
122 } else {
123 Ok(())
124 }
125 }
126}
127
128#[derive(Clone, Copy, Debug)]
129enum State {
130 Sleep,
131 InitiateReading,
132 Read,
133}
134
135impl<I: I2CDevice> I2CClient for Hs3003<'_, I> {
136 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
137 if let Err(i2c_err) = status {
138 self.state.set(State::Sleep);
139 self.buffer.replace(buffer);
140 self.temperature_client
141 .map(|client| client.callback(Err(i2c_err.into())));
142 self.humidity_client.map(|client| client.callback(0));
143 return;
144 }
145
146 match self.state.get() {
147 State::InitiateReading => {
148 if let Err((i2c_err, buffer)) = self.i2c.read(buffer, 4) {
149 self.state.set(State::Sleep);
150 self.buffer.replace(buffer);
151 self.temperature_client
152 .map(|client| client.callback(Err(i2c_err.into())));
153 self.humidity_client.map(|client| client.callback(0));
154 } else {
155 self.state.set(State::Read);
156 }
157 }
158 State::Read => {
159 let humidity_raw = (((buffer[0] & 0x3F) as u16) << 8) | buffer[1] as u16;
160 let humidity = ((humidity_raw as f32 / ((1 << 14) - 1) as f32) * 100.0) as usize;
161
162 let temperature_raw = ((buffer[2] as u16) << 8) | (buffer[3] as u16 >> 2);
163 let temperature = ((((temperature_raw as f32 / ((1 << 14) - 1) as f32) * 165.0)
166 - 40.0)
167 / 10.0) as i32;
168
169 self.buffer.replace(buffer);
170 self.i2c.disable();
171 if self.pending_temperature.get() {
172 self.pending_temperature.set(false);
173 self.temperature_client
174 .map(|client| client.callback(Ok(temperature)));
175 }
176 if self.pending_humidity.get() {
177 self.pending_humidity.set(false);
178 self.humidity_client.map(|client| client.callback(humidity));
179 }
180
181 self.state.set(State::Sleep);
182 }
183 State::Sleep => {} }
185 }
186}