firewire_fireworks_protocols/
phys_input.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Protocol about physical input.
5//!
6//! The module includes protocol about physical input defined by Echo Audio Digital Corporation for
7//! Fireworks board module.
8
9use super::*;
10
11const CATEGORY_PHYS_INPUT: u32 = 5;
12
13const CMD_SET_NOMINAL: u32 = 8;
14const CMD_GET_NOMINAL: u32 = 9;
15
16/// The parameters of physical inputs.
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct EfwPhysInputParameters {
19    /// The nominal signal level of physical input.
20    pub nominals: Vec<NominalSignalLevel>,
21}
22
23/// The specification of physical input.
24pub trait EfwPhysInputSpecification: EfwHardwareSpecification {
25    fn phys_analog_input_count() -> usize {
26        Self::PHYS_INPUT_GROUPS
27            .iter()
28            .filter(|(group_type, _)| PhysGroupType::Analog.eq(group_type))
29            .fold(0, |total, (_, count)| total + count)
30    }
31
32    fn create_phys_input_parameters() -> EfwPhysInputParameters {
33        EfwPhysInputParameters {
34            nominals: vec![Default::default(); Self::phys_analog_input_count()],
35        }
36    }
37}
38
39impl<O, P> EfwWhollyCachableParamsOperation<P, EfwPhysInputParameters> for O
40where
41    O: EfwPhysInputSpecification,
42    P: EfwProtocolExtManual,
43{
44    fn cache_wholly(
45        proto: &mut P,
46        states: &mut EfwPhysInputParameters,
47        timeout_ms: u32,
48    ) -> Result<(), Error> {
49        assert_eq!(states.nominals.len(), Self::phys_analog_input_count());
50
51        states
52            .nominals
53            .iter_mut()
54            .enumerate()
55            .try_for_each(|(ch, level)| {
56                let args = [ch as u32, 0];
57                let mut params = vec![0; 2];
58                proto
59                    .transaction(
60                        CATEGORY_PHYS_INPUT,
61                        CMD_GET_NOMINAL,
62                        &args,
63                        &mut params,
64                        timeout_ms,
65                    )
66                    .map(|_| deserialize_nominal_signal_level(level, params[1]))
67            })
68    }
69}
70
71impl<O, P> EfwPartiallyUpdatableParamsOperation<P, EfwPhysInputParameters> for O
72where
73    O: EfwPhysInputSpecification,
74    P: EfwProtocolExtManual,
75{
76    fn update_partially(
77        proto: &mut P,
78        states: &mut EfwPhysInputParameters,
79        updates: EfwPhysInputParameters,
80        timeout_ms: u32,
81    ) -> Result<(), Error> {
82        assert_eq!(states.nominals.len(), Self::phys_analog_input_count());
83        assert_eq!(updates.nominals.len(), Self::phys_analog_input_count());
84
85        states
86            .nominals
87            .iter_mut()
88            .zip(&updates.nominals)
89            .enumerate()
90            .filter(|(_, (o, n))| !o.eq(n))
91            .try_for_each(|(ch, (curr, level))| {
92                let args = [ch as u32, serialize_nominal_signal_level(level)];
93                proto
94                    .transaction(
95                        CATEGORY_PHYS_INPUT,
96                        CMD_SET_NOMINAL,
97                        &args,
98                        &mut vec![0; 2],
99                        timeout_ms,
100                    )
101                    .map(|_| *curr = *level)
102            })
103    }
104}