firewire_dice_protocols/tcelectronic/shell/
itwin.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2020 Takashi Sakamoto
3
4//! Protocol defined by TC Electronic for Impact Twin.
5//!
6//! The module includes structure, enumeration, and trait and its implementation for protocol
7//! defined by TC Electronic for Impact Twin.
8//!
9//! ## Diagram of internal signal flow
10//!
11//! ```text
12//!
13//!                              ++=========++
14//!                              ||         ||
15//! XLR input 1 ----or---------> ||         ||
16//! Phone input 1 --+            || channel ||
17//!                              ||  strip  || --> analog-intput-1/2
18//!                              || effects ||
19//! XLR input 2 ----or---------> ||   1/2   ||
20//! Phone input 2 --+            ||         ||
21//!                              ++=========++
22//! Phone input 3/4 -----------------------------> analog-input-3/4
23//! S/PDIF input 1/2 ----------------------------> coaxial-input-1/2
24//! ADAT input 1..8 or S/PDIF input 1/2 ---------> optical-input-1..8
25//!
26//!
27//! stream-input-1/2 ----------- (one of them) --> stream-source-1/2
28//! stream-input-3/4 -----------------+
29//! stream-input-5/6 -----------------+
30//! stream-input-7/8 -----------------+
31//! stream-input-9/10 ----------------+
32//! stream-input-11/12 ---------------+
33//! stream-input-13/14 ---------------+
34//!
35//!                              ++=========++
36//! analog-input-1/2 ----------> ||         ||
37//! analog-input-3/4 ----------> ||         ||
38//! coaxial-input-1/2 ---------> || 18 x 2  ||
39//! optical-input-1/2 ---------> ||         || --> reverb-effect-output-1/2
40//! optical-input-3/4 ---------> || reverb  ||
41//! optical-input-5/6 ---------> || effect  ||
42//! optical-input-7/8 ---------> ||         ||
43//! reverb-effect-output-1/2 --> ||         ||
44//! stream-source-1/2 ---------> ||         ||
45//!                              ++=========++
46//!
47//!                              ++=========++
48//! analog-input-1/2 ----------> ||         ||
49//! analog-input-3/4 ----------> ||         ||
50//! coaxial-input-1/2 ---------> || 18 x 2  ||
51//! optical-input-1/2 ---------> ||         || --> mixer-output-1/2
52//! optical-input-3/4 ---------> ||         ||
53//! optical-input-5/6 ---------> ||  mixer  ||
54//! optical-input-7/8 ---------> ||         ||
55//! reverb-effect-output-1/2 --> ||         ||
56//! stream-source-1/2 ---------> ||         ||
57//!                              ++=========++
58//!
59//!                              ++=========++
60//! analog-input-1/2 ----------> ||         ||
61//! analog-input-3/4 ----------> ||         ||
62//! coaxial-input-1/2 ---------> ||         ||
63//! optical-input-1/2 ---------> ||         ||
64//! optical-input-3/4 ---------> ||         || --> analog-output-1/2
65//! optical-input-5/6 ---------> ||         || --> analog-output-3/4
66//! optical-input-7/8 ---------> || 32 x 14 || --> coaxial-output-1/2
67//! stream-input-1/2 ----------> ||         || --> optical-output-1/2
68//! stream-input-3/4 ----------> || router  || --> optical-output-3/4
69//! stream-input-5/6 ----------> ||         || --> optical-output-5/6
70//! stream-input-7/8 ----------> ||         || --> optical-output-7/8
71//! stream-input-9/10 ---------> ||         ||
72//! stream-input-11/12 --------> ||         ||
73//! stream-input-13/14 --------> ||         ||
74//! mixer-output-1/2 ----------> ||         ||
75//! reverb-effect-source-1/2 --> ||         ||
76//!                              ++=========++
77//!
78//!
79//! ```
80
81use super::*;
82
83/// Protocol implementation of Impact Twin.
84#[derive(Default, Debug)]
85pub struct ItwinProtocol;
86
87impl TcatOperation for ItwinProtocol {}
88
89impl TcatGlobalSectionSpecification for ItwinProtocol {}
90
91/// Segment for knob. 0x0000..0x0027 (36 quads).
92pub type ItwinKnobSegment = TcKonnektSegment<ItwinKnob>;
93
94/// Segment for configuration. 0x0028..0x00cf (168 quads).
95pub type ItwinConfigSegment = TcKonnektSegment<ItwinConfig>;
96
97/// Segment for state of mixer. 0x00d0..0x0243 (93 quads).
98pub type ItwinMixerStateSegment = TcKonnektSegment<ItwinMixerState>;
99
100/// Segment for state of reverb effect. 0x0244..0x0287. (17 quads)
101pub type ItwinReverbStateSegment = TcKonnektSegment<ItwinReverbState>;
102
103/// Segment for states of channel strip effect. 0x028c..0x03ab (72 quads).
104pub type ItwinChStripStatesSegment = TcKonnektSegment<ItwinChStripStates>;
105
106// NOTE: Segment for tuner. 0x03ac..0x03c8 (8 quads).
107
108/// Segment for mixer meter. 0x106c..0x10c7 (23 quads).
109pub type ItwinMixerMeterSegment = TcKonnektSegment<ItwinMixerMeter>;
110
111/// Segment for state of hardware. 0x1008..0x1023 (7 quads).
112pub type ItwinHwStateSegment = TcKonnektSegment<ItwinHwState>;
113
114/// Segment for meter of reverb effect. 0x10c8..0x010df (6 quads).
115pub type ItwinReverbMeterSegment = TcKonnektSegment<ItwinReverbMeter>;
116
117/// Segment for meters of channel strip effect. 0x10e0..0x111b (15 quads).
118pub type ItwinChStripMetersSegment = TcKonnektSegment<ItwinChStripMeters>;
119
120macro_rules! segment_default {
121    ($p:ty, $t:ty) => {
122        impl Default for TcKonnektSegment<$t> {
123            fn default() -> Self {
124                Self {
125                    data: <$t>::default(),
126                    raw: vec![0; <$p as TcKonnektSegmentSerdes<$t>>::SIZE],
127                }
128            }
129        }
130    };
131}
132
133segment_default!(ItwinProtocol, ItwinKnob);
134segment_default!(ItwinProtocol, ItwinConfig);
135segment_default!(ItwinProtocol, ItwinMixerState);
136segment_default!(ItwinProtocol, ItwinReverbState);
137segment_default!(ItwinProtocol, ItwinChStripStates);
138segment_default!(ItwinProtocol, ItwinMixerMeter);
139segment_default!(ItwinProtocol, ItwinHwState);
140segment_default!(ItwinProtocol, ItwinReverbMeter);
141segment_default!(ItwinProtocol, ItwinChStripMeters);
142
143/// State of knob.
144#[derive(Debug, Copy, Clone, PartialEq, Eq)]
145pub struct ItwinKnob {
146    /// Target of 1st knob.
147    pub target: ShellKnob0Target,
148    /// Whether to recover sampling clock from any source jitter.
149    pub clock_recovery: bool,
150}
151
152impl Default for ItwinKnob {
153    fn default() -> Self {
154        Self {
155            target: <ItwinProtocol as ShellKnob0TargetSpecification>::KNOB0_TARGETS[0],
156            clock_recovery: Default::default(),
157        }
158    }
159}
160
161impl ShellKnob0TargetSpecification for ItwinProtocol {
162    const KNOB0_TARGETS: &'static [ShellKnob0Target] = &[
163        ShellKnob0Target::ChannelStrip0,
164        ShellKnob0Target::ChannelStrip1,
165        ShellKnob0Target::Reverb,
166        ShellKnob0Target::Mixer,
167    ];
168}
169
170impl TcKonnektSegmentSerdes<ItwinKnob> for ItwinProtocol {
171    const NAME: &'static str = "knob";
172    const OFFSET: usize = 0x0004;
173    const SIZE: usize = SHELL_KNOB_SEGMENT_SIZE;
174
175    fn serialize(params: &ItwinKnob, raw: &mut [u8]) -> Result<(), String> {
176        serialize_knob0_target::<ItwinProtocol>(&params.target, &mut raw[..4])?;
177        serialize_bool(&params.clock_recovery, &mut raw[8..12]);
178        Ok(())
179    }
180
181    fn deserialize(params: &mut ItwinKnob, raw: &[u8]) -> Result<(), String> {
182        deserialize_knob0_target::<ItwinProtocol>(&mut params.target, &raw[..4])?;
183        deserialize_bool(&mut params.clock_recovery, &raw[8..12]);
184        Ok(())
185    }
186}
187
188impl TcKonnektMutableSegmentOperation<ItwinKnob> for ItwinProtocol {}
189
190impl TcKonnektNotifiedSegmentOperation<ItwinKnob> for ItwinProtocol {
191    const NOTIFY_FLAG: u32 = SHELL_KNOB_NOTIFY_FLAG;
192}
193
194impl AsRef<ShellKnob0Target> for ItwinKnob {
195    fn as_ref(&self) -> &ShellKnob0Target {
196        &self.target
197    }
198}
199
200impl AsMut<ShellKnob0Target> for ItwinKnob {
201    fn as_mut(&mut self) -> &mut ShellKnob0Target {
202        &mut self.target
203    }
204}
205
206/// The number of pair for physical output.
207pub const ITWIN_PHYS_OUT_PAIR_COUNT: usize = 7;
208
209/// Source of stream for mixer.
210#[derive(Debug, Copy, Clone, PartialEq, Eq)]
211pub enum ItwinOutputPairSrc {
212    /// Mixer output 1/2.
213    MixerOut01,
214    /// Analog input 1/2.
215    Analog01,
216    /// Analog input 3/4.
217    Analog23,
218    /// S/PDIF input 1/2.
219    Spdif01,
220    /// ADAT input 1/2.
221    Adat01,
222    /// ADAT input 3/4.
223    Adat23,
224    /// ADAT input 5/6.
225    Adat45,
226    /// ADAT input 7/8.
227    Adat67,
228    /// Stream input 1/2.
229    Stream01,
230    /// Stream input 3/4.
231    Stream23,
232    /// Stream input 5/6.
233    Stream45,
234    /// Stream input 7/8.
235    Stream67,
236    /// Stream input 9/10.
237    Stream89,
238    /// Stream input 11/12.
239    Stream1011,
240    /// Stream input 13/14.
241    Stream1213,
242    /// Send source 1/2.
243    MixerSend01,
244}
245
246impl Default for ItwinOutputPairSrc {
247    fn default() -> Self {
248        Self::MixerOut01
249    }
250}
251
252const OUTPUT_PAIR_SOURCES: &[ItwinOutputPairSrc] = &[
253    ItwinOutputPairSrc::MixerOut01,
254    ItwinOutputPairSrc::Analog01,
255    ItwinOutputPairSrc::Analog23,
256    ItwinOutputPairSrc::Spdif01,
257    ItwinOutputPairSrc::Adat01,
258    ItwinOutputPairSrc::Adat23,
259    ItwinOutputPairSrc::Adat45,
260    ItwinOutputPairSrc::Adat67,
261    ItwinOutputPairSrc::Stream01,
262    ItwinOutputPairSrc::Stream23,
263    ItwinOutputPairSrc::Stream45,
264    ItwinOutputPairSrc::Stream67,
265    ItwinOutputPairSrc::Stream89,
266    ItwinOutputPairSrc::Stream1011,
267    ItwinOutputPairSrc::Stream1213,
268    ItwinOutputPairSrc::MixerSend01,
269];
270
271const OUTPUT_PAIR_SOURCE_LABEL: &str = "output pair source";
272
273fn serialize_output_pair_src(src: &ItwinOutputPairSrc, raw: &mut [u8]) -> Result<(), String> {
274    serialize_position(OUTPUT_PAIR_SOURCES, src, raw, OUTPUT_PAIR_SOURCE_LABEL)
275}
276
277fn deserialize_output_pair_src(src: &mut ItwinOutputPairSrc, raw: &[u8]) -> Result<(), String> {
278    deserialize_position(OUTPUT_PAIR_SOURCES, src, raw, OUTPUT_PAIR_SOURCE_LABEL)
279}
280
281/// Configuration.
282#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
283pub struct ItwinConfig {
284    /// Pair of stream source as mixer input.
285    pub mixer_stream_src_pair: ShellMixerStreamSourcePair,
286    /// Source of sampling clock at standalone mode.
287    pub standalone_src: ShellStandaloneClockSource,
288    /// Rate of sampling clock at standalone mode.
289    pub standalone_rate: TcKonnektStandaloneClockRate,
290    /// Pair of source for any type of physical output.
291    pub output_pair_src: [ItwinOutputPairSrc; ITWIN_PHYS_OUT_PAIR_COUNT],
292}
293
294impl ShellMixerStreamSourcePairSpecification for ItwinProtocol {
295    const MIXER_STREAM_SOURCE_PAIRS: &'static [ShellMixerStreamSourcePair] = &[
296        ShellMixerStreamSourcePair::Stream0_1,
297        ShellMixerStreamSourcePair::Stream2_3,
298        ShellMixerStreamSourcePair::Stream4_5,
299        ShellMixerStreamSourcePair::Stream6_7,
300        ShellMixerStreamSourcePair::Stream8_9,
301        ShellMixerStreamSourcePair::Stream10_11,
302        ShellMixerStreamSourcePair::Stream12_13,
303    ];
304}
305
306impl ShellStandaloneClockSpecification for ItwinProtocol {
307    const STANDALONE_CLOCK_SOURCES: &'static [ShellStandaloneClockSource] = &[
308        ShellStandaloneClockSource::Optical,
309        ShellStandaloneClockSource::Coaxial,
310        ShellStandaloneClockSource::Internal,
311    ];
312}
313
314impl TcKonnektSegmentSerdes<ItwinConfig> for ItwinProtocol {
315    const NAME: &'static str = "configuration";
316    const OFFSET: usize = 0x0028;
317    const SIZE: usize = 168;
318
319    fn serialize(params: &ItwinConfig, raw: &mut [u8]) -> Result<(), String> {
320        serialize_mixer_stream_source_pair::<ItwinProtocol>(
321            &params.mixer_stream_src_pair,
322            &mut raw[24..28],
323        )?;
324        serialize_standalone_clock_source::<ItwinProtocol>(
325            &params.standalone_src,
326            &mut raw[28..32],
327        )?;
328        serialize_standalone_clock_rate(&params.standalone_rate, &mut raw[32..36])?;
329        params
330            .output_pair_src
331            .iter()
332            .enumerate()
333            .try_for_each(|(i, src)| {
334                let pos = 120 + i * 4;
335                serialize_output_pair_src(src, &mut raw[pos..(pos + 4)])
336            })?;
337        Ok(())
338    }
339
340    fn deserialize(params: &mut ItwinConfig, raw: &[u8]) -> Result<(), String> {
341        deserialize_mixer_stream_source_pair::<ItwinProtocol>(
342            &mut params.mixer_stream_src_pair,
343            &raw[24..28],
344        )?;
345        deserialize_standalone_clock_source::<ItwinProtocol>(
346            &mut params.standalone_src,
347            &raw[28..32],
348        )?;
349        deserialize_standalone_clock_rate(&mut params.standalone_rate, &raw[32..36])?;
350        params
351            .output_pair_src
352            .iter_mut()
353            .enumerate()
354            .try_for_each(|(i, src)| {
355                let pos = 120 + i * 4;
356                deserialize_output_pair_src(src, &raw[pos..(pos + 4)])
357            })?;
358        Ok(())
359    }
360}
361
362impl TcKonnektMutableSegmentOperation<ItwinConfig> for ItwinProtocol {}
363
364impl TcKonnektNotifiedSegmentOperation<ItwinConfig> for ItwinProtocol {
365    const NOTIFY_FLAG: u32 = SHELL_CONFIG_NOTIFY_FLAG;
366}
367
368impl AsRef<ShellStandaloneClockSource> for ItwinConfig {
369    fn as_ref(&self) -> &ShellStandaloneClockSource {
370        &self.standalone_src
371    }
372}
373
374impl AsMut<ShellStandaloneClockSource> for ItwinConfig {
375    fn as_mut(&mut self) -> &mut ShellStandaloneClockSource {
376        &mut self.standalone_src
377    }
378}
379
380impl AsRef<TcKonnektStandaloneClockRate> for ItwinConfig {
381    fn as_ref(&self) -> &TcKonnektStandaloneClockRate {
382        &self.standalone_rate
383    }
384}
385
386impl AsMut<TcKonnektStandaloneClockRate> for ItwinConfig {
387    fn as_mut(&mut self) -> &mut TcKonnektStandaloneClockRate {
388        &mut self.standalone_rate
389    }
390}
391
392impl AsRef<ShellMixerStreamSourcePair> for ItwinConfig {
393    fn as_ref(&self) -> &ShellMixerStreamSourcePair {
394        &self.mixer_stream_src_pair
395    }
396}
397
398impl AsMut<ShellMixerStreamSourcePair> for ItwinConfig {
399    fn as_mut(&mut self) -> &mut ShellMixerStreamSourcePair {
400        &mut self.mixer_stream_src_pair
401    }
402}
403
404/// State of mixer.
405#[derive(Debug, Clone, PartialEq, Eq)]
406pub struct ItwinMixerState {
407    /// Configuration of internal mixer.
408    pub mixer: ShellMixerState,
409    /// The balance between analog and stream inputs to mix. 0..1000.
410    pub stream_mix_balance: u32,
411    /// Whether to enable mixer or not.
412    pub enabled: bool,
413}
414
415impl Default for ItwinMixerState {
416    fn default() -> Self {
417        ItwinMixerState {
418            mixer: ItwinProtocol::create_mixer_state(),
419            enabled: Default::default(),
420            stream_mix_balance: Default::default(),
421        }
422    }
423}
424
425impl ShellMixerStateSpecification for ItwinProtocol {
426    const MONITOR_SRC_MAP: [Option<ShellMixerMonitorSrcType>; SHELL_MIXER_MONITOR_SRC_COUNT] = [
427        Some(ShellMixerMonitorSrcType::Stream),
428        None,
429        None,
430        Some(ShellMixerMonitorSrcType::Spdif),
431        Some(ShellMixerMonitorSrcType::Analog),
432        Some(ShellMixerMonitorSrcType::Analog),
433        Some(ShellMixerMonitorSrcType::AdatSpdif),
434        Some(ShellMixerMonitorSrcType::Adat),
435        Some(ShellMixerMonitorSrcType::Adat),
436        Some(ShellMixerMonitorSrcType::Adat),
437    ];
438}
439
440impl TcKonnektSegmentSerdes<ItwinMixerState> for ItwinProtocol {
441    const NAME: &'static str = "mixer-state";
442    const OFFSET: usize = 0x00d0;
443    const SIZE: usize = ShellMixerState::SIZE + 56;
444
445    fn serialize(params: &ItwinMixerState, raw: &mut [u8]) -> Result<(), String> {
446        serialize_mixer_state::<ItwinProtocol>(&params.mixer, raw)?;
447
448        serialize_u32(&params.stream_mix_balance, &mut raw[348..352]);
449        serialize_bool(&params.enabled, &mut raw[352..356]);
450        Ok(())
451    }
452
453    fn deserialize(params: &mut ItwinMixerState, raw: &[u8]) -> Result<(), String> {
454        deserialize_mixer_state::<ItwinProtocol>(&mut params.mixer, raw)?;
455
456        deserialize_u32(&mut params.stream_mix_balance, &raw[348..352]);
457        deserialize_bool(&mut params.enabled, &raw[352..356]);
458        Ok(())
459    }
460}
461
462impl TcKonnektMutableSegmentOperation<ItwinMixerState> for ItwinProtocol {}
463
464impl TcKonnektNotifiedSegmentOperation<ItwinMixerState> for ItwinProtocol {
465    const NOTIFY_FLAG: u32 = SHELL_MIXER_NOTIFY_FLAG;
466}
467
468impl AsRef<ShellMixerState> for ItwinMixerState {
469    fn as_ref(&self) -> &ShellMixerState {
470        &self.mixer
471    }
472}
473
474impl AsMut<ShellMixerState> for ItwinMixerState {
475    fn as_mut(&mut self) -> &mut ShellMixerState {
476        &mut self.mixer
477    }
478}
479
480/// Configuration for reverb effect.
481#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
482pub struct ItwinReverbState(pub ReverbState);
483
484impl TcKonnektSegmentSerdes<ItwinReverbState> for ItwinProtocol {
485    const NAME: &'static str = "reverb-state";
486    const OFFSET: usize = 0x0244;
487    const SIZE: usize = ReverbState::SIZE;
488
489    fn serialize(params: &ItwinReverbState, raw: &mut [u8]) -> Result<(), String> {
490        serialize_reverb_state(&params.0, raw)
491    }
492
493    fn deserialize(params: &mut ItwinReverbState, raw: &[u8]) -> Result<(), String> {
494        deserialize_reverb_state(&mut params.0, raw)
495    }
496}
497
498impl TcKonnektMutableSegmentOperation<ItwinReverbState> for ItwinProtocol {}
499
500impl TcKonnektNotifiedSegmentOperation<ItwinReverbState> for ItwinProtocol {
501    const NOTIFY_FLAG: u32 = SHELL_REVERB_NOTIFY_FLAG;
502}
503
504impl AsRef<ReverbState> for ItwinReverbState {
505    fn as_ref(&self) -> &ReverbState {
506        &self.0
507    }
508}
509
510impl AsMut<ReverbState> for ItwinReverbState {
511    fn as_mut(&mut self) -> &mut ReverbState {
512        &mut self.0
513    }
514}
515
516/// Configuration for channel strip effect.
517#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
518pub struct ItwinChStripStates(pub [ChStripState; SHELL_CH_STRIP_COUNT]);
519
520impl TcKonnektSegmentSerdes<ItwinChStripStates> for ItwinProtocol {
521    const NAME: &'static str = "channel-strip-state";
522    const OFFSET: usize = 0x028c;
523    const SIZE: usize = ChStripState::SIZE * SHELL_CH_STRIP_COUNT + 4;
524
525    fn serialize(params: &ItwinChStripStates, raw: &mut [u8]) -> Result<(), String> {
526        serialize_ch_strip_states(&params.0, raw)
527    }
528
529    fn deserialize(params: &mut ItwinChStripStates, raw: &[u8]) -> Result<(), String> {
530        deserialize_ch_strip_states(&mut params.0, raw)
531    }
532}
533
534impl TcKonnektMutableSegmentOperation<ItwinChStripStates> for ItwinProtocol {}
535
536impl TcKonnektNotifiedSegmentOperation<ItwinChStripStates> for ItwinProtocol {
537    const NOTIFY_FLAG: u32 = SHELL_CH_STRIP_NOTIFY_FLAG;
538}
539
540impl AsRef<[ChStripState]> for ItwinChStripStates {
541    fn as_ref(&self) -> &[ChStripState] {
542        &self.0
543    }
544}
545
546impl AsMut<[ChStripState]> for ItwinChStripStates {
547    fn as_mut(&mut self) -> &mut [ChStripState] {
548        &mut self.0
549    }
550}
551
552/// The mode to listen for analog outputs.
553#[derive(Debug, Copy, Clone, PartialEq, Eq)]
554pub enum ListeningMode {
555    /// Monaural.
556    Monaural,
557    /// Stereo.
558    Stereo,
559    /// Side channels only.
560    Side,
561}
562
563impl Default for ListeningMode {
564    fn default() -> Self {
565        Self::Monaural
566    }
567}
568
569const LISTENING_MODES: &[ListeningMode] = &[
570    ListeningMode::Monaural,
571    ListeningMode::Stereo,
572    ListeningMode::Side,
573];
574
575const LISTENING_MODE_LABEL: &str = "listening mode";
576
577fn serialize_listening_mode(mode: &ListeningMode, raw: &mut [u8]) -> Result<(), String> {
578    serialize_position(LISTENING_MODES, mode, raw, LISTENING_MODE_LABEL)
579}
580
581fn deserialize_listening_mode(mode: &mut ListeningMode, raw: &[u8]) -> Result<(), String> {
582    deserialize_position(LISTENING_MODES, mode, raw, LISTENING_MODE_LABEL)
583}
584
585/// Hardware state.
586#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
587pub struct ItwinHwState {
588    /// State of hardware.
589    pub hw_state: ShellHwState,
590    /// Mode of listening.
591    pub listening_mode: ListeningMode,
592}
593
594impl TcKonnektSegmentSerdes<ItwinHwState> for ItwinProtocol {
595    const NAME: &'static str = "hardware-state";
596    const OFFSET: usize = 0x1008;
597    const SIZE: usize = ShellHwState::SIZE;
598
599    fn serialize(params: &ItwinHwState, raw: &mut [u8]) -> Result<(), String> {
600        serialize_hw_state(&params.hw_state, raw)?;
601        serialize_listening_mode(&params.listening_mode, &mut raw[8..12])?;
602        Ok(())
603    }
604
605    fn deserialize(params: &mut ItwinHwState, raw: &[u8]) -> Result<(), String> {
606        deserialize_hw_state(&mut params.hw_state, raw)?;
607        deserialize_listening_mode(&mut params.listening_mode, &raw[8..12])?;
608        Ok(())
609    }
610}
611
612impl TcKonnektMutableSegmentOperation<ItwinHwState> for ItwinProtocol {}
613
614impl TcKonnektNotifiedSegmentOperation<ItwinHwState> for ItwinProtocol {
615    const NOTIFY_FLAG: u32 = SHELL_HW_STATE_NOTIFY_FLAG;
616}
617
618impl AsRef<ShellHwState> for ItwinHwState {
619    fn as_ref(&self) -> &ShellHwState {
620        &self.hw_state
621    }
622}
623
624impl AsMut<ShellHwState> for ItwinHwState {
625    fn as_mut(&mut self) -> &mut ShellHwState {
626        &mut self.hw_state
627    }
628}
629
630impl AsRef<FireWireLedState> for ItwinHwState {
631    fn as_ref(&self) -> &FireWireLedState {
632        &self.hw_state.firewire_led
633    }
634}
635
636impl AsMut<FireWireLedState> for ItwinHwState {
637    fn as_mut(&mut self) -> &mut FireWireLedState {
638        &mut self.hw_state.firewire_led
639    }
640}
641
642/// Hardware metering for mixer function.
643#[derive(Debug, Clone, PartialEq, Eq)]
644pub struct ItwinMixerMeter(pub ShellMixerMeter);
645
646impl Default for ItwinMixerMeter {
647    fn default() -> Self {
648        ItwinMixerMeter(ItwinProtocol::create_meter_state())
649    }
650}
651
652impl ShellMixerMeterSpecification for ItwinProtocol {
653    const ANALOG_INPUT_COUNT: usize = 4;
654    const DIGITAL_INPUT_COUNT: usize = 8;
655}
656
657impl TcKonnektSegmentSerdes<ItwinMixerMeter> for ItwinProtocol {
658    const NAME: &'static str = "mixer-meter";
659    const OFFSET: usize = 0x106c;
660    const SIZE: usize = ShellMixerMeter::SIZE;
661
662    fn serialize(params: &ItwinMixerMeter, raw: &mut [u8]) -> Result<(), String> {
663        serialize_mixer_meter::<ItwinProtocol>(&params.0, raw)
664    }
665
666    fn deserialize(params: &mut ItwinMixerMeter, raw: &[u8]) -> Result<(), String> {
667        deserialize_mixer_meter::<ItwinProtocol>(&mut params.0, raw)
668    }
669}
670
671impl AsRef<ShellMixerMeter> for ItwinMixerMeter {
672    fn as_ref(&self) -> &ShellMixerMeter {
673        &self.0
674    }
675}
676
677impl AsMut<ShellMixerMeter> for ItwinMixerMeter {
678    fn as_mut(&mut self) -> &mut ShellMixerMeter {
679        &mut self.0
680    }
681}
682
683/// Hardware metering for reverb effect.
684#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
685pub struct ItwinReverbMeter(pub ReverbMeter);
686
687impl TcKonnektSegmentSerdes<ItwinReverbMeter> for ItwinProtocol {
688    const NAME: &'static str = "reverb-meter";
689    const OFFSET: usize = 0x10c8;
690    const SIZE: usize = ReverbMeter::SIZE;
691
692    fn serialize(params: &ItwinReverbMeter, raw: &mut [u8]) -> Result<(), String> {
693        serialize_reverb_meter(&params.0, raw)
694    }
695
696    fn deserialize(params: &mut ItwinReverbMeter, raw: &[u8]) -> Result<(), String> {
697        deserialize_reverb_meter(&mut params.0, raw)
698    }
699}
700
701impl AsRef<ReverbMeter> for ItwinReverbMeter {
702    fn as_ref(&self) -> &ReverbMeter {
703        &self.0
704    }
705}
706
707impl AsMut<ReverbMeter> for ItwinReverbMeter {
708    fn as_mut(&mut self) -> &mut ReverbMeter {
709        &mut self.0
710    }
711}
712
713/// Hardware metering for channel strip effect.
714#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
715pub struct ItwinChStripMeters(pub [ChStripMeter; SHELL_CH_STRIP_COUNT]);
716
717impl TcKonnektSegmentSerdes<ItwinChStripMeters> for ItwinProtocol {
718    const NAME: &'static str = "channel-strip-meter";
719    const OFFSET: usize = 0x10e0;
720    const SIZE: usize = ChStripMeter::SIZE * SHELL_CH_STRIP_COUNT + 4;
721
722    fn serialize(params: &ItwinChStripMeters, raw: &mut [u8]) -> Result<(), String> {
723        serialize_ch_strip_meters(&params.0, raw)
724    }
725
726    fn deserialize(params: &mut ItwinChStripMeters, raw: &[u8]) -> Result<(), String> {
727        deserialize_ch_strip_meters(&mut params.0, raw)
728    }
729}
730
731impl AsRef<[ChStripMeter]> for ItwinChStripMeters {
732    fn as_ref(&self) -> &[ChStripMeter] {
733        &self.0
734    }
735}
736
737impl AsMut<[ChStripMeter]> for ItwinChStripMeters {
738    fn as_mut(&mut self) -> &mut [ChStripMeter] {
739        &mut self.0
740    }
741}