diff --git a/src/main.zig b/src/main.zig index 258c28a..806c219 100644 --- a/src/main.zig +++ b/src/main.zig @@ -24,7 +24,9 @@ pub const RotInt = struct { offsets: AzEl = .{ .az = 0, .el = 0 }, requested_posture: AzEl = .{ .az = 0, .el = 0 }, current_posture: AzEl = .{ .az = 0, .el = 0 }, - flipflop: bool = false, + poll_interval: u64 = 100, + command_freq: u8 = 10, + pollcount: u9 = 0, state: State = .initial, termbuffer: std.io.BufferedWriter(4096, std.io.AnyWriter), @@ -38,8 +40,6 @@ pub const RotInt = struct { poller: xev.Timer, poll_completion: xev.Completion = undefined, - const poll_interval: u64 = 1000; - pub const State = enum { initial, rotator_connected, @@ -99,7 +99,11 @@ pub const RotInt = struct { return .disarm; }; - if (self.flipflop) { + // pre-increment so that this does not try to command when pollcount = 0 on the + // first call + self.pollcount = (self.pollcount + 1) % self.command_freq; + + if (self.pollcount == 0) { const mangled: AzEl = .{ .az = self.requested_posture.az + self.offsets.az, .el = self.requested_posture.el + self.offsets.el, @@ -108,7 +112,6 @@ pub const RotInt = struct { } else { self.sendRotatorCommand(.get_position); } - self.flipflop = !self.flipflop; return .disarm; } @@ -136,7 +139,7 @@ pub const RotInt = struct { .status => |code| if (code != .okay) self.warn("rotctl error {s}", .{@tagName(code)}), } - self.poller.run(self.loop, &self.poll_completion, poll_interval, RotInt, self, poll); + self.poller.run(self.loop, &self.poll_completion, self.poll_interval, RotInt, self, poll); } pub fn warn(_: *RotInt, comptime fmt: []const u8, args: anytype) void { @@ -178,7 +181,7 @@ pub const RotInt = struct { const win = self.vx.window(); win.clear(); - var lines: [3][128]u8 = undefined; + var lines: [4][128]u8 = undefined; const offsets: vaxis.Segment = .{ .text = try std.fmt.bufPrint( lines[0][0..], "Offsets: Az: {d: >6.1}, El: {d: >6.1}", @@ -194,13 +197,28 @@ pub const RotInt = struct { "Current: Az: {d: >6.1}, El: {d: >6.1}", .{ self.current_posture.az, self.current_posture.el }, ) }; + const pollinfo: vaxis.Segment = .{ .text = try std.fmt.bufPrint( + lines[3][0..], + "Poll: {d} ms, Command: {d} ms", + .{ self.poll_interval, self.command_freq * self.poll_interval }, + ) }; const center = vaxis.widgets.alignment.center(win, offsets.text.len, 1); _ = try center.printSegment(offsets, .{}); - const center_up = win.initChild(center.x_off, center.y_off + 1, .{ .limit = requested.text.len }, .{ .limit = 1 }); + const center_up = win.initChild(center.x_off, center.y_off - 1, .{ .limit = requested.text.len }, .{ .limit = 1 }); _ = try center_up.printSegment(requested, .{}); - const center_down = win.initChild(center.x_off, center.y_off - 1, .{ .limit = current.text.len }, .{ .limit = 1 }); + const center_down = win.initChild(center.x_off, center.y_off + 1, .{ .limit = current.text.len }, .{ .limit = 1 }); _ = try center_down.printSegment(current, .{}); + const poll_win = win.initChild(center.x_off, center.y_off + 3, .{ .limit = pollinfo.text.len }, .{ .limit = 1 }); + _ = try poll_win.printSegment(pollinfo, .{}); + + const help: vaxis.Segment = .{ + .text = "Keys: q/^c - quit, ↑/↓ - el +/- 1° (+shift - 0.1°), ←/→ - az -/+ 1° (+shift - 0.1°), ⏎ - reset offsets, ^l - redraw, w/a/s/d - poll rates", + .style = .{ .fg = .{ .index = 245 } }, + }; + + const helpwin = win.child(.{ .x_off = 0, .y_off = 0 }); + _ = try helpwin.printSegment(help, .{ .wrap = .word }); try self.vx.render(self.termbuffer.writer().any()); try self.termbuffer.flush(); @@ -214,44 +232,67 @@ pub const RotInt = struct { ) xev.CallbackAction { const self = self_.?; switch (event) { - .key_press => |key| keyp: { + .key_press => |key| { var mods = key.mods; mods.caps_lock = false; mods.num_lock = false; - const scale: f64 = if (std.meta.eql(mods, .{ .shift = true })) 1 else 10; - const delta: AzEl = switch (key.codepoint) { - vaxis.Key.left, vaxis.Key.kp_left => .{ .az = -0.1 * scale, .el = 0 }, - vaxis.Key.right, vaxis.Key.kp_right => .{ .az = 0.1 * scale, .el = 0 }, - vaxis.Key.up, vaxis.Key.kp_up => .{ .az = 0, .el = 0.1 * scale }, - vaxis.Key.down, vaxis.Key.kp_down => .{ .az = 0 * scale, .el = -0.1 * scale }, - 'l' => { - if (std.meta.eql(mods, .{ .ctrl = true })) - self.vx.queueRefresh(); - break :keyp; - }, - 'c' => { - if (std.meta.eql(mods, .{ .ctrl = true })) { - loop.stop(); - return .disarm; - } - break :keyp; - }, - 'q' => { - if (std.meta.eql(mods, .{})) { - loop.stop(); - return .disarm; - } - break :keyp; - }, - else => break :keyp, - }; + switch (key.codepoint) { + vaxis.Key.left, + vaxis.Key.kp_left, + vaxis.Key.right, + vaxis.Key.kp_right, + vaxis.Key.up, + vaxis.Key.kp_up, + vaxis.Key.down, + vaxis.Key.kp_down, + vaxis.Key.enter, + vaxis.Key.kp_enter, + => |arrow| { + const scale: f64 = if (std.meta.eql(mods, .{ .shift = true })) 1 else 10; + const delta: AzEl = switch (arrow) { + vaxis.Key.left, vaxis.Key.kp_left => .{ .az = -0.1 * scale, .el = 0 }, + vaxis.Key.right, vaxis.Key.kp_right => .{ .az = 0.1 * scale, .el = 0 }, + vaxis.Key.up, vaxis.Key.kp_up => .{ .az = 0, .el = 0.1 * scale }, + vaxis.Key.down, vaxis.Key.kp_down => .{ .az = 0 * scale, .el = -0.1 * scale }, + vaxis.Key.enter, vaxis.Key.kp_enter => .{ .az = -self.offsets.az, .el = -self.offsets.el }, + else => unreachable, + }; - self.offsets.az += delta.az; - self.offsets.el += delta.el; - self.draw() catch { - self.warn("draw failure", .{}); - }; + self.offsets.az += delta.az; + self.offsets.el += delta.el; + self.draw() catch { + self.warn("draw failure", .{}); + }; + }, + 'w', 'a', 's', 'd' => |wasd| { + switch (wasd) { + 'w' => self.poll_interval += 100, + 'a' => if (self.command_freq > 2) { + self.command_freq -= 1; + }, + 's' => if (self.poll_interval > 100) { + self.poll_interval -= 100; + }, + 'd' => self.command_freq += 1, + else => unreachable, + } + self.draw() catch {}; + }, + 'l' => if (std.meta.eql(mods, .{ .ctrl = true })) { + self.vx.queueRefresh(); + self.draw() catch {}; + }, + 'c' => if (std.meta.eql(mods, .{ .ctrl = true })) { + loop.stop(); + return .disarm; + }, + 'q' => if (std.meta.eql(mods, .{})) { + loop.stop(); + return .disarm; + }, + else => {}, + } }, .winsize => |ws| { watcher.vx.resize(self.allocator, watcher.tty.anyWriter(), ws) catch