diff --git a/integration/src/main.rs b/integration/src/main.rs index 1485f6d..80977af 100644 --- a/integration/src/main.rs +++ b/integration/src/main.rs @@ -26,6 +26,12 @@ fn test_case(test_case_name: &str, actual: T, ex } } +#[cfg(target_arch = "arm")] +const RESOURCE: &str = "RIO0"; + +#[cfg(not(target_arch = "arm"))] +const RESOURCE: &str = "rio://172.22.11.2/RIO0"; + #[allow(overflowing_literals)] fn main() -> Result<(), ni_fpga::Error> { let mut tmp_bitfile = NamedTempFile::new().unwrap(); @@ -34,7 +40,7 @@ fn main() -> Result<(), ni_fpga::Error> { let session = Session::open( tmp_bitfile.path().to_str().unwrap(), "D08F17F77A45A5692FA2342C6B86E0EE", - "RIO0", + RESOURCE, )?; test_case("read plain U8", session.read::(98306)?, 0b00000001); @@ -98,15 +104,12 @@ fn main() -> Result<(), ni_fpga::Error> { session.read::(98360)?, TestCluster { b: false, u: 1337 }, ); - // TODO: Investigate cluster array memory layout in order to fix this test. - // The expected array may be incorrect here, I don't exactly remember what I used for the - // fixture bitfile before my LabView FPGA trial expired. test_case( "read cluster array", - session.read::<[TestCluster; 2]>(98360)?, + session.read::<[TestCluster; 2]>(98364)?, [ - TestCluster { b: true, u: 255 }, - TestCluster { b: false, u: 1337 }, + TestCluster { b: true, u: 1234 }, + TestCluster { b: false, u: 5678 }, ], ); diff --git a/ni-fpga-sys/Cargo.toml b/ni-fpga-sys/Cargo.toml index e5d28bc..b4013a2 100644 --- a/ni-fpga-sys/Cargo.toml +++ b/ni-fpga-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ni-fpga-sys" -version = "1.0.1" +version = "2.0.0" authors = ["Connor Worley "] edition = "2018" license-file = "LICENSE.md" diff --git a/ni-fpga/Cargo.toml b/ni-fpga/Cargo.toml index 8e06bfd..13fd52b 100644 --- a/ni-fpga/Cargo.toml +++ b/ni-fpga/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ni-fpga" -version = "1.4.1" +version = "1.5.0" authors = ["Connor Worley "] edition = "2018" license = "MIT" @@ -10,6 +10,6 @@ readme = "README.md" repository = "https://github.com/first-rust-competition/ni-fpga-rs" [dependencies] -bitvec = "0.17.4" -ni-fpga-sys = { version = "1.0.1", path = "../ni-fpga-sys" } -thiserror = "1.0.19" +bitvec = "1.0.1" +ni-fpga-sys = { version = "2.0.0", path = "../ni-fpga-sys" } +thiserror = "1.0.48" diff --git a/ni-fpga/src/datatype.rs b/ni-fpga/src/datatype.rs index 4426535..5ac3d76 100644 --- a/ni-fpga/src/datatype.rs +++ b/ni-fpga/src/datatype.rs @@ -1,11 +1,15 @@ -use bitvec::prelude::*; +use bitvec::{access::BitSafeU8, prelude::*}; use crate::errors::Error; #[cfg(target_endian = "little")] -pub type FpgaBits = BitSlice; +pub type FpgaBits = BitSlice; +#[cfg(target_endian = "little")] +pub(crate) type FpgaBitsRaw = BitSlice; +#[cfg(target_endian = "big")] +pub type FpgaBits = BitSlice; #[cfg(target_endian = "big")] -pub type FpgaBits = BitSlice; +pub(crate) type FpgaBits = BitSlice; pub trait Datatype: Sized { const SIZE_IN_BITS: usize; @@ -24,6 +28,7 @@ impl Datatype for [T; N] { .try_for_each(|(src, bits)| Datatype::pack(bits, src)) } + #[allow(clippy::forget_non_drop)] fn unpack(fpga_bits: &FpgaBits) -> Result { let mut data: [std::mem::MaybeUninit; N] = std::mem::MaybeUninit::uninit_array(); data.iter_mut() diff --git a/ni-fpga/src/session.rs b/ni-fpga/src/session.rs index 535973a..1f7ed31 100644 --- a/ni-fpga/src/session.rs +++ b/ni-fpga/src/session.rs @@ -1,6 +1,6 @@ use std::ffi::CString; -use crate::datatype::{Datatype, FpgaBits}; +use crate::datatype::{Datatype, FpgaBitsRaw}; use crate::errors::Error; use crate::ffi; use crate::ffi::Offset; @@ -52,41 +52,52 @@ impl Session { where [u8; (T::SIZE_IN_BITS - 1) / 8 + 1]: Sized, { + let byte_size = (T::SIZE_IN_BITS - 1) / 8 + 1; let mut buffer = [0u8; (T::SIZE_IN_BITS - 1) / 8 + 1]; - let status = Status::from(unsafe { - self.api.base.NiFpgaDll_ReadArrayU8( - self.handle, - offset, - buffer.as_mut_ptr(), - (T::SIZE_IN_BITS - 1) / 8 + 1, - ) - }); - match status { - Status::Success => Ok(Datatype::unpack( - &FpgaBits::from_slice(&buffer) - [((T::SIZE_IN_BITS - 1) / 8 + 1) * 8 - T::SIZE_IN_BITS..], - )?), - _ => Err(Error::FPGA(status)), + let status = unsafe { + self.api + .base + .NiFpgaDll_ReadArrayU8(self.handle, offset, buffer.as_mut_ptr(), buffer.len()) + .into() + }; + if status != Status::Success { + return Err(Error::FPGA(status)); } + // Values larger then a single element (32 bit) are left justified, not right + let bit_slice = FpgaBitsRaw::from_slice_mut(&mut buffer); + let bit_slice = if byte_size <= 4 { + bit_slice.split_at_mut(byte_size * 8 - T::SIZE_IN_BITS).1 + } else { + bit_slice.split_at_mut(T::SIZE_IN_BITS).0 + }; + + Datatype::unpack(bit_slice) } pub fn write(&self, offset: Offset, data: &T) -> Result<(), Error> where [u8; (T::SIZE_IN_BITS - 1) / 8 + 1]: Sized, { + let byte_size = (T::SIZE_IN_BITS - 1) / 8 + 1; let mut buffer = [0u8; (T::SIZE_IN_BITS - 1) / 8 + 1]; - Datatype::pack( - &mut FpgaBits::from_slice_mut(&mut buffer) - [((T::SIZE_IN_BITS - 1) / 8 + 1) * 8 - T::SIZE_IN_BITS..], - data, - )?; - let status = Status::from(unsafe { - self.api.base.NiFpgaDll_WriteArrayU8( - self.handle, - offset, - buffer.as_ptr(), - (T::SIZE_IN_BITS - 1) / 8 + 1, - ) - }); + // Values larger then a single element (32 bit) are left justified, not right + let bit_slice = FpgaBitsRaw::from_slice_mut(&mut buffer); + let bit_slice = if byte_size <= 4 { + bit_slice.split_at_mut(byte_size * 8 - T::SIZE_IN_BITS).1 + } else { + bit_slice.split_at_mut(T::SIZE_IN_BITS).0 + }; + Datatype::pack(bit_slice, data)?; + let status = unsafe { + self.api + .base + .NiFpgaDll_WriteArrayU8( + self.handle, + offset, + buffer.as_ptr(), + (T::SIZE_IN_BITS - 1) / 8 + 1, + ) + .into() + }; match status { Status::Success => Ok(()), _ => Err(Error::FPGA(status)),