From 80c2bfde68adeb1a238462ef430015fbb1c60ef3 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:45:01 -0600 Subject: [PATCH 01/11] feat: generic serialport API --- CHANGELOG.md | 1 + packages/pros-sys/src/lib.rs | 4 +- packages/pros-sys/src/serial.rs | 2 +- packages/pros/src/devices/smart/mod.rs | 2 + packages/pros/src/devices/smart/serial.rs | 165 ++++++++++++++++++++++ packages/pros/src/lib.rs | 1 + 6 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 packages/pros/src/devices/smart/serial.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 84f68fb9..8b01aa88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Before releasing: - All ADI device bindings (#55) - `LocalKey` now has `Cell`/`RefCell`-specific methods for setting and taking values. (#42) - `Peripherals` and `DynamicPeripherals` structs to ensure that you have only registered one device on a given smart or ADI port. (#53) +- Capability to configure a smart port as a generic serial port and send/recieve data over serial. (#76) ### Fixed diff --git a/packages/pros-sys/src/lib.rs b/packages/pros-sys/src/lib.rs index 9d7b55ac..9fdb4927 100644 --- a/packages/pros-sys/src/lib.rs +++ b/packages/pros-sys/src/lib.rs @@ -20,6 +20,7 @@ pub mod motor; pub mod optical; pub mod rotation; pub mod rtos; +pub mod serial; pub mod vision; use core::ffi::{c_char, c_int, c_void}; @@ -38,11 +39,8 @@ pub use motor::*; pub use optical::*; pub use rotation::*; pub use rtos::*; -#[cfg(feaute = "apix")] pub use serial::*; pub use vision::*; -#[cfg(feaute = "apix")] -pub mod serial; pub const CLOCKS_PER_SEC: u32 = 1000; diff --git a/packages/pros-sys/src/serial.rs b/packages/pros-sys/src/serial.rs index 252b567c..22f8a08b 100644 --- a/packages/pros-sys/src/serial.rs +++ b/packages/pros-sys/src/serial.rs @@ -194,5 +194,5 @@ extern "C" { \return The number of bytes written or PROS_ERR if the operation failed, setting errno. */ - pub fn serial_write(port: u8, buffer: *mut u8, length: i32) -> i32; + pub fn serial_write(port: u8, buffer: *const u8, length: i32) -> i32; } diff --git a/packages/pros/src/devices/smart/mod.rs b/packages/pros/src/devices/smart/mod.rs index 9a7c081e..156d54cf 100644 --- a/packages/pros/src/devices/smart/mod.rs +++ b/packages/pros/src/devices/smart/mod.rs @@ -21,6 +21,7 @@ pub mod link; pub mod motor; pub mod optical; pub mod rotation; +pub mod serial; pub mod vision; pub use distance::DistanceSensor; @@ -30,6 +31,7 @@ pub use link::{Link, RxLink, TxLink}; pub use motor::Motor; pub use optical::OpticalSensor; pub use rotation::RotationSensor; +pub use serial::SerialPort; pub use vision::VisionSensor; use crate::{error::bail_on, prelude::PortError}; diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs new file mode 100644 index 00000000..8988b39d --- /dev/null +++ b/packages/pros/src/devices/smart/serial.rs @@ -0,0 +1,165 @@ +use no_std_io::io; +use pros_sys::PROS_ERR; +use snafu::Snafu; + +use super::{SmartDevice, SmartDeviceType, SmartPort}; +use crate::error::{bail_on, map_errno, PortError}; + +#[derive(Debug, Eq, PartialEq)] +pub struct SerialPort { + port: SmartPort, +} + +impl SerialPort { + /// Open and configure a serial port on a [`SmartPort`]. + /// + /// This configures a smart port to act as a generic serial device, capable of sending/recieving + /// data. + pub fn open(port: SmartPort, baud_rate: u32) -> Result { + unsafe { + bail_on!(PROS_ERR, pros_sys::serial_enable(port.index())); + bail_on!( + PROS_ERR, + // libv5rt allows passing in negative baudrate for internal reasons. Other than + // for very specific cases, this at best isn't useful and at worst is undefined + // behavior, so we take a u32 baudrate and call it a day. + pros_sys::serial_set_baudrate(port.index(), baud_rate as i32) + ); + } + + Ok(Self { port }) + } + + fn recieve(&self, buf: &mut [u8]) -> Result { + Ok(bail_on!(PROS_ERR, unsafe { + pros_sys::serial_read(self.port.index(), buf.as_mut_ptr(), buf.len() as i32) + }) as usize) + } + + fn transmit(&mut self, buf: &[u8]) -> Result { + Ok(bail_on!(PROS_ERR, unsafe { + pros_sys::serial_write(self.port.index(), buf.as_ptr(), buf.len() as i32) + }) as usize) + } + + fn flush(&mut self) -> Result<(), SerialError> { + bail_on!(PROS_ERR, unsafe { + pros_sys::serial_flush(self.port.index()) + }); + + Ok(()) + } + + /// Read the next byte available in the port's input buffer. + pub fn read_byte(&self) -> Result, SerialError> { + let read = bail_on!(PROS_ERR, unsafe { + pros_sys::serial_read_byte(self.port.index()) + }); + + Ok(match read { + -1 => None, + _ => Some(read as u8), + }) + } + + /// Read the next byte available in the port's input buffer without removing it. + pub fn peek_byte(&self) -> Result, SerialError> { + let peeked = bail_on!(PROS_ERR, unsafe { + pros_sys::serial_peek_byte(self.port.index()) + }); + + Ok(match peeked { + -1 => None, + _ => Some(peeked as u8), + }) + } + + /// Write the single byte to the port's output buffer. + pub fn write_byte(&mut self, byte: u8) -> Result { + Ok(bail_on!(PROS_ERR, unsafe { + pros_sys::serial_write_byte(self.port.index(), byte) + }) as usize) + } + + // Returns the number of bytes available to be read in the the port's FIFO input buffer. + pub fn bytes_to_read(&self) -> Result { + Ok(bail_on!(PROS_ERR, unsafe { + pros_sys::serial_get_read_avail(self.port.index()) + }) as usize) + } + + /// Returns the number of bytes free in the port's FIFO output buffer. + pub fn available_write_bytes(&self) -> Result { + Ok(bail_on!(PROS_ERR, unsafe { + pros_sys::serial_get_write_free(self.port.index()) + }) as usize) + } +} + +impl io::Read for SerialPort { + /// Read some bytes from this serial port into the specified buffer, returning + /// how many bytes were read. + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let bytes_read = self.recieve(buf).map_err(|err| match err { + SerialError::InternalWriteError => io::ErrorKind::Other, + SerialError::Port { source } => match source { + PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, + PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + }, + })?; + + Ok(bytes_read) + } +} + +impl io::Write for SerialPort { + /// Write a buffer into the serial port's output buffer, returning how many bytes were written. + fn write(&mut self, buf: &[u8]) -> io::Result { + let bytes_written = self.transmit(buf).map_err(|err| match err { + SerialError::InternalWriteError => io::ErrorKind::Other, + SerialError::Port { source } => match source { + PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, + PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + }, + })?; + + Ok(bytes_written) + } + + /// Flush the serial port's output buffer, ensuring that all intermediately buffered + /// contents reach their destination. + fn flush(&mut self) -> io::Result<()> { + Ok(self.flush().map_err(|err| match err { + SerialError::InternalWriteError => io::ErrorKind::Other, + SerialError::Port { source } => match source { + PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, + PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + }, + })?) + } +} + +impl SmartDevice for SerialPort { + fn port_index(&self) -> u8 { + self.port.index() + } + + fn device_type(&self) -> SmartDeviceType { + SmartDeviceType::Serial + } +} + +#[derive(Debug, Snafu)] +pub enum SerialError { + #[snafu(display("Serious internal write error occurred."))] + InternalWriteError, + #[snafu(display("{source}"), context(false))] + Port { source: PortError }, +} + +map_errno! { + SerialError { + EIO => Self::InternalWriteError, + } + inherit PortError; +} diff --git a/packages/pros/src/lib.rs b/packages/pros/src/lib.rs index f9b6a4a2..da8fcd3e 100644 --- a/packages/pros/src/lib.rs +++ b/packages/pros/src/lib.rs @@ -393,6 +393,7 @@ pub mod prelude { motor::{BrakeMode, Gearset, Motor}, optical::OpticalSensor, rotation::RotationSensor, + serial::SerialPort, vision::VisionSensor, SmartDevice, SmartPort, }, From cb17ec5baecf926e588ba9d293cfba8b97b5a9bb Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:08:32 -0600 Subject: [PATCH 02/11] docs: add serial port example --- packages/pros/examples/serial.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 packages/pros/examples/serial.rs diff --git a/packages/pros/examples/serial.rs b/packages/pros/examples/serial.rs new file mode 100644 index 00000000..2f313a29 --- /dev/null +++ b/packages/pros/examples/serial.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] + +use pros::prelude::*; + +#[derive(Default)] +pub struct Robot { + peripherals: Peripherals, +} + +impl Robot { + pub fn new(peripherals: Peripherals) { + Self { peripherals } + } +} + +impl AsyncRobot for Robot { + async fn opcontrol(&mut self) -> pros::Result { + let port = SerialPort::open(self.peripherals.port_1, 9600).expect("Failed to open port"); + + let mut buffer = [0; 256]; + loop { + let read = port.read(&mut buffer)?; + port.write(&buffer[..read])?; + } + + Ok(()) + } +} + +async_robot!(Robot, Robot::new(Peripherals::take().unwrap())); From ccafe4c956bccb7c716f274b103f5d25c84d774b Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:35:13 -0600 Subject: [PATCH 03/11] fix: serial examplee --- packages/pros/examples/serial.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/pros/examples/serial.rs b/packages/pros/examples/serial.rs index 2f313a29..6cae6205 100644 --- a/packages/pros/examples/serial.rs +++ b/packages/pros/examples/serial.rs @@ -1,30 +1,32 @@ #![no_std] #![no_main] +use core::time::Duration; + use pros::prelude::*; -#[derive(Default)] pub struct Robot { - peripherals: Peripherals, + serial_port: SerialPort, } impl Robot { - pub fn new(peripherals: Peripherals) { - Self { peripherals } + pub fn new(peripherals: Peripherals) -> Self { + Self { + serial_port: SerialPort::open(peripherals.port_1, 9600).expect("Failed to open port"), + } } } impl AsyncRobot for Robot { async fn opcontrol(&mut self) -> pros::Result { - let port = SerialPort::open(self.peripherals.port_1, 9600).expect("Failed to open port"); - let mut buffer = [0; 256]; + loop { - let read = port.read(&mut buffer)?; - port.write(&buffer[..read])?; - } + let read = self.serial_port.read(&mut buffer).unwrap(); + self.serial_port.write(&buffer[..read]).unwrap(); - Ok(()) + pros::task::delay(Duration::from_millis(10)); + } } } From 272615858663cf22082f631f2da5ef89d86eab9b Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:17:46 -0600 Subject: [PATCH 04/11] refactor: cast const ptr to *mut u8 --- packages/pros-sys/src/serial.rs | 2 +- packages/pros/src/devices/smart/serial.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pros-sys/src/serial.rs b/packages/pros-sys/src/serial.rs index 22f8a08b..252b567c 100644 --- a/packages/pros-sys/src/serial.rs +++ b/packages/pros-sys/src/serial.rs @@ -194,5 +194,5 @@ extern "C" { \return The number of bytes written or PROS_ERR if the operation failed, setting errno. */ - pub fn serial_write(port: u8, buffer: *const u8, length: i32) -> i32; + pub fn serial_write(port: u8, buffer: *mut u8, length: i32) -> i32; } diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index 8988b39d..f5ce1ed3 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -38,7 +38,7 @@ impl SerialPort { fn transmit(&mut self, buf: &[u8]) -> Result { Ok(bail_on!(PROS_ERR, unsafe { - pros_sys::serial_write(self.port.index(), buf.as_ptr(), buf.len() as i32) + pros_sys::serial_write(self.port.index(), buf.as_ptr() as *mut u8, buf.len() as i32) }) as usize) } From b7693bf6d51fc4032d9374cfb4c7141a9598cdd5 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:22:21 -0600 Subject: [PATCH 05/11] docs: more comments --- packages/pros/src/devices/smart/serial.rs | 103 ++++++++++++++++++++-- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index f5ce1ed3..9278f764 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -13,8 +13,15 @@ pub struct SerialPort { impl SerialPort { /// Open and configure a serial port on a [`SmartPort`]. /// - /// This configures a smart port to act as a generic serial device, capable of sending/recieving - /// data. + /// This configures a [`SmartPort`] to act as a generic serial controller capable of sending/recieving + /// data. Providing a baud rate, or the transmission rate of bits is required. The maximum theoretical + /// baud rate is 921600. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// ``` pub fn open(port: SmartPort, baud_rate: u32) -> Result { unsafe { bail_on!(PROS_ERR, pros_sys::serial_enable(port.index())); @@ -50,7 +57,21 @@ impl SerialPort { Ok(()) } - /// Read the next byte available in the port's input buffer. + /// Read the next byte available in the serial port's input buffer, or `None` if the input + /// buffer is empty. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// loop { + /// if let Some(byte) = serial.read_byte()? { + /// println!("Got byte: {}", byte); + /// } + /// pros::task::delay(Duration::from_millis(10)); + /// } + /// ``` pub fn read_byte(&self) -> Result, SerialError> { let read = bail_on!(PROS_ERR, unsafe { pros_sys::serial_read_byte(self.port.index()) @@ -62,7 +83,18 @@ impl SerialPort { }) } - /// Read the next byte available in the port's input buffer without removing it. + /// Read the next byte available in the port's input buffer without removing it. Returns + /// `None` if the input buffer is empty. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// if let Some(next_byte) = serial.peek_byte()? { + /// println!("Next byte: {}", next_byte); + /// } + /// ``` pub fn peek_byte(&self) -> Result, SerialError> { let peeked = bail_on!(PROS_ERR, unsafe { pros_sys::serial_peek_byte(self.port.index()) @@ -74,14 +106,33 @@ impl SerialPort { }) } - /// Write the single byte to the port's output buffer. + /// Write a single byte to the port's output buffer. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// // Write 0x80 (128u8) to the output buffer + /// serial.write_byte(0x80)?; + /// ``` pub fn write_byte(&mut self, byte: u8) -> Result { Ok(bail_on!(PROS_ERR, unsafe { pros_sys::serial_write_byte(self.port.index(), byte) }) as usize) } - // Returns the number of bytes available to be read in the the port's FIFO input buffer. + /// Returns the number of bytes available to be read in the the port's FIFO input buffer. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// if serial.byets_to_read()? > 0 { + /// println!("{}", serial.read_byte()?.unwrap()); + /// } + /// ``` pub fn bytes_to_read(&self) -> Result { Ok(bail_on!(PROS_ERR, unsafe { pros_sys::serial_get_read_avail(self.port.index()) @@ -89,6 +140,16 @@ impl SerialPort { } /// Returns the number of bytes free in the port's FIFO output buffer. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// if serial.available_write_bytes()? > 0 { + /// serial.write_byte(0x80)?; + /// } + /// ``` pub fn available_write_bytes(&self) -> Result { Ok(bail_on!(PROS_ERR, unsafe { pros_sys::serial_get_write_free(self.port.index()) @@ -99,6 +160,19 @@ impl SerialPort { impl io::Read for SerialPort { /// Read some bytes from this serial port into the specified buffer, returning /// how many bytes were read. + /// + /// # Examples + /// + /// ``` + /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// let mut buffer = Vec::new(); + /// + /// loop { + /// serial.read(&mut buffer); + /// pros::task::delay(Duration::from_millis(10)); + /// } + /// ``` fn read(&mut self, buf: &mut [u8]) -> io::Result { let bytes_read = self.recieve(buf).map_err(|err| match err { SerialError::InternalWriteError => io::ErrorKind::Other, @@ -113,7 +187,8 @@ impl io::Read for SerialPort { } impl io::Write for SerialPort { - /// Write a buffer into the serial port's output buffer, returning how many bytes were written. + /// Write a buffer into the serial port's output buffer, returning how many bytes + /// were written. fn write(&mut self, buf: &[u8]) -> io::Result { let bytes_written = self.transmit(buf).map_err(|err| match err { SerialError::InternalWriteError => io::ErrorKind::Other, @@ -126,8 +201,18 @@ impl io::Write for SerialPort { Ok(bytes_written) } - /// Flush the serial port's output buffer, ensuring that all intermediately buffered - /// contents reach their destination. + /// Clears the internal input and output FIFO buffers. + /// + /// This can be useful to reset state and remove old, potentially unneeded data + /// from the input FIFO buffer or to cancel sending any data in the output FIFO + /// buffer. + /// + /// # Flushing does not send data. + /// + /// This function does not cause the data in the output buffer to be + /// written, it simply clears the internal buffers. Unlike stdout, generic + /// serial does not use buffered IO (the FIFO buffers are written as soon + /// as possible). fn flush(&mut self) -> io::Result<()> { Ok(self.flush().map_err(|err| match err { SerialError::InternalWriteError => io::ErrorKind::Other, From ade59b83e5faf71c6112368e1cf73ec2fe107a7d Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:56:32 -0600 Subject: [PATCH 06/11] docs: add remaining examples --- packages/pros/examples/serial.rs | 8 +++++--- packages/pros/src/devices/smart/serial.rs | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/pros/examples/serial.rs b/packages/pros/examples/serial.rs index 6cae6205..8e737c8f 100644 --- a/packages/pros/examples/serial.rs +++ b/packages/pros/examples/serial.rs @@ -1,7 +1,10 @@ #![no_std] #![no_main] +extern crate alloc; + use core::time::Duration; +use alloc::vec::Vec; use pros::prelude::*; @@ -19,11 +22,10 @@ impl Robot { impl AsyncRobot for Robot { async fn opcontrol(&mut self) -> pros::Result { - let mut buffer = [0; 256]; + let mut buffer = Vec::new(); loop { - let read = self.serial_port.read(&mut buffer).unwrap(); - self.serial_port.write(&buffer[..read]).unwrap(); + self.serial_port.read(&mut buffer); pros::task::delay(Duration::from_millis(10)); } diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index 9278f764..79f4e140 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -164,7 +164,7 @@ impl io::Read for SerialPort { /// # Examples /// /// ``` - /// let serial = SerialPort::open(peripherals.port_1, 115200)?; + /// let mut serial = SerialPort::open(peripherals.port_1, 115200)?; /// /// let mut buffer = Vec::new(); /// @@ -189,6 +189,14 @@ impl io::Read for SerialPort { impl io::Write for SerialPort { /// Write a buffer into the serial port's output buffer, returning how many bytes /// were written. + /// + /// # Examples + /// + /// ``` + /// let mut serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// buffer.write(b"some bytes")?; + /// ``` fn write(&mut self, buf: &[u8]) -> io::Result { let bytes_written = self.transmit(buf).map_err(|err| match err { SerialError::InternalWriteError => io::ErrorKind::Other, @@ -213,6 +221,13 @@ impl io::Write for SerialPort { /// written, it simply clears the internal buffers. Unlike stdout, generic /// serial does not use buffered IO (the FIFO buffers are written as soon /// as possible). + /// + /// ``` + /// let mut serial = SerialPort::open(peripherals.port_1, 115200)?; + /// + /// buffer.write(b"some bytes")?; + /// buffer.flush()?; + /// ``` fn flush(&mut self) -> io::Result<()> { Ok(self.flush().map_err(|err| match err { SerialError::InternalWriteError => io::ErrorKind::Other, From abc9d631b5f2fd8be78dfe27a92ab870b1ec7eb3 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 26 Jan 2024 23:19:20 -0600 Subject: [PATCH 07/11] docs: module header --- packages/pros/examples/serial.rs | 2 +- packages/pros/src/devices/smart/serial.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/pros/examples/serial.rs b/packages/pros/examples/serial.rs index 8e737c8f..64eee03f 100644 --- a/packages/pros/examples/serial.rs +++ b/packages/pros/examples/serial.rs @@ -3,8 +3,8 @@ extern crate alloc; -use core::time::Duration; use alloc::vec::Vec; +use core::time::Duration; use pros::prelude::*; diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index 79f4e140..c296c53a 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -1,3 +1,7 @@ +//! Generic serial device module. +//! +//! Provides support for using [`SmartPort`]s as generic serial communication devices. + use no_std_io::io; use pros_sys::PROS_ERR; use snafu::Snafu; From 2175d382adc5f1cc822f1b7c2645c8d5b3b236b5 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:44:49 -0600 Subject: [PATCH 08/11] chore: fmt --- packages/pros-sys/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pros-sys/src/lib.rs b/packages/pros-sys/src/lib.rs index b56a84ea..d10d8c13 100644 --- a/packages/pros-sys/src/lib.rs +++ b/packages/pros-sys/src/lib.rs @@ -19,13 +19,15 @@ pub mod motor; pub mod optical; pub mod rotation; pub mod rtos; -pub mod serial; pub mod screen; +pub mod serial; pub mod vision; use core::ffi::{c_char, c_int, c_void}; pub use adi::*; +#[cfg(feature = "xapi")] +pub use apix::*; pub use colors::*; pub use distance::*; pub use error::*; @@ -41,8 +43,6 @@ pub use rtos::*; pub use screen::*; pub use serial::*; pub use vision::*; -#[cfg(feature = "xapi")] -pub use apix::*; pub const CLOCKS_PER_SEC: u32 = 1000; From dbcf0c0e1592ce97323f1e5d1755c425afab7b98 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:47:12 -0600 Subject: [PATCH 09/11] docs: document `SerialPort` --- packages/pros/src/devices/smart/serial.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index c296c53a..ae66b8bf 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -9,6 +9,7 @@ use snafu::Snafu; use super::{SmartDevice, SmartDeviceType, SmartPort}; use crate::error::{bail_on, map_errno, PortError}; +/// Represents a smart port configured as a generic serial controller. #[derive(Debug, Eq, PartialEq)] pub struct SerialPort { port: SmartPort, From d1781abbbc94b45884386118caa4c06b1d2f8050 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:50:05 -0600 Subject: [PATCH 10/11] docs: document --- packages/pros/examples/serial.rs | 2 +- packages/pros/src/devices/smart/serial.rs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/pros/examples/serial.rs b/packages/pros/examples/serial.rs index 64eee03f..e296aa72 100644 --- a/packages/pros/examples/serial.rs +++ b/packages/pros/examples/serial.rs @@ -25,7 +25,7 @@ impl AsyncRobot for Robot { let mut buffer = Vec::new(); loop { - self.serial_port.read(&mut buffer); + self.serial_port.read(&mut buffer).unwrap(); pros::task::delay(Duration::from_millis(10)); } diff --git a/packages/pros/src/devices/smart/serial.rs b/packages/pros/src/devices/smart/serial.rs index ae66b8bf..b6b29092 100644 --- a/packages/pros/src/devices/smart/serial.rs +++ b/packages/pros/src/devices/smart/serial.rs @@ -254,12 +254,18 @@ impl SmartDevice for SerialPort { } } +/// Errors that can occur when interacting with a [`SerialPort`]. #[derive(Debug, Snafu)] pub enum SerialError { - #[snafu(display("Serious internal write error occurred."))] + /// Serious internal write error occurred. InternalWriteError, + + /// Generic port related error. #[snafu(display("{source}"), context(false))] - Port { source: PortError }, + Port { + /// The source of the error. + source: PortError, + }, } map_errno! { From 488274eb4baa17df861645c900b85607fa5561ad Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Wed, 6 Mar 2024 19:00:58 -0600 Subject: [PATCH 11/11] fix: standard I/O error mapping --- packages/pros-devices/src/smart/serial.rs | 11 +++++++---- packages/pros/src/lib.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/pros-devices/src/smart/serial.rs b/packages/pros-devices/src/smart/serial.rs index b6b29092..942b58d5 100644 --- a/packages/pros-devices/src/smart/serial.rs +++ b/packages/pros-devices/src/smart/serial.rs @@ -3,11 +3,11 @@ //! Provides support for using [`SmartPort`]s as generic serial communication devices. use no_std_io::io; +use pros_core::{bail_on, error::PortError, map_errno}; use pros_sys::PROS_ERR; use snafu::Snafu; use super::{SmartDevice, SmartDeviceType, SmartPort}; -use crate::error::{bail_on, map_errno, PortError}; /// Represents a smart port configured as a generic serial controller. #[derive(Debug, Eq, PartialEq)] @@ -183,7 +183,8 @@ impl io::Read for SerialPort { SerialError::InternalWriteError => io::ErrorKind::Other, SerialError::Port { source } => match source { PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, - PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + PortError::PortCannotBeConfigured => io::ErrorKind::AlreadyExists, + PortError::AlreadyInUse => io::ErrorKind::AddrInUse, }, })?; @@ -207,7 +208,8 @@ impl io::Write for SerialPort { SerialError::InternalWriteError => io::ErrorKind::Other, SerialError::Port { source } => match source { PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, - PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + PortError::PortCannotBeConfigured => io::ErrorKind::AlreadyExists, + PortError::AlreadyInUse => io::ErrorKind::AddrInUse, }, })?; @@ -238,7 +240,8 @@ impl io::Write for SerialPort { SerialError::InternalWriteError => io::ErrorKind::Other, SerialError::Port { source } => match source { PortError::PortOutOfRange => io::ErrorKind::AddrNotAvailable, - PortError::PortCannotBeConfigured => io::ErrorKind::AddrInUse, + PortError::PortCannotBeConfigured => io::ErrorKind::AlreadyExists, + PortError::AlreadyInUse => io::ErrorKind::AddrInUse, }, })?) } diff --git a/packages/pros/src/lib.rs b/packages/pros/src/lib.rs index 5af7448f..6ff3578f 100644 --- a/packages/pros/src/lib.rs +++ b/packages/pros/src/lib.rs @@ -109,8 +109,8 @@ pub mod prelude { motor::{BrakeMode, Gearset, Motor}, optical::OpticalSensor, rotation::RotationSensor, - vision::VisionSensor, serial::SerialPort, + vision::VisionSensor, SmartDevice, SmartPort, }, };