const std = @import("std"); const c = @cImport({ @cInclude("SDL2/SDL.h"); @cInclude("termios.h"); }); fn init_ttyacm0(port: [:0]const u8) !std.posix.fd_t { const fd = try std.posix.open(port, .{ .ACCMODE = .RDWR, .NOCTTY = true, .SYNC = true }, 0); var tty: c.termios = .{}; if (c.tcgetattr(fd, &tty) != 0) { std.posix.close(fd); return error.TTY_ERROR; } _ = c.cfsetospeed(&tty, c.B115200); _ = c.cfsetispeed(&tty, c.B115200); const csize: c_uint = @intCast(c.CSIZE); tty.c_cflag = (tty.c_cflag & ~csize) | c.CS8; tty.c_cflag |= (c.CLOCAL | c.CREAD); const parenb: c_uint = @intCast(c.PARENB); const parodd: c_uint = @intCast(c.PARODD); tty.c_cflag &= ~(parenb | parodd); const cstopb: c_uint = @intCast(c.CSTOPB); tty.c_cflag &= ~cstopb; const crtscts: c_uint = @intCast(c.CRTSCTS); tty.c_cflag &= ~crtscts; const ignbrk: c_uint = @intCast(c.IGNBRK); tty.c_iflag &= ~ignbrk; tty.c_lflag = 0; tty.c_oflag = 0; tty.c_cc[c.VMIN] = 1; tty.c_cc[c.VTIME] = 5; if (c.tcsetattr(fd, c.TCSANOW, &tty) != 0) { std.posix.close(fd); return error.TTY_INIT; } return fd; } pub fn main() !void { const fd = try init_ttyacm0("/dev/ttyACM0"); defer std.posix.close(fd); // _ = try std.posix.write(fd, "ssss"); // _ = std.c.fsync(fd); _ = c.SDL_Init(c.SDL_INIT_VIDEO); const window = c.SDL_CreateWindow("hello", 0, 0, 800, 600, c.SDL_WINDOW_SHOWN) orelse unreachable; const renderer = c.SDL_CreateRenderer(window, 0, 0) orelse unreachable; var running = true; _ = c.SDL_SetRelativeMouseMode(c.SDL_TRUE); // grabs pointer and delivers relative motion _ = c.SDL_ShowCursor(c.SDL_DISABLE); // optional: hide cursor var dx_acc: i32 = 0; var dy_acc: i32 = 0; while (running) { var e: c.SDL_Event = undefined; while (c.SDL_PollEvent(&e) != 0) { switch (e.type) { c.SDL_QUIT => { running = false; }, c.SDL_MOUSEMOTION => { const dx = e.motion.xrel; // movement since last event on x const dy = e.motion.yrel; // movement since last event on y dx_acc += dx; dy_acc += dy; const speed = 32; if (dx > 0) { const count: usize = @intCast(@divTrunc(dx_acc, speed)); dx_acc = @rem(dx_acc, speed); for (0..count) |_| { _ = try std.posix.write(fd, "l"); } } else { const count: usize = @intCast(@divTrunc(@abs(dx_acc), speed)); dx_acc = @rem(dx_acc, speed); for (0..count) |_| { _ = try std.posix.write(fd, "j"); } } if (dy > 0) { const count: usize = @intCast(@divTrunc(dy_acc, speed)); dy_acc = @rem(dy_acc, speed); for (0..count) |_| { _ = try std.posix.write(fd, "k"); } } else { const count: usize = @intCast(@divTrunc(@abs(dy_acc), speed)); dy_acc = @rem(dy_acc, speed); for (0..count) |_| { _ = try std.posix.write(fd, "i"); } } }, // c.SDL_KEYDOWN => { // switch (e.key.keysym.scancode) { // c.SDL_SCANCODE_W => _ = try std.posix.write(fd, "wwww"), // c.SDL_SCANCODE_S => _ = try std.posix.write(fd, "ssss"), // c.SDL_SCANCODE_A => _ = try std.posix.write(fd, "aaaa"), // c.SDL_SCANCODE_D => _ = try std.posix.write(fd, "dddd"), // else => {}, // } // }, else => {}, } } const state: [*]const u8 = c.SDL_GetKeyboardState(null); if (state[c.SDL_SCANCODE_W] != 0) _ = try std.posix.write(fd, "w"); if (state[c.SDL_SCANCODE_S] != 0) _ = try std.posix.write(fd, "s"); if (state[c.SDL_SCANCODE_A] != 0) _ = try std.posix.write(fd, "a"); if (state[c.SDL_SCANCODE_D] != 0) _ = try std.posix.write(fd, "d"); if (state[c.SDL_SCANCODE_SPACE] != 0) _ = try std.posix.write(fd, "e"); if (state[c.SDL_SCANCODE_LSHIFT] != 0) _ = try std.posix.write(fd, "q"); _ = c.SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF); _ = c.SDL_RenderClear(renderer); _ = c.SDL_RenderPresent(renderer); c.SDL_Delay(10); } }