From 7f5a3bfc39639e83fb64b988258ad48b9c9a9745 Mon Sep 17 00:00:00 2001 From: Daan Steenbergen Date: Fri, 6 Dec 2024 16:21:26 +0100 Subject: [PATCH] feat(vt): add more detailed attribute structs for auxiliary objects --- src/object_pool/object.rs | 16 +-- src/object_pool/object_attributes.rs | 152 +++++++++++++++++++++++++++ src/object_pool/reader.rs | 8 +- src/object_pool/vt_version.rs | 2 +- 4 files changed, 167 insertions(+), 11 deletions(-) diff --git a/src/object_pool/object.rs b/src/object_pool/object.rs index aebf65e..ab831d7 100644 --- a/src/object_pool/object.rs +++ b/src/object_pool/object.rs @@ -11,7 +11,9 @@ use crate::object_pool::object_attributes::{ use crate::object_pool::object_id::ObjectId; use crate::object_pool::{Colour, ObjectType}; -use super::object_attributes::{DataCodeType, FontSize, FontStyle, FontType, PictureGraphicFormat}; +use super::object_attributes::{ + DataCodeType, FontSize, FontStyle, FontType, FunctionAttributes, PictureGraphicFormat, +}; use super::object_id::NullableObjectId; #[derive(Debug, Clone, PartialEq)] @@ -352,7 +354,9 @@ impl Object { | Object::AuxiliaryInputType1(_) | Object::AuxiliaryFunctionType2(_) | Object::AuxiliaryInputType2(_) => (), // No references - Object::AuxiliaryControlDesignatorType2(o) => refs.push(o.auxiliary_object_id), + Object::AuxiliaryControlDesignatorType2(o) => { + push_nullable_id(&mut refs, &o.auxiliary_object_id) + } Object::WindowMask(o) => { push_nullable_id(&mut refs, &o.window_title); push_nullable_id(&mut refs, &o.window_icon); @@ -967,7 +971,7 @@ pub struct FillAttributes { #[derive(Debug, PartialEq, Clone)] pub struct InputAttributes { pub id: ObjectId, - pub validation_type: u8, + pub validation_type: ValidationType, pub validation_string: String, pub macro_refs: Vec, } @@ -1049,7 +1053,7 @@ pub struct AuxiliaryInputType1 { pub struct AuxiliaryFunctionType2 { pub id: ObjectId, pub background_colour: u8, - pub function_attributes: u8, + pub function_attributes: FunctionAttributes, pub object_refs: Vec, } @@ -1057,7 +1061,7 @@ pub struct AuxiliaryFunctionType2 { pub struct AuxiliaryInputType2 { pub id: ObjectId, pub background_colour: u8, - pub function_attributes: u8, + pub function_attributes: FunctionAttributes, pub object_refs: Vec, } @@ -1065,7 +1069,7 @@ pub struct AuxiliaryInputType2 { pub struct AuxiliaryControlDesignatorType2 { pub id: ObjectId, pub pointer_type: u8, - pub auxiliary_object_id: ObjectId, + pub auxiliary_object_id: NullableObjectId, } #[derive(Debug, PartialEq, Clone)] diff --git a/src/object_pool/object_attributes.rs b/src/object_pool/object_attributes.rs index d4326d6..8e830ea 100644 --- a/src/object_pool/object_attributes.rs +++ b/src/object_pool/object_attributes.rs @@ -1339,3 +1339,155 @@ impl From for u8 { bit_data.load::() } } + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum AuxiliaryFunctionType { + /// 0 = Boolean (Latching), two-position switch (maintains position) + /// On/Off with values 0,1 + BooleanLatching = 0, + + /// 1 = Analogue (maintains position setting) + /// Value 1: 0–100% of position, Value 2: FFFF16 = reserved + AnalogueMaintains = 1, + + /// 2 = Boolean (Non-Latching), two-position switch (return to off) + /// Momentary On/Off with values 0,1,2 (0=Off, 1=On, 2=Held) + BooleanNonLatching = 2, + + /// 3 = Analogue (return to 50%), two-way analogue return to center + /// 0% to 100%, centered at 50% + AnalogueReturnToCenter = 3, + + /// 4 = Analogue (return to 0%), one-way analogue return to zero + /// 0% to 100%, returning to 0% position + AnalogueReturnToZero = 4, + + /// 5 = Dual Boolean (Latching), three-position switch (latching) + /// Maintains position with values 0,1,4 + DualBooleanLatching = 5, + + /// 6 = Dual Boolean (Non-Latching), three-position switch returning to center + /// Values may include momentary and held states + DualBooleanNonLatching = 6, + + /// 7 = Dual Boolean (Latching Up, Momentary Down), three-position switch + /// Latching in one direction, momentary in the other + DualBooleanLatchingUp = 7, + + /// 8 = Dual Boolean (Latching Down, Momentary Up), three-position switch + /// Latching in one direction, momentary in the other + DualBooleanLatchingDown = 8, + + /// 9 = Combined Analogue (return to 50%) with Dual Boolean Latching at endpoints + /// Analogue axis returning to center with latchable endpoints + CombinedAnalogueReturnWithLatch = 9, + + /// 10 = Combined Analogue (maintains position) with Dual Boolean Latching at endpoints + /// Analogue axis maintains position with latchable endpoints + CombinedAnalogueMaintainsWithLatch = 10, + + /// 11 = Quadrature Boolean (Non-Latching) + /// Two axes of non-latching boolean states, represented as bit pairs + QuadratureBooleanNonLatching = 11, + + /// 12 = Quadrature Analogue (maintains position) + /// Two axes of analogue with full maintainable positions + QuadratureAnalogueMaintains = 12, + + /// 13 = Quadrature Analogue (return to 50%) + /// Two axes of analogue returning to center + QuadratureAnalogueReturnToCenter = 13, + + /// 14 = Bidirectional Encoder + /// Value increments/decrements as an encoder is turned + BidirectionalEncoder = 14, + + /// 15–30 = Reserved + Reserved(u8), + + /// 31 = Reserved for remove assignment command + RemoveAssignment = 31, +} + +impl From for AuxiliaryFunctionType { + fn from(value: u8) -> Self { + match value { + 0 => AuxiliaryFunctionType::BooleanLatching, + 1 => AuxiliaryFunctionType::AnalogueMaintains, + 2 => AuxiliaryFunctionType::BooleanNonLatching, + 3 => AuxiliaryFunctionType::AnalogueReturnToCenter, + 4 => AuxiliaryFunctionType::AnalogueReturnToZero, + 5 => AuxiliaryFunctionType::DualBooleanLatching, + 6 => AuxiliaryFunctionType::DualBooleanNonLatching, + 7 => AuxiliaryFunctionType::DualBooleanLatchingUp, + 8 => AuxiliaryFunctionType::DualBooleanLatchingDown, + 9 => AuxiliaryFunctionType::CombinedAnalogueReturnWithLatch, + 10 => AuxiliaryFunctionType::CombinedAnalogueMaintainsWithLatch, + 11 => AuxiliaryFunctionType::QuadratureBooleanNonLatching, + 12 => AuxiliaryFunctionType::QuadratureAnalogueMaintains, + 13 => AuxiliaryFunctionType::QuadratureAnalogueReturnToCenter, + 14 => AuxiliaryFunctionType::BidirectionalEncoder, + 31 => AuxiliaryFunctionType::RemoveAssignment, + v if v > 14 && v < 31 => AuxiliaryFunctionType::Reserved(v), + _ => panic!("Invalid function type"), + } + } +} + +impl From for u8 { + fn from(value: AuxiliaryFunctionType) -> Self { + match value { + AuxiliaryFunctionType::BooleanLatching => 0, + AuxiliaryFunctionType::AnalogueMaintains => 1, + AuxiliaryFunctionType::BooleanNonLatching => 2, + AuxiliaryFunctionType::AnalogueReturnToCenter => 3, + AuxiliaryFunctionType::AnalogueReturnToZero => 4, + AuxiliaryFunctionType::DualBooleanLatching => 5, + AuxiliaryFunctionType::DualBooleanNonLatching => 6, + AuxiliaryFunctionType::DualBooleanLatchingUp => 7, + AuxiliaryFunctionType::DualBooleanLatchingDown => 8, + AuxiliaryFunctionType::CombinedAnalogueReturnWithLatch => 9, + AuxiliaryFunctionType::CombinedAnalogueMaintainsWithLatch => 10, + AuxiliaryFunctionType::QuadratureBooleanNonLatching => 11, + AuxiliaryFunctionType::QuadratureAnalogueMaintains => 12, + AuxiliaryFunctionType::QuadratureAnalogueReturnToCenter => 13, + AuxiliaryFunctionType::BidirectionalEncoder => 14, + AuxiliaryFunctionType::RemoveAssignment => 31, + AuxiliaryFunctionType::Reserved(v) => v, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FunctionAttributes { + pub function_type: AuxiliaryFunctionType, // Bit 0-4 + pub critical: bool, // Bit 5 + pub restricted: bool, // Bit 6 for AuxiliaryFunctionType2, reserved for AuxiliaryInputType2 + pub single_assignment: bool, // Bit 7 +} + +impl From for FunctionAttributes { + fn from(value: u8) -> Self { + let mut bit_data = value.view_bits::().to_bitvec(); + FunctionAttributes { + function_type: bit_data[0..5].load::().into(), + critical: bit_data.pop().unwrap(), + restricted: bit_data.pop().unwrap(), + single_assignment: bit_data.pop().unwrap(), + } + } +} + +impl From for u8 { + fn from(value: FunctionAttributes) -> u8 { + let mut bit_data: BitVec = BitVec::new(); + let ft_val: u8 = value.function_type.into(); + let ft_bits = ft_val.view_bits::()[0..5].iter().copied(); + bit_data.extend(ft_bits); + bit_data.push(value.critical); + bit_data.push(value.restricted); + bit_data.push(value.single_assignment); + bit_data.load::() + } +} diff --git a/src/object_pool/reader.rs b/src/object_pool/reader.rs index 7878141..84feec5 100644 --- a/src/object_pool/reader.rs +++ b/src/object_pool/reader.rs @@ -918,7 +918,7 @@ impl Object { ) -> Result { let mut o = InputAttributes { id, - validation_type: Self::read_u8(data)?, + validation_type: Self::read_u8(data)?.into(), validation_string: Self::read_string(Self::read_u8(data)?.into(), data)?, macro_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -995,7 +995,7 @@ impl Object { let mut o = AuxiliaryFunctionType2 { id, background_colour: Self::read_u8(data)?.into(), - function_attributes: Self::read_u8(data)?, + function_attributes: Self::read_u8(data)?.into(), object_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -1012,7 +1012,7 @@ impl Object { let mut o = AuxiliaryInputType2 { id, background_colour: Self::read_u8(data)?.into(), - function_attributes: Self::read_u8(data)?, + function_attributes: Self::read_u8(data)?.into(), object_refs: Vec::with_capacity(Self::read_u8(data)?.into()), }; @@ -1029,7 +1029,7 @@ impl Object { let o = AuxiliaryControlDesignatorType2 { id, pointer_type: Self::read_u8(data)?, - auxiliary_object_id: Self::read_u16(data)?.try_into()?, + auxiliary_object_id: Self::read_u16(data)?.into(), }; Ok(Object::AuxiliaryControlDesignatorType2(o)) diff --git a/src/object_pool/vt_version.rs b/src/object_pool/vt_version.rs index cfc7d3e..1692d4a 100644 --- a/src/object_pool/vt_version.rs +++ b/src/object_pool/vt_version.rs @@ -1,7 +1,7 @@ use crate::object_pool::ParseError; use crate::object_pool::ParseError::UnsupportedVtVersion; -#[derive(Debug, Default, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] pub enum VtVersion { Version0, Version1,