autocore-std 3.3.40

Standard library for AutoCore control programs - shared memory, IPC, and logging utilities
Documentation
//! Borrowed view into GlobalMemory for one Beckhoff EL3356 strain-gauge terminal.
//!
//! Groups the set of GM variables that map to the EL3356's EtherCAT process
//! image into a single typed struct with lifetime-bound references. One
//! `El3356View` is built per-tick via the [`el3356_view!`] macro, then passed
//! to [`El3356::tick`](crate::fb::beckhoff::El3356::tick).
//!
//! # GM naming convention
//!
//! For a device with logical prefix `impact`, the control program's
//! `project.json` should define these linked variables:
//!
//! | GM variable            | Type   | Direction | Maps to            |
//! |------------------------|--------|-----------|--------------------|
//! | `impact_load`          | `f32`  | input     | scaled load value  |
//! | `impact_load_steady`   | `bool` | input     | steady-state flag  |
//! | `impact_load_error`    | `bool` | input     | general error bit  |
//! | `impact_load_overrange`| `bool` | input     | overrange bit      |
//! | `impact_tare`          | `bool` | output    | tare command bit   |
//!
//! Use the [`el3356_view!`] macro to construct the view at the start of each
//! control cycle — no hand-written borrowing is required.

/// Borrowed view into GlobalMemory for one EL3356 terminal.
///
/// Holds mutable references to output (RxPDO) fields and shared references
/// to input (TxPDO) fields. Construct via the [`el3356_view!`] macro.
pub struct El3356View<'a> {
    /// Tare command bit (output to device).
    pub tare: &'a mut bool,

    /// Current scaled load (input from device).
    pub load: &'a f32,
    /// Steady-state flag (input from device). `true` when the signal has
    /// been stable within the configured band for long enough.
    pub load_steady: &'a bool,
    /// General error flag (input from device).
    pub load_error: &'a bool,
    /// Overrange flag (input from device).
    pub load_overrange: &'a bool,
}

/// Create an [`El3356View`] by projecting GlobalMemory fields with a common prefix.
///
/// Fields must follow the naming convention `{prefix}_load`,
/// `{prefix}_load_steady`, `{prefix}_load_error`, `{prefix}_load_overrange`,
/// and `{prefix}_tare`. See the module docs for the full table.
///
/// # Example
///
/// ```ignore
/// let mut view = el3356_view!(ctx.gm, impact);
/// self.load_cell.tick(&mut view, ctx.client);
/// ```
#[macro_export]
macro_rules! el3356_view {
    ($gm:expr, $prefix:ident) => {
        paste::paste! {
            $crate::fb::beckhoff::El3356View {
                tare:           &mut $gm.[<$prefix _tare>],
                load:           & $gm.[<$prefix _load>],
                load_steady:    & $gm.[<$prefix _load_steady>],
                load_error:     & $gm.[<$prefix _load_error>],
                load_overrange: & $gm.[<$prefix _load_overrange>],
            }
        }
    };
}

#[cfg(test)]
mod tests {
    use super::*;

    /// Local storage for PDO fields used in tests. Avoids depending on
    /// auto-generated GlobalMemory field names.
    #[derive(Default)]
    pub(crate) struct TestPdo {
        pub tare: bool,
        pub load: f32,
        pub load_steady: bool,
        pub load_error: bool,
        pub load_overrange: bool,
    }

    impl TestPdo {
        pub(crate) fn view(&mut self) -> El3356View<'_> {
            El3356View {
                tare:           &mut self.tare,
                load:           &self.load,
                load_steady:    &self.load_steady,
                load_error:     &self.load_error,
                load_overrange: &self.load_overrange,
            }
        }
    }

    #[test]
    fn view_reads_inputs() {
        let mut pdo = TestPdo { load: 42.5, load_steady: true, ..Default::default() };
        let view = pdo.view();
        assert_eq!(*view.load, 42.5);
        assert!(*view.load_steady);
        assert!(!*view.load_error);
    }

    #[test]
    fn view_writes_tare() {
        let mut pdo = TestPdo::default();
        {
            let mut view = pdo.view();
            *view.tare = true;
        }
        assert!(pdo.tare);
    }
}