macro_rules! process_image {
(
$( #[$meta:meta] )*
$vis:vis struct $ProcessImage:ident, mut $ProcessImageMut:ident: $SIZE:literal {
$(
$( #[$field_meta:meta] )*
$field_vis:vis $field_name:ident: ($($tag:tt)+)
),*
$(,)?
}
) => { ... };
(
$( #[$meta:meta] )*
$vis:vis struct mut $ProcessImageMut:ident: $SIZE:literal {
$(
$( #[$field_meta:meta] )*
$field_vis:vis $field_name:ident: ($($tag:tt)+)
),*
$(,)?
}
) => { ... };
(
$( #[$meta:meta] )*
$vis:vis struct $ProcessImage:ident: $SIZE:literal {
$(
$( #[$field_meta:meta] )*
$field_vis:vis $field_name:ident: ($($tag:tt)+)
),*
$(,)?
}
) => { ... };
}Expand description
Build tag table for symbolic access into a process image buffer.
- You will get two structs, one for mutable and one for immutable access (or just one of them, if you want).
- The process image has a fixed size which is always enforced.
- The tag addresses are in the format described in the
tag!()macro. - The process image buffer is referenced, for owned buffers,
see
process_image_owned!{}.
ยงExample
process_image::process_image! {
// +-- Size of the process image in bytes
// V
pub struct PiExample, mut PiExampleMut: 16 {
// +-- Tag Name +-- Absolute Address
// V V
pub sensor_left: (X, 0, 0), // %MX0.0
pub sensor_right: (X, 0, 1), // %MX0.1
pub temperature: (D, 4), // %MD4
pub setpoint: (W, 2), // %MW2
}
}
let mut pi_buf = [0x00; 16];
let pi = PiExample::from(&pi_buf);
dbg!(pi.sensor_left());
dbg!(pi.sensor_left());
// You need to use try_from() when using a slice. The unwrap() will panic when the size of the
// slice does not match the size of the process image.
let pi_slice = &pi_buf[..];
let pi = PiExample::try_from(pi_slice).unwrap();
// Mutable access:
let pi_slice_mut = &mut pi_buf[..];
let mut pi = PiExampleMut::try_from(pi_slice_mut).unwrap();
*pi.temperature() = 1234;
*pi.setpoint() = 72;
*pi.sensor_left() = false;As mentioned above, you can also generate just the mutable or just the immutable version:
process_image::process_image! {
pub struct PiInputs: 16 {
pub sensor_left: (X, 0, 0), // %IX0.0
pub sensor_right: (X, 0, 1), // %IX0.1
pub temperature: (D, 12), // %ID12
}
}
process_image::process_image! {
pub struct mut PiOutputs: 8 {
pub indicator_green: (X, 1, 0), // %QX1.0
pub indicator_red: (X, 1, 2), // %QX1.2
pub setpoint: (W, 2), // %QW2
}
}
let inp = PiInputs::try_from(&buffer_in).unwrap();
let mut out = PiOutputs::try_from(&mut buffer_out).unwrap();
let left_or_right = inp.sensor_left() || inp.sensor_right();
*out.indicator_green() = !left_or_right;
*out.indicator_red() = left_or_right;