From 63227024017f21f2bf397d9df2e87ce4ef984e08 Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 13:58:29 +0200 Subject: [PATCH 1/9] Modified the description --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e89db8a..1004cf5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,14 @@ //! * Limited device support: FT232H, FT2232H, FT4232H. //! * Limited SPI modes support: MODE0, MODE2. //! +//! Note regarding the FT4232H: +//! +//! * Ports A and B support MPSSE, in addition to UART and bit-bang modes. +//! * Ports C and D support UART and bit-bang modes only. +//! +//! Because of this, Ports C and D only support GPIO traits, via the FtHalSbb class, +//! operated in synchronous bit-bang mode. The FtHalSbb class only supports the ftdi-rs drive at this time. +//! //! # Examples //! //! ## SPI From 4d4e3ae8946e8a566f62d9f44f2b8a261a121acd Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:16:59 +0200 Subject: [PATCH 2/9] Added example --- examples/blink_sbb.rs | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/blink_sbb.rs diff --git a/examples/blink_sbb.rs b/examples/blink_sbb.rs new file mode 100644 index 0000000..75a257e --- /dev/null +++ b/examples/blink_sbb.rs @@ -0,0 +1,44 @@ +use eh0::digital::v2::OutputPin; +use ftdi_embedded_hal as hal; +use std::{thread::sleep, time::Duration}; + +const NUM_BLINK: usize = 10; +const SLEEP_DURATION: Duration = Duration::from_millis(500); + +/// Toggle the AD0 output by reading its state on AD1, inverting, and +/// writing it back out on AD0. This test requires that AD0 and AD1 are +/// connected together. +fn main() { + cfg_if::cfg_if! { + if #[cfg(feature = "ftdi")] { + // FTDI FT4232H: vid=0x0403, pid=0x6011. + let device = ftdi::find_by_vid_pid(0x0403, 0x6011) + .interface(ftdi::Interface::D) + .open() + .unwrap(); + + // Default settings suffice. + let hal_cfg = hal::FtHalSbbSettings::default(); + let hal = hal::FtHalSbb::init(epe_if_d, hal_cfg).unwrap(); + + // Assign the GPIO pins. + let gpio_ado0 = hal.ad0().unwrap(); + let gpio_adi1 = hal.adi1().unwrap(); + + println!("Starting blinky using synchronous bit-bang gpio example"); + for n in 0..NUM_BLINK { + let state = gpio_adi1.get().expect("failed to get GPIO AD1"); + println!("Read State: {}", state); + + gpio_ado0.set(!state).expect("failed to set GPIO AD0"); + + sleep(SLEEP_DURATION); + + println!("Blinked {}/{} times", n + 1, NUM_BLINK); + } + + } else { + compile_error!("Feature 'ftdi' must be enabled"); + } + } +} From a19acf5d3478d781275f0c77a372158fc47091ee Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:17:26 +0200 Subject: [PATCH 3/9] Added synchronous bit-bang gpio support --- src/fthalsbb.rs | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gpiosbb.rs | 267 +++++++++++++++++++++++++++++++++++ src/lib.rs | 10 ++ 3 files changed, 646 insertions(+) create mode 100644 src/fthalsbb.rs create mode 100644 src/gpiosbb.rs diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs new file mode 100644 index 0000000..c43a14a --- /dev/null +++ b/src/fthalsbb.rs @@ -0,0 +1,369 @@ +use std::io::Read; +use std::marker::PhantomData; +use std::sync::{Arc, Mutex}; + +use crate::error::Error; +use crate::gpiosbb::{InputPinSbb, OutputPinSbb, Pin}; +use crate::{GpioByte, PinUse}; + +use ftdi; + +/// FTHal Synchronous Bit-Bang mode settings struct. +/// The defaults are a sensible starting point: +/// +/// * Reset the FTDI device. +/// * 4k USB transfer size for read and write. +/// * 16ms latency timer. +/// * 100kHz clock frequency. +#[derive(Debug)] +pub struct FtHalSbbSettings { + reset: bool, + read_chunksize: u32, + write_chunksize: u32, + latency_timer_ms: u8, + clock_frequency: u32, +} + +impl Default for FtHalSbbSettings { + fn default() -> Self { + FtHalSbbSettings { + reset: true, + read_chunksize: 4096, + write_chunksize: 4096, + latency_timer_ms: 16, + clock_frequency: 100_000, + } + } +} + +// Internal struct to hold in the mutex. +// Need the FTDI device, but also the pin directions and types. +// TODO: remove pub when turning into library. +pub struct FtInnerSbb { + pub ft: ftdi::Device, + pub lower: GpioByte, + pub upper: GpioByte, +} + +impl FtInnerSbb { + /// Allocate a pin in the lower byte for a specific use. + pub fn allocate_pin(&mut self, idx: u8, purpose: PinUse) { + assert!(idx < 8, "Pin index {idx} is out of range 0 - 7"); + + if let Some(current) = self.lower.pins[usize::from(idx)] { + panic!( + "Unable to allocate pin {idx} for {purpose}, pin is already allocated for {current}" + ); + } else { + self.lower.pins[usize::from(idx)] = Some(purpose) + } + } + + /// Allocate a pin for a specific use. + pub fn allocate_pin_any(&mut self, pin: Pin, purpose: PinUse) { + let (byte, idx) = match pin { + Pin::Lower(idx) => (&mut self.lower, idx), + Pin::Upper(idx) => (&mut self.upper, idx), + }; + assert!(idx < 8, "Pin index {idx} is out of range 0 - 7"); + + if let Some(current) = byte.pins[usize::from(idx)] { + panic!( + "Unable to allocate pin {idx} for {purpose}, pin is already allocated for {current}" + ); + } else { + byte.pins[usize::from(idx)] = Some(purpose) + } + } +} + +/// For the FT4232H, ports C and D do not support the MPSSE. Only UART and +/// bit-bang modes are possible. This means that a different method of port +/// access is required. As there is no MPSSE, only GPIO mode is supported. +/// +/// The GPIO operations are implemented using the synchronous bit-bang mode. +/// This mode keeps stimulus-response in lock-step, which is the expected +/// behavior when setting and getting GPIO pin states. There is a gotcha that +/// is explained in the FT4232H data sheet, V2.6, Ch. 4.5.2, p.23: +/// +/// With Synchronous Bit-Bang mode, data will only be sent-out by the chip +/// if there is space in the chip's USB TX FIFO for data to be read from the +/// parallel interface pins. The data bus parallel I/O pins are read first, +/// before data from the USB RX FIFO is transmitted. It is therefore 1 byte +/// behind the output, and so to read the inputs for the byte that you have +/// just sent, another byte must be sent. +/// +/// For example: +/// (1) Pins start at 0xFF +/// - Send 0x55,0xAA +/// - Pins go to 0x55 and then to 0xAA +/// - Data read = 0xFF,0x55 +/// +/// (2) Pins start at 0xFF +/// - Send 0x55,0xAA,0xAA +/// (repeat the last byte sent) +/// - Pins go to 0x55 and then to 0xAA +/// - Data read = 0xFF,0x55,0xAA +/// +/// In the code below, the (2) sequence is used. +/// +/// Because a write is required to precede a read, the (at least) doubling of +/// the last written data byte is implemented in the gpio read (get): the +/// complete gpio output byte set-up for the previous gpio write (set) is +/// repeated, so that any read is always preceded by (at least) a double write +/// of the last gpio output byte. +/// +/// To avoid potential problems of the chip's USB TX FIFO overflowing after a +/// long sequence of writes (set), all data is read from it, both in the set +/// and get functions. Writes cannot occur when this FIFO is full, so +/// explicitly clearing it out before any write is not a bad idea. +pub struct FtHalSbb { + mtx: Arc>, + // To satisfy the compiler. We need a type parameter on the struct, + // otherwise the impl constraints fail. But it is not used in the struct. + // The use of a PhantomData member that uses solves this problem. + _p: PhantomData, +} + +impl FtHalSbb +where + E: std::error::Error, + Error: From, +{ + /// Initialize the FTDI synchronous bit-bang interface with custom values. + /// + /// # Example + /// + /// ```no_run + /// use ftdi_embedded_hal as hal; + /// + /// let sbb = FtHalSbbSettings { + /// reset: false, + /// read_chunksize: 4096, + /// write_chunksize: 4096, + /// latency_timer: 32, + /// clock_frequency: 1_000_000, + /// }; + /// + /// # #[cfg(feature = "ftdi")] + /// # { + /// let device = ftdi::find_by_vid_pid(0x0403, 0x6011) + /// .interface(ftdi::Interface::D) + /// .open() + /// .unwrap(); + /// + /// let hal_cfg = FtHalSbbSettings::default(); + /// let hal = FtHalSbb::init(epe_if_d, hal_cfg).unwrap(); + /// # } + /// # Ok::<(), std::boxed::Box>(()) + /// ``` + /// + /// [`FtHalSbbSettings`]: crate::fthalsbb::FtHalSbbSettings + pub fn init(device: ftdi::Device, settings: FtHalSbbSettings) -> Result, Error> { + // Keep the device handler and pin settings together in a struct. + // The arc mutex will eventually wrap this in turn. + let mut inner = FtInnerSbb { + ft: device, // Holds the ftdi::Device struct. + lower: GpioByte { + direction: 0, // Initialize all pins as inputs. (Safer!) + value: 0, // All to zeros. + pins: [None; 8], // No pins uses allocated yet. + }, + upper: GpioByte { + direction: 0, // Initialize all pins as inputs. (Safer!) + value: 0, // All to zeros. + pins: [None; 8], // No pins uses allocated yet. + }, + }; + + // Initialize the ftdi device using the passed configuration struct. + // The data is clocked-out at a rate controlled by the baud rate + // generator. See: FT4232H data sheet, V2.6, Ch. 4.5.1, p. 23. + if settings.reset { + inner.ft.usb_reset()?; + } + inner.ft.usb_purge_buffers()?; + inner.ft.set_read_chunksize(settings.read_chunksize); + inner.ft.set_write_chunksize(settings.write_chunksize); + inner.ft.set_latency_timer(settings.latency_timer_ms)?; + inner.ft.set_baud_rate(settings.clock_frequency)?; + + // Configure synchronous bit-bang mode and the pin direction set above. + // When pins are assigned later, the direction is modified accordingly. + inner + .ft + .set_bitmode(inner.lower.direction, ftdi::BitMode::SyncBB)?; + + // Purge the read buffer and discard. + // There can be a few stray bytes in it at this point. Also, a write + // will only execute if there is space in the chip's USB TX FIFO, so + // it is best to insure it is empty from the get go. + let mut stray_bytes = vec![]; + inner.ft.read_to_end(&mut stray_bytes)?; + + Ok(FtHalSbb { + mtx: Arc::new(Mutex::new(inner)), + _p: PhantomData, + }) + } + + /// Acquire the digital output pin 0 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad0(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(0)) + } + + /// Acquire the digital input pin 0 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi0(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(0)) + } + + /// Acquire the digital output pin 1 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad1(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(1)) + } + + /// Acquire the digital input pin 1 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi1(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(1)) + } + + /// Acquire the digital output pin 2 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad2(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(2)) + } + + /// Acquire the digital input pin 2 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi2(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(2)) + } + + /// Acquire the digital output pin 3 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad3(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(3)) + } + + /// Acquire the digital input pin 3 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi3(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(3)) + } + + /// Acquire the digital output pin 4 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad4(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(4)) + } + + /// Acquire the digital input pin 4 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi4(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(4)) + } + + /// Acquire the digital output pin 5 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad5(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(5)) + } + + /// Acquire the digital input pin 5 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi5(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(5)) + } + + /// Acquire the digital output pin 6 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad6(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(6)) + } + + /// Acquire the digital input pin 6 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi6(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(6)) + } + + /// Acquire the digital output pin 7 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn ad7(&self) -> Result, Error> { + OutputPinSbb::new(self.mtx.clone(), Pin::Lower(7)) + } + + /// Acquire the digital input pin 7 for the FTx232H, using synchronous + /// bit-bang mode. + /// + /// # Panics + /// + /// Panics if the pin is already in-use. + pub fn adi7(&self) -> Result, Error> { + InputPinSbb::new(self.mtx.clone(), Pin::Lower(7)) + } +} diff --git a/src/gpiosbb.rs b/src/gpiosbb.rs new file mode 100644 index 0000000..d8341e0 --- /dev/null +++ b/src/gpiosbb.rs @@ -0,0 +1,267 @@ +use crate::error::Error; +use crate::fthalsbb::FtInnerSbb; +use crate::PinUse; +use std::io::{Read, Write}; +use std::marker::PhantomData; +use std::sync::{Arc, Mutex}; + +pub use ftdi; + +// ---------------------------------------------------------------------------- +// Taken from ftdi-embedded-hal without change. + +/// Pin number +#[derive(Debug, Copy, Clone)] +pub(crate) enum Pin { + Lower(u8), + Upper(u8), +} + +// ---------------------------------------------------------------------------- + +/// FTDI output pin. +/// +/// This is created by calling [`FtHalSbb::ad0`] - [`FtHalSbb::ad7`]. +/// +/// [`FtHalSbb::ad0`]: crate::FtHalSbb::ad0 +/// [`FtHalSbb::ad7`]: crate::FtHalSbb::ad7 +pub struct OutputPinSbb { + /// Parent FTDI device. + mtx: Arc>, + /// GPIO pin index. 0-7 for the FTx232H. + pin: Pin, + // Satisfy the compiler. + _p: PhantomData, +} + +impl OutputPinSbb +where + E: std::error::Error, + Error: From, +{ + pub(crate) fn new(mtx: Arc>, pin: Pin) -> Result, Error> { + { + let mut lock = mtx.lock().expect("Failed to acquire FTDI mutex"); + + lock.allocate_pin_any(pin, PinUse::Output); + + let (byte, idx) = match pin { + Pin::Lower(idx) => (&mut lock.lower, idx), + Pin::Upper(idx) => (&mut lock.upper, idx), + }; + byte.direction |= 1 << idx; + + let out_mask = byte.direction; + + match pin { + Pin::Lower(_) => lock.ft.set_bitmode(out_mask, ftdi::BitMode::SyncBB)?, + Pin::Upper(_) => panic!("Upper byte not supported by FtHalSbb."), + } + } + Ok(OutputPinSbb { + mtx, + pin, + _p: PhantomData, + }) + } + + pub(crate) fn set(&self, state: bool) -> Result<(), Error> { + let mut lock = self.mtx.lock().expect("Failed to acquire FTDI mutex"); + + let byte = match self.pin { + Pin::Lower(_) => &mut lock.lower, + Pin::Upper(_) => &mut lock.upper, + }; + + if state { + byte.value |= self.mask(); + } else { + byte.value &= !self.mask(); + }; + + let out_buf = [byte.value]; + + // Read the GPIO pin states (from the parallel I/O port itself) and + // discard. This entire-buffer read makes sure that the USB TX FIFO in + // the chip can't fill-up due to executing many writes without a read + // in sequence. It also avoids any accumulation of stray bytes in the + // buffer. (This has never happened after the initial purge thus far, + // but it is a safeguard.) + let mut read_bytes = vec![]; + lock.ft.read_to_end(&mut read_bytes)?; + + // Write the new pin states to the output. + lock.ft.write_all(&out_buf)?; + + Ok(()) + } +} + +impl OutputPinSbb +where + E: std::error::Error, + Error: From, +{ + /// Convert the GPIO pin index to a pin mask + pub(crate) fn mask(&self) -> u8 { + let idx = match self.pin { + Pin::Lower(idx) => idx, + Pin::Upper(idx) => idx, + }; + 1 << idx + } +} + +impl eh1::digital::ErrorType for OutputPinSbb +where + E: std::error::Error, + Error: From, +{ + type Error = Error; +} + +impl eh1::digital::OutputPin for OutputPinSbb +where + E: std::error::Error, + Error: From, +{ + fn set_low(&mut self) -> Result<(), Error> { + self.set(false) + } + + fn set_high(&mut self) -> Result<(), Error> { + self.set(true) + } +} + +/// FTDI input pin. +/// +/// This is created by calling [`FtHalSbb::adi0`] - [`FtHalSbb::adi7`]. +/// +/// [`FtHalSbb::adi0`]: crate::FtHalSbb::adi0 +/// [`FtHalSbb::adi7`]: crate::FtHalSbb::adi7 +pub struct InputPinSbb { + /// Parent FTDI device. + mtx: Arc>, + /// GPIO pin index. 0-7 for the FTx232H. + pin: Pin, + // Satisfy the compiler. + _p: PhantomData, +} + +impl InputPinSbb +where + E: std::error::Error, + Error: From, +{ + pub(crate) fn new(mtx: Arc>, pin: Pin) -> Result, Error> { + { + let mut lock = mtx.lock().expect("Failed to acquire FTDI mutex"); + + lock.allocate_pin_any(pin, PinUse::Input); + + let (byte, idx) = match pin { + Pin::Lower(idx) => (&mut lock.lower, idx), + Pin::Upper(idx) => (&mut lock.upper, idx), + }; + byte.direction &= !(1 << idx); + + let out_mask = byte.direction; + + match pin { + Pin::Lower(_) => lock.ft.set_bitmode(out_mask, ftdi::BitMode::SyncBB)?, + Pin::Upper(_) => panic!("Upper byte not supported by FtHalSbb."), + } + } + Ok(InputPinSbb { + mtx, + pin, + _p: PhantomData, + }) + } + + pub(crate) fn get(&self) -> Result> { + let mut lock = self.mtx.lock().expect("Failed to acquire FTDI mutex"); + + // The read can return empty if the chip's USB TX buffer is empty. + // Because the bit-bang is synchronous, a write is required to obtain + // data to read-back. Thus, two reads in a row need a write in-between. + // Also, the last byte written should be doubled-up, so that the read + // (which has a one byte delay) is synchronous again. + // + // Thus, by always writing-out the output state before a read, both + // requirements satisfied. + let byte = match self.pin { + Pin::Lower(_) => &mut lock.lower, + Pin::Upper(_) => &mut lock.upper, + }; + + let out_buf = [byte.value]; + lock.ft.write_all(&out_buf)?; + + // Read the GPIO pin states (from the parallel I/O port itself). + // All bytes in the buffer are taken-in, discarding all but the last + // one, which is the result of writing the previous bit pattern. + // This entire-buffer read makes sure that the USB TX FIFO in the chip + // can't fill-up due to cumulative weirdness. (This has never happened + // after the initial purge thus far, but it is a safeguard.) + let mut read_bytes = vec![]; + lock.ft.read_to_end(&mut read_bytes)?; + let pin_states = *(read_bytes.last().unwrap()); + + Ok((pin_states & self.mask()) != 0) + } +} + +impl InputPinSbb +where + E: std::error::Error, + Error: From, +{ + /// Convert the GPIO pin index to a pin mask + pub(crate) fn mask(&self) -> u8 { + let idx = match self.pin { + Pin::Lower(idx) => idx, + Pin::Upper(idx) => idx, + }; + 1 << idx + } +} + +impl eh1::digital::ErrorType for InputPinSbb +where + E: std::error::Error, + Error: From, +{ + type Error = Error; +} + +impl eh1::digital::InputPin for InputPinSbb +where + E: std::error::Error, + Error: From, +{ + fn is_high(&mut self) -> Result { + self.get() + } + + fn is_low(&mut self) -> Result { + self.get().map(|res| !res) + } +} + +impl eh0::digital::v2::InputPin for InputPinSbb +where + E: std::error::Error, + Error: From, +{ + type Error = Error; + + fn is_high(&self) -> Result { + self.get() + } + + fn is_low(&self) -> Result { + self.get().map(|res| !res) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1004cf5..de02584 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -173,12 +173,22 @@ mod gpio; mod i2c; mod spi; +#[cfg(feature = "ftdi")] +mod fthalsbb; +#[cfg(feature = "ftdi")] +mod gpiosbb; + pub use crate::error::{Error, ErrorKind}; pub use delay::Delay; pub use gpio::{InputPin, OutputPin}; pub use i2c::I2c; pub use spi::{Spi, SpiDevice}; +#[cfg(feature = "ftdi")] +pub use fthalsbb::{FtHalSbb, FtHalSbbSettings}; +#[cfg(feature = "ftdi")] +pub use gpiosbb::{InputPinSbb, OutputPinSbb}; + use gpio::Pin; use ftdi_mpsse::{MpsseCmdExecutor, MpsseSettings}; From 0de1fbd83d12a9546f83b5b91f8e740f9adb475e Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:29:30 +0200 Subject: [PATCH 4/9] Fixed example tu use public api --- examples/blink_sbb.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/blink_sbb.rs b/examples/blink_sbb.rs index 75a257e..0e643b4 100644 --- a/examples/blink_sbb.rs +++ b/examples/blink_sbb.rs @@ -22,15 +22,19 @@ fn main() { let hal = hal::FtHalSbb::init(epe_if_d, hal_cfg).unwrap(); // Assign the GPIO pins. - let gpio_ado0 = hal.ad0().unwrap(); - let gpio_adi1 = hal.adi1().unwrap(); + let mut gpio_ado0 = hal.ad0().unwrap(); + let mut gpio_adi1 = hal.adi1().unwrap(); println!("Starting blinky using synchronous bit-bang gpio example"); for n in 0..NUM_BLINK { - let state = gpio_adi1.get().expect("failed to get GPIO AD1"); + let state = gpio_adi1.is_high().expect("failed to get GPIO AD1 state"); println!("Read State: {}", state); - gpio_ado0.set(!state).expect("failed to set GPIO AD0"); + if state { + gpio_ado0.set_low().expect("failed to set GPIO AD0 low"); + } else { + gpio_ado0.set_high().expect("failed to set GPIO AD0 high"); + } sleep(SLEEP_DURATION); From d7d39226e94e6c8fdea86bea9787ffc44e388f19 Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:30:29 +0200 Subject: [PATCH 5/9] Fixed publicness of internal struct --- src/fthalsbb.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs index c43a14a..34f4345 100644 --- a/src/fthalsbb.rs +++ b/src/fthalsbb.rs @@ -38,11 +38,10 @@ impl Default for FtHalSbbSettings { // Internal struct to hold in the mutex. // Need the FTDI device, but also the pin directions and types. -// TODO: remove pub when turning into library. -pub struct FtInnerSbb { - pub ft: ftdi::Device, - pub lower: GpioByte, - pub upper: GpioByte, +struct FtInnerSbb { + ft: ftdi::Device, + lower: GpioByte, + upper: GpioByte, } impl FtInnerSbb { From ddd410a3ea821e482f415fec21284d7badb4a622 Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:32:55 +0200 Subject: [PATCH 6/9] Pub(crate) of FtInnerSbb --- src/fthalsbb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs index 34f4345..8cb2ea2 100644 --- a/src/fthalsbb.rs +++ b/src/fthalsbb.rs @@ -38,7 +38,7 @@ impl Default for FtHalSbbSettings { // Internal struct to hold in the mutex. // Need the FTDI device, but also the pin directions and types. -struct FtInnerSbb { +pub(crate) struct FtInnerSbb { ft: ftdi::Device, lower: GpioByte, upper: GpioByte, From a7abdf7480b290c17fd58dc95753d80f3268c24a Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 14:33:43 +0200 Subject: [PATCH 7/9] More pub(crate) --- src/fthalsbb.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs index 8cb2ea2..9bbbb72 100644 --- a/src/fthalsbb.rs +++ b/src/fthalsbb.rs @@ -39,9 +39,9 @@ impl Default for FtHalSbbSettings { // Internal struct to hold in the mutex. // Need the FTDI device, but also the pin directions and types. pub(crate) struct FtInnerSbb { - ft: ftdi::Device, - lower: GpioByte, - upper: GpioByte, + pub(crate) ft: ftdi::Device, + pub(crate) lower: GpioByte, + pub(crate) upper: GpioByte, } impl FtInnerSbb { From 8450549d815115289f3769dd54245e97044f93e5 Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 17:08:50 +0200 Subject: [PATCH 8/9] Made FtHalSbbSettings fields also public --- src/fthalsbb.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs index 9bbbb72..9aaf16e 100644 --- a/src/fthalsbb.rs +++ b/src/fthalsbb.rs @@ -17,11 +17,11 @@ use ftdi; /// * 100kHz clock frequency. #[derive(Debug)] pub struct FtHalSbbSettings { - reset: bool, - read_chunksize: u32, - write_chunksize: u32, - latency_timer_ms: u8, - clock_frequency: u32, + pub reset: bool, + pub read_chunksize: u32, + pub write_chunksize: u32, + pub latency_timer_ms: u8, + pub clock_frequency: u32, } impl Default for FtHalSbbSettings { From f5a402cfe98f6d8e08acbff2bb4c93f1894092a4 Mon Sep 17 00:00:00 2001 From: Tom De Rybel Date: Tue, 16 Jul 2024 17:57:28 +0200 Subject: [PATCH 9/9] Documented the FtHalSbbSettings struct better. --- src/fthalsbb.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fthalsbb.rs b/src/fthalsbb.rs index 9aaf16e..85b4634 100644 --- a/src/fthalsbb.rs +++ b/src/fthalsbb.rs @@ -17,10 +17,15 @@ use ftdi; /// * 100kHz clock frequency. #[derive(Debug)] pub struct FtHalSbbSettings { + /// Reset the gpio state at device initialization (when true). pub reset: bool, + /// Read chunk size, in bytes. pub read_chunksize: u32, + /// Write chunk size, in bytes. pub write_chunksize: u32, + /// USB latency timer, in ms. pub latency_timer_ms: u8, + /// GPIO clock frequency, in Hz. pub clock_frequency: u32, }