diff --git a/main.zig b/main.zig new file mode 100644 index 0000000..777c23b --- /dev/null +++ b/main.zig @@ -0,0 +1,123 @@ +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); + } +}