|
5 | 5 |
|
6 | 6 | use crate::player::{DeviceConfigCmd, DeviceConfigEdit}; |
7 | 7 | use crate::ui::DeviceConfigSnapshot; |
| 8 | +use usbsid_pico_config::protocol::{cfg as cfg_op, encode_packet}; |
8 | 9 | use usbsid_pico_config::transport::Transport; |
9 | 10 | use usbsid_pico_config::Device; |
10 | 11 |
|
| 12 | +/// Send a single fire-and-forget config opcode (no response expected). |
| 13 | +/// Used for the diagnostic / hardware action commands the crate doesn't |
| 14 | +/// expose as named wrappers (TEST_SID, RESET_USBSID, MIDI state, etc.). |
| 15 | +fn send_cfg_opcode<T: Transport>( |
| 16 | + dev: &mut Device<T>, |
| 17 | + cmd: u8, |
| 18 | + args: [u8; 4], |
| 19 | +) -> Result<(), String> { |
| 20 | + let packet = encode_packet(cmd, args); |
| 21 | + dev.transport_mut() |
| 22 | + .send(&packet) |
| 23 | + .map_err(|e| format!("send opcode {cmd:#04X}: {e}")) |
| 24 | +} |
| 25 | + |
11 | 26 | /// Execute `op` against the device wrapped by `transport`. Returns |
12 | 27 | /// `Some(snapshot)` only for `Refresh` (and as an after-effect of |
13 | 28 | /// auto-detect, since callers will want the resulting config). For |
@@ -73,6 +88,85 @@ pub fn run<T: Transport>( |
73 | 88 | std::thread::sleep(std::time::Duration::from_millis(3500)); |
74 | 89 | refresh(&mut dev).map(Some) |
75 | 90 | } |
| 91 | + |
| 92 | + DeviceConfigCmd::Confirm => { |
| 93 | + dev.confirm_config() |
| 94 | + .map_err(|e| format!("confirm_config: {e}"))?; |
| 95 | + refresh(&mut dev).map(Some) |
| 96 | + } |
| 97 | + |
| 98 | + DeviceConfigCmd::DetectSids => { |
| 99 | + dev.detect_sids().map_err(|e| format!("detect_sids: {e}"))?; |
| 100 | + std::thread::sleep(std::time::Duration::from_millis(1500)); |
| 101 | + refresh(&mut dev).map(Some) |
| 102 | + } |
| 103 | + |
| 104 | + DeviceConfigCmd::DetectClones => { |
| 105 | + dev.detect_clones() |
| 106 | + .map_err(|e| format!("detect_clones: {e}"))?; |
| 107 | + std::thread::sleep(std::time::Duration::from_millis(2500)); |
| 108 | + refresh(&mut dev).map(Some) |
| 109 | + } |
| 110 | + |
| 111 | + DeviceConfigCmd::TestSid(which) => { |
| 112 | + let cmd = match *which { |
| 113 | + 0 => cfg_op::TEST_ALLSIDS, |
| 114 | + 1 => cfg_op::TEST_SID1, |
| 115 | + 2 => cfg_op::TEST_SID2, |
| 116 | + 3 => cfg_op::TEST_SID3, |
| 117 | + 4 => cfg_op::TEST_SID4, |
| 118 | + other => return Err(format!("TestSid: invalid SID index {other}")), |
| 119 | + }; |
| 120 | + send_cfg_opcode(&mut dev, cmd, [0, 0, 0, 0])?; |
| 121 | + Ok(None) |
| 122 | + } |
| 123 | + |
| 124 | + DeviceConfigCmd::StopTests => { |
| 125 | + send_cfg_opcode(&mut dev, cfg_op::STOP_TESTS, [0, 0, 0, 0])?; |
| 126 | + Ok(None) |
| 127 | + } |
| 128 | + |
| 129 | + DeviceConfigCmd::ResetUsbsid => { |
| 130 | + send_cfg_opcode(&mut dev, cfg_op::RESET_USBSID, [0, 0, 0, 0])?; |
| 131 | + // Device re-enumerates — drop the handle; the GUI will reconnect. |
| 132 | + Ok(None) |
| 133 | + } |
| 134 | + |
| 135 | + DeviceConfigCmd::RestartBus => { |
| 136 | + send_cfg_opcode(&mut dev, cfg_op::RESTART_BUS, [0, 0, 0, 0])?; |
| 137 | + Ok(None) |
| 138 | + } |
| 139 | + |
| 140 | + DeviceConfigCmd::RestartBusClk => { |
| 141 | + send_cfg_opcode(&mut dev, cfg_op::RESTART_BUS_CLK, [0, 0, 0, 0])?; |
| 142 | + Ok(None) |
| 143 | + } |
| 144 | + |
| 145 | + DeviceConfigCmd::SyncPios => { |
| 146 | + send_cfg_opcode(&mut dev, cfg_op::SYNC_PIOS, [0, 0, 0, 0])?; |
| 147 | + Ok(None) |
| 148 | + } |
| 149 | + |
| 150 | + DeviceConfigCmd::SocketDetect => { |
| 151 | + send_cfg_opcode(&mut dev, cfg_op::SOCKET_DETECT, [0, 0, 0, 0])?; |
| 152 | + std::thread::sleep(std::time::Duration::from_millis(500)); |
| 153 | + refresh(&mut dev).map(Some) |
| 154 | + } |
| 155 | + |
| 156 | + DeviceConfigCmd::MidiLoadState => { |
| 157 | + send_cfg_opcode(&mut dev, cfg_op::LOAD_MIDI_STATE, [0, 0, 0, 0])?; |
| 158 | + Ok(None) |
| 159 | + } |
| 160 | + |
| 161 | + DeviceConfigCmd::MidiSaveState => { |
| 162 | + send_cfg_opcode(&mut dev, cfg_op::SAVE_MIDI_STATE, [0, 0, 0, 0])?; |
| 163 | + Ok(None) |
| 164 | + } |
| 165 | + |
| 166 | + DeviceConfigCmd::MidiResetState => { |
| 167 | + send_cfg_opcode(&mut dev, cfg_op::RESET_MIDI_STATE, [0, 0, 0, 0])?; |
| 168 | + Ok(None) |
| 169 | + } |
76 | 170 | } |
77 | 171 | } |
78 | 172 |
|
@@ -106,8 +200,17 @@ fn apply_edit(cfg: &mut usbsid_pico_config::DeviceConfig, edit: DeviceConfigEdit |
106 | 200 | Flipped(v) => cfg.flipped = v, |
107 | 201 | Mixed(v) => cfg.mixed = v, |
108 | 202 | FmoplEnabled(v) => cfg.protocols.fmopl_enabled = v, |
| 203 | + FmoplSidno(v) => cfg.protocols.fmopl_sidno = v, |
109 | 204 | LockClockrate(v) => cfg.lock_clockrate = v, |
110 | 205 | ExternalClock(v) => cfg.external_clock = v, |
| 206 | + LedEnabled(v) => cfg.led.enabled = v, |
| 207 | + LedIdleBreathe(v) => cfg.led.idle_breathe = v, |
| 208 | + RgbLedEnabled(v) => cfg.rgb_led.enabled = v, |
| 209 | + RgbLedIdleBreathe(v) => cfg.rgb_led.idle_breathe = v, |
| 210 | + RgbLedBrightness(v) => cfg.rgb_led.brightness = v, |
| 211 | + RgbLedSidToUse(v) => cfg.rgb_led.sid_to_use = v, |
| 212 | + NeedConfirmation(v) => cfg.need_confirmation = v, |
| 213 | + DisableChangeDetect(v) => cfg.disable_changedetect = v, |
111 | 214 | } |
112 | 215 | } |
113 | 216 |
|
|
0 commit comments