mx_remote/types/amp.rs
1// Author: Lars Op den Kamp (lars@opdenkamp-it.nl)
2// Copyright (c) 2026 Op den Kamp IT Solutions
3
4//! ProAmp8 zone and Dolby settings.
5
6/// Number of EQ bands a zone carries (`AMP_DOLBYEQBANDS_MAX`).
7pub const AMP_EQ_BANDS: usize = 5;
8
9/// The neutral value for bass, treble and the EQ bands.
10///
11/// These are raw unsigned bytes; the firmware header describes a signed range,
12/// which is wrong at both ends.
13pub const AMP_TONE_FLAT: u8 = 128;
14
15/// Lowest tone value the amp's own HTTP API accepts.
16///
17/// Nothing enforces this here: the mesh receive path copies these bytes
18/// straight through without a range check, so a peer can put any value on the
19/// wire and the amp will take it. This library reports what arrived. Clamping
20/// to these bounds imposes one device's HTTP policy on a mesh peer - reasonable,
21/// but a caller's decision to make knowingly.
22pub const AMP_TONE_HTTP_MIN: u8 = 104;
23
24/// Highest tone value the amp's own HTTP API accepts. See [`AMP_TONE_HTTP_MIN`].
25pub const AMP_TONE_HTTP_MAX: u8 = 140;
26
27/// A ProAmp8 zone's gain, delay, tone and power settings.
28///
29/// Gains and volume limits run 0-248 in 0.5dB steps, with 200 as 0dB. Gains are
30/// `int16` inside the amp but a byte on the mesh, so a frame cannot carry the
31/// amp's full internal range.
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub struct AmpZoneSettings {
34 /// Left channel gain.
35 pub gain_left: u8,
36 /// Right channel gain.
37 pub gain_right: u8,
38 /// Lowest volume the zone may be set to.
39 pub volume_min: u8,
40 /// Highest volume the zone may be set to.
41 pub volume_max: u8,
42 /// Left channel delay, in 1/48000 second increments.
43 pub delay_left: u32,
44 /// Right channel delay, in 1/48000 second increments.
45 pub delay_right: u32,
46 /// Bass tone control, neutral at [`AMP_TONE_FLAT`].
47 pub bass: u8,
48 /// Treble tone control, neutral at [`AMP_TONE_FLAT`].
49 pub treble: u8,
50 /// 0 = normal, 1 = bridged.
51 pub bridged: u8,
52 /// Power-on mode.
53 pub power_mode: u8,
54 /// Signal level that switches the zone on automatically.
55 pub power_level: u8,
56 /// Idle time before the zone powers down, in seconds.
57 pub power_timeout: u32,
58 /// Left channel EQ, from 100Hz to 10KHz, neutral at [`AMP_TONE_FLAT`].
59 pub eq_left: [u8; AMP_EQ_BANDS],
60 /// Right channel EQ, from 100Hz to 10KHz, neutral at [`AMP_TONE_FLAT`].
61 pub eq_right: [u8; AMP_EQ_BANDS],
62}
63
64impl Default for AmpZoneSettings {
65 fn default() -> Self {
66 Self {
67 gain_left: 0,
68 gain_right: 0,
69 volume_min: 0,
70 volume_max: 0,
71 delay_left: 0,
72 delay_right: 0,
73 bass: AMP_TONE_FLAT,
74 treble: AMP_TONE_FLAT,
75 bridged: 0,
76 power_mode: 0,
77 power_level: 0,
78 power_timeout: 0,
79 eq_left: [AMP_TONE_FLAT; AMP_EQ_BANDS],
80 eq_right: [AMP_TONE_FLAT; AMP_EQ_BANDS],
81 }
82 }
83}
84
85/// The Dolby processing state of a ProAmp8.
86#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
87pub struct AmpDolbySettings {
88 /// 0 = standard, 1 = 3-zone Dolby, 2 = 4-zone Dolby.
89 pub mode: u8,
90 /// Whether PCM is up-mixed to 5.1 rather than passed through.
91 pub pcm_upmix: bool,
92 /// Whether a Dolby stream was detected.
93 pub dolby_detected: bool,
94 /// Whether up-mixing is currently running.
95 pub pcm_upmix_active: bool,
96}