valentine

Terminal control panel for the Focusrite Scarlett 18i20 — a from-scratch replacement for Focusrite Control.
Log | Files | Refs | README | LICENSE

commit 59fadb844d09c033ffa3ff387ec8817cf1e6ee86
parent 3d156748656c3759baf294fc5e4197a5adc96af9
Author: Matthew Gantenbein <ganten1998@gmail.com>
Date:   Mon,  1 Jun 2026 15:40:58 -0500

diag(spike): adatset writes each routing table separately to find 0x3

Diffstat:
Mscarlett-core/src/matrix.rs | 17+++++++++++++++++
Mspike/src/bin/adatset.rs | 30+++++++++++++++++++-----------
2 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/scarlett-core/src/matrix.rs b/scarlett-core/src/matrix.rs @@ -328,6 +328,23 @@ impl<T: Transport> Scarlett<T> { Ok(()) } + /// Write a single routing table by index — diagnostics: pinpoint which of the + /// 3 sample-rate-band tables the device rejects. + pub fn write_routing_table( + &mut self, + table_num: u16, + data: &[u32], + ) -> Result<(), TransportError> { + let mut payload = Vec::with_capacity(4 + data.len() * 4); + payload.extend_from_slice(&0u16.to_le_bytes()); + payload.extend_from_slice(&table_num.to_le_bytes()); + for v in data { + payload.extend_from_slice(&v.to_le_bytes()); + } + self.command(op::SET_MUX, &payload, 0)?; + Ok(()) + } + /// Build (but do NOT send) the per-table SET_MUX payload byte-vectors for a /// routing state — for inspection / dry-run verification before writing. pub fn dry_run_routing(tables: &[Vec<u32>]) -> Vec<Vec<u8>> { diff --git a/spike/src/bin/adatset.rs b/spike/src/bin/adatset.rs @@ -44,20 +44,28 @@ fn run() -> Result<(), Box<dyn std::error::Error>> { let db: f32 = arg.parse().map_err(|_| "pass a dB number, or 'direct'")?; println!("Routing ADAT via mixer and setting level to {db} dB (persisting)…"); - match dev.route_group_via_mixer(pc, g) { - Ok(_) => println!(" route_group_via_mixer: OK"), - Err(e) => { - println!(" route_group_via_mixer: FAILED — {e}"); - return Err(e.into()); - } + + // Write the 3 sample-rate-band tables SEPARATELY to see which one fails. + use scarlett_core::mux::{id_to_num, mux_assignment_18i20_gen3, num_dsts, Dir, MuxState}; + let n = |dir, id| id_to_num(&pc, dir, id).unwrap_or(0); + let entries = dev.get_mux(num_dsts(&pc))?; + let mut st = MuxState::from_entries(pc, &entries); + for i in 0..g.count { + st.set(n(Dir::Out, 0x300 + g.mix_in_base + i), n(Dir::In, 0x600 + g.pcm_base + i)); + st.set(n(Dir::Out, g.out_id_base + i), n(Dir::In, 0x300 + g.bus_base + i)); } - match dev.set_group_level(g, db, inputs) { - Ok(()) => println!(" set_group_level: OK"), - Err(e) => { - println!(" set_group_level: FAILED — {e}"); - return Err(e.into()); + let tables = st.encode_all(&mux_assignment_18i20_gen3()); + for (i, t) in tables.iter().enumerate() { + match dev.write_routing_table(i as u16, t) { + Ok(()) => println!(" table {i} ({} entries): OK", t.len()), + Err(e) => println!(" table {i} ({} entries): FAILED — {e}", t.len()), } } + if let Err(e) = dev.set_group_level(g, db, inputs) { + println!(" set_group_level: FAILED — {e}"); + } else { + println!(" set_group_level: OK"); + } // Read back so we report the truth. let raw = dev.get_mix(g.bus_base, inputs)?;