1#![no_std]
2
3use embedded_hal::serial::{Read, Write};
4use nb::block;
5use scroll::{Pread, Pwrite, BE};
6
7mod read_fsm;
8
9const CMD_FRAME_SIZE: usize = 7;
10const OUTPUT_FRAME_SIZE: usize = 32;
11const RESPONSE_FRAME_SIZE: usize = 8;
12const CHECKSUM_SIZE: usize = 2;
13
14type Response = [u8; RESPONSE_FRAME_SIZE];
15
16pub const MN1: u8 = 0x42;
17pub const MN2: u8 = 0x4D;
18const PASSIVE_MODE_RESPONSE: Response = [MN1, MN1, 0x00, 0x04, 0xE1, 0x00, 0x01, 0x74];
19const ACTIVE_MODE_RESPONSE: Response = [MN1, MN2, 0x00, 0x04, 0xE1, 0x01, 0x01, 0x75];
20const SLEEP_RESPONSE: Response = [MN1, MN2, 0x00, 0x04, 0xE4, 0x00, 0x01, 0x77];
21
22#[derive(Debug)]
23pub enum Error {
24 SendFailed,
25 ReadFailed,
26 ChecksumError,
27 IncorrectResponse,
28 NoResponse,
29}
30
31pub struct Pms7003Sensor<Serial>
33where
34 Serial: Read<u8> + Write<u8>,
35{
36 serial: Serial,
37}
38
39impl<Serial> Pms7003Sensor<Serial>
40where
41 Serial: Read<u8> + Write<u8>,
42{
43 pub fn new(mut serial: Serial) -> Self {
46 loop {
47 if serial.read().is_err() {
48 break;
49 }
50 }
51
52 Self { serial }
53 }
54
55 fn read_from_device<T: AsMut<[u8]>>(&mut self, mut buffer: T) -> Result<T, Error> {
56 use read_fsm::*;
57
58 let mut read = ReadStateMachine::new(buffer.as_mut(), 10);
59 loop {
60 match read.update(self.serial.read()) {
61 ReadStatus::Failed => return Err(Error::ReadFailed),
62 ReadStatus::Finished => return Ok(buffer),
63 ReadStatus::InProgress => {}
64 }
65 }
66 }
67
68 pub fn read(&mut self) -> Result<OutputFrame, Error> {
70 OutputFrame::from_buffer(&self.read_from_device([0_u8; OUTPUT_FRAME_SIZE])?)
71 }
72
73 pub fn sleep(&mut self) -> Result<(), Error> {
75 self.send_cmd(&create_command(0xe4, 0))?;
76 self.receive_response(SLEEP_RESPONSE)
77 }
78
79 pub fn wake(&mut self) -> Result<(), Error> {
80 self.send_cmd(&create_command(0xe4, 1))
81 }
82
83 pub fn passive(&mut self) -> Result<(), Error> {
85 self.send_cmd(&create_command(0xe1, 0))?;
86 self.receive_response(PASSIVE_MODE_RESPONSE)
87 }
88
89 pub fn active(&mut self) -> Result<(), Error> {
91 self.send_cmd(&create_command(0xe1, 1))?;
92 self.receive_response(ACTIVE_MODE_RESPONSE)
93 }
94
95 pub fn request(&mut self) -> Result<(), Error> {
97 self.send_cmd(&create_command(0xe2, 0))
98 }
99
100 fn send_cmd(&mut self, cmd: &[u8]) -> Result<(), Error> {
101 for byte in cmd {
102 block!(self.serial.write(*byte)).map_err(|_| Error::SendFailed)?;
103 }
104 Ok(())
105 }
106
107 fn receive_response(&mut self, expected_response: Response) -> Result<(), Error> {
108 if self.read_from_device([0u8; RESPONSE_FRAME_SIZE])? != expected_response {
109 Err(Error::IncorrectResponse)
110 } else {
111 Ok(())
112 }
113 }
114}
115
116fn create_command(cmd: u8, data: u16) -> [u8; CMD_FRAME_SIZE] {
117 let mut buffer = [0_u8; CMD_FRAME_SIZE];
118 let mut offset = 0usize;
119
120 buffer.gwrite::<u8>(MN1, &mut offset).unwrap();
121 buffer.gwrite::<u8>(MN2, &mut offset).unwrap();
122 buffer.gwrite::<u8>(cmd, &mut offset).unwrap();
123 buffer.gwrite_with::<u16>(data, &mut offset, BE).unwrap();
124
125 let checksum = buffer
126 .iter()
127 .take(CMD_FRAME_SIZE - CHECKSUM_SIZE)
128 .map(|b| *b as u16)
129 .sum::<u16>();
130 buffer
131 .gwrite_with::<u16>(checksum, &mut offset, BE)
132 .unwrap();
133
134 buffer
135}
136
137#[derive(Default, Debug)]
139pub struct OutputFrame {
140 pub start1: u8,
141 pub start2: u8,
142 pub frame_length: u16,
143 pub pm1_0: u16,
144 pub pm2_5: u16,
145 pub pm10: u16,
146 pub pm1_0_atm: u16,
147 pub pm2_5_atm: u16,
148 pub pm10_atm: u16,
149 pub beyond_0_3: u16,
150 pub beyond_0_5: u16,
151 pub beyond_1_0: u16,
152 pub beyond_2_5: u16,
153 pub beyond_5_0: u16,
154 pub beyond_10_0: u16,
155 pub reserved: u16,
156 pub check: u16,
157}
158
159impl OutputFrame {
160 pub fn from_buffer(buffer: &[u8; OUTPUT_FRAME_SIZE]) -> Result<Self, Error> {
161 let sum: usize = buffer
162 .iter()
163 .take(OUTPUT_FRAME_SIZE - CHECKSUM_SIZE)
164 .map(|e| *e as usize)
165 .sum();
166
167 let mut frame = OutputFrame::default();
168 let mut offset = 0usize;
169
170 frame.start1 = buffer.gread::<u8>(&mut offset).unwrap();
171 frame.start2 = buffer.gread::<u8>(&mut offset).unwrap();
172 frame.frame_length = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
173 frame.pm1_0 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
174 frame.pm2_5 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
175 frame.pm10 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
176 frame.pm1_0_atm = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
177 frame.pm2_5_atm = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
178 frame.pm10_atm = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
179 frame.beyond_0_3 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
180 frame.beyond_0_5 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
181 frame.beyond_1_0 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
182 frame.beyond_2_5 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
183 frame.beyond_5_0 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
184 frame.beyond_10_0 = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
185 frame.reserved = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
186 frame.check = buffer.gread_with::<u16>(&mut offset, BE).unwrap();
187
188 if sum != frame.check as usize {
189 return Err(Error::ChecksumError);
190 }
191
192 Ok(frame)
193 }
194}
195
196impl<TX, RX> Pms7003Sensor<Wrapper<TX, RX>>
197where
198 TX: Write<u8>,
199 RX: Read<u8>,
200{
201 pub fn new_tx_rx(tx: TX, rx: RX) -> Self {
205 Self::new(Wrapper(tx, rx))
206 }
207}
208
209pub struct Wrapper<TX, RX>(TX, RX)
211where
212 TX: Write<u8>,
213 RX: Read<u8>;
214
215impl<TX, RX> Read<u8> for Wrapper<TX, RX>
216where
217 TX: Write<u8>,
218 RX: Read<u8>,
219{
220 type Error = RX::Error;
221
222 fn read(&mut self) -> nb::Result<u8, Self::Error> {
223 self.1.read()
224 }
225}
226
227impl<TX, RX> Write<u8> for Wrapper<TX, RX>
228where
229 TX: Write<u8>,
230 RX: Read<u8>,
231{
232 type Error = TX::Error;
233
234 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
235 self.0.write(word)
236 }
237
238 fn flush(&mut self) -> nb::Result<(), Self::Error> {
239 self.0.flush()
240 }
241}