Skip to main content

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}