firewire_fireface_protocols/
former.rs

1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (c) 2021 Takashi Sakamoto
3
4//! Protocol defined by RME GmbH for former models of Firewire series.
5
6pub mod ff400;
7pub mod ff800;
8
9use super::*;
10
11/// The specification of former model.
12pub trait RmeFfFormerSpecification {
13    /// The number of analog (line and microphone) inputs.
14    const ANALOG_INPUT_COUNT: usize;
15    /// The number of S/PDIF inputs.
16    const SPDIF_INPUT_COUNT: usize;
17    /// The number of ADAT inputs.
18    const ADAT_INPUT_COUNT: usize;
19    /// The number of stream inputs.
20    const STREAM_INPUT_COUNT: usize;
21
22    /// The number of analog outputs.
23    const ANALOG_OUTPUT_COUNT: usize;
24    /// The number of S/PDIF outputs.
25    const SPDIF_OUTPUT_COUNT: usize;
26    /// The number of ADAT outputs.
27    const ADAT_OUTPUT_COUNT: usize;
28
29    /// The number of physical inputs (line, microphone, S/PDIF, and ADAT).
30    const PHYS_INPUT_COUNT: usize =
31        Self::ANALOG_INPUT_COUNT + Self::SPDIF_INPUT_COUNT + Self::ADAT_INPUT_COUNT;
32    /// The number of physical outputs (line, S/PDIF, and ADAT).
33    const PHYS_OUTPUT_COUNT: usize =
34        Self::ANALOG_OUTPUT_COUNT + Self::SPDIF_OUTPUT_COUNT + Self::ADAT_OUTPUT_COUNT;
35}
36
37/// State of hardware meter.
38///
39/// Each value of 32 bit integer is between 0x00000000 and 0x7fffff00 to represent -90.03 and
40/// 0.00 dB. When reaching saturation, 1 byte in LSB side represent ratio of overload.
41#[derive(Default, Debug, Clone, PartialEq, Eq)]
42pub struct FormerMeterState {
43    /// The detected levels for analog (line and microphone) inputs.
44    pub analog_inputs: Vec<i32>,
45    /// The detected levels for S/PDIF inputs.
46    pub spdif_inputs: Vec<i32>,
47    /// The detected levels for ADAT inputs.
48    pub adat_inputs: Vec<i32>,
49    /// The detected levels for stream inputs.
50    pub stream_inputs: Vec<i32>,
51    /// The detected levels for analog outputs.
52    pub analog_outputs: Vec<i32>,
53    /// The detected levels for S/PDIF outputs.
54    pub spdif_outputs: Vec<i32>,
55    /// The detected levels for ADAT outputs.
56    pub adat_outputs: Vec<i32>,
57}
58
59/// The specification of hardware metering in former models.
60pub trait RmeFfFormerMeterSpecification: RmeFfFormerSpecification {
61    const METER_OFFSET: u64;
62
63    const LEVEL_MIN: i32 = 0x00000000;
64    const LEVEL_MAX: i32 = 0x7fffff00;
65    const LEVEL_STEP: i32 = 0x100;
66
67    fn create_meter_state() -> FormerMeterState {
68        FormerMeterState {
69            analog_inputs: vec![0; Self::ANALOG_INPUT_COUNT],
70            spdif_inputs: vec![0; Self::SPDIF_INPUT_COUNT],
71            adat_inputs: vec![0; Self::ADAT_INPUT_COUNT],
72            stream_inputs: vec![0; Self::STREAM_INPUT_COUNT],
73            analog_outputs: vec![0; Self::ANALOG_OUTPUT_COUNT],
74            spdif_outputs: vec![0; Self::SPDIF_OUTPUT_COUNT],
75            adat_outputs: vec![0; Self::ADAT_OUTPUT_COUNT],
76        }
77    }
78}
79
80const METER_LEVEL_MASK: i32 = 0x7fffff00;
81
82// MEMO: The content of meter appears to consist of three regions. The purpose of each region is
83// still unclear. Let us use the last region.
84fn serialize_meter(
85    params: &FormerMeterState,
86    phys_input_count: usize,
87    stream_input_count: usize,
88    phys_output_count: usize,
89) -> Vec<u8> {
90    let offset = 4 * (phys_input_count + stream_input_count + phys_output_count) * 2;
91    let mut raw = vec![0; offset];
92    raw.reserve(
93        params.analog_inputs.len()
94            + params.spdif_inputs.len()
95            + params.stream_inputs.len()
96            + params.analog_outputs.len()
97            + params.spdif_outputs.len()
98            + params.adat_outputs.len(),
99    );
100    params
101        .analog_inputs
102        .iter()
103        .chain(params.spdif_inputs.iter())
104        .chain(params.adat_inputs.iter())
105        .chain(params.stream_inputs.iter())
106        .chain(params.analog_outputs.iter())
107        .chain(params.spdif_outputs.iter())
108        .chain(params.adat_outputs.iter())
109        .for_each(|meter| {
110            raw.extend_from_slice(&(meter & METER_LEVEL_MASK).to_le_bytes());
111        });
112    raw
113}
114
115fn deserialize_meter(
116    params: &mut FormerMeterState,
117    raw: &[u8],
118    phys_input_count: usize,
119    stream_input_count: usize,
120    phys_output_count: usize,
121) {
122    // TODO: pick up overload.
123    let mut quadlet = [0; 4];
124    let offset = 4 * (phys_input_count + stream_input_count + phys_output_count) * 2;
125    params
126        .analog_inputs
127        .iter_mut()
128        .chain(params.spdif_inputs.iter_mut())
129        .chain(params.adat_inputs.iter_mut())
130        .chain(params.stream_inputs.iter_mut())
131        .chain(params.analog_outputs.iter_mut())
132        .chain(params.spdif_outputs.iter_mut())
133        .chain(params.adat_outputs.iter_mut())
134        .enumerate()
135        .for_each(|(i, meter)| {
136            let pos = offset + i * 4;
137            quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
138            *meter = i32::from_le_bytes(quadlet) & METER_LEVEL_MASK;
139        });
140}
141
142impl<O: RmeFfFormerSpecification> RmeFfOffsetParamsSerialize<FormerMeterState> for O {
143    fn serialize_offsets(params: &FormerMeterState) -> Vec<u8> {
144        serialize_meter(
145            params,
146            Self::PHYS_INPUT_COUNT,
147            Self::STREAM_INPUT_COUNT,
148            Self::PHYS_OUTPUT_COUNT,
149        )
150    }
151}
152
153impl<O: RmeFfFormerMeterSpecification> RmeFfOffsetParamsDeserialize<FormerMeterState> for O {
154    fn deserialize_offsets(params: &mut FormerMeterState, raw: &[u8]) {
155        deserialize_meter(
156            params,
157            raw,
158            Self::PHYS_INPUT_COUNT,
159            Self::STREAM_INPUT_COUNT,
160            Self::PHYS_OUTPUT_COUNT,
161        );
162    }
163}
164
165impl<O: RmeFfFormerMeterSpecification + RmeFfOffsetParamsDeserialize<FormerMeterState>>
166    RmeFfCacheableParamsOperation<FormerMeterState> for O
167{
168    fn cache_wholly(
169        req: &mut FwReq,
170        node: &mut FwNode,
171        params: &mut FormerMeterState,
172        timeout_ms: u32,
173    ) -> Result<(), Error> {
174        // NOTE:
175        // Each of the first octuples is for level of corresponding source to mixer.
176        // Each of the following octuples is for level of corresponding output from mixer (pre-fader).
177        // Each of the following octuples is for level of corresponding output from mixer (post-fader).
178        // Each of the following quadlets is for level of corresponding physical input.
179        // Each of the following quadlets is for level of corresponding stream input.
180        // Each of the following quadlets is for level of corresponding physical output.
181        let length = 8 * (Self::PHYS_INPUT_COUNT + Self::PHYS_OUTPUT_COUNT * 2)
182            + 4 * (Self::PHYS_INPUT_COUNT + Self::STREAM_INPUT_COUNT + Self::PHYS_OUTPUT_COUNT);
183        let mut raw = vec![0; length];
184        req.transaction_sync(
185            node,
186            FwTcode::ReadBlockRequest,
187            Self::METER_OFFSET,
188            raw.len(),
189            &mut raw,
190            timeout_ms,
191        )
192        .map(|_| Self::deserialize_offsets(params, &raw))
193    }
194}
195
196/// State of output volumes.
197///
198/// The value for volume is between 0x00000000 and 0x00010000 through 0x00000001 and 0x00080000 to
199/// represent the range from negative infinite to 6.00 dB through -90.30 dB and 0.00 dB.
200#[derive(Default, Debug, Clone, PartialEq, Eq)]
201pub struct FormerOutputVolumeState(pub Vec<i32>);
202
203/// Output protocol specific to former models of RME Fireface.
204pub trait RmeFormerOutputSpecification: RmeFfFormerSpecification {
205    const VOL_MIN: i32 = 0x00000000;
206    const VOL_ZERO: i32 = 0x00008000;
207    const VOL_MAX: i32 = 0x00010000;
208    const VOL_STEP: i32 = 1;
209
210    fn create_output_volume_state() -> FormerOutputVolumeState {
211        FormerOutputVolumeState(vec![0; Self::PHYS_OUTPUT_COUNT])
212    }
213}
214
215impl<O: RmeFfFormerSpecification> RmeFormerOutputSpecification for O {}
216
217fn serialize_output_volumes(params: &FormerOutputVolumeState, phys_output_count: usize) -> Vec<u8> {
218    assert!(params.0.len() >= phys_output_count);
219
220    params.0.iter().flat_map(|vol| vol.to_le_bytes()).collect()
221}
222
223fn deserialize_output_volumes(
224    params: &mut FormerOutputVolumeState,
225    raw: &[u8],
226    phys_output_count: usize,
227) {
228    assert!(raw.len() >= phys_output_count * 4);
229
230    let mut quadlet = [0; 4];
231    params.0.iter_mut().enumerate().for_each(|(i, vol)| {
232        let pos = i * 4;
233        quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
234        *vol = i32::from_le_bytes(quadlet);
235    });
236}
237
238impl<O: RmeFormerOutputSpecification> RmeFfOffsetParamsSerialize<FormerOutputVolumeState> for O {
239    fn serialize_offsets(params: &FormerOutputVolumeState) -> Vec<u8> {
240        serialize_output_volumes(params, Self::PHYS_OUTPUT_COUNT)
241    }
242}
243
244impl<O: RmeFormerOutputSpecification> RmeFfOffsetParamsDeserialize<FormerOutputVolumeState> for O {
245    fn deserialize_offsets(params: &mut FormerOutputVolumeState, raw: &[u8]) {
246        deserialize_output_volumes(params, raw, Self::PHYS_OUTPUT_COUNT)
247    }
248}
249
250/// Sources of mixer specific to former models of RME Fireface.
251///
252/// The value is between 0x00000000 and 0x00010000 through 0x00008000 to represent -90.30 and 6.02 dB
253/// through 0x00008000.
254#[derive(Default, Debug, Clone, PartialEq, Eq)]
255pub struct FormerMixerSrc {
256    /// Gains of sources from analog inputs.
257    pub analog_gains: Vec<i32>,
258    /// Gains of sources from S/PDIF inputs.
259    pub spdif_gains: Vec<i32>,
260    /// Gains of sources from ADAT inputs.
261    pub adat_gains: Vec<i32>,
262    /// Gains of sources from stream inputs.
263    pub stream_gains: Vec<i32>,
264}
265
266/// State of mixer.
267#[derive(Default, Debug, Clone, PartialEq, Eq)]
268pub struct FormerMixerState(pub Vec<FormerMixerSrc>);
269
270/// The specification of mixer in former models.
271pub trait RmeFormerMixerSpecification: RmeFfFormerSpecification {
272    const MIXER_OFFSET: u64;
273    const AVAIL_COUNT: usize;
274
275    const DST_COUNT: usize =
276        Self::ANALOG_OUTPUT_COUNT + Self::SPDIF_OUTPUT_COUNT + Self::ADAT_OUTPUT_COUNT;
277
278    const GAIN_MIN: i32 = 0x00000000;
279    const GAIN_ZERO: i32 = 0x00008000;
280    const GAIN_MAX: i32 = 0x00010000;
281    const GAIN_STEP: i32 = 1;
282
283    fn create_mixer_state() -> FormerMixerState {
284        FormerMixerState(vec![
285            FormerMixerSrc {
286                analog_gains: vec![0; Self::ANALOG_INPUT_COUNT],
287                spdif_gains: vec![0; Self::SPDIF_INPUT_COUNT],
288                adat_gains: vec![0; Self::ADAT_INPUT_COUNT],
289                stream_gains: vec![0; Self::STREAM_INPUT_COUNT],
290            };
291            Self::DST_COUNT
292        ])
293    }
294}
295
296fn calculate_mixer_length(avail_count: usize) -> usize {
297    avail_count * 2 * 4
298}
299
300fn calculate_mixer_total_length(dst_count: usize, avail_count: usize) -> usize {
301    calculate_mixer_length(avail_count) * dst_count
302}
303
304fn serialize_mixer(params: &FormerMixerState, dst_count: usize, avail_count: usize) -> Vec<u8> {
305    let mut raw = vec![0; calculate_mixer_total_length(dst_count, avail_count)];
306
307    params.0.iter().enumerate().for_each(|(i, mixer)| {
308        mixer
309            .analog_gains
310            .iter()
311            .chain(mixer.spdif_gains.iter())
312            .chain(mixer.adat_gains.iter())
313            .enumerate()
314            .for_each(|(j, gain)| {
315                let pos = ((avail_count * 2) * i + j) * 4;
316                raw[pos..(pos + 4)].copy_from_slice(&gain.to_le_bytes());
317            });
318
319        mixer.stream_gains.iter().enumerate().for_each(|(j, gain)| {
320            let pos = ((avail_count * 2) * i + (avail_count + j)) * 4;
321            raw[pos..(pos + 4)].copy_from_slice(&gain.to_le_bytes());
322        });
323    });
324
325    raw
326}
327
328fn deserialize_mixer(
329    params: &mut FormerMixerState,
330    raw: &[u8],
331    dst_count: usize,
332    avail_count: usize,
333) {
334    assert!(raw.len() >= calculate_mixer_total_length(dst_count, avail_count));
335
336    let mut quadlet = [0; 4];
337    params.0.iter_mut().enumerate().for_each(|(i, mixer)| {
338        mixer
339            .analog_gains
340            .iter_mut()
341            .chain(mixer.spdif_gains.iter_mut())
342            .chain(mixer.adat_gains.iter_mut())
343            .enumerate()
344            .for_each(|(j, gain)| {
345                let pos = ((avail_count * 2) * i + j) * 4;
346                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
347                *gain = i32::from_le_bytes(quadlet)
348            });
349
350        mixer
351            .stream_gains
352            .iter_mut()
353            .enumerate()
354            .for_each(|(j, gain)| {
355                let pos = ((avail_count * 2) * i + (avail_count + j)) * 4;
356                quadlet.copy_from_slice(&raw[pos..(pos + 4)]);
357                *gain = i32::from_le_bytes(quadlet)
358            });
359    });
360}
361
362impl<O: RmeFormerMixerSpecification> RmeFfOffsetParamsSerialize<FormerMixerState> for O {
363    fn serialize_offsets(params: &FormerMixerState) -> Vec<u8> {
364        serialize_mixer(params, Self::DST_COUNT, Self::AVAIL_COUNT)
365    }
366}
367
368impl<O: RmeFormerMixerSpecification> RmeFfOffsetParamsDeserialize<FormerMixerState> for O {
369    fn deserialize_offsets(params: &mut FormerMixerState, raw: &[u8]) {
370        deserialize_mixer(params, raw, Self::DST_COUNT, Self::AVAIL_COUNT)
371    }
372}
373
374impl<O> RmeFfWhollyUpdatableParamsOperation<FormerMixerState> for O
375where
376    O: RmeFormerMixerSpecification + RmeFfOffsetParamsDeserialize<FormerMixerState>,
377{
378    fn update_wholly(
379        req: &mut FwReq,
380        node: &mut FwNode,
381        params: &FormerMixerState,
382        timeout_ms: u32,
383    ) -> Result<(), Error> {
384        let mut raw = Self::serialize_offsets(params);
385
386        let mixer_length = calculate_mixer_length(Self::AVAIL_COUNT);
387
388        (0..(raw.len() / mixer_length)).try_for_each(|i| {
389            let pos = i * mixer_length;
390            req.transaction_sync(
391                node,
392                FwTcode::WriteBlockRequest,
393                Self::MIXER_OFFSET + pos as u64,
394                mixer_length,
395                &mut raw[pos..(pos + mixer_length)],
396                timeout_ms,
397            )
398        })
399    }
400}
401
402impl<O> RmeFfPartiallyUpdatableParamsOperation<FormerMixerState> for O
403where
404    O: RmeFormerMixerSpecification + RmeFfOffsetParamsDeserialize<FormerMixerState>,
405{
406    fn update_partially(
407        req: &mut FwReq,
408        node: &mut FwNode,
409        params: &mut FormerMixerState,
410        update: FormerMixerState,
411        timeout_ms: u32,
412    ) -> Result<(), Error> {
413        let old = Self::serialize_offsets(params);
414        let mut new = Self::serialize_offsets(&update);
415
416        let mixer_length = calculate_mixer_length(Self::AVAIL_COUNT);
417
418        (0..(new.len() / mixer_length))
419            .try_for_each(|i| {
420                let pos = i * mixer_length;
421                if new[pos..(pos + mixer_length)] != old[pos..(pos + mixer_length)] {
422                    req.transaction_sync(
423                        node,
424                        FwTcode::WriteBlockRequest,
425                        Self::MIXER_OFFSET + pos as u64,
426                        mixer_length,
427                        &mut new[pos..(pos + mixer_length)],
428                        timeout_ms,
429                    )
430                } else {
431                    Ok(())
432                }
433            })
434            .map(|_| *params = update)
435    }
436}
437
438const FORMER_CONFIG_SIZE: usize = 12;
439
440fn write_config<T: RmeFfOffsetParamsSerialize<U>, U>(
441    req: &mut FwReq,
442    node: &mut FwNode,
443    offset: u64,
444    config: &U,
445    timeout_ms: u32,
446) -> Result<(), Error> {
447    let mut raw = T::serialize_offsets(config);
448
449    req.transaction_sync(
450        node,
451        FwTcode::WriteBlockRequest,
452        offset,
453        raw.len(),
454        &mut raw,
455        timeout_ms,
456    )
457}
458
459const FORMER_STATUS_SIZE: usize = 8;
460
461fn read_status<T: RmeFfOffsetParamsDeserialize<U>, U>(
462    req: &mut FwReq,
463    node: &mut FwNode,
464    offset: u64,
465    status: &mut U,
466    timeout_ms: u32,
467) -> Result<(), Error> {
468    let mut raw = [0; FORMER_STATUS_SIZE];
469    req.transaction_sync(
470        node,
471        FwTcode::ReadBlockRequest,
472        offset,
473        raw.len(),
474        &mut raw,
475        timeout_ms,
476    )
477    .map(|_| T::deserialize_offsets(status, &raw))
478}
479
480/// Configuration of S/PDIF output.
481#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
482pub struct FormerSpdifOutput {
483    /// The format of S/PDIF signal.
484    pub format: SpdifFormat,
485    /// Whether to boost signal.
486    pub emphasis: bool,
487    /// Whether to transfer non-audio bit in preemble.
488    pub non_audio: bool,
489}
490
491/// Nominal level of line inputs.
492#[derive(Debug, Copy, Clone, PartialEq, Eq)]
493pub enum FormerLineInNominalLevel {
494    Low,
495    /// -10 dBV.
496    Consumer,
497    /// +4 dBu.
498    Professional,
499}
500
501impl Default for FormerLineInNominalLevel {
502    fn default() -> Self {
503        Self::Low
504    }
505}
506
507#[cfg(test)]
508mod test {
509    use super::*;
510
511    #[test]
512    fn meter_serdes() {
513        let mut orig = FormerMeterState {
514            analog_inputs: vec![0, 1],
515            spdif_inputs: vec![2, 3],
516            adat_inputs: vec![4, 5],
517            stream_inputs: vec![6, 7],
518            analog_outputs: vec![8, 9],
519            spdif_outputs: vec![10, 11],
520            adat_outputs: vec![12, 13],
521        };
522        orig.analog_inputs
523            .iter_mut()
524            .chain(orig.spdif_inputs.iter_mut())
525            .chain(orig.adat_inputs.iter_mut())
526            .chain(orig.stream_inputs.iter_mut())
527            .chain(orig.analog_outputs.iter_mut())
528            .chain(orig.spdif_outputs.iter_mut())
529            .chain(orig.adat_outputs.iter_mut())
530            .for_each(|gain| *gain <<= 8);
531        let raw = serialize_meter(&orig, 6, 2, 6);
532        let mut target = FormerMeterState {
533            analog_inputs: vec![0; 2],
534            spdif_inputs: vec![0; 2],
535            adat_inputs: vec![0; 2],
536            stream_inputs: vec![0; 2],
537            analog_outputs: vec![0; 2],
538            spdif_outputs: vec![0; 2],
539            adat_outputs: vec![0; 2],
540        };
541        deserialize_meter(&mut target, &raw, 6, 2, 6);
542
543        assert_eq!(target, orig);
544    }
545
546    #[test]
547    fn mixer_serdes() {
548        let orig = FormerMixerState(vec![
549            FormerMixerSrc {
550                analog_gains: vec![0, 1],
551                spdif_gains: vec![2, 3],
552                adat_gains: vec![4, 5],
553                stream_gains: vec![6, 7],
554            },
555            FormerMixerSrc {
556                analog_gains: vec![8, 9],
557                spdif_gains: vec![10, 11],
558                adat_gains: vec![12, 13],
559                stream_gains: vec![14, 15],
560            },
561        ]);
562        let raw = serialize_mixer(&orig, 6, 8);
563        let mut target = FormerMixerState(vec![
564            FormerMixerSrc {
565                analog_gains: vec![0; 2],
566                spdif_gains: vec![0; 2],
567                adat_gains: vec![0; 2],
568                stream_gains: vec![0; 2],
569            },
570            FormerMixerSrc {
571                analog_gains: vec![0; 2],
572                spdif_gains: vec![0; 2],
573                adat_gains: vec![0; 2],
574                stream_gains: vec![0; 2],
575            },
576        ]);
577        deserialize_mixer(&mut target, &raw, 6, 8);
578
579        assert_eq!(target, orig);
580    }
581
582    #[test]
583    fn output_volume_serdes() {
584        let orig = FormerOutputVolumeState(vec![0, 1, 2, 3]);
585        let raw = serialize_output_volumes(&orig, 4);
586        let mut target = FormerOutputVolumeState(vec![0; 4]);
587        deserialize_output_volumes(&mut target, &raw, 4);
588
589        assert_eq!(target, orig);
590    }
591}