1use handwired_rs::TensorExecutor;
10use handwired_rs::dsl::Params;
11use handwired_rs::handwired;
12
13const TOGGLE: (i16, i16, i16, i16) = (40, 40, 144, 96);
16const SLIDER_LEFT: i16 = 40;
17
18#[handwired]
22#[allow(clippy::too_many_arguments)]
23fn ui_frame(
24 on: bool,
25 armed: bool,
26 dragging: bool,
27 #[range(0, 100)] level: u8,
28 #[range(0, 1)] thumb: f32,
29 #[range(0, 480)] x: i16,
30 #[range(0, 200)] y: i16,
31 pressed: bool,
32 released: bool,
33) -> (bool, bool, bool, u8, f32) {
34 let mut on = on;
35 let mut armed = armed;
36 let mut dragging = dragging;
37 let mut level = level;
38 let mut thumb = thumb;
39 let on_toggle = x >= 40 && x < 144 && y >= 40 && y < 96;
40 let on_slider = x >= 28 && x < 452 && y >= 134 && y < 166;
41
42 if pressed {
43 armed = on_toggle;
44 if on_slider {
45 dragging = true;
46 }
47 }
48 if dragging {
49 let raw = ((x - 40) / 4).clamp(0, 100);
51 level = ((raw + 2) / 5 * 5) as u8;
52 }
53 if released {
54 if armed && on_toggle {
55 on = !on;
56 }
57 armed = false;
58 dragging = false;
59 }
60
61 let target: f32 = if on { 1.0 } else { 0.0 };
63 thumb = (thumb + (target - thumb) * 0.3).clamp(0.0, 1.0);
64 if (target - thumb).abs() < 0.01 {
65 thumb = target;
66 }
67 (on, armed, dragging, level, thumb)
68}
69
70fn script() -> Vec<(i16, i16, bool, bool, bool)> {
72 let mut frames = Vec::new();
73 let mut at = (300i16, 20i16);
74 let mut held = false;
75 let move_to = |frames: &mut Vec<_>, at: &mut (i16, i16), held: bool, target: (i16, i16), steps: i16| {
76 let start = *at;
77 for step in 1..=steps {
78 let x = start.0 + (target.0 - start.0) * step / steps;
79 let y = start.1 + (target.1 - start.1) * step / steps;
80 frames.push((x, y, false, false, held));
81 }
82 *at = target;
83 };
84 let pause = |frames: &mut Vec<_>, at: (i16, i16), held: bool, count: usize| {
85 for _ in 0..count {
86 frames.push((at.0, at.1, false, false, held));
87 }
88 };
89 let press = |frames: &mut Vec<_>, at: (i16, i16), held: &mut bool| {
90 *held = true;
91 frames.push((at.0, at.1, true, false, true));
92 };
93 let release = |frames: &mut Vec<_>, at: (i16, i16), held: &mut bool| {
94 *held = false;
95 frames.push((at.0, at.1, false, true, false));
96 };
97 pause(&mut frames, at, held, 8);
98 move_to(&mut frames, &mut at, held, (92, 68), 14);
100 press(&mut frames, at, &mut held);
101 pause(&mut frames, at, held, 4);
102 release(&mut frames, at, &mut held);
103 pause(&mut frames, at, held, 14);
104 move_to(&mut frames, &mut at, held, (SLIDER_LEFT, 150), 12);
106 press(&mut frames, at, &mut held);
107 move_to(&mut frames, &mut at, held, (346, 152), 26);
108 pause(&mut frames, at, held, 4);
109 release(&mut frames, at, &mut held);
110 pause(&mut frames, at, held, 8);
111 move_to(&mut frames, &mut at, held, (100, 70), 14);
113 press(&mut frames, at, &mut held);
114 pause(&mut frames, at, held, 4);
115 move_to(&mut frames, &mut at, held, (220, 80), 8);
116 release(&mut frames, at, &mut held);
117 pause(&mut frames, at, held, 8);
118 move_to(&mut frames, &mut at, held, (340, 150), 12);
120 press(&mut frames, at, &mut held);
121 move_to(&mut frames, &mut at, held, (120, 148), 20);
122 release(&mut frames, at, &mut held);
123 pause(&mut frames, at, held, 6);
124 move_to(&mut frames, &mut at, held, (70, 66), 14);
125 press(&mut frames, at, &mut held);
126 pause(&mut frames, at, held, 3);
127 release(&mut frames, at, &mut held);
128 pause(&mut frames, at, held, 20);
129 frames
130}
131
132fn main() {
133 let compiled = ui_frame_circuit();
134 let report = compiled.verify(20_000).unwrap();
135 eprintln!(
136 "ui_frame: {} live operations in {} layers; verified on {} sampled inputs",
137 compiled.program.live_operation_count(),
138 compiled.program.layers.len(),
139 report.checked
140 );
141 let _ = (TOGGLE, SLIDER_LEFT);
142 let mut executor = TensorExecutor::new(&compiled.program);
143 let mut source = Vec::new();
144 let mut state = (false, false, false, 0u8, 0.0f32);
145 println!("frame,x,y,held,pressed,released,on,armed,dragging,level,thumb");
146 for (frame, (x, y, pressed, released, held)) in script().into_iter().enumerate() {
147 let args = (state.0, state.1, state.2, state.3, state.4, x, y, pressed, released);
148 source.clear();
149 args.encode(&mut source);
150 let outputs = executor.run(&source);
151 let next = (outputs[0] == 1.0, outputs[1] == 1.0, outputs[2] == 1.0, outputs[3] as u8, outputs[4]);
152 let expected = ui_frame(state.0, state.1, state.2, state.3, state.4, x, y, pressed, released);
153 assert_eq!(next, expected, "frame {frame}: the circuit disagrees with ui_frame()");
154 state = next;
155 println!(
156 "{frame},{x},{y},{},{},{},{},{},{},{},{}",
157 held as u8, pressed as u8, released as u8, state.0 as u8, state.1 as u8, state.2 as u8, state.3, state.4
158 );
159 }
160}