1use serial2::SerialPort;
2use std::path::Path;
3use std::time::{Duration, Instant};
4
5use crate::bytestuff;
6use crate::checksum::calculate_checksum;
7use crate::endian::{read_u16_le, read_u32_le, read_u8_le, write_u16_le};
8use crate::{ReadError, TransferError, WriteError};
9
10const HEADER_PREFIX: [u8; 4] = [0xFF, 0xFF, 0xFD, 0x00];
11const HEADER_SIZE: usize = 8;
12const STATUS_HEADER_SIZE: usize = 9;
13
14pub struct Bus<ReadBuffer, WriteBuffer> {
16 serial_port: SerialPort,
18
19 baud_rate: u32,
21
22 read_buffer: ReadBuffer,
24
25 read_len: usize,
27
28 used_bytes: usize,
30
31 write_buffer: WriteBuffer,
33}
34
35impl<ReadBuffer, WriteBuffer> std::fmt::Debug for Bus<ReadBuffer, WriteBuffer> {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 #[derive(Debug)]
38 #[allow(dead_code)] enum Raw {
40 #[cfg(unix)]
41 Fd(std::os::unix::io::RawFd),
42 #[cfg(windows)]
43 Handle(std::os::windows::io::RawHandle),
44 }
45
46 #[cfg(unix)]
47 let raw = {
48 use std::os::unix::io::AsRawFd;
49 Raw::Fd(self.serial_port.as_raw_fd())
50 };
51 #[cfg(windows)]
52 let raw = {
53 use std::os::windows::io::AsRawHandle;
54 Raw::Handle(self.serial_port.as_raw_handle())
55 };
56
57 f.debug_struct("Bus")
58 .field("serial_port", &raw)
59 .field("baud_rate", &self.baud_rate)
60 .finish_non_exhaustive()
61 }
62}
63
64impl Bus<Vec<u8>, Vec<u8>> {
65 pub fn open(path: impl AsRef<Path>, baud_rate: u32) -> std::io::Result<Self> {
70 let port = SerialPort::open(path, baud_rate)?;
71 Ok(Self::with_buffers_and_baud_rate(port, vec![0; 128], vec![0; 128], baud_rate))
72 }
73
74 pub fn new(serial_port: SerialPort) -> Result<Self, crate::InitializeError> {
82 Self::with_buffers(serial_port, vec![0; 128], vec![0; 128])
83 }
84}
85
86impl<ReadBuffer, WriteBuffer> Bus<ReadBuffer, WriteBuffer>
87where
88 ReadBuffer: AsRef<[u8]> + AsMut<[u8]>,
89 WriteBuffer: AsRef<[u8]> + AsMut<[u8]>,
90{
91 pub fn open_with_buffers(
95 path: impl AsRef<Path>,
96 baud_rate: u32,
97 read_buffer: ReadBuffer,
98 write_buffer: WriteBuffer,
99 ) -> std::io::Result<Self> {
100 let port = SerialPort::open(path, baud_rate)?;
101 Ok(Self::with_buffers_and_baud_rate(port, read_buffer, write_buffer, baud_rate))
102 }
103
104 pub fn with_buffers(serial_port: SerialPort, read_buffer: ReadBuffer, write_buffer: WriteBuffer) -> Result<Self, crate::InitializeError> {
109 let baud_rate = serial_port.get_configuration()
110 .map_err(crate::InitializeError::GetConfiguration)?
111 .get_baud_rate()
112 .map_err(crate::InitializeError::GetBaudRate)?;
113
114 Ok(Self::with_buffers_and_baud_rate(serial_port, read_buffer, write_buffer, baud_rate))
115 }
116
117 fn with_buffers_and_baud_rate(serial_port: SerialPort, read_buffer: ReadBuffer, mut write_buffer: WriteBuffer, baud_rate: u32) -> Self {
119 assert!(write_buffer.as_mut().len() >= HEADER_SIZE + 2);
122 write_buffer.as_mut()[..4].copy_from_slice(&HEADER_PREFIX);
123
124 Self {
125 serial_port,
126 baud_rate,
127 read_buffer,
128 read_len: 0,
129 used_bytes: 0,
130 write_buffer,
131 }
132 }
133
134 pub fn serial_port(&self) -> &SerialPort {
141 &self.serial_port
142 }
143
144 pub fn into_serial_port(self) -> SerialPort {
149 self.serial_port
150 }
151
152 pub fn baud_rate(&self) -> u32 {
154 self.baud_rate
155 }
156
157 pub fn set_baud_rate(&mut self, baud_rate: u32) -> Result<(), std::io::Error> {
159 let mut settings = self.serial_port.get_configuration()?;
160 settings.set_baud_rate(baud_rate)?;
161 self.serial_port.set_configuration(&settings)?;
162 self.baud_rate = baud_rate;
163 Ok(())
164 }
165
166 pub fn transfer_single<F>(
174 &mut self,
175 packet_id: u8,
176 instruction_id: u8,
177 parameter_count: usize,
178 expected_response_parameters: u16,
179 encode_parameters: F,
180 ) -> Result<StatusPacket<'_>, TransferError>
181 where
182 F: FnOnce(&mut [u8]),
183 {
184 self.write_instruction(packet_id, instruction_id, parameter_count, encode_parameters)?;
185 let response = self.read_status_response(expected_response_parameters)?;
186 crate::error::InvalidPacketId::check(response.packet_id(), packet_id).map_err(crate::ReadError::from)?;
187 Ok(response)
188 }
189
190 pub fn write_instruction<F>(
192 &mut self,
193 packet_id: u8,
194 instruction_id: u8,
195 parameter_count: usize,
196 encode_parameters: F,
197 ) -> Result<(), WriteError>
198 where
199 F: FnOnce(&mut [u8]),
200 {
201 let buffer = self.write_buffer.as_mut();
202
203 crate::error::BufferTooSmallError::check(HEADER_SIZE + parameter_count + 2, buffer.len())?;
205
206 buffer[4] = packet_id;
208 buffer[5] = 0;
209 buffer[6] = 0;
210 buffer[7] = instruction_id;
211 encode_parameters(&mut buffer[HEADER_SIZE..][..parameter_count]);
212
213 let stuffed_body_len = bytestuff::stuff_inplace(&mut buffer[HEADER_SIZE..], parameter_count)?;
216
217 write_u16_le(&mut buffer[5..], stuffed_body_len as u16 + 3);
218
219 let checksum_index = HEADER_SIZE + stuffed_body_len;
221 let checksum = calculate_checksum(0, &buffer[..checksum_index]);
222 write_u16_le(&mut buffer[checksum_index..], checksum);
223
224 self.read_len = 0;
228 self.used_bytes = 0;
229 self.serial_port.discard_input_buffer().map_err(WriteError::DiscardBuffer)?;
230
231 let stuffed_message = &buffer[..checksum_index + 2];
233 trace!("sending instruction: {:02X?}", stuffed_message);
234 self.serial_port.write_all(stuffed_message).map_err(WriteError::Write)?;
235 Ok(())
236 }
237
238 pub fn read_status_response_deadline(&mut self, deadline: Instant) -> Result<StatusPacket, ReadError> {
240 crate::error::BufferTooSmallError::check(STATUS_HEADER_SIZE, self.read_buffer.as_mut().len())?;
242
243 let stuffed_message_len = loop {
244 self.remove_garbage();
245
246 if self.read_len > STATUS_HEADER_SIZE {
249 let read_buffer = &self.read_buffer.as_mut()[..self.read_len];
250 let body_len = read_buffer[5] as usize + read_buffer[6] as usize * 256;
251 let body_len = body_len - 2; crate::error::BufferTooSmallError::check(STATUS_HEADER_SIZE + body_len, self.read_buffer.as_mut().len())?;
256
257 if self.read_len >= STATUS_HEADER_SIZE + body_len {
258 break STATUS_HEADER_SIZE + body_len;
259 }
260 }
261
262 let timeout = match deadline.checked_duration_since(Instant::now()) {
263 Some(x) => x,
264 None => {
265 trace!(
266 "timeout reading status response, data in buffer: {:02X?}",
267 &self.read_buffer.as_ref()[..self.read_len]
268 );
269 return Err(std::io::ErrorKind::TimedOut.into());
270 },
271 };
272
273 self.serial_port.set_read_timeout(timeout).ok();
275 let new_data = self.serial_port.read(&mut self.read_buffer.as_mut()[self.read_len..])?;
276 if new_data == 0 {
277 continue;
278 }
279
280 self.read_len += new_data;
281 };
282
283 let buffer = self.read_buffer.as_mut();
284 let parameters_end = stuffed_message_len - 2;
285 trace!("read packet: {:02X?}", &buffer[..parameters_end]);
286
287 let checksum_message = read_u16_le(&buffer[parameters_end..]);
288 let checksum_computed = calculate_checksum(0, &buffer[..parameters_end]);
289 if checksum_message != checksum_computed {
290 self.consume_read_bytes(stuffed_message_len);
291 return Err(crate::InvalidChecksum {
292 message: checksum_message,
293 computed: checksum_computed,
294 }
295 .into());
296 }
297
298 self.used_bytes += stuffed_message_len;
300
301 let parameter_count = bytestuff::unstuff_inplace(&mut buffer[STATUS_HEADER_SIZE..parameters_end]);
303
304 let response = StatusPacket {
306 data: &self.read_buffer.as_ref()[..STATUS_HEADER_SIZE + parameter_count],
307 };
308
309 crate::InvalidInstruction::check(response.instruction_id(), crate::instructions::instruction_id::STATUS)?;
310 crate::MotorError::check(response.error())?;
311 Ok(response)
312 }
313
314 pub fn read_status_response(&mut self, expected_parameters: u16) -> Result<StatusPacket, ReadError> {
318 let message_size = STATUS_HEADER_SIZE as u32 + u32::from(expected_parameters) + 2;
320 let timeout = message_transfer_time(message_size, self.baud_rate) + Duration::from_millis(34);
321 self.read_status_response_deadline(Instant::now() + timeout)
322 }
323}
324
325pub(crate) fn message_transfer_time(message_size: u32, baud_rate: u32) -> Duration {
329 let baud_rate = u64::from(baud_rate);
330 let bits = u64::from(message_size) * 10; let secs = bits / baud_rate;
332 let subsec_bits = bits % baud_rate;
333 let nanos = (subsec_bits * 1_000_000_000).div_ceil(baud_rate);
334 Duration::new(secs, nanos as u32)
335}
336
337impl<ReadBuffer, WriteBuffer> Bus<ReadBuffer, WriteBuffer>
338where
339 ReadBuffer: AsRef<[u8]> + AsMut<[u8]>,
340 WriteBuffer: AsRef<[u8]> + AsMut<[u8]>,
341{
342 fn remove_garbage(&mut self) {
344 let read_buffer = self.read_buffer.as_mut();
345 let garbage_len = find_header(&read_buffer[..self.read_len][self.used_bytes..]);
346 if garbage_len > 0 {
347 debug!("skipping {} bytes of leading garbage.", garbage_len);
348 trace!("skipped garbage: {:02X?}", &read_buffer[..garbage_len]);
349 }
350 self.consume_read_bytes(self.used_bytes + garbage_len);
351 debug_assert_eq!(self.used_bytes, 0);
352 }
353
354 fn consume_read_bytes(&mut self, len: usize) {
355 debug_assert!(len <= self.read_len);
356 self.read_buffer.as_mut().copy_within(len..self.read_len, 0);
357 self.used_bytes = self.used_bytes.saturating_sub(len);
361 self.read_len -= len;
362 }
363}
364
365#[derive(Debug)]
369pub struct StatusPacket<'a> {
370 data: &'a [u8],
372}
373
374impl<'a> StatusPacket<'a> {
375 pub fn as_bytes(&self) -> &[u8] {
380 self.data
381 }
382
383 pub fn packet_id(&self) -> u8 {
385 self.as_bytes()[4]
386 }
387
388 pub fn instruction_id(&self) -> u8 {
390 self.as_bytes()[7]
391 }
392
393 pub fn error(&self) -> u8 {
395 self.as_bytes()[8]
396 }
397
398 pub fn error_number(&self) -> u8 {
402 self.error() & !0x80
403 }
404
405 pub fn alert(&self) -> bool {
412 self.error() & 0x80 != 0
413 }
414
415 pub fn parameters(&self) -> &[u8] {
417 &self.data[STATUS_HEADER_SIZE..]
418 }
419}
420
421fn find_header(buffer: &[u8]) -> usize {
427 for i in 0..buffer.len() {
428 let possible_prefix = HEADER_PREFIX.len().min(buffer.len() - i);
429 if buffer[i..].starts_with(&HEADER_PREFIX[..possible_prefix]) {
430 return i;
431 }
432 }
433
434 buffer.len()
435}
436
437#[derive(Debug, Clone, Eq, PartialEq)]
442pub struct Response<T> {
443 pub motor_id: u8,
445
446 pub alert: bool,
451
452 pub data: T,
454}
455
456impl<'a> TryFrom<StatusPacket<'a>> for Response<()> {
457 type Error = crate::InvalidParameterCount;
458
459 fn try_from(status_packet: StatusPacket<'a>) -> Result<Self, Self::Error> {
460 crate::InvalidParameterCount::check(status_packet.parameters().len(), 0)?;
461 Ok(Self {
462 motor_id: status_packet.packet_id(),
463 alert: status_packet.alert(),
464 data: (),
465 })
466 }
467}
468
469impl<'a, 'b> From<&'b StatusPacket<'a>> for Response<&'b [u8]> {
470 fn from(status_packet: &'b StatusPacket<'a>) -> Self {
471 Self {
472 motor_id: status_packet.packet_id(),
473 alert: status_packet.alert(),
474 data: status_packet.parameters(),
475 }
476 }
477}
478
479impl<'a> From<StatusPacket<'a>> for Response<Vec<u8>> {
480 fn from(status_packet: StatusPacket<'a>) -> Self {
481 Self {
482 motor_id: status_packet.packet_id(),
483 alert: status_packet.alert(),
484 data: status_packet.parameters().to_owned(),
485 }
486 }
487}
488
489impl<'a> TryFrom<StatusPacket<'a>> for Response<u8> {
490 type Error = crate::InvalidParameterCount;
491
492 fn try_from(status_packet: StatusPacket<'a>) -> Result<Self, Self::Error> {
493 crate::InvalidParameterCount::check(status_packet.parameters().len(), 1)?;
494 Ok(Self {
495 motor_id: status_packet.packet_id(),
496 alert: status_packet.alert(),
497 data: read_u8_le(status_packet.parameters()),
498 })
499 }
500}
501
502impl<'a> TryFrom<StatusPacket<'a>> for Response<u16> {
503 type Error = crate::InvalidParameterCount;
504
505 fn try_from(status_packet: StatusPacket<'a>) -> Result<Self, Self::Error> {
506 crate::InvalidParameterCount::check(status_packet.parameters().len(), 2)?;
507 Ok(Self {
508 motor_id: status_packet.packet_id(),
509 alert: status_packet.alert(),
510 data: read_u16_le(status_packet.parameters()),
511 })
512 }
513}
514
515impl<'a> TryFrom<StatusPacket<'a>> for Response<u32> {
516 type Error = crate::InvalidParameterCount;
517
518 fn try_from(status_packet: StatusPacket<'a>) -> Result<Self, Self::Error> {
519 crate::InvalidParameterCount::check(status_packet.parameters().len(), 4)?;
520 Ok(Self {
521 motor_id: status_packet.packet_id(),
522 alert: status_packet.alert(),
523 data: read_u32_le(status_packet.parameters()),
524 })
525 }
526}
527
528#[cfg(test)]
529mod test {
530 use super::*;
531 use assert2::assert;
532
533 #[test]
534 fn test_find_garbage_end() {
535 assert!(find_header(&[0xFF]) == 0);
536 assert!(find_header(&[0xFF, 0xFF]) == 0);
537 assert!(find_header(&[0xFF, 0xFF, 0xFD]) == 0);
538 assert!(find_header(&[0xFF, 0xFF, 0xFD, 0x00]) == 0);
539 assert!(find_header(&[0xFF, 0xFF, 0xFD, 0x00, 9]) == 0);
540
541 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF]) == 5);
542 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF, 0xFF]) == 5);
543 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF, 0xFF, 0xFD]) == 5);
544 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF, 0xFF, 0xFD, 0x00]) == 5);
545 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF, 0xFF, 0xFD, 0x00, 9]) == 5);
546
547 assert!(find_header(&[0xFF, 1]) == 2);
548 assert!(find_header(&[0, 1, 2, 3, 4, 0xFF, 6]) == 7);
549 }
550
551 #[test]
552 fn test_message_transfer_time() {
553 assert!(message_transfer_time(100, 1_000) == Duration::from_secs(1));
555 assert!(message_transfer_time(1_000, 10_000) == Duration::from_secs(1));
556 assert!(message_transfer_time(1_000, 1_000_000) == Duration::from_millis(10));
557 assert!(message_transfer_time(1_000, 10_000_000) == Duration::from_millis(1));
558 assert!(message_transfer_time(1_000, 100_000_000) == Duration::from_micros(100));
559 assert!(message_transfer_time(1_000, 1_000_000_000) == Duration::from_micros(10));
560 assert!(message_transfer_time(1_000, 2_000_000_000) == Duration::from_micros(5));
561 assert!(message_transfer_time(1_000, 4_000_000_000) == Duration::from_nanos(2500));
562 assert!(message_transfer_time(10_000, 4_000_000_000) == Duration::from_micros(25));
563 assert!(message_transfer_time(1_000_000, 4_000_000_000) == Duration::from_micros(2500));
564 assert!(message_transfer_time(10_000_000, 4_000_000_000) == Duration::from_millis(25));
565 assert!(message_transfer_time(100_000_000, 4_000_000_000) == Duration::from_millis(250));
566 assert!(message_transfer_time(1_000_000_000, 4_000_000_000) == Duration::from_millis(2500));
567 assert!(message_transfer_time(2_000_000_000, 4_000_000_000) == Duration::from_secs(5));
568 assert!(message_transfer_time(4_000_000_000, 4_000_000_000) == Duration::from_secs(10));
569 assert!(message_transfer_time(4_000_000_000, 2_000_000_000) == Duration::from_secs(20));
570 assert!(message_transfer_time(4_000_000_000, 1_000_000_000) == Duration::from_secs(40));
571 assert!(message_transfer_time(4_000_000_000, 100_000_000) == Duration::from_secs(400));
572 assert!(message_transfer_time(4_000_000_000, 10_000_000) == Duration::from_secs(4_000));
573 assert!(message_transfer_time(4_000_000_000, 1_000_000) == Duration::from_secs(40_000));
574 assert!(message_transfer_time(4_000_000_000, 100_000) == Duration::from_secs(400_000));
575 assert!(message_transfer_time(4_000_000_000, 10_000) == Duration::from_secs(4_000_000));
576 assert!(message_transfer_time(4_000_000_000, 1_000) == Duration::from_secs(40_000_000));
577 assert!(message_transfer_time(4_000_000_000, 100) == Duration::from_secs(400_000_000));
578 assert!(message_transfer_time(4_000_000_000, 10) == Duration::from_secs(4_000_000_000));
579 assert!(message_transfer_time(4_000_000_000, 1) == Duration::from_secs(40_000_000_000));
580
581 assert!(message_transfer_time(43, 1) == Duration::from_secs(430));
582 assert!(message_transfer_time(43, 10) == Duration::from_secs(43));
583 assert!(message_transfer_time(43, 2) == Duration::from_secs(215));
584 assert!(message_transfer_time(43, 20) == Duration::from_millis(21_500));
585 assert!(message_transfer_time(43, 200) == Duration::from_millis(2_150));
586 assert!(message_transfer_time(43, 2_000_000) == Duration::from_micros(215));
587 assert!(message_transfer_time(43, 2_000_000_000) == Duration::from_nanos(215));
588 assert!(message_transfer_time(43, 4_000_000_000) == Duration::from_nanos(108)); assert!(message_transfer_time(3, 4_000_000_000) == Duration::from_nanos(8)); assert!(message_transfer_time(5, 4_000_000_000) == Duration::from_nanos(13)); let lots = u32::MAX - 1; assert!(message_transfer_time(lots, 1) == Duration::from_secs(u64::from(lots) * 10));
594 assert!(message_transfer_time(lots, lots) == Duration::from_secs(10));
595 assert!(message_transfer_time(lots / 2, lots) == Duration::from_secs(5));
596 assert!(message_transfer_time(lots, lots / 2) == Duration::from_secs(20));
597 }
598}