valentine

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

adatfader.rs (3505B)


      1 //! ADAT-fader chain diagnostic. Runs the exact via-mixer + level sequence the
      2 //! TUI does, reading device state back at each step so we can see precisely
      3 //! where the fader chain breaks. Restores ADAT to direct-from-DAW at the end.
      4 //!
      5 //! Run with Focusrite Control quit:  cargo run -p spike --bin adatfader
      6 
      7 use scarlett_core::matrix::mixer_value_to_db;
      8 use scarlett_core::model::S18I20_GEN3;
      9 use scarlett_core::mux::{id_to_num, num_dsts, num_to_id, Dir, MuxState, PORT_COUNT_18I20_GEN3};
     10 use scarlett_core::ports::source_name;
     11 use scarlett_core::{Scarlett, UsbTransport};
     12 
     13 fn main() {
     14     if let Err(e) = run() {
     15         eprintln!("\x1b[31mADATFADER FAILED:\x1b[0m {e}");
     16         std::process::exit(1);
     17     }
     18 }
     19 
     20 fn adat_group() -> &'static scarlett_core::matrix::MonitorGroup {
     21     scarlett_core::matrix::MONITOR_GROUPS
     22         .iter()
     23         .find(|g| g.name.starts_with("ADAT"))
     24         .expect("ADAT group exists")
     25 }
     26 
     27 fn show_adat_routing(dev: &mut Scarlett<UsbTransport>, pc: [(u16, u16); 6], tag: &str) {
     28     let entries = dev.get_mux(num_dsts(&pc)).unwrap();
     29     let st = MuxState::from_entries(pc, &entries);
     30     println!("--- ADAT Out routing [{tag}] ---");
     31     for i in 0..8u16 {
     32         let out = id_to_num(&pc, Dir::Out, 0x200 + i).unwrap_or(0);
     33         let src = num_to_id(&pc, Dir::In, st.get(out));
     34         println!("  ADAT Out {} ← {}", i + 1, source_name(src));
     35     }
     36 }
     37 
     38 fn run() -> Result<(), Box<dyn std::error::Error>> {
     39     let mut dev = Scarlett::new(UsbTransport::open_default()?);
     40     dev.init()?;
     41     let pc = PORT_COUNT_18I20_GEN3;
     42     let g = adat_group();
     43     let inputs = S18I20_GEN3.mixer_inputs() as usize;
     44     println!("connected: {}\n", S18I20_GEN3.name);
     45 
     46     show_adat_routing(&mut dev, pc, "before");
     47 
     48     // Step 1: route ADAT via mixer.
     49     println!("\n>>> route_group_via_mixer(ADAT)");
     50     dev.route_group_via_mixer(pc, g)?;
     51     show_adat_routing(&mut dev, pc, "after via-mixer");
     52 
     53     // What feeds the ADAT mixer-inputs now?
     54     let entries = dev.get_mux(num_dsts(&pc))?;
     55     let st = MuxState::from_entries(pc, &entries);
     56     println!("--- ADAT mixer-input feeds ---");
     57     for i in 0..g.count {
     58         let mi = id_to_num(&pc, Dir::Out, 0x300 + g.mix_in_base + i).unwrap_or(0);
     59         let src = num_to_id(&pc, Dir::In, st.get(mi));
     60         println!("  MixerIn {} ← {}", g.mix_in_base + i + 1, source_name(src));
     61     }
     62 
     63     // Step 2: set group level to -40 dB and read the buses back.
     64     println!("\n>>> set_group_level(ADAT, -40 dB)");
     65     dev.set_group_level(g, -40.0, inputs)?;
     66     for i in 0..g.count {
     67         let bus = g.bus_base + i;
     68         let raw = dev.get_mix(bus, inputs)?;
     69         let in_idx = (g.mix_in_base + i) as usize;
     70         let this = raw.get(in_idx).map(|&v| mixer_value_to_db(v)).unwrap_or(-99.0);
     71         let nonzero = raw.iter().filter(|&&v| v > 0).count();
     72         println!(
     73             "  Mix bus {bus:>2}: input {} = {this:>6.1} dB   ({nonzero} non-silent inputs total)",
     74             in_idx + 1
     75         );
     76     }
     77 
     78     println!(
     79         "\nEXPECTED: ADAT Out ← Mix C..J; MixerIn ← PCM 13..20; each bus shows its\n\
     80          one input at -40 dB. If routing still shows ← PCM, the route write failed.\n\
     81          If the bus input isn't -40, the level write/index is wrong."
     82     );
     83 
     84     // Restore: ADAT back to direct from DAW.
     85     println!("\n>>> restoring ADAT to direct-from-DAW");
     86     dev.route_group_direct(pc, g)?;
     87     show_adat_routing(&mut dev, pc, "restored");
     88 
     89     println!("\nADATFADER DONE.");
     90     Ok(())
     91 }