firewire_fireface_protocols/former/
ff800.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Protocol defined by RME GmbH for Fireface 800.
5
6use super::*;
7
8/// Unique protocol for Fireface 800.
9#[derive(Default, Debug)]
10pub struct Ff800Protocol;
11
12const MIXER_OFFSET: u64 = 0x000080080000;
13const OUTPUT_OFFSET: u64 = 0x000080081f80;
14const METER_OFFSET: u64 = 0x000080100000;
15const STATUS_OFFSET: u64 = 0x0000801c0000;
16const CFG_OFFSET: u64 = 0x0000fc88f014;
17
18// TODO: 4 quadlets are read at once.
19#[allow(dead_code)]
20const TCO_STATUS_OFFSET: usize = 0x0000801f0000;
21
22// TODO; 4 quadlets are written at once.
23#[allow(dead_code)]
24const TCO_CFG_OFFSET: usize = 0x0000810f0020;
25
26impl RmeFfFormerSpecification for Ff800Protocol {
27    const ANALOG_INPUT_COUNT: usize = 10;
28    const SPDIF_INPUT_COUNT: usize = 2;
29    const ADAT_INPUT_COUNT: usize = 16;
30    const STREAM_INPUT_COUNT: usize = 28;
31
32    const ANALOG_OUTPUT_COUNT: usize = 10;
33    const SPDIF_OUTPUT_COUNT: usize = 2;
34    const ADAT_OUTPUT_COUNT: usize = 16;
35}
36
37impl RmeFfFormerMeterSpecification for Ff800Protocol {
38    const METER_OFFSET: u64 = METER_OFFSET;
39}
40
41impl RmeFfWhollyUpdatableParamsOperation<FormerOutputVolumeState> for Ff800Protocol {
42    fn update_wholly(
43        req: &mut FwReq,
44        node: &mut FwNode,
45        params: &FormerOutputVolumeState,
46        timeout_ms: u32,
47    ) -> Result<(), Error> {
48        let mut raw = Self::serialize_offsets(params);
49        req.transaction_sync(
50            node,
51            FwTcode::WriteBlockRequest,
52            OUTPUT_OFFSET,
53            raw.len(),
54            &mut raw,
55            timeout_ms,
56        )
57    }
58}
59
60impl RmeFfPartiallyUpdatableParamsOperation<FormerOutputVolumeState> for Ff800Protocol {
61    fn update_partially(
62        req: &mut FwReq,
63        node: &mut FwNode,
64        params: &mut FormerOutputVolumeState,
65        update: FormerOutputVolumeState,
66        timeout_ms: u32,
67    ) -> Result<(), Error> {
68        let old = Self::serialize_offsets(params);
69        let mut new = Self::serialize_offsets(&update);
70
71        (0..(new.len() / 4))
72            .try_for_each(|i| {
73                let pos = i * 4;
74                if new[pos..(pos + 4)] != old[pos..(pos + 4)] {
75                    req.transaction_sync(
76                        node,
77                        FwTcode::WriteBlockRequest,
78                        OUTPUT_OFFSET + pos as u64,
79                        4,
80                        &mut new[pos..(pos + 4)],
81                        timeout_ms,
82                    )
83                } else {
84                    Ok(())
85                }
86            })
87            .map(|_| *params = update)
88    }
89}
90
91impl RmeFormerMixerSpecification for Ff800Protocol {
92    const MIXER_OFFSET: u64 = MIXER_OFFSET;
93    const AVAIL_COUNT: usize = 32;
94}
95
96/// Signal source of sampling clock.
97#[derive(Debug, Copy, Clone, PartialEq, Eq)]
98pub enum Ff800ClkSrc {
99    Internal,
100    WordClock,
101    AdatA,
102    AdatB,
103    Spdif,
104    Tco,
105}
106
107impl Default for Ff800ClkSrc {
108    fn default() -> Self {
109        Self::AdatA
110    }
111}
112
113// NOTE: for first quadlet of status quadlets.
114const Q0_SYNC_WORD_CLOCK_MASK: u32 = 0x40000000;
115const Q0_LOCK_WORD_CLOCK_MASK: u32 = 0x20000000;
116const Q0_EXT_CLK_RATE_MASK: u32 = 0x1e000000;
117const Q0_EXT_CLK_RATE_192000_FLAGS: u32 = 0x12000000;
118const Q0_EXT_CLK_RATE_176400_FLAGS: u32 = 0x10000000;
119const Q0_EXT_CLK_RATE_128000_FLAGS: u32 = 0x0c000000;
120const Q0_EXT_CLK_RATE_96000_FLAGS: u32 = 0x0e000000;
121const Q0_EXT_CLK_RATE_88200_FLAGS: u32 = 0x0a000000;
122const Q0_EXT_CLK_RATE_64000_FLAGS: u32 = 0x08000000;
123const Q0_EXT_CLK_RATE_48000_FLAGS: u32 = 0x06000000;
124const Q0_EXT_CLK_RATE_44100_FLAGS: u32 = 0x04000000;
125const Q0_EXT_CLK_RATE_32000_FLAGS: u32 = 0x02000000;
126const Q0_ACTIVE_CLK_SRC_MASK: u32 = 0x01c00000;
127const Q0_ACTIVE_CLK_SRC_INTERNAL_FLAGS: u32 = 0x01c00000;
128const Q0_ACTIVE_CLK_SRC_TCO_FLAGS: u32 = 0x01800000;
129const Q0_ACTIVE_CLK_SRC_WORD_CLK_FLAGS: u32 = 0x01000000;
130const Q0_ACTIVE_CLK_SRC_SPDIF_FLAGS: u32 = 0x00c00000;
131const Q0_ACTIVE_CLK_SRC_ADAT_B_FLAGS: u32 = 0x00400000;
132const Q0_ACTIVE_CLK_SRC_ADAT_A_FLAGS: u32 = 0x00000000;
133const Q0_SYNC_SPDIF_MASK: u32 = 0x00100000;
134const Q0_LOCK_SPDIF_MASK: u32 = 0x00040000;
135const Q0_SPDIF_RATE_MASK: u32 = 0x0003c000;
136const Q0_SPDIF_RATE_192000_FLAGS: u32 = 0x00024000;
137const Q0_SPDIF_RATE_176400_FLAGS: u32 = 0x00020000;
138const Q0_SPDIF_RATE_128000_FLAGS: u32 = 0x0001c000;
139const Q0_SPDIF_RATE_96000_FLAGS: u32 = 0x00018000;
140const Q0_SPDIF_RATE_88200_FLAGS: u32 = 0x00014000;
141const Q0_SPDIF_RATE_64000_FLAGS: u32 = 0x00010000;
142const Q0_SPDIF_RATE_48000_FLAGS: u32 = 0x0000c000;
143const Q0_SPDIF_RATE_44100_FLAGS: u32 = 0x00008000;
144const Q0_SPDIF_RATE_32000_FLAGS: u32 = 0x00004000;
145const Q0_LOCK_ADAT_B_MASK: u32 = 0x00002000;
146const Q0_LOCK_ADAT_A_MASK: u32 = 0x00001000;
147const Q0_SYNC_ADAT_B_MASK: u32 = 0x00000800;
148const Q0_SYNC_ADAT_A_MASK: u32 = 0x00000400;
149
150// NOTE: for second quadlet of status quadlets.
151const Q1_SYNC_TCO_MASK: u32 = 0x00800000;
152const Q1_LOCK_TCO_MASK: u32 = 0x00400000;
153const Q1_WORD_OUT_SINGLE_MASK: u32 = 0x00002000;
154const Q1_CONF_CLK_SRC_MASK: u32 = 0x00001c01;
155const Q1_CONF_CLK_SRC_TCO_FLAGS: u32 = 0x00001800;
156const Q1_CONF_CLK_SRC_WORD_CLK_FLAGS: u32 = 0x00001000;
157const Q1_CONF_CLK_SRC_SPDIF_FLAGS: u32 = 0x00000c00;
158const Q1_CONF_CLK_SRC_ADAT_B_FLAGS: u32 = 0x00000400;
159const Q1_CONF_CLK_SRC_INTERNAL_FLAGS: u32 = 0x00000001;
160const Q1_CONF_CLK_SRC_ADAT_A_FLAGS: u32 = 0x00000000;
161const Q1_SPDIF_IN_IFACE_MASK: u32 = 0x00000200;
162const Q1_OPT_OUT_SIGNAL_MASK: u32 = 0x00000100;
163const Q1_SPDIF_OUT_EMPHASIS_MASK: u32 = 0x00000040;
164const Q1_SPDIF_OUT_FMT_MASK: u32 = 0x00000020;
165const Q1_CONF_CLK_RATE_MASK: u32 = 0x0000001e;
166const Q1_CONF_CLK_RATE_192000_FLAGS: u32 = 0x00000016;
167const Q1_CONF_CLK_RATE_176400_FLAGS: u32 = 0x00000010;
168const Q1_CONF_CLK_RATE_128000_FLAGS: u32 = 0x00000012;
169const Q1_CONF_CLK_RATE_96000_FLAGS: u32 = 0x0000000e;
170const Q1_CONF_CLK_RATE_88200_FLAGS: u32 = 0x00000008;
171const Q1_CONF_CLK_RATE_64000_FLAGS: u32 = 0x0000000a;
172const Q1_CONF_CLK_RATE_48000_FLAGS: u32 = 0x00000006;
173const Q1_CONF_CLK_RATE_44100_FLAGS: u32 = 0x00000000;
174const Q1_CONF_CLK_RATE_32000_FLAGS: u32 = 0x00000002;
175
176/// Status of clock locking.
177#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
178pub struct Ff800ClkLockStatus {
179    pub adat_a: bool,
180    pub adat_b: bool,
181    pub spdif: bool,
182    pub word_clock: bool,
183    pub tco: bool,
184}
185
186impl Ff800ClkLockStatus {
187    const QUADLET_COUNT: usize = 2;
188}
189
190fn serialize_lock_status(status: &Ff800ClkLockStatus, quads: &mut [u32]) {
191    assert!(quads.len() >= Ff800ClkLockStatus::QUADLET_COUNT);
192
193    quads[0] &= !Q0_LOCK_ADAT_A_MASK;
194    if status.adat_a {
195        quads[0] |= Q0_LOCK_ADAT_A_MASK;
196    }
197
198    quads[0] &= !Q0_LOCK_ADAT_B_MASK;
199    if status.adat_b {
200        quads[0] |= Q0_LOCK_ADAT_B_MASK;
201    }
202
203    quads[0] &= !Q0_LOCK_SPDIF_MASK;
204    if status.spdif {
205        quads[0] |= Q0_LOCK_SPDIF_MASK;
206    }
207
208    quads[0] &= !Q0_LOCK_WORD_CLOCK_MASK;
209    if status.word_clock {
210        quads[0] |= Q0_LOCK_WORD_CLOCK_MASK;
211    }
212
213    quads[1] &= !Q1_LOCK_TCO_MASK;
214    if status.tco {
215        quads[1] |= Q1_LOCK_TCO_MASK;
216    }
217}
218
219fn deserialize_lock_status(status: &mut Ff800ClkLockStatus, quads: &[u32]) {
220    assert!(quads.len() >= Ff800ClkLockStatus::QUADLET_COUNT);
221
222    status.adat_a = quads[0] & Q0_LOCK_ADAT_A_MASK > 0;
223    status.adat_b = quads[0] & Q0_LOCK_ADAT_B_MASK > 0;
224    status.spdif = quads[0] & Q0_LOCK_SPDIF_MASK > 0;
225    status.word_clock = quads[0] & Q0_LOCK_WORD_CLOCK_MASK > 0;
226    status.tco = quads[1] & Q1_LOCK_TCO_MASK > 0;
227}
228
229/// Status of clock synchronization.
230#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
231pub struct Ff800ClkSyncStatus {
232    pub adat_a: bool,
233    pub adat_b: bool,
234    pub spdif: bool,
235    pub word_clock: bool,
236    pub tco: bool,
237}
238
239impl Ff800ClkSyncStatus {
240    const QUADLET_COUNT: usize = 2;
241}
242
243fn serialize_sync_status(status: &Ff800ClkSyncStatus, quads: &mut [u32]) {
244    assert!(quads.len() >= Ff800ClkSyncStatus::QUADLET_COUNT);
245
246    quads[0] &= !Q0_SYNC_ADAT_A_MASK;
247    if status.adat_a {
248        quads[0] |= Q0_SYNC_ADAT_A_MASK;
249    }
250
251    quads[0] &= !Q0_SYNC_ADAT_B_MASK;
252    if status.adat_b {
253        quads[0] |= Q0_SYNC_ADAT_B_MASK;
254    }
255
256    quads[0] &= !Q0_SYNC_SPDIF_MASK;
257    if status.spdif {
258        quads[0] |= Q0_SYNC_SPDIF_MASK;
259    }
260
261    quads[0] &= !Q0_SYNC_WORD_CLOCK_MASK;
262    if status.word_clock {
263        quads[0] |= Q0_SYNC_WORD_CLOCK_MASK;
264    }
265
266    quads[1] &= !Q1_SYNC_TCO_MASK;
267    if status.tco {
268        quads[1] |= Q1_SYNC_TCO_MASK;
269    }
270}
271
272fn deserialize_sync_status(status: &mut Ff800ClkSyncStatus, quads: &[u32]) {
273    assert!(quads.len() >= Ff800ClkSyncStatus::QUADLET_COUNT);
274
275    status.adat_a = quads[0] & Q0_SYNC_ADAT_A_MASK > 0;
276    status.adat_b = quads[0] & Q0_SYNC_ADAT_B_MASK > 0;
277    status.spdif = quads[0] & Q0_SYNC_SPDIF_MASK > 0;
278    status.word_clock = quads[0] & Q0_SYNC_WORD_CLOCK_MASK > 0;
279    status.tco = quads[1] & Q1_SYNC_TCO_MASK > 0;
280}
281
282/// Status of clock synchronization.
283#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
284pub struct Ff800Status {
285    /// For S/PDIF input.
286    pub spdif_in: SpdifInput,
287    /// For S/PDIF output.
288    pub spdif_out: FormerSpdifOutput,
289    /// The type of signal to optical output interface.
290    pub opt_out_signal: OpticalOutputSignal,
291    /// Whether to fix speed to single even if at double/quadruple rate.
292    pub word_out_single: bool,
293    /// For status of synchronization to external clocks.
294    pub sync: Ff800ClkSyncStatus,
295    /// For status of locking to external clocks.
296    pub lock: Ff800ClkLockStatus,
297
298    pub spdif_rate: Option<ClkNominalRate>,
299    pub active_clk_src: Ff800ClkSrc,
300    pub external_clk_rate: Option<ClkNominalRate>,
301    pub configured_clk_src: Ff800ClkSrc,
302    pub configured_clk_rate: ClkNominalRate,
303}
304
305impl Ff800Status {
306    const QUADLET_COUNT: usize = FORMER_STATUS_SIZE / 4;
307}
308
309impl RmeFfOffsetParamsSerialize<Ff800Status> for Ff800Protocol {
310    fn serialize_offsets(params: &Ff800Status) -> Vec<u8> {
311        let mut quads = [0; Ff800Status::QUADLET_COUNT];
312
313        serialize_lock_status(&params.lock, &mut quads);
314        serialize_sync_status(&params.sync, &mut quads);
315
316        quads[0] &= !Q0_SPDIF_RATE_MASK;
317        if let Some(rate) = &params.spdif_rate {
318            let flag = match rate {
319                ClkNominalRate::R32000 => Q0_SPDIF_RATE_32000_FLAGS,
320                ClkNominalRate::R44100 => Q0_SPDIF_RATE_44100_FLAGS,
321                ClkNominalRate::R48000 => Q0_SPDIF_RATE_48000_FLAGS,
322                ClkNominalRate::R64000 => Q0_SPDIF_RATE_64000_FLAGS,
323                ClkNominalRate::R88200 => Q0_SPDIF_RATE_88200_FLAGS,
324                ClkNominalRate::R96000 => Q0_SPDIF_RATE_96000_FLAGS,
325                ClkNominalRate::R128000 => Q0_SPDIF_RATE_128000_FLAGS,
326                ClkNominalRate::R176400 => Q0_SPDIF_RATE_176400_FLAGS,
327                ClkNominalRate::R192000 => Q0_SPDIF_RATE_192000_FLAGS,
328            };
329            quads[0] |= flag;
330        }
331
332        quads[0] &= !Q0_ACTIVE_CLK_SRC_MASK;
333        let flag = match &params.active_clk_src {
334            Ff800ClkSrc::AdatA => Q0_ACTIVE_CLK_SRC_ADAT_A_FLAGS,
335            Ff800ClkSrc::AdatB => Q0_ACTIVE_CLK_SRC_ADAT_B_FLAGS,
336            Ff800ClkSrc::Spdif => Q0_ACTIVE_CLK_SRC_SPDIF_FLAGS,
337            Ff800ClkSrc::WordClock => Q0_ACTIVE_CLK_SRC_WORD_CLK_FLAGS,
338            Ff800ClkSrc::Tco => Q0_ACTIVE_CLK_SRC_TCO_FLAGS,
339            Ff800ClkSrc::Internal => Q0_ACTIVE_CLK_SRC_INTERNAL_FLAGS,
340        };
341        quads[0] |= flag;
342
343        quads[0] &= !Q0_EXT_CLK_RATE_MASK;
344        if let Some(rate) = &params.external_clk_rate {
345            let flag = match rate {
346                ClkNominalRate::R32000 => Q0_EXT_CLK_RATE_32000_FLAGS,
347                ClkNominalRate::R44100 => Q0_EXT_CLK_RATE_44100_FLAGS,
348                ClkNominalRate::R48000 => Q0_EXT_CLK_RATE_48000_FLAGS,
349                ClkNominalRate::R64000 => Q0_EXT_CLK_RATE_64000_FLAGS,
350                ClkNominalRate::R88200 => Q0_EXT_CLK_RATE_88200_FLAGS,
351                ClkNominalRate::R96000 => Q0_EXT_CLK_RATE_96000_FLAGS,
352                ClkNominalRate::R128000 => Q0_EXT_CLK_RATE_128000_FLAGS,
353                ClkNominalRate::R176400 => Q0_EXT_CLK_RATE_176400_FLAGS,
354                ClkNominalRate::R192000 => Q0_EXT_CLK_RATE_192000_FLAGS,
355            };
356            quads[0] |= flag;
357        }
358
359        quads[1] &= !Q1_SPDIF_IN_IFACE_MASK;
360        if params.spdif_in.iface == SpdifIface::Optical {
361            quads[1] |= Q1_SPDIF_IN_IFACE_MASK;
362        }
363
364        quads[1] &= !Q1_SPDIF_OUT_FMT_MASK;
365        if params.spdif_out.format == SpdifFormat::Professional {
366            quads[1] |= Q1_SPDIF_OUT_FMT_MASK;
367        }
368
369        quads[1] &= !Q1_SPDIF_OUT_EMPHASIS_MASK;
370        if params.spdif_out.emphasis {
371            quads[1] |= Q1_SPDIF_OUT_EMPHASIS_MASK;
372        }
373
374        quads[1] &= !Q1_OPT_OUT_SIGNAL_MASK;
375        if params.opt_out_signal == OpticalOutputSignal::Spdif {
376            quads[1] |= Q1_OPT_OUT_SIGNAL_MASK;
377        }
378
379        quads[1] &= !Q1_WORD_OUT_SINGLE_MASK;
380        if params.word_out_single {
381            quads[1] |= Q1_WORD_OUT_SINGLE_MASK;
382        }
383
384        quads[1] &= !Q1_CONF_CLK_SRC_MASK;
385        let flag = match &params.configured_clk_src {
386            Ff800ClkSrc::Internal => Q1_CONF_CLK_SRC_INTERNAL_FLAGS,
387            Ff800ClkSrc::AdatB => Q1_CONF_CLK_SRC_ADAT_B_FLAGS,
388            Ff800ClkSrc::Spdif => Q1_CONF_CLK_SRC_SPDIF_FLAGS,
389            Ff800ClkSrc::WordClock => Q1_CONF_CLK_SRC_WORD_CLK_FLAGS,
390            Ff800ClkSrc::Tco => Q1_CONF_CLK_SRC_TCO_FLAGS,
391            Ff800ClkSrc::AdatA => Q1_CONF_CLK_SRC_ADAT_A_FLAGS,
392        };
393        quads[1] |= flag;
394
395        quads[1] &= !Q1_CONF_CLK_RATE_MASK;
396        let flag = match &params.configured_clk_rate {
397            ClkNominalRate::R32000 => Q1_CONF_CLK_RATE_32000_FLAGS,
398            ClkNominalRate::R44100 => Q1_CONF_CLK_RATE_44100_FLAGS,
399            ClkNominalRate::R48000 => Q1_CONF_CLK_RATE_48000_FLAGS,
400            ClkNominalRate::R64000 => Q1_CONF_CLK_RATE_64000_FLAGS,
401            ClkNominalRate::R88200 => Q1_CONF_CLK_RATE_88200_FLAGS,
402            ClkNominalRate::R96000 => Q1_CONF_CLK_RATE_96000_FLAGS,
403            ClkNominalRate::R128000 => Q1_CONF_CLK_RATE_128000_FLAGS,
404            ClkNominalRate::R176400 => Q1_CONF_CLK_RATE_176400_FLAGS,
405            ClkNominalRate::R192000 => Q1_CONF_CLK_RATE_192000_FLAGS,
406        };
407        quads[1] |= flag;
408
409        quads.iter().flat_map(|quad| quad.to_le_bytes()).collect()
410    }
411}
412
413impl RmeFfOffsetParamsDeserialize<Ff800Status> for Ff800Protocol {
414    fn deserialize_offsets(params: &mut Ff800Status, raw: &[u8]) {
415        assert!(raw.len() >= FORMER_STATUS_SIZE);
416
417        let mut quads = [0; Ff800Status::QUADLET_COUNT];
418        let mut quadlet = [0; 4];
419        quads.iter_mut().enumerate().for_each(|(i, quad)| {
420            let pos = i * 4;
421            quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
422            *quad = u32::from_le_bytes(quadlet);
423        });
424
425        deserialize_lock_status(&mut params.lock, &quads);
426        deserialize_sync_status(&mut params.sync, &quads);
427
428        params.spdif_rate = match quads[0] & Q0_SPDIF_RATE_MASK {
429            Q0_SPDIF_RATE_32000_FLAGS => Some(ClkNominalRate::R32000),
430            Q0_SPDIF_RATE_44100_FLAGS => Some(ClkNominalRate::R44100),
431            Q0_SPDIF_RATE_48000_FLAGS => Some(ClkNominalRate::R48000),
432            Q0_SPDIF_RATE_64000_FLAGS => Some(ClkNominalRate::R64000),
433            Q0_SPDIF_RATE_88200_FLAGS => Some(ClkNominalRate::R88200),
434            Q0_SPDIF_RATE_96000_FLAGS => Some(ClkNominalRate::R96000),
435            Q0_SPDIF_RATE_128000_FLAGS => Some(ClkNominalRate::R128000),
436            Q0_SPDIF_RATE_176400_FLAGS => Some(ClkNominalRate::R176400),
437            Q0_SPDIF_RATE_192000_FLAGS => Some(ClkNominalRate::R192000),
438            _ => None,
439        };
440
441        params.active_clk_src = match quads[0] & Q0_ACTIVE_CLK_SRC_MASK {
442            Q0_ACTIVE_CLK_SRC_ADAT_A_FLAGS => Ff800ClkSrc::AdatA,
443            Q0_ACTIVE_CLK_SRC_ADAT_B_FLAGS => Ff800ClkSrc::AdatB,
444            Q0_ACTIVE_CLK_SRC_SPDIF_FLAGS => Ff800ClkSrc::Spdif,
445            Q0_ACTIVE_CLK_SRC_WORD_CLK_FLAGS => Ff800ClkSrc::WordClock,
446            Q0_ACTIVE_CLK_SRC_TCO_FLAGS => Ff800ClkSrc::Tco,
447            Q0_ACTIVE_CLK_SRC_INTERNAL_FLAGS => Ff800ClkSrc::Internal,
448            _ => unreachable!(),
449        };
450
451        params.external_clk_rate = match quads[0] & Q0_EXT_CLK_RATE_MASK {
452            Q0_EXT_CLK_RATE_32000_FLAGS => Some(ClkNominalRate::R32000),
453            Q0_EXT_CLK_RATE_44100_FLAGS => Some(ClkNominalRate::R44100),
454            Q0_EXT_CLK_RATE_48000_FLAGS => Some(ClkNominalRate::R48000),
455            Q0_EXT_CLK_RATE_64000_FLAGS => Some(ClkNominalRate::R64000),
456            Q0_EXT_CLK_RATE_88200_FLAGS => Some(ClkNominalRate::R88200),
457            Q0_EXT_CLK_RATE_96000_FLAGS => Some(ClkNominalRate::R96000),
458            Q0_EXT_CLK_RATE_128000_FLAGS => Some(ClkNominalRate::R128000),
459            Q0_EXT_CLK_RATE_176400_FLAGS => Some(ClkNominalRate::R176400),
460            Q0_EXT_CLK_RATE_192000_FLAGS => Some(ClkNominalRate::R192000),
461            _ => None,
462        };
463
464        params.spdif_in.iface = if quads[1] & Q1_SPDIF_IN_IFACE_MASK > 0 {
465            SpdifIface::Optical
466        } else {
467            SpdifIface::Coaxial
468        };
469
470        params.spdif_out.format = if quads[1] & Q1_SPDIF_OUT_FMT_MASK > 0 {
471            SpdifFormat::Professional
472        } else {
473            SpdifFormat::Consumer
474        };
475
476        params.spdif_out.emphasis = quads[1] & Q1_SPDIF_OUT_EMPHASIS_MASK > 0;
477
478        params.opt_out_signal = if quads[1] & Q1_OPT_OUT_SIGNAL_MASK > 0 {
479            OpticalOutputSignal::Spdif
480        } else {
481            OpticalOutputSignal::Adat
482        };
483
484        params.word_out_single = quads[1] & Q1_WORD_OUT_SINGLE_MASK > 0;
485
486        params.configured_clk_src = match quads[1] & Q1_CONF_CLK_SRC_MASK {
487            Q1_CONF_CLK_SRC_INTERNAL_FLAGS => Ff800ClkSrc::Internal,
488            Q1_CONF_CLK_SRC_ADAT_B_FLAGS => Ff800ClkSrc::AdatB,
489            Q1_CONF_CLK_SRC_SPDIF_FLAGS => Ff800ClkSrc::Spdif,
490            Q1_CONF_CLK_SRC_WORD_CLK_FLAGS => Ff800ClkSrc::WordClock,
491            Q1_CONF_CLK_SRC_TCO_FLAGS => Ff800ClkSrc::Tco,
492            Q1_CONF_CLK_SRC_ADAT_A_FLAGS | _ => Ff800ClkSrc::AdatA,
493        };
494
495        params.configured_clk_rate = match quads[1] & Q1_CONF_CLK_RATE_MASK {
496            Q1_CONF_CLK_RATE_32000_FLAGS => ClkNominalRate::R32000,
497            Q1_CONF_CLK_RATE_48000_FLAGS => ClkNominalRate::R48000,
498            Q1_CONF_CLK_RATE_64000_FLAGS => ClkNominalRate::R64000,
499            Q1_CONF_CLK_RATE_88200_FLAGS => ClkNominalRate::R88200,
500            Q1_CONF_CLK_RATE_96000_FLAGS => ClkNominalRate::R96000,
501            Q1_CONF_CLK_RATE_128000_FLAGS => ClkNominalRate::R128000,
502            Q1_CONF_CLK_RATE_176400_FLAGS => ClkNominalRate::R176400,
503            Q1_CONF_CLK_RATE_192000_FLAGS => ClkNominalRate::R192000,
504            Q1_CONF_CLK_RATE_44100_FLAGS | _ => ClkNominalRate::R44100,
505        };
506    }
507}
508
509impl RmeFfCacheableParamsOperation<Ff800Status> for Ff800Protocol {
510    fn cache_wholly(
511        req: &mut FwReq,
512        node: &mut FwNode,
513        params: &mut Ff800Status,
514        timeout_ms: u32,
515    ) -> Result<(), Error> {
516        read_status::<Ff800Protocol, Ff800Status>(req, node, STATUS_OFFSET, params, timeout_ms)
517    }
518}
519
520// NOTE: for first quadlet of configuration quadlets.
521const Q0_LINE_OUT_LEVEL_MASK: u32 = 0x00001c00;
522const Q0_LINE_OUT_LEVEL_CON_FLAG: u32 = 0x00001000;
523const Q0_LINE_OUT_LEVEL_PRO_FLAG: u32 = 0x00000800;
524const Q0_LINE_OUT_LEVEL_HIGH_FLAG: u32 = 0x00000400;
525const Q0_INPUT_0_INST_DRIVE_MASK: u32 = 0x00000200;
526const Q0_INPUT_9_POWERING_MASK: u32 = 0x00000100;
527const Q0_INPUT_7_POWERING_MASK: u32 = 0x00000080;
528const Q0_LINE_IN_LEVEL_MASK: u32 = 0x00000038;
529const Q0_LINE_IN_LEVEL_PRO_FLAG: u32 = 0x00000010;
530const Q0_LINE_IN_LEVEL_CON_FLAG: u32 = 0x00000020;
531const Q0_LINE_IN_LEVEL_LOW_FLAG: u32 = 0x00000008;
532const Q0_INPUT_0_INST_SPKR_EMU_MASK: u32 = 0x00000004;
533const Q0_INPUT_8_POWERING_MASK: u32 = 0x00000002;
534const Q0_INPUT_6_POWERING_MASK: u32 = 0x00000001;
535
536// NOTE: for second quadlet of configuration quadlets.
537const Q1_INPUT_0_FRONT_JACK_MASK: u32 = 0x00000800;
538const Q1_INPUT_0_INST_DRIVE_MASK: u32 = 0x00000200;
539const Q1_INPUT_7_REAR_JACK_MASK: u32 = 0x00000100;
540const Q1_INPUT_7_FRONT_JACK_MASK: u32 = 0x00000080;
541const Q1_INPUT_6_REAR_JACK_MASK: u32 = 0x00000040;
542const Q1_INPUT_6_FRONT_JACK_MASK: u32 = 0x00000020;
543const Q1_LINE_OUT_LEVEL_MASK: u32 = 0x00000018;
544const Q1_LINE_OUT_LEVEL_PRO_FLAG: u32 = 0x00000018;
545const Q1_LINE_OUT_LEVEL_HIGH_FLAG: u32 = 0x00000010;
546const Q1_LINE_OUT_LEVEL_CON_FLAG: u32 = 0x00000008;
547const Q1_INPUT_0_REAR_JACK_MASK: u32 = 0x00000004;
548const Q1_LINE_IN_LEVEL_MASK: u32 = 0x00000003;
549const Q1_LINE_IN_LEVEL_CON_FLAG: u32 = 0x00000003;
550const Q1_LINE_IN_LEVEL_PRO_FLAG: u32 = 0x00000002;
551const Q1_LINE_IN_LEVEL_LOW_FLAG: u32 = 0x00000000;
552
553// NOTE: for third quadlet of configuration quadlets.
554const Q2_SPDIF_IN_USE_PREEMBLE: u32 = 0x40000000;
555const Q2_INPUT_0_INST_LIMITTER_MASK: u32 = 0x00010000;
556const Q2_WORD_OUT_SINGLE_SPEED_MASK: u32 = 0x00002000;
557const Q2_CLK_SRC_MASK: u32 = 0x00001c01;
558const Q2_CLK_SRC_TCO_FLAG: u32 = 0x00001c00;
559const Q2_CLK_SRC_WORD_CLK_FLAG: u32 = 0x00001400;
560const Q2_CLK_SRC_SPDIF_FLAG: u32 = 0x00000c00;
561const Q2_CLK_SRC_ADAT_B_FLAG: u32 = 0x00000400;
562const Q2_CLK_SRC_INTERNAL_FLAG: u32 = 0x00000001;
563const Q2_CLK_SRC_ADAT_A_FLAG: u32 = 0x00000000;
564const Q2_SPDIF_IN_IFACE_OPT_MASK: u32 = 0x00000200;
565const Q2_OPT_OUT_SIGNAL_MASK: u32 = 0x00000100;
566const Q2_SPDIF_OUT_NON_AUDIO_MASK: u32 = 0x00000080;
567const Q2_SPDIF_OUT_EMPHASIS_MASK: u32 = 0x00000040;
568const Q2_SPDIF_OUT_FMT_PRO_MASK: u32 = 0x00000020;
569const Q2_CLK_AVAIL_RATE_QUADRUPLE_MASK: u32 = 0x00000010;
570const Q2_CLK_AVAIL_RATE_DOUBLE_MASK: u32 = 0x00000008;
571const Q2_CLK_AVAIL_RATE_BASE_48000_MASK: u32 = 0x00000004;
572const Q2_CLK_AVAIL_RATE_BASE_44100_MASK: u32 = 0x00000002;
573const Q2_CONTINUE_AT_ERRORS: u32 = 0x80000000;
574
575/// Configurations of sampling clock.
576#[derive(Debug, Copy, Clone, PartialEq, Eq)]
577pub struct Ff800ClkConfig {
578    pub primary_src: Ff800ClkSrc,
579    avail_rate_44100: bool,
580    avail_rate_48000: bool,
581    avail_rate_double: bool,
582    avail_rate_quadruple: bool,
583}
584
585impl Default for Ff800ClkConfig {
586    fn default() -> Self {
587        Self {
588            primary_src: Ff800ClkSrc::default(),
589            avail_rate_44100: true,
590            avail_rate_48000: true,
591            avail_rate_double: true,
592            avail_rate_quadruple: true,
593        }
594    }
595}
596
597impl Ff800ClkConfig {
598    const QUADLET_COUNT: usize = 3;
599}
600
601fn serialize_clock_config(config: &Ff800ClkConfig, quads: &mut [u32]) {
602    assert!(quads.len() >= Ff800ClkConfig::QUADLET_COUNT);
603
604    quads[2] &= !Q2_CLK_SRC_MASK;
605    let flag = match config.primary_src {
606        Ff800ClkSrc::Internal => Q2_CLK_SRC_INTERNAL_FLAG,
607        Ff800ClkSrc::WordClock => Q2_CLK_SRC_WORD_CLK_FLAG,
608        Ff800ClkSrc::AdatA => Q2_CLK_SRC_ADAT_A_FLAG,
609        Ff800ClkSrc::AdatB => Q2_CLK_SRC_ADAT_B_FLAG,
610        Ff800ClkSrc::Spdif => Q2_CLK_SRC_SPDIF_FLAG,
611        Ff800ClkSrc::Tco => Q2_CLK_SRC_TCO_FLAG,
612    };
613    quads[2] |= flag;
614
615    quads[2] &= !Q2_CLK_AVAIL_RATE_BASE_44100_MASK;
616    if config.avail_rate_44100 {
617        quads[2] |= Q2_CLK_AVAIL_RATE_BASE_44100_MASK;
618    }
619
620    quads[2] &= !Q2_CLK_AVAIL_RATE_BASE_48000_MASK;
621    if config.avail_rate_48000 {
622        quads[2] |= Q2_CLK_AVAIL_RATE_BASE_48000_MASK;
623    }
624
625    quads[2] &= !Q2_CLK_AVAIL_RATE_DOUBLE_MASK;
626    if config.avail_rate_double {
627        quads[2] |= Q2_CLK_AVAIL_RATE_DOUBLE_MASK;
628    }
629
630    quads[2] &= !Q2_CLK_AVAIL_RATE_QUADRUPLE_MASK;
631    if config.avail_rate_quadruple {
632        quads[2] |= Q2_CLK_AVAIL_RATE_QUADRUPLE_MASK;
633    }
634}
635
636fn deserialize_clock_config(config: &mut Ff800ClkConfig, quads: &[u32]) {
637    assert!(quads.len() >= Ff800ClkConfig::QUADLET_COUNT);
638
639    config.primary_src = match quads[2] & Q2_CLK_SRC_MASK {
640        Q2_CLK_SRC_INTERNAL_FLAG => Ff800ClkSrc::Internal,
641        Q2_CLK_SRC_WORD_CLK_FLAG => Ff800ClkSrc::WordClock,
642        Q2_CLK_SRC_ADAT_B_FLAG => Ff800ClkSrc::AdatB,
643        Q2_CLK_SRC_SPDIF_FLAG => Ff800ClkSrc::Spdif,
644        Q2_CLK_SRC_TCO_FLAG => Ff800ClkSrc::Tco,
645        Q2_CLK_SRC_ADAT_A_FLAG | _ => Ff800ClkSrc::AdatA,
646    };
647
648    config.avail_rate_44100 = quads[2] & Q2_CLK_AVAIL_RATE_BASE_44100_MASK > 0;
649    config.avail_rate_48000 = quads[2] & Q2_CLK_AVAIL_RATE_BASE_48000_MASK > 0;
650    config.avail_rate_double = quads[2] & Q2_CLK_AVAIL_RATE_DOUBLE_MASK > 0;
651    config.avail_rate_quadruple = quads[2] & Q2_CLK_AVAIL_RATE_QUADRUPLE_MASK > 0;
652}
653
654/// Configurations for instrument.
655#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
656pub struct Ff800InstConfig {
657    /// Whether to add extra gain by 25 dB.
658    pub drive: bool,
659    /// Whether to soft limitter to reduce by -10 dB.
660    pub limitter: bool,
661    /// Whether to enable low pass and high pass filter.
662    pub speaker_emulation: bool,
663}
664
665impl Ff800InstConfig {
666    const QUADLET_COUNT: usize = 3;
667}
668
669fn serialize_instrument_config(config: &Ff800InstConfig, quads: &mut [u32]) {
670    assert!(quads.len() >= Ff800InstConfig::QUADLET_COUNT);
671
672    quads[0] &= !Q0_INPUT_0_INST_DRIVE_MASK;
673    quads[1] &= !Q1_INPUT_0_INST_DRIVE_MASK;
674    if config.drive {
675        quads[0] |= Q0_INPUT_0_INST_DRIVE_MASK;
676        quads[1] |= Q1_INPUT_0_INST_DRIVE_MASK;
677    }
678
679    quads[2] &= !Q2_INPUT_0_INST_LIMITTER_MASK;
680    if config.limitter {
681        quads[2] |= Q2_INPUT_0_INST_LIMITTER_MASK;
682    }
683
684    quads[0] &= !Q0_INPUT_0_INST_SPKR_EMU_MASK;
685    if config.speaker_emulation {
686        quads[0] |= Q0_INPUT_0_INST_SPKR_EMU_MASK;
687    }
688}
689
690fn deserialize_instrument_config(config: &mut Ff800InstConfig, quads: &[u32]) {
691    assert!(quads.len() >= Ff800InstConfig::QUADLET_COUNT);
692
693    config.drive =
694        quads[0] & Q0_INPUT_0_INST_DRIVE_MASK > 0 && quads[0] & Q1_INPUT_0_INST_DRIVE_MASK > 0;
695    config.limitter = quads[2] & Q2_INPUT_0_INST_LIMITTER_MASK > 0;
696    config.speaker_emulation = quads[0] & Q0_INPUT_0_INST_SPKR_EMU_MASK > 0;
697}
698
699/// Jack of analog inputs.
700#[derive(Debug, Copy, Clone, PartialEq, Eq)]
701pub enum Ff800AnalogInputJack {
702    Front,
703    Rear,
704    FrontRear,
705}
706
707impl Default for Ff800AnalogInputJack {
708    fn default() -> Self {
709        Self::Front
710    }
711}
712
713/// Configuration for analog inputs.
714#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
715pub struct Ff800AnalogInConfig {
716    /// Whether to use rear jack instead of front jack for input 1, 7, and 8.
717    pub jacks: [Ff800AnalogInputJack; 3],
718    /// The nominal level of audio signal for line input.
719    pub line_level: FormerLineInNominalLevel,
720    /// Whether to deliver +48 V powering for mic 7, 8, 9, 10.
721    pub phantom_powering: [bool; 4],
722    /// The configurations for instrument input.
723    pub inst: Ff800InstConfig,
724}
725
726impl Ff800AnalogInConfig {
727    const QUADLET_COUNT: usize = 2;
728}
729
730fn serialize_analog_input_config(config: &Ff800AnalogInConfig, quads: &mut [u32]) {
731    assert!(quads.len() >= Ff800AnalogInConfig::QUADLET_COUNT);
732
733    [
734        (Q1_INPUT_0_REAR_JACK_MASK, Q1_INPUT_0_FRONT_JACK_MASK),
735        (Q1_INPUT_6_REAR_JACK_MASK, Q1_INPUT_6_FRONT_JACK_MASK),
736        (Q1_INPUT_7_REAR_JACK_MASK, Q1_INPUT_7_FRONT_JACK_MASK),
737    ]
738    .iter()
739    .zip(&config.jacks)
740    .for_each(|(&(rear_mask, front_mask), &jack)| {
741        if jack != Ff800AnalogInputJack::Front {
742            quads[1] |= rear_mask;
743        }
744        if jack != Ff800AnalogInputJack::Rear {
745            quads[1] |= front_mask;
746        }
747    });
748
749    quads[0] &= !Q0_LINE_IN_LEVEL_MASK;
750    quads[1] &= !Q1_LINE_IN_LEVEL_MASK;
751    match config.line_level {
752        FormerLineInNominalLevel::Low => {
753            quads[0] |= Q0_LINE_IN_LEVEL_LOW_FLAG;
754            quads[1] |= Q1_LINE_IN_LEVEL_LOW_FLAG;
755        }
756        FormerLineInNominalLevel::Consumer => {
757            quads[0] |= Q0_LINE_IN_LEVEL_CON_FLAG;
758            quads[1] |= Q1_LINE_IN_LEVEL_CON_FLAG;
759        }
760        FormerLineInNominalLevel::Professional => {
761            quads[0] |= Q0_LINE_IN_LEVEL_PRO_FLAG;
762            quads[1] |= Q1_LINE_IN_LEVEL_PRO_FLAG;
763        }
764    }
765
766    if config.phantom_powering[0] {
767        quads[0] |= Q0_INPUT_6_POWERING_MASK;
768    }
769    if config.phantom_powering[1] {
770        quads[0] |= Q0_INPUT_7_POWERING_MASK;
771    }
772    if config.phantom_powering[2] {
773        quads[0] |= Q0_INPUT_8_POWERING_MASK;
774    }
775    if config.phantom_powering[3] {
776        quads[0] |= Q0_INPUT_9_POWERING_MASK;
777    }
778
779    serialize_instrument_config(&config.inst, quads);
780}
781
782fn deserialize_analog_input_config(config: &mut Ff800AnalogInConfig, quads: &[u32]) {
783    assert!(quads.len() >= Ff800AnalogInConfig::QUADLET_COUNT);
784
785    [
786        (Q1_INPUT_0_REAR_JACK_MASK, Q1_INPUT_0_FRONT_JACK_MASK),
787        (Q1_INPUT_6_REAR_JACK_MASK, Q1_INPUT_6_FRONT_JACK_MASK),
788        (Q1_INPUT_7_REAR_JACK_MASK, Q1_INPUT_7_FRONT_JACK_MASK),
789    ]
790    .iter()
791    .zip(&mut config.jacks)
792    .for_each(|(&(rear_mask, front_mask), jack)| {
793        *jack = match (quads[1] & rear_mask > 0, quads[1] & front_mask > 0) {
794            (true, true) => Ff800AnalogInputJack::FrontRear,
795            (true, false) => Ff800AnalogInputJack::Rear,
796            (false, true) => Ff800AnalogInputJack::Front,
797            _ => unreachable!(),
798        };
799    });
800
801    let pair = (
802        quads[0] & Q0_LINE_IN_LEVEL_MASK,
803        quads[1] & Q1_LINE_IN_LEVEL_MASK,
804    );
805    config.line_level = match pair {
806        (Q0_LINE_IN_LEVEL_LOW_FLAG, Q1_LINE_IN_LEVEL_LOW_FLAG) => FormerLineInNominalLevel::Low,
807        (Q0_LINE_IN_LEVEL_CON_FLAG, Q1_LINE_IN_LEVEL_CON_FLAG) => {
808            FormerLineInNominalLevel::Consumer
809        }
810        (Q0_LINE_IN_LEVEL_PRO_FLAG, Q1_LINE_IN_LEVEL_PRO_FLAG) => {
811            FormerLineInNominalLevel::Professional
812        }
813        _ => unreachable!(),
814    };
815
816    config.phantom_powering[0] = quads[0] & Q0_INPUT_6_POWERING_MASK > 0;
817    config.phantom_powering[1] = quads[0] & Q0_INPUT_7_POWERING_MASK > 0;
818    config.phantom_powering[2] = quads[0] & Q0_INPUT_8_POWERING_MASK > 0;
819    config.phantom_powering[3] = quads[0] & Q0_INPUT_9_POWERING_MASK > 0;
820
821    deserialize_instrument_config(&mut config.inst, quads);
822}
823
824/// Configurations for Fireface 800.
825#[derive(Debug, Copy, Clone, PartialEq, Eq)]
826pub struct Ff800Config {
827    /// For sampling clock.
828    pub clk: Ff800ClkConfig,
829    /// For analog inputs.
830    pub analog_in: Ff800AnalogInConfig,
831    /// The nominal level of audio signal for line output.
832    pub line_out_level: LineOutNominalLevel,
833    /// For S/PDIF input.
834    pub spdif_in: SpdifInput,
835    /// For S/PDIF output.
836    pub spdif_out: FormerSpdifOutput,
837    /// The type of signal to optical output interface.
838    pub opt_out_signal: OpticalOutputSignal,
839    /// Whether to fix speed to single even if at double/quadruple rate.
840    pub word_out_single: bool,
841    /// Whether to continue audio processing against any synchronization corruption.
842    continue_at_errors: bool,
843}
844
845impl Default for Ff800Config {
846    fn default() -> Self {
847        Self {
848            clk: Default::default(),
849            analog_in: Default::default(),
850            line_out_level: Default::default(),
851            spdif_in: Default::default(),
852            spdif_out: Default::default(),
853            opt_out_signal: Default::default(),
854            word_out_single: Default::default(),
855            continue_at_errors: true,
856        }
857    }
858}
859
860impl Ff800Config {
861    const QUADLET_COUNT: usize = FORMER_CONFIG_SIZE / 4;
862
863    /// Although the configuration registers are write-only, some of them are available in status
864    /// registers.
865    pub fn init(&mut self, status: &Ff800Status) {
866        self.clk.primary_src = status.configured_clk_src;
867        self.spdif_in = status.spdif_in;
868        self.spdif_out = status.spdif_out;
869        self.opt_out_signal = status.opt_out_signal;
870        self.word_out_single = status.word_out_single;
871    }
872}
873
874impl RmeFfOffsetParamsSerialize<Ff800Config> for Ff800Protocol {
875    fn serialize_offsets(params: &Ff800Config) -> Vec<u8> {
876        let mut quads = [0; Ff800Config::QUADLET_COUNT];
877
878        serialize_clock_config(&params.clk, &mut quads);
879        serialize_analog_input_config(&params.analog_in, &mut quads);
880
881        quads[0] &= !Q0_LINE_OUT_LEVEL_MASK;
882        quads[1] &= !Q1_LINE_OUT_LEVEL_MASK;
883        match params.line_out_level {
884            LineOutNominalLevel::High => {
885                quads[0] |= Q0_LINE_OUT_LEVEL_HIGH_FLAG;
886                quads[1] |= Q1_LINE_OUT_LEVEL_HIGH_FLAG;
887            }
888            LineOutNominalLevel::Consumer => {
889                quads[0] |= Q0_LINE_OUT_LEVEL_CON_FLAG;
890                quads[1] |= Q1_LINE_OUT_LEVEL_CON_FLAG;
891            }
892            LineOutNominalLevel::Professional => {
893                quads[0] |= Q0_LINE_OUT_LEVEL_PRO_FLAG;
894                quads[1] |= Q1_LINE_OUT_LEVEL_PRO_FLAG;
895            }
896        }
897
898        quads[2] &= !Q2_SPDIF_IN_IFACE_OPT_MASK;
899        if params.spdif_in.iface == SpdifIface::Optical {
900            quads[2] |= Q2_SPDIF_IN_IFACE_OPT_MASK;
901        }
902
903        quads[2] &= !Q2_SPDIF_IN_USE_PREEMBLE;
904        if params.spdif_in.use_preemble {
905            quads[2] |= Q2_SPDIF_IN_USE_PREEMBLE;
906        }
907
908        quads[2] &= !Q2_OPT_OUT_SIGNAL_MASK;
909        if params.opt_out_signal == OpticalOutputSignal::Spdif {
910            quads[2] |= Q2_OPT_OUT_SIGNAL_MASK;
911        }
912
913        quads[2] &= !Q2_SPDIF_OUT_FMT_PRO_MASK;
914        if params.spdif_out.format == SpdifFormat::Professional {
915            quads[2] |= Q2_SPDIF_OUT_FMT_PRO_MASK;
916        }
917
918        quads[2] &= !Q2_SPDIF_OUT_EMPHASIS_MASK;
919        if params.spdif_out.emphasis {
920            quads[2] |= Q2_SPDIF_OUT_EMPHASIS_MASK;
921        }
922
923        quads[2] &= !Q2_SPDIF_OUT_NON_AUDIO_MASK;
924        if params.spdif_out.non_audio {
925            quads[2] |= Q2_SPDIF_OUT_NON_AUDIO_MASK;
926        }
927
928        quads[2] &= !Q2_WORD_OUT_SINGLE_SPEED_MASK;
929        if params.word_out_single {
930            quads[2] |= Q2_WORD_OUT_SINGLE_SPEED_MASK;
931        }
932
933        quads[2] &= !Q2_CONTINUE_AT_ERRORS;
934        if params.continue_at_errors {
935            quads[2] |= Q2_CONTINUE_AT_ERRORS;
936        }
937
938        quads.iter().flat_map(|quad| quad.to_le_bytes()).collect()
939    }
940}
941
942impl RmeFfOffsetParamsDeserialize<Ff800Config> for Ff800Protocol {
943    fn deserialize_offsets(params: &mut Ff800Config, raw: &[u8]) {
944        let mut quads = [0; Ff800Config::QUADLET_COUNT];
945
946        let mut quadlet = [0; 4];
947        quads.iter_mut().enumerate().for_each(|(i, quad)| {
948            let pos = i * 4;
949            quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
950            *quad = u32::from_le_bytes(quadlet);
951        });
952
953        deserialize_clock_config(&mut params.clk, &quads);
954        deserialize_analog_input_config(&mut params.analog_in, &quads);
955
956        let pair = (
957            quads[0] & Q0_LINE_OUT_LEVEL_MASK,
958            quads[1] & Q1_LINE_OUT_LEVEL_MASK,
959        );
960        params.line_out_level = match pair {
961            (Q0_LINE_OUT_LEVEL_HIGH_FLAG, Q1_LINE_OUT_LEVEL_HIGH_FLAG) => LineOutNominalLevel::High,
962            (Q0_LINE_OUT_LEVEL_CON_FLAG, Q1_LINE_OUT_LEVEL_CON_FLAG) => {
963                LineOutNominalLevel::Consumer
964            }
965            (Q0_LINE_OUT_LEVEL_PRO_FLAG, Q1_LINE_OUT_LEVEL_PRO_FLAG) => {
966                LineOutNominalLevel::Professional
967            }
968            _ => unreachable!(),
969        };
970
971        params.spdif_in.iface = if quads[2] & Q2_SPDIF_IN_IFACE_OPT_MASK > 0 {
972            SpdifIface::Optical
973        } else {
974            SpdifIface::Coaxial
975        };
976        params.spdif_in.use_preemble = quads[2] & Q2_SPDIF_IN_USE_PREEMBLE > 0;
977
978        params.spdif_out.format = if quads[2] & Q2_SPDIF_OUT_FMT_PRO_MASK > 0 {
979            SpdifFormat::Professional
980        } else {
981            SpdifFormat::Consumer
982        };
983        params.spdif_out.emphasis = quads[2] & Q2_SPDIF_OUT_EMPHASIS_MASK > 0;
984        params.spdif_out.non_audio = quads[2] & Q2_SPDIF_OUT_NON_AUDIO_MASK > 0;
985
986        params.opt_out_signal = if quads[2] & Q2_OPT_OUT_SIGNAL_MASK > 0 {
987            OpticalOutputSignal::Spdif
988        } else {
989            OpticalOutputSignal::Adat
990        };
991
992        params.word_out_single = quads[2] & Q2_WORD_OUT_SINGLE_SPEED_MASK > 0;
993        params.continue_at_errors = quads[2] & Q2_CONTINUE_AT_ERRORS > 0;
994    }
995}
996
997impl RmeFfWhollyUpdatableParamsOperation<Ff800Config> for Ff800Protocol {
998    fn update_wholly(
999        req: &mut FwReq,
1000        node: &mut FwNode,
1001        params: &Ff800Config,
1002        timeout_ms: u32,
1003    ) -> Result<(), Error> {
1004        write_config::<Ff800Protocol, Ff800Config>(req, node, CFG_OFFSET, params, timeout_ms)
1005    }
1006}
1007
1008#[cfg(test)]
1009mod test {
1010    use super::*;
1011
1012    #[test]
1013    fn lock_status_serdes() {
1014        let orig = Ff800ClkLockStatus {
1015            adat_a: true,
1016            adat_b: true,
1017            spdif: true,
1018            word_clock: true,
1019            tco: true,
1020        };
1021        let mut quads = [0; Ff800ClkLockStatus::QUADLET_COUNT];
1022        serialize_lock_status(&orig, &mut quads);
1023        let mut target = Ff800ClkLockStatus::default();
1024        deserialize_lock_status(&mut target, &quads);
1025
1026        assert_eq!(target, orig);
1027    }
1028
1029    #[test]
1030    fn sync_status_serdes() {
1031        let orig = Ff800ClkSyncStatus {
1032            adat_a: true,
1033            adat_b: true,
1034            spdif: true,
1035            word_clock: true,
1036            tco: true,
1037        };
1038        let mut quads = [0; Ff800ClkSyncStatus::QUADLET_COUNT];
1039        serialize_sync_status(&orig, &mut quads);
1040        let mut target = Ff800ClkSyncStatus::default();
1041        deserialize_sync_status(&mut target, &quads);
1042
1043        assert_eq!(target, orig);
1044    }
1045
1046    fn quads_to_bytes(quads: &[u32]) -> Vec<u8> {
1047        quads.iter().flat_map(|quad| quad.to_le_bytes()).collect()
1048    }
1049
1050    #[test]
1051    fn status_serdes() {
1052        let mut status = Ff800Status::default();
1053
1054        let quads = [0x02001000, 0x00000000];
1055        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1056        assert_eq!(status.lock.adat_a, true);
1057
1058        let quads = [0x02002000, 0x00000000];
1059        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1060        assert_eq!(status.lock.adat_b, true);
1061
1062        let quads = [0x02040000, 0x00000000];
1063        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1064        assert_eq!(status.lock.spdif, true);
1065
1066        let quads = [0x22000000, 0x00000000];
1067        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1068        assert_eq!(status.lock.word_clock, true);
1069
1070        let quads = [0x02000400, 0x00000000];
1071        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1072        assert_eq!(status.sync.adat_a, true);
1073
1074        let quads = [0x02000800, 0x00000000];
1075        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1076        assert_eq!(status.sync.adat_b, true);
1077
1078        let quads = [0x02100800, 0x00000000];
1079        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1080        assert_eq!(status.sync.spdif, true);
1081
1082        let quads = [0x42000000, 0x00000000];
1083        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1084        assert_eq!(status.sync.word_clock, true);
1085
1086        let quads = [0x02000000, 0x00800000];
1087        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1088        assert_eq!(status.sync.tco, true);
1089
1090        let quads = [0x02004000, 0x00000000];
1091        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1092        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R32000));
1093
1094        let quads = [0x02008000, 0x00000000];
1095        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1096        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R44100));
1097
1098        let quads = [0x0200c000, 0x00000000];
1099        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1100        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R48000));
1101
1102        let quads = [0x02010000, 0x00000000];
1103        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1104        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R64000));
1105
1106        let quads = [0x02014000, 0x00000000];
1107        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1108        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R88200));
1109
1110        let quads = [0x02018000, 0x00000000];
1111        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1112        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R96000));
1113
1114        let quads = [0x0201c000, 0x00000000];
1115        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1116        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R128000));
1117
1118        let quads = [0x02020000, 0x00000000];
1119        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1120        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R176400));
1121
1122        let quads = [0x02024000, 0x00000000];
1123        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1124        assert_eq!(status.spdif_rate, Some(ClkNominalRate::R192000));
1125
1126        let quads = [0x02000000, 0x00000000];
1127        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1128        assert_eq!(status.active_clk_src, Ff800ClkSrc::AdatA);
1129
1130        let quads = [0x02400000, 0x00000000];
1131        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1132        assert_eq!(status.active_clk_src, Ff800ClkSrc::AdatB);
1133
1134        let quads = [0x02c00000, 0x00000000];
1135        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1136        assert_eq!(status.active_clk_src, Ff800ClkSrc::Spdif);
1137
1138        let quads = [0x03000000, 0x00000000];
1139        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1140        assert_eq!(status.active_clk_src, Ff800ClkSrc::WordClock);
1141
1142        let quads = [0x03800000, 0x00000000];
1143        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1144        assert_eq!(status.active_clk_src, Ff800ClkSrc::Tco);
1145
1146        let quads = [0x03c00000, 0x00000000];
1147        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1148        assert_eq!(status.active_clk_src, Ff800ClkSrc::Internal);
1149
1150        let quads = [0x02000000, 0x00000000];
1151        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1152        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R32000));
1153
1154        let quads = [0x04000000, 0x00000000];
1155        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1156        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R44100));
1157
1158        let quads = [0x06000000, 0x00000000];
1159        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1160        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R48000));
1161
1162        let quads = [0x08000000, 0x00000000];
1163        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1164        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R64000));
1165
1166        let quads = [0x0a000000, 0x00000000];
1167        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1168        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R88200));
1169
1170        let quads = [0x0e000000, 0x00000000];
1171        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1172        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R96000));
1173
1174        let quads = [0x0c000000, 0x00000000];
1175        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1176        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R128000));
1177
1178        let quads = [0x10000000, 0x00000000];
1179        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1180        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R176400));
1181
1182        let quads = [0x12000000, 0x00000000];
1183        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1184        assert_eq!(status.external_clk_rate, Some(ClkNominalRate::R192000));
1185
1186        let quads = [0x02000000, 0x00400000];
1187        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1188        assert_eq!(status.lock.tco, true);
1189
1190        let quads = [0x02000000, 0x00800000];
1191        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1192        assert_eq!(status.sync.tco, true);
1193
1194        let quads = [0x02000000, 0x00002000];
1195        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1196        assert_eq!(status.word_out_single, true);
1197
1198        let quads = [0x02000000, 0x00000200];
1199        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1200        assert_eq!(status.spdif_in.iface, SpdifIface::Optical);
1201
1202        let quads = [0x02000000, 0x00000100];
1203        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1204        assert_eq!(status.opt_out_signal, OpticalOutputSignal::Spdif);
1205
1206        let quads = [0x02000000, 0x00000040];
1207        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1208        assert_eq!(status.spdif_out.emphasis, true);
1209
1210        let quads = [0x02000000, 0x00000020];
1211        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1212        assert_eq!(status.spdif_out.format, SpdifFormat::Professional);
1213
1214        let quads = [0x02000000, 0x00000002];
1215        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1216        assert_eq!(status.configured_clk_rate, ClkNominalRate::R32000);
1217
1218        let quads = [0x02000000, 0x00000000];
1219        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1220        assert_eq!(status.configured_clk_rate, ClkNominalRate::R44100);
1221
1222        let quads = [0x02000000, 0x00000006];
1223        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1224        assert_eq!(status.configured_clk_rate, ClkNominalRate::R48000);
1225
1226        let quads = [0x02000000, 0x0000000a];
1227        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1228        assert_eq!(status.configured_clk_rate, ClkNominalRate::R64000);
1229
1230        let quads = [0x02000000, 0x00000008];
1231        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1232        assert_eq!(status.configured_clk_rate, ClkNominalRate::R88200);
1233
1234        let quads = [0x02000000, 0x0000000e];
1235        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1236        assert_eq!(status.configured_clk_rate, ClkNominalRate::R96000);
1237
1238        let quads = [0x02000000, 0x00000012];
1239        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1240        assert_eq!(status.configured_clk_rate, ClkNominalRate::R128000);
1241
1242        let quads = [0x02000000, 0x00000010];
1243        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1244        assert_eq!(status.configured_clk_rate, ClkNominalRate::R176400);
1245
1246        let quads = [0x02000000, 0x00000016];
1247        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1248        assert_eq!(status.configured_clk_rate, ClkNominalRate::R192000);
1249
1250        let quads = [0x02000000, 0x00001000];
1251        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1252        assert_eq!(status.configured_clk_src, Ff800ClkSrc::WordClock);
1253
1254        let quads = [0x02000000, 0x00001800];
1255        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1256        assert_eq!(status.configured_clk_src, Ff800ClkSrc::Tco);
1257
1258        let quads = [0x02000000, 0x00000c00];
1259        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1260        assert_eq!(status.configured_clk_src, Ff800ClkSrc::Spdif);
1261
1262        let quads = [0x02000000, 0x00000400];
1263        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1264        assert_eq!(status.configured_clk_src, Ff800ClkSrc::AdatB);
1265
1266        let quads = [0x02000000, 0x00000001];
1267        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1268        assert_eq!(status.configured_clk_src, Ff800ClkSrc::Internal);
1269
1270        let quads = [0x02000000, 0x00000000];
1271        Ff800Protocol::deserialize_offsets(&mut status, &quads_to_bytes(&quads));
1272        assert_eq!(status.configured_clk_src, Ff800ClkSrc::AdatA);
1273
1274        let raw = Ff800Protocol::serialize_offsets(&status);
1275        let mut target = Ff800Status::default();
1276        Ff800Protocol::deserialize_offsets(&mut target, &raw);
1277        assert_eq!(target, status);
1278    }
1279
1280    #[test]
1281    fn clock_config_serdes() {
1282        let mut orig = Ff800ClkConfig::default();
1283        let mut cfg = Ff800ClkConfig::default();
1284
1285        orig.primary_src = Ff800ClkSrc::Internal;
1286        let mut quads = [0u32; 3];
1287        serialize_clock_config(&orig, &mut quads);
1288        assert_eq!(quads[2], 0x0000001f);
1289        deserialize_clock_config(&mut cfg, &quads);
1290        assert_eq!(cfg, orig);
1291
1292        orig.primary_src = Ff800ClkSrc::WordClock;
1293        let mut quads = [0u32; 3];
1294        serialize_clock_config(&orig, &mut quads);
1295        assert_eq!(quads[2], 0x0000141e);
1296        deserialize_clock_config(&mut cfg, &quads);
1297        assert_eq!(cfg, orig);
1298
1299        orig.primary_src = Ff800ClkSrc::AdatA;
1300        let mut quads = [0u32; 3];
1301        serialize_clock_config(&orig, &mut quads);
1302        assert_eq!(quads[2], 0x0000001e);
1303        deserialize_clock_config(&mut cfg, &quads);
1304        assert_eq!(cfg, orig);
1305
1306        orig.primary_src = Ff800ClkSrc::AdatB;
1307        let mut quads = [0u32; 3];
1308        serialize_clock_config(&orig, &mut quads);
1309        assert_eq!(quads[2], 0x0000041e);
1310        deserialize_clock_config(&mut cfg, &quads);
1311        assert_eq!(cfg, orig);
1312
1313        orig.primary_src = Ff800ClkSrc::Spdif;
1314        let mut quads = [0u32; 3];
1315        serialize_clock_config(&orig, &mut quads);
1316        assert_eq!(quads[2], 0x00000c1e);
1317        deserialize_clock_config(&mut cfg, &quads);
1318        assert_eq!(cfg, orig);
1319
1320        orig.primary_src = Ff800ClkSrc::Tco;
1321        let mut quads = [0u32; 3];
1322        serialize_clock_config(&orig, &mut quads);
1323        assert_eq!(quads[2], 0x00001c1e);
1324        deserialize_clock_config(&mut cfg, &quads);
1325        assert_eq!(cfg, orig);
1326    }
1327
1328    #[test]
1329    fn instrument_config_serdes() {
1330        let mut orig = Ff800InstConfig::default();
1331        let mut cfg = Ff800InstConfig::default();
1332
1333        orig.drive = false;
1334        orig.limitter = false;
1335        orig.speaker_emulation = false;
1336        let mut quads = [0u32; 3];
1337        serialize_instrument_config(&orig, &mut quads);
1338        assert_eq!(&quads[..], &[0x00000000, 0x00000000, 0x00000000]);
1339        deserialize_instrument_config(&mut cfg, &quads);
1340        assert_eq!(cfg, orig);
1341
1342        orig.drive = true;
1343        let mut quads = [0u32; 3];
1344        serialize_instrument_config(&orig, &mut quads);
1345        assert_eq!(&quads[..], &[0x00000200, 0x00000200, 0x00000000]);
1346        deserialize_instrument_config(&mut cfg, &quads);
1347        assert_eq!(cfg, orig);
1348
1349        orig.limitter = true;
1350        let mut quads = [0u32; 3];
1351        serialize_instrument_config(&orig, &mut quads);
1352        assert_eq!(&quads[..], &[0x00000200, 0x00000200, 0x00010000]);
1353        deserialize_instrument_config(&mut cfg, &quads);
1354        assert_eq!(cfg, orig);
1355
1356        orig.speaker_emulation = true;
1357        let mut quads = [0u32; 3];
1358        serialize_instrument_config(&orig, &mut quads);
1359        assert_eq!(&quads[..], &[0x00000204, 0x00000200, 0x00010000]);
1360        deserialize_instrument_config(&mut cfg, &quads);
1361        assert_eq!(cfg, orig);
1362    }
1363
1364    #[test]
1365    fn analog_input_config_serdes() {
1366        let mut orig = Ff800AnalogInConfig::default();
1367        let mut cfg = Ff800AnalogInConfig::default();
1368
1369        orig.jacks[0] = Ff800AnalogInputJack::FrontRear;
1370        let mut quads = [0u32; 3];
1371        serialize_analog_input_config(&orig, &mut quads);
1372        assert_eq!(&quads[..], &[0x00000008, 0x000008a4, 0x00000000]);
1373        deserialize_analog_input_config(&mut cfg, &quads);
1374        assert_eq!(cfg, orig);
1375
1376        orig.jacks[1] = Ff800AnalogInputJack::FrontRear;
1377        let mut quads = [0u32; 3];
1378        serialize_analog_input_config(&orig, &mut quads);
1379        assert_eq!(&quads[..], &[0x00000008, 0x000008e4, 0x00000000]);
1380        deserialize_analog_input_config(&mut cfg, &quads);
1381        assert_eq!(cfg, orig);
1382
1383        orig.jacks[2] = Ff800AnalogInputJack::FrontRear;
1384        let mut quads = [0u32; 3];
1385        serialize_analog_input_config(&orig, &mut quads);
1386        assert_eq!(&quads[..], &[0x00000008, 0x000009e4, 0x00000000]);
1387        deserialize_analog_input_config(&mut cfg, &quads);
1388        assert_eq!(cfg, orig);
1389
1390        orig.line_level = FormerLineInNominalLevel::Consumer;
1391        let mut quads = [0u32; 3];
1392        serialize_analog_input_config(&orig, &mut quads);
1393        assert_eq!(&quads[..], &[0x00000020, 0x000009e7, 0x00000000]);
1394        deserialize_analog_input_config(&mut cfg, &quads);
1395        assert_eq!(cfg, orig);
1396
1397        orig.line_level = FormerLineInNominalLevel::Professional;
1398        let mut quads = [0u32; 3];
1399        serialize_analog_input_config(&orig, &mut quads);
1400        assert_eq!(&quads[..], &[0x00000010, 0x000009e6, 0x00000000]);
1401        deserialize_analog_input_config(&mut cfg, &quads);
1402        assert_eq!(cfg, orig);
1403
1404        orig.phantom_powering[0] = true;
1405        let mut quads = [0u32; 3];
1406        serialize_analog_input_config(&orig, &mut quads);
1407        assert_eq!(&quads[..], &[0x00000011, 0x000009e6, 0x00000000]);
1408        deserialize_analog_input_config(&mut cfg, &quads);
1409        assert_eq!(cfg, orig);
1410
1411        orig.phantom_powering[1] = true;
1412        let mut quads = [0u32; 3];
1413        serialize_analog_input_config(&orig, &mut quads);
1414        assert_eq!(&quads[..], &[0x00000091, 0x000009e6, 0x00000000]);
1415        deserialize_analog_input_config(&mut cfg, &quads);
1416        assert_eq!(cfg, orig);
1417
1418        orig.phantom_powering[2] = true;
1419        let mut quads = [0u32; 3];
1420        serialize_analog_input_config(&orig, &mut quads);
1421        assert_eq!(&quads[..], &[0x00000093, 0x000009e6, 0x00000000]);
1422        deserialize_analog_input_config(&mut cfg, &quads);
1423        assert_eq!(cfg, orig);
1424
1425        orig.phantom_powering[3] = true;
1426        let mut quads = [0u32; 3];
1427        serialize_analog_input_config(&orig, &mut quads);
1428        assert_eq!(&quads[..], &[0x00000193, 0x000009e6, 0x00000000]);
1429        deserialize_analog_input_config(&mut cfg, &quads);
1430        assert_eq!(cfg, orig);
1431    }
1432
1433    fn config_to_quads(raw: &[u8]) -> Vec<u32> {
1434        let mut quadlet = [0; 4];
1435        (0..Ff800Config::QUADLET_COUNT)
1436            .map(|i| {
1437                let pos = i * 4;
1438                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
1439                u32::from_le_bytes(quadlet)
1440            })
1441            .collect()
1442    }
1443
1444    #[test]
1445    fn config_serdes() {
1446        let mut orig = Ff800Config::default();
1447        let mut cfg = Ff800Config::default();
1448
1449        orig.line_out_level = LineOutNominalLevel::High;
1450        let raw = Ff800Protocol::serialize_offsets(&orig);
1451        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1452        assert_eq!(cfg, orig);
1453        let quads = config_to_quads(&raw);
1454        assert_eq!(&quads[..], &[0x00000408, 0x000008b0, 0x8000001e]);
1455
1456        orig.line_out_level = LineOutNominalLevel::Consumer;
1457        let raw = Ff800Protocol::serialize_offsets(&orig);
1458        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1459        assert_eq!(cfg, orig);
1460        let quads = config_to_quads(&raw);
1461        assert_eq!(&quads[..], &[0x00001008, 0x000008a8, 0x8000001e]);
1462
1463        orig.line_out_level = LineOutNominalLevel::Professional;
1464        let raw = Ff800Protocol::serialize_offsets(&orig);
1465        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1466        assert_eq!(cfg, orig);
1467        let quads = config_to_quads(&raw);
1468        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0x8000001e]);
1469
1470        orig.spdif_in.iface = SpdifIface::Optical;
1471        let raw = Ff800Protocol::serialize_offsets(&orig);
1472        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1473        assert_eq!(cfg, orig);
1474        let quads = config_to_quads(&raw);
1475        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0x8000021e]);
1476
1477        orig.spdif_in.use_preemble = true;
1478        let raw = Ff800Protocol::serialize_offsets(&orig);
1479        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1480        assert_eq!(cfg, orig);
1481        let quads = config_to_quads(&raw);
1482        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc000021e]);
1483
1484        orig.opt_out_signal = OpticalOutputSignal::Spdif;
1485        let raw = Ff800Protocol::serialize_offsets(&orig);
1486        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1487        assert_eq!(cfg, orig);
1488        let quads = config_to_quads(&raw);
1489        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc000031e]);
1490
1491        orig.spdif_out.format = SpdifFormat::Professional;
1492        let raw = Ff800Protocol::serialize_offsets(&orig);
1493        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1494        assert_eq!(cfg, orig);
1495        let quads = config_to_quads(&raw);
1496        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc000033e]);
1497
1498        orig.spdif_out.emphasis = true;
1499        let raw = Ff800Protocol::serialize_offsets(&orig);
1500        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1501        assert_eq!(cfg, orig);
1502        let quads = config_to_quads(&raw);
1503        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc000037e]);
1504
1505        orig.spdif_out.non_audio = true;
1506        let raw = Ff800Protocol::serialize_offsets(&orig);
1507        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1508        assert_eq!(cfg, orig);
1509        let quads = config_to_quads(&raw);
1510        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc00003fe]);
1511
1512        orig.word_out_single = true;
1513        let raw = Ff800Protocol::serialize_offsets(&orig);
1514        Ff800Protocol::deserialize_offsets(&mut cfg, &raw);
1515        assert_eq!(cfg, orig);
1516        let quads = config_to_quads(&raw);
1517        assert_eq!(&quads[..], &[0x00000808, 0x000008b8, 0xc00023fe]);
1518    }
1519}