1use super::{register_dsp::*, *};
10
11#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub enum V2ClkSrc {
14 Internal,
16 SpdifCoax,
18 WordClk,
20 SignalOpt,
22 AdatOpt,
24 AdatDsub,
26 AesebuXlr,
28}
29
30impl Default for V2ClkSrc {
31 fn default() -> Self {
32 Self::Internal
33 }
34}
35
36#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
38pub struct Version2ClockParameters {
39 pub rate: ClkRate,
41 pub source: V2ClkSrc,
43}
44
45const CLK_RATE_LABEL: &str = "clock-rate-v2";
46const CLK_RATE_MASK: u32 = 0x00000038;
47const CLK_RATE_SHIFT: usize = 3;
48
49const CLK_SRC_LABEL: &str = "clock-source-v2";
50const CLK_SRC_MASK: u32 = 0x00000007;
51const CLK_SRC_SHIFT: usize = 0;
52
53pub trait MotuVersion2ClockSpecification {
55 const CLK_RATES: &'static [ClkRate];
56 const CLK_RATE_VALS: &'static [u8];
57
58 const CLK_SRCS: &'static [V2ClkSrc];
59 const CLK_SRC_VALS: &'static [u8];
60}
61
62impl<O> MotuWhollyCacheableParamsOperation<Version2ClockParameters> for O
63where
64 O: MotuVersion2ClockSpecification,
65{
66 fn cache_wholly(
67 req: &mut FwReq,
68 node: &mut FwNode,
69 params: &mut Version2ClockParameters,
70 timeout_ms: u32,
71 ) -> Result<(), Error> {
72 let quad = read_quad(req, node, OFFSET_CLK, timeout_ms)?;
73
74 deserialize_flag(
75 &mut params.rate,
76 &quad,
77 CLK_RATE_MASK,
78 CLK_RATE_SHIFT,
79 Self::CLK_RATES,
80 Self::CLK_RATE_VALS,
81 CLK_RATE_LABEL,
82 )?;
83
84 deserialize_flag(
85 &mut params.source,
86 &quad,
87 CLK_SRC_MASK,
88 CLK_SRC_SHIFT,
89 Self::CLK_SRCS,
90 Self::CLK_SRC_VALS,
91 CLK_SRC_LABEL,
92 )
93 }
94}
95
96impl<O> MotuWhollyUpdatableParamsOperation<Version2ClockParameters> for O
97where
98 O: MotuVersion2ClockSpecification,
99{
100 fn update_wholly(
101 req: &mut FwReq,
102 node: &mut FwNode,
103 params: &Version2ClockParameters,
104 timeout_ms: u32,
105 ) -> Result<(), Error> {
106 let mut quad = read_quad(req, node, OFFSET_CLK, timeout_ms)?;
107
108 serialize_flag(
109 ¶ms.rate,
110 &mut quad,
111 CLK_RATE_MASK,
112 CLK_RATE_SHIFT,
113 Self::CLK_RATES,
114 Self::CLK_RATE_VALS,
115 CLK_RATE_LABEL,
116 )?;
117
118 serialize_flag(
119 ¶ms.source,
120 &mut quad,
121 CLK_SRC_MASK,
122 CLK_SRC_SHIFT,
123 Self::CLK_SRCS,
124 Self::CLK_SRC_VALS,
125 CLK_SRC_LABEL,
126 )?;
127
128 write_quad(req, node, OFFSET_CLK, quad, timeout_ms)
129 }
130}
131
132#[derive(Debug, Copy, Clone, PartialEq, Eq)]
134pub enum V2OptIfaceMode {
135 None,
136 Adat,
137 Spdif,
138}
139
140impl Default for V2OptIfaceMode {
141 fn default() -> Self {
142 Self::None
143 }
144}
145
146#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
148pub struct Version2OpticalIfaceParameters {
149 pub input_mode: V2OptIfaceMode,
151 pub output_mode: V2OptIfaceMode,
153}
154
155const OPT_IN_IFACE_LABEL: &str = "optical-input-iface-v2";
156const OPT_IN_IFACE_MASK: u32 = 0x00000300;
157const OPT_IN_IFACE_SHIFT: usize = 8;
158
159const OPT_OUT_IFACE_LABEL: &str = "optical-output-iface-v2";
160const OPT_OUT_IFACE_MASK: u32 = 0x00000c00;
161const OPT_OUT_IFACE_SHIFT: usize = 10;
162
163const OPT_IFACE_MODE_VALS: &[u8] = &[0x00, 0x01, 0x02];
164
165pub trait MotuVersion2OpticalIfaceSpecification {
167 const OPT_IFACE_MODES: &'static [V2OptIfaceMode];
168}
169
170impl<O> MotuWhollyCacheableParamsOperation<Version2OpticalIfaceParameters> for O
171where
172 O: MotuVersion2OpticalIfaceSpecification,
173{
174 fn cache_wholly(
175 req: &mut FwReq,
176 node: &mut FwNode,
177 params: &mut Version2OpticalIfaceParameters,
178 timeout_ms: u32,
179 ) -> Result<(), Error> {
180 let quad = read_quad(req, node, OFFSET_PORT, timeout_ms)?;
181
182 deserialize_flag(
183 &mut params.input_mode,
184 &quad,
185 OPT_IN_IFACE_MASK,
186 OPT_IN_IFACE_SHIFT,
187 Self::OPT_IFACE_MODES,
188 OPT_IFACE_MODE_VALS,
189 OPT_IN_IFACE_LABEL,
190 )?;
191
192 deserialize_flag(
193 &mut params.output_mode,
194 &quad,
195 OPT_OUT_IFACE_MASK,
196 OPT_OUT_IFACE_SHIFT,
197 Self::OPT_IFACE_MODES,
198 OPT_IFACE_MODE_VALS,
199 OPT_OUT_IFACE_LABEL,
200 )
201 }
202}
203
204impl<O> MotuWhollyUpdatableParamsOperation<Version2OpticalIfaceParameters> for O
205where
206 O: MotuVersion2OpticalIfaceSpecification,
207{
208 fn update_wholly(
209 req: &mut FwReq,
210 node: &mut FwNode,
211 params: &Version2OpticalIfaceParameters,
212 timeout_ms: u32,
213 ) -> Result<(), Error> {
214 let mut quad = read_quad(req, node, OFFSET_PORT, timeout_ms)?;
215
216 serialize_flag(
217 ¶ms.input_mode,
218 &mut quad,
219 OPT_IN_IFACE_MASK,
220 OPT_IN_IFACE_SHIFT,
221 Self::OPT_IFACE_MODES,
222 OPT_IFACE_MODE_VALS,
223 OPT_IN_IFACE_LABEL,
224 )?;
225
226 serialize_flag(
227 ¶ms.output_mode,
228 &mut quad,
229 OPT_OUT_IFACE_MASK,
230 OPT_OUT_IFACE_SHIFT,
231 Self::OPT_IFACE_MODES,
232 OPT_IFACE_MODE_VALS,
233 OPT_OUT_IFACE_LABEL,
234 )?;
235
236 write_quad(req, node, OFFSET_PORT, quad, timeout_ms)
237 }
238}
239
240#[derive(Default)]
242pub struct F828mk2Protocol;
243
244impl MotuPortAssignSpecification for F828mk2Protocol {
245 const ASSIGN_PORT_TARGETS: &'static [TargetPort] = &[
246 TargetPort::PhonePair, TargetPort::AnalogPair(0), TargetPort::AnalogPair(1), TargetPort::AnalogPair(2), TargetPort::AnalogPair(3), TargetPort::MainPair, TargetPort::SpdifPair, TargetPort::AdatPair(0), TargetPort::AdatPair(1), TargetPort::AdatPair(2), TargetPort::AdatPair(3), ];
258
259 const ASSIGN_PORT_VALS: &'static [u8] = &[
260 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, ];
272}
273
274impl MotuWordClockOutputSpecification for F828mk2Protocol {}
275
276impl MotuClockNameDisplaySpecification for F828mk2Protocol {}
277
278impl MotuVersion2ClockSpecification for F828mk2Protocol {
279 const CLK_RATES: &'static [ClkRate] = &[
280 ClkRate::R44100,
281 ClkRate::R48000,
282 ClkRate::R88200,
283 ClkRate::R96000,
284 ];
285 const CLK_RATE_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x03];
286
287 const CLK_SRCS: &'static [V2ClkSrc] = &[
288 V2ClkSrc::Internal,
289 V2ClkSrc::SignalOpt,
290 V2ClkSrc::SpdifCoax,
291 V2ClkSrc::WordClk,
292 V2ClkSrc::AdatDsub,
293 ];
294 const CLK_SRC_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x04, 0x05];
295}
296
297impl MotuVersion2OpticalIfaceSpecification for F828mk2Protocol {
298 const OPT_IFACE_MODES: &'static [V2OptIfaceMode] = &[
299 V2OptIfaceMode::None,
300 V2OptIfaceMode::Adat,
301 V2OptIfaceMode::Spdif,
302 ];
303}
304
305impl MotuRegisterDspSpecification for F828mk2Protocol {
306 const MIXER_OUTPUT_DESTINATIONS: &'static [TargetPort] = &[
307 TargetPort::Disabled,
308 TargetPort::PhonePair,
309 TargetPort::AnalogPair(0),
310 TargetPort::AnalogPair(1),
311 TargetPort::AnalogPair(2),
312 TargetPort::AnalogPair(3),
313 TargetPort::MainPair,
314 TargetPort::SpdifPair,
315 TargetPort::AdatPair(0),
316 TargetPort::AdatPair(1),
317 TargetPort::AdatPair(2),
318 TargetPort::AdatPair(3),
319 ];
320}
321
322impl MotuRegisterDspMixerMonauralSourceSpecification for F828mk2Protocol {
323 const MIXER_SOURCES: &'static [TargetPort] = &[
324 TargetPort::Analog(0),
325 TargetPort::Analog(1),
326 TargetPort::Analog(2),
327 TargetPort::Analog(3),
328 TargetPort::Analog(4),
329 TargetPort::Analog(5),
330 TargetPort::Analog(6),
331 TargetPort::Analog(7),
332 TargetPort::Analog(8), TargetPort::Analog(9), TargetPort::Spdif(0),
335 TargetPort::Spdif(1),
336 TargetPort::Adat(0),
337 TargetPort::Adat(1),
338 TargetPort::Adat(2),
339 TargetPort::Adat(3),
340 TargetPort::Adat(4),
341 TargetPort::Adat(5),
342 TargetPort::Adat(6),
343 TargetPort::Adat(7),
344 ];
345}
346
347impl MotuRegisterDspLineInputSpecification for F828mk2Protocol {
348 const LINE_INPUT_COUNT: usize = 8;
349 const CH_OFFSET: usize = 0;
350}
351
352impl F828mk2Protocol {
353 pub const NOTIFY_PORT_CHANGE: u32 = 0x40000000;
356
357 pub const NOTIFY_FOOTSWITCH_MASK: u32 = 0x01000000;
359}
360
361impl MotuRegisterDspMeterSpecification for F828mk2Protocol {
362 const INPUT_PORTS: &'static [TargetPort] = &[
363 TargetPort::Analog(0),
364 TargetPort::Analog(1),
365 TargetPort::Analog(2),
366 TargetPort::Analog(3),
367 TargetPort::Analog(4),
368 TargetPort::Analog(5),
369 TargetPort::Analog(6),
370 TargetPort::Analog(7),
371 TargetPort::Analog(8),
372 TargetPort::Analog(9),
373 TargetPort::Spdif(0),
374 TargetPort::Spdif(1),
375 TargetPort::Adat(0),
376 TargetPort::Adat(1),
377 TargetPort::Adat(2),
378 TargetPort::Adat(3),
379 TargetPort::Adat(4),
380 TargetPort::Adat(5),
381 TargetPort::Adat(6),
382 TargetPort::Adat(7),
383 ];
384 const OUTPUT_PORT_PAIRS: &'static [TargetPort] = &[
385 TargetPort::PhonePair,
386 TargetPort::AnalogPair(0),
387 TargetPort::AnalogPair(1),
388 TargetPort::AnalogPair(2),
389 TargetPort::AnalogPair(3),
390 TargetPort::MainPair,
391 TargetPort::SpdifPair,
392 TargetPort::AdatPair(0),
393 TargetPort::AdatPair(1),
394 TargetPort::AdatPair(2),
395 TargetPort::AdatPair(3),
396 ];
397 const OUTPUT_PORT_PAIR_POS: &'static [[usize; 2]] = &[
398 [2, 3],
399 [4, 5],
400 [6, 7],
401 [8, 9],
402 [10, 11],
403 [12, 13],
404 [14, 15],
405 [16, 17],
406 [18, 19],
407 [20, 21],
408 [22, 23],
409 ];
410}
411
412impl MotuRegisterDspMeterOutputTargetSpecification for F828mk2Protocol {}
413
414#[derive(Default)]
416pub struct F8preProtocol;
417
418impl MotuPortAssignSpecification for F8preProtocol {
419 const ASSIGN_PORT_TARGETS: &'static [TargetPort] =
420 &[TargetPort::PhonePair, TargetPort::MainPair];
421 const ASSIGN_PORT_VALS: &'static [u8] = &[0x01, 0x02];
422}
423
424impl MotuVersion2ClockSpecification for F8preProtocol {
425 const CLK_RATES: &'static [ClkRate] = &[
426 ClkRate::R44100,
427 ClkRate::R48000,
428 ClkRate::R88200,
429 ClkRate::R96000,
430 ];
431 const CLK_RATE_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x03];
432
433 const CLK_SRCS: &'static [V2ClkSrc] = &[V2ClkSrc::Internal, V2ClkSrc::AdatOpt];
434 const CLK_SRC_VALS: &'static [u8] = &[0x00, 0x01];
435}
436
437impl MotuVersion2OpticalIfaceSpecification for F8preProtocol {
438 const OPT_IFACE_MODES: &'static [V2OptIfaceMode] =
439 &[V2OptIfaceMode::None, V2OptIfaceMode::Adat];
440}
441
442impl MotuRegisterDspSpecification for F8preProtocol {
443 const MIXER_OUTPUT_DESTINATIONS: &'static [TargetPort] = &[
444 TargetPort::Disabled,
445 TargetPort::PhonePair,
446 TargetPort::MainPair,
447 TargetPort::AdatPair(0),
448 TargetPort::AdatPair(1),
449 TargetPort::AdatPair(2),
450 TargetPort::AdatPair(3),
451 ];
452}
453
454impl MotuRegisterDspMixerMonauralSourceSpecification for F8preProtocol {
455 const MIXER_SOURCES: &'static [TargetPort] = &[
456 TargetPort::Analog(0),
457 TargetPort::Analog(1),
458 TargetPort::Analog(2),
459 TargetPort::Analog(3),
460 TargetPort::Analog(4),
461 TargetPort::Analog(5),
462 TargetPort::Analog(6),
463 TargetPort::Analog(7),
464 TargetPort::Adat(0),
465 TargetPort::Adat(1),
466 TargetPort::Adat(2),
467 TargetPort::Adat(3),
468 TargetPort::Adat(4),
469 TargetPort::Adat(5),
470 TargetPort::Adat(6),
471 TargetPort::Adat(7),
472 ];
473}
474
475impl MotuRegisterDspMeterSpecification for F8preProtocol {
476 const INPUT_PORTS: &'static [TargetPort] = &[
477 TargetPort::Analog(0),
478 TargetPort::Analog(1),
479 TargetPort::Analog(2),
480 TargetPort::Analog(3),
481 TargetPort::Analog(4),
482 TargetPort::Analog(5),
483 TargetPort::Analog(6),
484 TargetPort::Analog(7),
485 TargetPort::Adat(0),
486 TargetPort::Adat(1),
487 TargetPort::Adat(2),
488 TargetPort::Adat(3),
489 TargetPort::Adat(4),
490 TargetPort::Adat(5),
491 TargetPort::Adat(6),
492 TargetPort::Adat(7),
493 ];
494 const OUTPUT_PORT_PAIRS: &'static [TargetPort] = &[
495 TargetPort::PhonePair,
496 TargetPort::AnalogPair(0),
497 TargetPort::AdatPair(0),
498 TargetPort::AdatPair(1),
499 TargetPort::AdatPair(2),
500 TargetPort::AdatPair(3),
501 ];
502 const OUTPUT_PORT_PAIR_POS: &'static [[usize; 2]] =
503 &[[2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]];
504}
505
506#[derive(Default)]
508pub struct TravelerProtocol;
509
510impl MotuPortAssignSpecification for TravelerProtocol {
511 const ASSIGN_PORT_TARGETS: &'static [TargetPort] = &[
512 TargetPort::PhonePair, TargetPort::AnalogPair(0), TargetPort::AnalogPair(1), TargetPort::AnalogPair(2), TargetPort::AnalogPair(3), TargetPort::AesEbuPair, TargetPort::SpdifPair, TargetPort::AdatPair(0), TargetPort::AdatPair(1), TargetPort::AdatPair(2), TargetPort::AdatPair(3), ];
524
525 const ASSIGN_PORT_VALS: &'static [u8] = &[
526 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, ];
538}
539
540impl MotuWordClockOutputSpecification for TravelerProtocol {}
541
542impl MotuClockNameDisplaySpecification for TravelerProtocol {}
543
544impl MotuVersion2ClockSpecification for TravelerProtocol {
545 const CLK_RATES: &'static [ClkRate] = &[
546 ClkRate::R44100,
547 ClkRate::R48000,
548 ClkRate::R88200,
549 ClkRate::R96000,
550 ClkRate::R176400,
551 ClkRate::R192000,
552 ];
553 const CLK_RATE_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05];
554
555 const CLK_SRCS: &'static [V2ClkSrc] = &[
556 V2ClkSrc::Internal,
557 V2ClkSrc::SignalOpt,
558 V2ClkSrc::SpdifCoax,
559 V2ClkSrc::WordClk,
560 V2ClkSrc::AdatDsub,
561 V2ClkSrc::AesebuXlr,
562 ];
563 const CLK_SRC_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x04, 0x05, 0x07];
564}
565
566impl MotuVersion2OpticalIfaceSpecification for TravelerProtocol {
567 const OPT_IFACE_MODES: &'static [V2OptIfaceMode] = &[
568 V2OptIfaceMode::None,
569 V2OptIfaceMode::Adat,
570 V2OptIfaceMode::Spdif,
571 ];
572}
573
574impl MotuRegisterDspSpecification for TravelerProtocol {
575 const MIXER_OUTPUT_DESTINATIONS: &'static [TargetPort] = &[
576 TargetPort::Disabled,
577 TargetPort::PhonePair,
578 TargetPort::AnalogPair(0),
579 TargetPort::AnalogPair(1),
580 TargetPort::AnalogPair(2),
581 TargetPort::AnalogPair(3),
582 TargetPort::AesEbuPair,
583 TargetPort::SpdifPair,
584 TargetPort::AdatPair(0),
585 TargetPort::AdatPair(1),
586 TargetPort::AdatPair(2),
587 TargetPort::AdatPair(3),
588 ];
589}
590
591impl MotuRegisterDspMixerMonauralSourceSpecification for TravelerProtocol {
592 const MIXER_SOURCES: &'static [TargetPort] = &[
593 TargetPort::Analog(0),
594 TargetPort::Analog(1),
595 TargetPort::Analog(2),
596 TargetPort::Analog(3),
597 TargetPort::Analog(4),
598 TargetPort::Analog(5),
599 TargetPort::Analog(6),
600 TargetPort::Analog(7),
601 TargetPort::AesEbu(0),
602 TargetPort::AesEbu(1),
603 TargetPort::Spdif(0),
604 TargetPort::Spdif(1),
605 TargetPort::Adat(0),
606 TargetPort::Adat(1),
607 TargetPort::Adat(2),
608 TargetPort::Adat(3),
609 TargetPort::Adat(4),
610 TargetPort::Adat(5),
611 TargetPort::Adat(6),
612 TargetPort::Adat(7),
613 ];
614}
615
616impl MotuRegisterDspLineInputSpecification for TravelerProtocol {
617 const LINE_INPUT_COUNT: usize = 4;
618 const CH_OFFSET: usize = 4;
619}
620
621impl MotuRegisterDspMeterSpecification for TravelerProtocol {
622 const INPUT_PORTS: &'static [TargetPort] = &[
623 TargetPort::Analog(0),
624 TargetPort::Analog(1),
625 TargetPort::Analog(2),
626 TargetPort::Analog(3),
627 TargetPort::Analog(4),
628 TargetPort::Analog(5),
629 TargetPort::Analog(6),
630 TargetPort::Analog(7),
631 TargetPort::AesEbu(8),
632 TargetPort::AesEbu(9),
633 TargetPort::Spdif(0),
634 TargetPort::Spdif(1),
635 TargetPort::Adat(0),
636 TargetPort::Adat(1),
637 TargetPort::Adat(2),
638 TargetPort::Adat(3),
639 TargetPort::Adat(4),
640 TargetPort::Adat(5),
641 TargetPort::Adat(6),
642 TargetPort::Adat(7),
643 ];
644 const OUTPUT_PORT_PAIRS: &'static [TargetPort] = &[
645 TargetPort::PhonePair,
646 TargetPort::AnalogPair(0),
647 TargetPort::AnalogPair(1),
648 TargetPort::AnalogPair(2),
649 TargetPort::AnalogPair(3),
650 TargetPort::AesEbuPair,
651 TargetPort::SpdifPair,
652 TargetPort::AdatPair(0),
653 TargetPort::AdatPair(1),
654 TargetPort::AdatPair(2),
655 TargetPort::AdatPair(3),
656 ];
657 const OUTPUT_PORT_PAIR_POS: &'static [[usize; 2]] = &[
658 [2, 3],
659 [4, 5],
660 [6, 7],
661 [8, 9],
662 [10, 11],
663 [12, 13],
664 [14, 15],
665 [16, 17],
666 [18, 19],
667 [20, 21],
668 [22, 23],
669 ];
670}
671
672impl MotuRegisterDspMeterOutputTargetSpecification for TravelerProtocol {}
673
674#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
676pub struct TravelerMicInputState {
677 pub gain: [u8; TravelerProtocol::MIC_INPUT_COUNT],
679 pub pad: [bool; TravelerProtocol::MIC_INPUT_COUNT],
681}
682
683const TRAVELER_MIC_PARAM_OFFSET: usize = 0x0c1c;
684const TRAVELER_MIC_GAIN_MASK: u8 = 0x3f;
685const TRAVELER_MIC_PAD_FLAG: u8 = 0x40;
686const TRAVELER_MIC_CHANGE_FLAG: u8 = 0x80;
687
688impl TravelerProtocol {
689 pub const NOTIFY_MIC_PARAM_MASK: u32 = 0x20000000;
691
692 pub const NOTIFY_PORT_CHANGE: u32 = 0x40000000;
694
695 pub const NOTIFY_FORMAT_CHANGE: u32 = 0x08000000;
697
698 pub const MIC_INPUT_COUNT: usize = 4;
700
701 pub const MIC_GAIN_MIN: u8 = 0x00;
703 pub const MIC_GAIN_MAX: u8 = 0x35;
705 pub const MIC_GAIN_STEP: u8 = 0x01;
707}
708
709impl MotuWhollyCacheableParamsOperation<TravelerMicInputState> for TravelerProtocol {
710 fn cache_wholly(
711 req: &mut FwReq,
712 node: &mut FwNode,
713 params: &mut TravelerMicInputState,
714 timeout_ms: u32,
715 ) -> Result<(), Error> {
716 read_quad(req, node, TRAVELER_MIC_PARAM_OFFSET as u32, timeout_ms).map(|val| {
717 (0..Self::MIC_INPUT_COUNT).for_each(|i| {
718 let v = ((val >> (i * 8)) & 0xff) as u8;
719 params.gain[i] = v & TRAVELER_MIC_GAIN_MASK;
720 params.pad[i] = v & TRAVELER_MIC_PAD_FLAG > 0;
721 });
722 })
723 }
724}
725
726impl MotuWhollyUpdatableParamsOperation<TravelerMicInputState> for TravelerProtocol {
727 fn update_wholly(
728 req: &mut FwReq,
729 node: &mut FwNode,
730 params: &TravelerMicInputState,
731 timeout_ms: u32,
732 ) -> Result<(), Error> {
733 let val = (0..Self::MIC_INPUT_COUNT).fold(0u32, |val, i| {
734 let mut v = TRAVELER_MIC_CHANGE_FLAG;
735 if params.pad[i] {
736 v |= TRAVELER_MIC_PAD_FLAG;
737 }
738 v |= params.gain[i] & TRAVELER_MIC_GAIN_MASK;
739 val | ((v as u32) << (i * 8))
740 });
741 write_quad(req, node, TRAVELER_MIC_PARAM_OFFSET as u32, val, timeout_ms)
742 }
743}
744
745#[derive(Default)]
747pub struct UltraliteProtocol;
748
749impl MotuPortAssignSpecification for UltraliteProtocol {
750 const ASSIGN_PORT_TARGETS: &'static [TargetPort] = &[
751 TargetPort::PhonePair, TargetPort::AnalogPair(0), TargetPort::AnalogPair(1), TargetPort::AnalogPair(2), TargetPort::AnalogPair(3), TargetPort::MainPair, TargetPort::SpdifPair, ];
759
760 const ASSIGN_PORT_VALS: &'static [u8] = &[
761 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ];
769}
770
771impl MotuClockNameDisplaySpecification for UltraliteProtocol {}
772
773impl MotuVersion2ClockSpecification for UltraliteProtocol {
774 const CLK_RATES: &'static [ClkRate] = &[
775 ClkRate::R44100,
776 ClkRate::R48000,
777 ClkRate::R88200,
778 ClkRate::R96000,
779 ];
780 const CLK_RATE_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x03];
781
782 const CLK_SRCS: &'static [V2ClkSrc] = &[V2ClkSrc::Internal, V2ClkSrc::SpdifCoax];
783 const CLK_SRC_VALS: &'static [u8] = &[0x00, 0x02];
784}
785
786impl MotuRegisterDspSpecification for UltraliteProtocol {
787 const MIXER_OUTPUT_DESTINATIONS: &'static [TargetPort] = &[
788 TargetPort::Disabled,
789 TargetPort::PhonePair,
790 TargetPort::AnalogPair(0),
791 TargetPort::AnalogPair(1),
792 TargetPort::AnalogPair(2),
793 TargetPort::AnalogPair(3),
794 TargetPort::MainPair,
795 TargetPort::SpdifPair,
796 ];
797}
798
799impl MotuRegisterDspMixerMonauralSourceSpecification for UltraliteProtocol {
800 const MIXER_SOURCES: &'static [TargetPort] = &[
801 TargetPort::Analog(0),
802 TargetPort::Analog(1),
803 TargetPort::Analog(2),
804 TargetPort::Analog(3),
805 TargetPort::Analog(4),
806 TargetPort::Analog(5),
807 TargetPort::Analog(6),
808 TargetPort::Analog(7),
809 TargetPort::Spdif(0),
810 TargetPort::Spdif(1),
811 ];
812}
813
814impl MotuRegisterDspMonauralInputSpecification for UltraliteProtocol {}
815
816impl MotuRegisterDspMeterSpecification for UltraliteProtocol {
817 const INPUT_PORTS: &'static [TargetPort] = &[
818 TargetPort::Analog(0),
819 TargetPort::Analog(1),
820 TargetPort::Analog(2),
821 TargetPort::Analog(3),
822 TargetPort::Analog(4),
823 TargetPort::Analog(5),
824 TargetPort::Analog(6),
825 TargetPort::Analog(7),
826 TargetPort::Spdif(0),
827 TargetPort::Spdif(1),
828 ];
829 const OUTPUT_PORT_PAIRS: &'static [TargetPort] = &[
830 TargetPort::PhonePair,
831 TargetPort::AnalogPair(0),
832 TargetPort::AnalogPair(1),
833 TargetPort::AnalogPair(2),
834 TargetPort::AnalogPair(3),
835 TargetPort::MainPair,
836 TargetPort::SpdifPair,
837 ];
838 const OUTPUT_PORT_PAIR_POS: &'static [[usize; 2]] =
839 &[[2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15]];
840}
841
842#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
844pub struct UltraliteMainAssign(pub TargetPort);
845
846const ULTRALITE_MAIN_ASSIGN_MASK: u32 = 0x000f0000;
847const ULTRALITE_MAIN_ASSIGN_SHIFT: usize = 16;
848const ULTRALITE_MAIN_ASSIGN_LABEL: &str = "ultralite-main-assign";
849
850impl UltraliteProtocol {
851 pub const NOTIFY_PORT_CHANGE: u32 = 0x40000000;
854
855 pub const KNOB_TARGETS: &'static [TargetPort] = &[
857 TargetPort::MainPair,
858 TargetPort::Analog6Pairs,
859 TargetPort::Analog8Pairs,
860 TargetPort::SpdifPair,
861 ];
862
863 pub const INPUT_COUNT: usize = 10;
865
866 pub const INPUT_GAIN_MIN: u8 = 0x00;
868 pub const INPUT_GAIN_MAX: u8 = 0x18;
870 pub const INPUT_GAIN_STEP: u8 = 0x01;
872}
873
874const KNOB_TARGET_VALS: &[u8] = &[0x00, 0x01, 0x02, 0x03];
875
876impl MotuWhollyCacheableParamsOperation<UltraliteMainAssign> for UltraliteProtocol {
877 fn cache_wholly(
878 req: &mut FwReq,
879 node: &mut FwNode,
880 params: &mut UltraliteMainAssign,
881 timeout_ms: u32,
882 ) -> Result<(), Error> {
883 let quad = read_quad(req, node, OFFSET_PORT, timeout_ms)?;
884 deserialize_flag(
885 &mut params.0,
886 &quad,
887 ULTRALITE_MAIN_ASSIGN_MASK,
888 ULTRALITE_MAIN_ASSIGN_SHIFT,
889 Self::KNOB_TARGETS,
890 KNOB_TARGET_VALS,
891 ULTRALITE_MAIN_ASSIGN_LABEL,
892 )
893 }
894}
895
896impl MotuWhollyUpdatableParamsOperation<UltraliteMainAssign> for UltraliteProtocol {
897 fn update_wholly(
899 req: &mut FwReq,
900 node: &mut FwNode,
901 params: &UltraliteMainAssign,
902 timeout_ms: u32,
903 ) -> Result<(), Error> {
904 let mut quad = read_quad(req, node, OFFSET_PORT, timeout_ms)?;
905 serialize_flag(
906 ¶ms.0,
907 &mut quad,
908 ULTRALITE_MAIN_ASSIGN_MASK,
909 ULTRALITE_MAIN_ASSIGN_SHIFT,
910 Self::KNOB_TARGETS,
911 KNOB_TARGET_VALS,
912 ULTRALITE_MAIN_ASSIGN_LABEL,
913 )?;
914 write_quad(req, node, OFFSET_PORT, quad, timeout_ms)
915 }
916}
917
918#[derive(Default)]
920pub struct F896hdProtocol;
921
922impl F896hdProtocol {
923 pub const NOTIFY_PROGRAMMABLE_METER_MASK: u32 = 0x40000000;
925
926 pub const NOTIFY_FOOTSWITCH_MASK: u32 = 0x01000000;
928}
929
930impl MotuPortAssignSpecification for F896hdProtocol {
931 const ASSIGN_PORT_TARGETS: &'static [TargetPort] = &[
932 TargetPort::PhonePair, TargetPort::AnalogPair(0), TargetPort::AnalogPair(1), TargetPort::AnalogPair(2), TargetPort::AnalogPair(3), TargetPort::MainPair, TargetPort::AesEbuPair, TargetPort::AdatPair(0), TargetPort::AdatPair(1), TargetPort::AdatPair(2), TargetPort::AdatPair(3), ];
944
945 const ASSIGN_PORT_VALS: &'static [u8] = &[
946 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, ];
958}
959
960impl MotuWordClockOutputSpecification for F896hdProtocol {}
961
962impl MotuAesebuRateConvertSpecification for F896hdProtocol {
963 const AESEBU_RATE_CONVERT_MASK: u32 = 0x00000300;
964 const AESEBU_RATE_CONVERT_SHIFT: usize = 8;
965}
966
967impl MotuLevelMetersSpecification for F896hdProtocol {
968 const LEVEL_METERS_PROGRAMMABLE_MODES: &'static [LevelMetersProgrammableMode] = &[
969 LevelMetersProgrammableMode::AnalogOutput,
970 LevelMetersProgrammableMode::AdatAInput,
971 LevelMetersProgrammableMode::AdatAOutput,
972 ];
973}
974
975impl MotuVersion2ClockSpecification for F896hdProtocol {
976 const CLK_RATES: &'static [ClkRate] = &[
977 ClkRate::R44100,
978 ClkRate::R48000,
979 ClkRate::R88200,
980 ClkRate::R96000,
981 ClkRate::R176400,
982 ClkRate::R192000,
983 ];
984 const CLK_RATE_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05];
985
986 const CLK_SRCS: &'static [V2ClkSrc] = &[
987 V2ClkSrc::Internal,
988 V2ClkSrc::AdatOpt,
989 V2ClkSrc::AesebuXlr,
990 V2ClkSrc::WordClk,
991 V2ClkSrc::AdatDsub,
992 ];
993 const CLK_SRC_VALS: &'static [u8] = &[0x00, 0x01, 0x02, 0x04, 0x05];
994}
995
996impl MotuVersion2OpticalIfaceSpecification for F896hdProtocol {
997 const OPT_IFACE_MODES: &'static [V2OptIfaceMode] =
998 &[V2OptIfaceMode::None, V2OptIfaceMode::Adat];
999}
1000
1001impl MotuRegisterDspSpecification for F896hdProtocol {
1002 const MIXER_OUTPUT_DESTINATIONS: &'static [TargetPort] = &[
1003 TargetPort::Disabled,
1004 TargetPort::PhonePair,
1005 TargetPort::AnalogPair(0),
1006 TargetPort::AnalogPair(1),
1007 TargetPort::AnalogPair(2),
1008 TargetPort::AnalogPair(3),
1009 TargetPort::MainPair,
1010 TargetPort::AesEbuPair,
1011 TargetPort::AdatPair(0),
1012 TargetPort::AdatPair(1),
1013 TargetPort::AdatPair(2),
1014 TargetPort::AdatPair(3),
1015 ];
1016}
1017
1018impl MotuRegisterDspMixerMonauralSourceSpecification for F896hdProtocol {
1019 const MIXER_SOURCES: &'static [TargetPort] = &[
1020 TargetPort::Analog(0),
1021 TargetPort::Analog(1),
1022 TargetPort::Analog(2),
1023 TargetPort::Analog(3),
1024 TargetPort::Analog(4),
1025 TargetPort::Analog(5),
1026 TargetPort::Analog(6),
1027 TargetPort::Analog(7),
1028 TargetPort::AesEbu(0),
1029 TargetPort::AesEbu(1),
1030 TargetPort::Adat(0),
1031 TargetPort::Adat(1),
1032 TargetPort::Adat(2),
1033 TargetPort::Adat(3),
1034 TargetPort::Adat(4),
1035 TargetPort::Adat(5),
1036 TargetPort::Adat(6),
1037 TargetPort::Adat(7),
1038 ];
1039}
1040
1041impl MotuRegisterDspMeterSpecification for F896hdProtocol {
1042 const INPUT_PORTS: &'static [TargetPort] = &[
1043 TargetPort::Analog(0),
1044 TargetPort::Analog(1),
1045 TargetPort::Analog(2),
1046 TargetPort::Analog(3),
1047 TargetPort::Analog(4),
1048 TargetPort::Analog(5),
1049 TargetPort::Analog(6),
1050 TargetPort::Analog(7),
1051 TargetPort::AesEbu(0),
1052 TargetPort::AesEbu(1),
1053 TargetPort::Adat(0),
1054 TargetPort::Adat(1),
1055 TargetPort::Adat(2),
1056 TargetPort::Adat(3),
1057 TargetPort::Adat(4),
1058 TargetPort::Adat(5),
1059 TargetPort::Adat(6),
1060 TargetPort::Adat(7),
1061 ];
1062 const OUTPUT_PORT_PAIRS: &'static [TargetPort] = &[
1063 TargetPort::PhonePair,
1064 TargetPort::AnalogPair(0),
1065 TargetPort::AnalogPair(1),
1066 TargetPort::AnalogPair(2),
1067 TargetPort::AnalogPair(3),
1068 TargetPort::MainPair,
1069 TargetPort::AesEbuPair,
1070 TargetPort::AdatPair(0),
1071 TargetPort::AdatPair(1),
1072 TargetPort::AdatPair(2),
1073 TargetPort::AdatPair(3),
1074 ];
1075 const OUTPUT_PORT_PAIR_POS: &'static [[usize; 2]] = &[
1076 [2, 3],
1077 [4, 5],
1078 [6, 7],
1079 [8, 9],
1080 [10, 11],
1081 [12, 13],
1082 [14, 15],
1083 [16, 17],
1084 [18, 19],
1085 [20, 21],
1086 [22, 23],
1087 ];
1088}
1089
1090impl MotuRegisterDspMeterOutputTargetSpecification for F896hdProtocol {}
1091
1092#[cfg(test)]
1093mod test {
1094 use super::*;
1095
1096 #[test]
1097 fn common_assign_port_specification() {
1098 assert_eq!(
1099 F828mk2Protocol::ASSIGN_PORT_TARGETS.len(),
1100 F828mk2Protocol::ASSIGN_PORT_VALS.len()
1101 );
1102 assert_eq!(
1103 F8preProtocol::ASSIGN_PORT_TARGETS.len(),
1104 F8preProtocol::ASSIGN_PORT_VALS.len()
1105 );
1106 assert_eq!(
1107 TravelerProtocol::ASSIGN_PORT_TARGETS.len(),
1108 TravelerProtocol::ASSIGN_PORT_VALS.len()
1109 );
1110 assert_eq!(
1111 UltraliteProtocol::ASSIGN_PORT_TARGETS.len(),
1112 UltraliteProtocol::ASSIGN_PORT_VALS.len()
1113 );
1114 assert_eq!(
1115 F896hdProtocol::ASSIGN_PORT_TARGETS.len(),
1116 F896hdProtocol::ASSIGN_PORT_VALS.len()
1117 );
1118 }
1119
1120 #[test]
1121 fn v2_clock_specification() {
1122 assert_eq!(
1123 F828mk2Protocol::CLK_RATES.len(),
1124 F828mk2Protocol::CLK_RATE_VALS.len()
1125 );
1126 assert_eq!(
1127 F828mk2Protocol::CLK_SRCS.len(),
1128 F828mk2Protocol::CLK_SRC_VALS.len()
1129 );
1130
1131 assert_eq!(
1132 F8preProtocol::CLK_RATES.len(),
1133 F8preProtocol::CLK_RATE_VALS.len()
1134 );
1135 assert_eq!(
1136 F8preProtocol::CLK_SRCS.len(),
1137 F8preProtocol::CLK_SRC_VALS.len()
1138 );
1139
1140 assert_eq!(
1141 TravelerProtocol::CLK_RATES.len(),
1142 TravelerProtocol::CLK_RATE_VALS.len()
1143 );
1144 assert_eq!(
1145 TravelerProtocol::CLK_SRCS.len(),
1146 TravelerProtocol::CLK_SRC_VALS.len()
1147 );
1148
1149 assert_eq!(
1150 UltraliteProtocol::CLK_RATES.len(),
1151 UltraliteProtocol::CLK_RATE_VALS.len()
1152 );
1153 assert_eq!(
1154 UltraliteProtocol::CLK_SRCS.len(),
1155 UltraliteProtocol::CLK_SRC_VALS.len()
1156 );
1157
1158 assert_eq!(
1159 F896hdProtocol::CLK_RATES.len(),
1160 F896hdProtocol::CLK_RATE_VALS.len()
1161 );
1162 assert_eq!(
1163 F896hdProtocol::CLK_SRCS.len(),
1164 F896hdProtocol::CLK_SRC_VALS.len()
1165 );
1166 }
1167
1168 #[test]
1169 fn register_dsp_meter_specification() {
1170 assert_eq!(
1171 F828mk2Protocol::OUTPUT_PORT_PAIRS.len(),
1172 F828mk2Protocol::OUTPUT_PORT_PAIR_POS.len(),
1173 );
1174
1175 assert_eq!(
1176 F8preProtocol::OUTPUT_PORT_PAIRS.len(),
1177 F8preProtocol::OUTPUT_PORT_PAIR_POS.len(),
1178 );
1179
1180 assert_eq!(
1181 TravelerProtocol::OUTPUT_PORT_PAIRS.len(),
1182 TravelerProtocol::OUTPUT_PORT_PAIR_POS.len(),
1183 );
1184
1185 assert_eq!(
1186 UltraliteProtocol::OUTPUT_PORT_PAIRS.len(),
1187 UltraliteProtocol::OUTPUT_PORT_PAIR_POS.len(),
1188 );
1189
1190 assert_eq!(
1191 F896hdProtocol::OUTPUT_PORT_PAIRS.len(),
1192 F896hdProtocol::OUTPUT_PORT_PAIR_POS.len(),
1193 );
1194 }
1195
1196 #[test]
1197 fn ultralite_specification() {
1198 assert_eq!(
1199 UltraliteProtocol::KNOB_TARGETS.len(),
1200 KNOB_TARGET_VALS.len()
1201 );
1202 }
1203}