Skip to content

Commit

Permalink
Seperate Native Register Code
Browse files Browse the repository at this point in the history
 Move this to its own sub-module so we can seperate from cluster or fxp support.
  • Loading branch information
JamesMc86 committed Sep 25, 2023
1 parent a060ee0 commit 2ea8126
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 146 deletions.
11 changes: 2 additions & 9 deletions examples/host_example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
use ni_fpga_interface::{
registers::{Register, RegisterInterface},
session::Session,
};
use ni_fpga_interface::session::Session;
use std::path::Path;

extern "C" {
fn NiFpga_Initialize() -> i32;
}

mod fpga_defs {
include!(concat!(env!("OUT_DIR"), "/NiFpga_Main.rs"));
}

fn main() {
let bitfile = Path::new("../fpga_c_interface/NiFpga_Main.lvbitx");
let mut session = Session::new(
let session = Session::new(
bitfile.to_str().unwrap(),
fpga_defs::SIGNATURE,
"rio://192.168.10.17/RIO0",
Expand Down
2 changes: 1 addition & 1 deletion ni-fpga-interface/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Error support for the FPGA Interface.
pub type NiFpga_Status = i32;
pub type NiFpgaStatus = i32;

#[derive(Debug)]
pub enum FPGAError {
Expand Down
130 changes: 0 additions & 130 deletions ni-fpga-interface/src/registers.rs

This file was deleted.

80 changes: 80 additions & 0 deletions ni-fpga-interface/src/registers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//! Implements the register interfaces to the FPGA.
//!
mod native_types;
pub use native_types::*;

use crate::error::Result;

type RegisterAddress = u32;

/// Provides a binding to a register address including a type.
///
/// By generating these as part of an initialisation step - the registers can then be accessed safely at later steps knowing the address and types are matched.
pub struct Register<T> {
address: RegisterAddress,
phantom: std::marker::PhantomData<T>,
}

impl<T: Default + Copy> Register<T> {
pub const fn new(address: RegisterAddress) -> Self {
Self {
address,
phantom: std::marker::PhantomData,
}
}

pub fn read(&self, session: &impl RegisterInterface<T>) -> Result<T> {
session.read(self.address)
}

pub fn write(&self, session: &impl RegisterInterface<T>, value: T) -> Result<()> {
session.write(self.address, value)
}
}

pub struct ArrayRegister<T, const N: usize> {
address: RegisterAddress,
phantom_type: std::marker::PhantomData<T>,
}

impl<T: Default + Copy, const N: usize> ArrayRegister<T, N> {
pub const fn new(address: RegisterAddress) -> Self {
Self {
address,
phantom_type: std::marker::PhantomData,
}
}

pub fn read(&self, session: &impl RegisterInterface<T>) -> Result<[T; N]> {
session.read_array(self.address)
}

pub fn write(&self, session: &impl RegisterInterface<T>, value: &[T; N]) -> Result<()> {
session.write_array(self.address, value)
}
}

pub trait RegisterInterface<T: Default + Copy> {
fn read(&self, address: RegisterAddress) -> Result<T>;
fn write(&self, address: RegisterAddress, data: T) -> Result<()>;
fn read_array<const N: usize>(&self, address: RegisterAddress) -> Result<[T; N]> {
let mut array: [T; N] = [T::default(); N];
self.read_array_mut(address, &mut array)?;
Ok(array)
}
fn read_array_mut<const N: usize>(
&self,
address: RegisterAddress,
array: &mut [T; N],
) -> Result<()>;
fn write_array<const N: usize>(&self, address: RegisterAddress, data: &[T; N]) -> Result<()>;
}

/// Used to allow the implementation of clusters.
///
/// S is size in bytes of the type.
trait CustomRegisterType<const S: usize> {
fn from_buffer(buffer: &[u8; S]) -> Self;
fn to_buffer(&self, buffer: &mut [u8; S]);
}
59 changes: 59 additions & 0 deletions ni-fpga-interface/src/registers/native_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Code to support registers for the native numeric types.
use super::{RegisterAddress, RegisterInterface};
use crate::error::NiFpgaStatus;
use crate::error::{to_fpga_result, Result};
use crate::session::{Session, SessionHandle};
use libc::size_t;
use paste::paste;

#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct FpgaBool(u8);

/// First entry is the rust type, second is the text used for that type in the FPGA interface.
macro_rules! impl_register_interface {
($rust_type:ty, $fpga_type:literal) => {

extern "C" {
paste! { fn [<NiFpga_Read $fpga_type >](session: SessionHandle, offset: u32, value: *mut $rust_type) -> NiFpgaStatus; }
paste! { fn [<NiFpga_Write $fpga_type >](session: SessionHandle, offset: u32, value: $rust_type) -> NiFpgaStatus; }
paste! { fn [<NiFpga_ReadArray $fpga_type >](session: SessionHandle, offset: u32, value: *mut $rust_type, size: size_t) -> NiFpgaStatus; }
paste! { fn [<NiFpga_WriteArray $fpga_type >](session: SessionHandle, offset: u32, value: *const $rust_type, size: size_t) -> NiFpgaStatus; }
}

paste! {
impl RegisterInterface<$rust_type> for Session {
fn read(&self, address: RegisterAddress) -> Result<$rust_type> {
let mut value: $rust_type = $rust_type::default();
let return_code = unsafe {[< NiFpga_Read $fpga_type >](self.handle, address, &mut value)};
to_fpga_result(value, return_code)
}
fn write(&self, address: RegisterAddress, value: $rust_type) -> Result<()> {
let return_code = unsafe {[< NiFpga_Write $fpga_type >](self.handle, address, value)};
to_fpga_result((), return_code)
}
fn read_array_mut<const N:usize>(&self, address: RegisterAddress, array: &mut [$rust_type; N]) -> Result<()> {
let return_code = unsafe {[< NiFpga_ReadArray $fpga_type >](self.handle, address, array.as_mut_ptr(), N)};
to_fpga_result((), return_code)
}
fn write_array<const N:usize>(&self, address: RegisterAddress, value: &[$rust_type;N]) -> Result<()> {
let return_code = unsafe {[< NiFpga_WriteArray $fpga_type >](self.handle, address, value.as_ptr(), N)};
to_fpga_result((), return_code)
}
}
}
};
}

impl_register_interface!(u8, "U8");
impl_register_interface!(u16, "U16");
impl_register_interface!(u32, "U32");
impl_register_interface!(u64, "U64");
impl_register_interface!(i8, "I8");
impl_register_interface!(i16, "I16");
impl_register_interface!(i32, "I32");
impl_register_interface!(i64, "I64");
impl_register_interface!(f32, "Sgl");
impl_register_interface!(f64, "Dbl");
impl_register_interface!(FpgaBool, "Bool");
12 changes: 6 additions & 6 deletions ni-fpga-interface/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
use std::sync::Once;

use crate::error::{to_fpga_result, NiFpga_Status};
use crate::error::{to_fpga_result, NiFpgaStatus};

static LIB_INIT: Once = Once::new();

Expand All @@ -15,10 +15,10 @@ extern "C" {
resource: *const i8,
attribute: u32,
session: *mut SessionHandle,
) -> NiFpga_Status;
fn NiFpga_Reset(session: SessionHandle) -> NiFpga_Status;
fn NiFpga_Run(session: SessionHandle) -> NiFpga_Status;
fn NiFpga_Close(session: SessionHandle, attribute: u32) -> NiFpga_Status;
) -> NiFpgaStatus;
fn NiFpga_Reset(session: SessionHandle) -> NiFpgaStatus;
fn NiFpga_Run(session: SessionHandle) -> NiFpgaStatus;
fn NiFpga_Close(session: SessionHandle, attribute: u32) -> NiFpgaStatus;
}

pub type SessionHandle = u32;
Expand Down Expand Up @@ -69,7 +69,7 @@ impl Session {
pub fn close(self) -> Result<(), crate::error::FPGAError> {
let result = unsafe { NiFpga_Close(self.handle, 0) };

to_fpga_result((), 0)
to_fpga_result((), result)
}
}

Expand Down

0 comments on commit 2ea8126

Please sign in to comment.