1#![cfg_attr(not(test), no_std)]
27
28use core::convert::TryInto;
29use core::fmt;
30#[cfg(not(test))]
31use defmt::*;
32use embedded_hal::{
33 digital::v2::{InputPin, OutputPin},
34 serial::{Read, Write},
35};
36use heapless::Vec;
37#[cfg(test)]
38use log::*;
39
40#[cfg(not(test))]
41use defmt as logger;
42#[cfg(test)]
43use std as logger;
44
45pub mod registers;
47#[cfg(test)]
48pub mod tests;
49
50pub use registers::{CommandStatus, ReadRegister, Request, Response, WriteRegister};
51
52#[derive(Debug, Clone, Copy, defmt::Format, PartialEq, Eq)]
54pub enum AfterRequest {
55 Continue,
56 Exit,
57}
58
59#[derive(Debug, Clone, Copy, defmt::Format, PartialEq, Eq)]
60enum LaserTransferState {
61 Command(Request),
63 WaitForClear(Response),
65 ReadErrorStatus(Request),
67 Ready,
69}
70
71pub enum Error<S: Read<u8> + Write<u8>, I: InputPin, R: OutputPin, M: OutputPin> {
72 Tx(<S as Write<u8>>::Error),
73 Rx(<S as Read<u8>>::Error),
74 SrqPin(<I as InputPin>::Error),
75 ResetPin(<R as OutputPin>::Error),
76 CommResetPin(<M as OutputPin>::Error),
77 Srq(Response),
78 CommandError(Request, Response),
79 TooManyRetries(u32),
80}
81
82impl<S: Read<u8> + Write<u8>, I: InputPin, R: OutputPin, M: OutputPin> fmt::Debug
83 for Error<S, I, R, M>
84where
85 <S as Write<u8>>::Error: fmt::Debug,
86 <S as Read<u8>>::Error: fmt::Debug,
87 <I as InputPin>::Error: fmt::Debug,
88 <R as OutputPin>::Error: fmt::Debug,
89 <M as OutputPin>::Error: fmt::Debug,
90{
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 match self {
93 Self::Tx(tx) => core::write!(f, "Error while transmitting: {:?}", tx),
94 Self::Rx(rx) => core::write!(f, "Error while receiving: {:?}", rx),
95 Self::SrqPin(srq) => core::write!(f, "Could not read srq pin: {:?}", srq),
96 Self::ResetPin(reset) => core::write!(f, "Could not reset pin: {:?}", reset),
97 Self::CommResetPin(comms) => {
98 core::write!(f, "Could not change communication reset pin: {:?}", comms)
99 }
100 Self::Srq(_response) => core::write!(f, "Requested attention"),
101 Self::CommandError(req, resp) => {
102 core::write!(f, "Command {:?} returned error {:?}", req, resp)
103 }
104 Self::TooManyRetries(retries) => {
105 core::write!(f, "The laser was not ready after {} retries", retries)
106 }
107 }
108 }
109}
110
111#[derive(Debug)]
112pub struct Laser<R, D, M, I, S, F> {
113 n_reset: R,
115 n_disable: D,
116 n_ms: M,
117 srq: I,
118 serial: S,
119 tx_buf: Vec<u8, 4>,
121 rx_buf: Vec<u8, 4>,
122 state: LaserTransferState,
123 last_ok: bool,
125 after_request: Option<F>,
127 retries: u32,
128}
129
130#[derive(Debug, defmt::Format, Clone, Copy, PartialEq, Eq)]
131#[non_exhaustive]
132pub enum LastCommandError {
135 Ok = 0x00,
136 RegisterNotImplemented = 0x01,
137 RegisterNotWriteable = 0x02,
138 RegisterValueRangeError = 0x03,
139 Pending = 0x04,
140 Initializing = 0x05,
141 AddressInvalid = 0x06,
142 AddressReadOnly = 0x07,
143 ExecutionFailure = 0x08,
144 OutputEnabled = 0x09,
145 InvalidConfig = 0x0A,
146 Vendor = 0x0F,
147}
148
149impl<R, D, M, I, S> Laser<R, D, M, I, S, fn(u32) -> AfterRequest>
150where
151 R: OutputPin,
152 D: OutputPin,
153 M: OutputPin,
154 I: InputPin,
155 S: Read<u8> + Write<u8>,
156{
157 pub fn new(
159 n_reset: R,
160 n_disable: D,
161 n_ms: M,
162 srq: I,
163 serial: S,
164 ) -> Result<Self, Error<S, I, R, M>> {
165 Self::new_with_handler_between_retries(n_reset, n_disable, n_ms, srq, serial, None)
166 }
167}
168
169impl<R, D, M, I, S, F> Laser<R, D, M, I, S, F>
170where
171 R: OutputPin,
172 D: OutputPin,
173 M: OutputPin,
174 I: InputPin,
175 S: Read<u8> + Write<u8>,
176 F: FnMut(u32) -> AfterRequest,
177{
178 pub fn new_with_handler_between_retries(
183 n_reset: R,
184 n_disable: D,
185 n_ms: M,
186 srq: I,
187 serial: S,
188 between_retries: Option<F>,
189 ) -> Result<Self, Error<S, I, R, M>> {
190 let mut this = Self {
191 n_reset,
192 n_disable,
193 n_ms,
194 srq,
195 serial,
196 tx_buf: Vec::new(),
197 rx_buf: Vec::new(),
198 state: LaserTransferState::Ready,
199 last_ok: true,
200 after_request: between_retries,
201 retries: 0,
202 };
203 this.n_ms.set_high().map_err(Error::CommResetPin)?;
204 this.reset().map_err(Error::ResetPin)?;
205 Ok(this)
206 }
207
208 pub fn release(self) -> (R, D, M, I, S) {
210 (
211 self.n_reset,
212 self.n_disable,
213 self.n_ms,
214 self.srq,
215 self.serial,
216 )
217 }
218
219 pub fn serial(&mut self) -> &mut S {
224 &mut self.serial
225 }
226
227 fn start_send(&mut self) {
229 logger::assert!(self.tx_buf.is_empty(), "Tx buffer is not empty");
231 logger::assert!(self.rx_buf.is_empty(), "Rx buffer is not empty");
232 let req = self
233 .current_command()
234 .expect("Need a command to start sending it to the laser");
235
236 self.tx_buf
237 .extend(req.encode(self.last_ok).iter().rev().copied());
238 #[cfg(test)]
239 debug!("Send command {:X?} => {:?}", &self.tx_buf[..], req);
240 #[cfg(not(test))]
241 debug!("Send command {:X} => {}", &self.tx_buf[..], req);
242 }
243
244 pub fn current_command(&self) -> Option<Request> {
246 match self.state {
247 LaserTransferState::Ready => None,
248 LaserTransferState::Command(req) => Some(req),
249 LaserTransferState::ReadErrorStatus(_req) => Some(registers::Status::read()),
250 LaserTransferState::WaitForClear(_req) => Some(registers::Status::read()),
251 }
252 }
253
254 pub fn step(&mut self) -> nb::Result<Response, Error<S, I, R, M>> {
262 logger::assert_ne!(
264 self.state,
265 LaserTransferState::Ready,
266 "Tried to poll after completion"
267 );
268 while let Some(byte) = self.tx_buf.last().copied() {
270 self.serial.write(byte).map_err(|e| e.map(Error::Tx))?;
271 trace!("Printed {:X}", byte);
272 self.tx_buf.pop();
274 }
275 while self.rx_buf.len() < 4 {
277 let byte = self.serial.read().map_err(|e| e.map(Error::Rx))?;
278 trace!("Received {:X}", byte);
279 self.rx_buf.push(byte).expect("Length is less than 4");
280 }
281 let buf: [u8; 4] = AsRef::<[u8]>::as_ref(&self.rx_buf)
283 .try_into()
284 .expect("Length is 4");
285 let resp = Response::decode(buf);
286 #[cfg(test)]
287 debug!("Received response {:X?} => {:?}", self.rx_buf, resp);
288 #[cfg(not(test))]
289 debug!("Received response {:X} => {}", self.rx_buf, resp);
290 self.rx_buf.clear();
291 self.last_ok = resp.is_some();
292 let resp = match resp {
293 Some(r) if !r.ce => r,
294 _ => {
295 warn!("Communication error");
296 self.start_send();
297 return self.step();
298 }
299 };
300 if resp.status == CommandStatus::ExecutionError {
301 self.state = LaserTransferState::ReadErrorStatus(
304 self.current_command().expect("Not in ready state"),
305 );
306 self.start_send();
307 return self.step();
308 }
309 if resp.status != CommandStatus::Ok {
310 #[cfg(test)]
311 debug!("Status: {:?}", resp.status);
312 #[cfg(not(test))]
313 debug!("Status: {}", resp.status);
314 }
315 logger::assert_eq!(
317 resp.register,
318 self.current_command()
319 .expect("Tested at top of function")
320 .register(),
321 "Request register is not output register?"
322 );
323 if self.srq().map_err(Error::SrqPin)? {
324 return Err(Error::Srq(resp).into());
325 }
326 let out = match self.state {
327 LaserTransferState::Ready => logger::unreachable!("Checked at start of function"),
328 LaserTransferState::Command(_command) => {
329 if resp.status == CommandStatus::CommandPending {
330 self.retries = 1;
331 self.state = LaserTransferState::WaitForClear(resp);
333 self.start_send();
334 self.step()
335 } else {
336 self.state = LaserTransferState::Ready;
337 Ok(resp)
338 }
339 }
340 LaserTransferState::ReadErrorStatus(command) => {
341 self.state = LaserTransferState::Ready;
342 error!("Error: {}", resp.val() & 0x00_0F);
343 Err(Error::CommandError(command, resp).into())
344 }
345 LaserTransferState::WaitForClear(prev_resp) => {
346 const PENDING_FLAGS: u16 = 0xFF_00;
348 const MRDY_FLAG: u16 = 0x00_10;
349
350 if resp.val() & PENDING_FLAGS == 0x00_00 && resp.val() & MRDY_FLAG == MRDY_FLAG {
354 self.state = LaserTransferState::Ready;
355 Ok(prev_resp)
356 } else {
357 let retries = self.retries;
358 if self
359 .after_request
360 .as_mut()
361 .map_or(AfterRequest::Continue, |f| f(retries))
362 == AfterRequest::Continue
363 {
364 self.retries += 1;
365 self.start_send();
366 self.step()
367 } else {
368 Err(nb::Error::Other(Error::TooManyRetries(self.retries)))
369 }
370 }
371 }
372 }?;
373 Ok(out)
374 }
375
376 pub fn srq(&self) -> Result<bool, <I as InputPin>::Error> {
378 self.srq.is_low()
379 }
380
381 pub fn disable(&mut self) -> Result<(), <D as OutputPin>::Error> {
383 self.n_disable.set_low()
384 }
385
386 pub fn enable(&mut self) -> Result<(), <D as OutputPin>::Error> {
388 self.n_disable.set_high()
389 }
390
391 fn reset_state(&mut self) {
393 while self.serial.read().is_ok() {} self.tx_buf.clear();
395 self.rx_buf.clear();
396 self.last_ok = true;
397 self.state = LaserTransferState::Ready;
398 }
399
400 pub fn reset(&mut self) -> Result<(), <R as OutputPin>::Error> {
403 self.n_reset.set_low()?;
404 self.n_reset.set_high()?;
405 self.reset_state();
406 Ok(())
407 }
408
409 pub fn reset_comms(&mut self) -> Result<(), <M as OutputPin>::Error> {
412 self.n_ms.set_low()?;
413 self.n_ms.set_high()?;
414 self.reset_state();
415 Ok(())
416 }
417
418 pub fn send(&mut self, command: Request) {
421 logger::assert_eq!(
422 self.state,
423 LaserTransferState::Ready,
424 "Can't send command while there is still one pending"
425 );
426 self.state = LaserTransferState::Command(command);
427 self.start_send();
428 }
429
430 pub fn wait_for_clear(&mut self) -> nb::Result<(), Error<S, I, R, M>> {
434 trace!("Waiting for laser clear");
435 self.retries = 0;
436 loop {
437 self.send(registers::Status::read());
438 let resp = nb::block!(self.step())?;
439 let flags = resp.val();
440 trace!("Laser flags: {:X}", flags);
441 if flags & 0xFF_00 == 0 && flags & 0x00_10 == 0x00_10 {
442 trace!("Laser clear");
443 return Ok(());
444 }
445 let retries = self.retries;
446 let early_exit = self
447 .after_request
448 .as_mut()
449 .map_or(AfterRequest::Continue, |f| f(retries));
450 if early_exit == AfterRequest::Exit {
451 debug!("Requested early stop of wait_for_clear");
452 return Err(nb::Error::Other(Error::TooManyRetries(self.retries)));
453 }
454 self.retries = self.retries.saturating_add(1);
455 }
456 }
457}