~xdavidwu/motion-control

f49519c81f73aad42d952956920251d2f6fa7bad — Pinghao Wu 2 months ago 1e1394b
tree-wide: updates for hare 0.24.2

(compiles, untested)
M aux/event-codes/main.ha => aux/event-codes/main.ha +3 -12
@@ 5,21 5,14 @@ use os;
use strings;

export fn main() void = {
	for (true) {
		const line = match (bufio::scanline(os::stdin)!) {
		case let s: []u8 =>
			yield strings::fromutf8(s);
		case io::EOF =>
			return;
		};

	const scanner = bufio::newscanner(os::stdin);
	defer bufio::finish(&scanner);
	for (const line => bufio::scan_line(&scanner)!) {
		if (!strings::hasprefix(line, "#define")) {
			free(line);
			continue;
		};
		const iend = match (strings::index(strings::sub(line, 8, strings::end), '\t')) {
		case void =>
			free(line);
			continue;
		case let s: size =>
			yield s + 8;


@@ 32,7 25,5 @@ export fn main() void = {
			yield strings::sub(val, 0, s);
		};
		fmt::printfln("export def {}: u16\t= {};", strings::sub(line, 8, iend), val)!;

		free(line);
	};
};

M cmd/motion-control/main+gy801.ha => cmd/motion-control/main+gy801.ha +5 -7
@@ 17,7 17,7 @@ use strconv;
use time;
use unix::signal;

export fn main() int = {
export fn main() void = {
	const help: []getopt::help = [
		"control pointerd with motion",
		"bus address",


@@ 25,7 25,7 @@ export fn main() int = {
	const cmd = getopt::parse(os::args, help...);
	defer getopt::finish(&cmd);
	if (len(cmd.args) != 2) {
		getopt::printusage(os::stderr, os::args[0], help);
		getopt::printusage(os::stderr, os::args[0], help)!;
		os::exit(-1);
	};
	const bus = match (strconv::stoi(cmd.args[0])) {


@@ 37,7 37,7 @@ export fn main() int = {

	const buf = control::request {
		code = control::code::RELATIVE_MOVEMENT,
		...,
		...
	};

	const sock = match (dial::dial("udp", cmd.args[1], strconv::u16tos(control::DEFAULT_PORT))) {


@@ 74,8 74,8 @@ export fn main() int = {
	const fd = timerfd::new(time::clock::MONOTONIC, 0)!;
	defer io::close(fd)!;
	timerfd::set(fd, (10 * time::MILLISECOND): timerfd::interval, 0)!;
	signal::handle(signal::SIGINT, &sigint, signal::flag::RESTART);
	signal::handle(signal::SIGUSR1, &sigusr1, signal::flag::RESTART);
	signal::handle(signal::sig::INT, &sigint, signal::flag::RESTART);
	signal::handle(signal::sig::USR1, &sigusr1, signal::flag::RESTART);

	timerfd::read(fd)!;
	const acc_readings = ADXL345::read(ADXL345)!;


@@ 113,6 113,4 @@ export fn main() int = {
			break;
		};
	};

	return 0;
};

M cmd/motion-control/main+joycon.ha => cmd/motion-control/main+joycon.ha +8 -8
@@ 24,13 24,13 @@ export fn main() int = {
	const cmd = getopt::parse(os::args, help...);
	defer getopt::finish(&cmd);
	if (len(cmd.args) != 1) {
		getopt::printusage(os::stderr, os::args[0], help);
		getopt::printusage(os::stderr, os::args[0], help)!;
		os::exit(-1);
	};

	const buf = control::request {
		code = control::code::RELATIVE_MOVEMENT,
		...,
		...
	};

	const sock = match (dial::dial("udp", cmd.args[0], strconv::u16tos(control::DEFAULT_PORT))) {


@@ 47,7 47,7 @@ export fn main() int = {
	const joycon = joycon::new(void)!;
	defer joycon::destroy(joycon);

	const joycon_epoll = rt::epoll_event {
	let joycon_epoll = rt::epoll_event {
		events = rt::EPOLLIN,
		data = rt::epoll_data {
			fd = joycon.fd,


@@ 55,10 55,10 @@ export fn main() int = {
	};
	rt::epoll_ctl(epoll, rt::EPOLL_CTL_ADD, joycon.fd, &joycon_epoll)!;

	const fd = timerfd::new(time::clock::MONOTONIC, rt::O_NONBLOCK)!;
	const fd = timerfd::new(time::clock::MONOTONIC, timerfd::new_flag::NONBLOCK)!;
	defer io::close(fd)!;
	timerfd::set(fd, (10 * time::MILLISECOND): timerfd::interval, 0)!;
	const timer_epoll = rt::epoll_event {
	let timer_epoll = rt::epoll_event {
		events = rt::EPOLLIN | rt::EPOLLET,
		data = rt::epoll_data {
			fd = fd,


@@ 66,15 66,15 @@ export fn main() int = {
	};
	rt::epoll_ctl(epoll, rt::EPOLL_CTL_ADD, fd, &timer_epoll)!;

	signal::handle(signal::SIGINT, &sigint, signal::flag::RESTART);
	signal::handle(signal::SIGUSR1, &sigusr1, signal::flag::RESTART);
	signal::handle(signal::sig::INT, &sigint, signal::flag::RESTART);
	signal::handle(signal::sig::USR1, &sigusr1, signal::flag::RESTART);

	const sample = joycon::next_sample(joycon)!;
	let prev_us = sample.timestamp;

	let complementary = complementary::new(sample.accelerometer, 0.02);

	let e = rt::epoll_event {...};
	let e = rt::epoll_event { data = rt::epoll_data { ... }, ...};
	for (global_state != state::EXIT) {
		match (rt::epoll_wait(epoll, &e, 1, -1)) {
		case let e: rt::errno =>

M cmd/motion-control/state.ha => cmd/motion-control/state.ha +2 -2
@@ 10,11 10,11 @@ type state = enum u8 {

let global_state: state	= state::NORMAL;

fn sigint(sig: int, info: *signal::siginfo, ucontext: *void) void = {
fn sigint(sig: signal::sig, info: *signal::siginfo, ucontext: *opaque) void = {
	global_state = state::EXIT;
};

fn sigusr1(sig: int, info: *signal::siginfo, ucontext: *void) void = {
fn sigusr1(sig: signal::sig, info: *signal::siginfo, ucontext: *opaque) void = {
	switch (global_state) {
	case state::NORMAL =>
		fmt::println("Block")!;

M cmd/pointerd/main.ha => cmd/pointerd/main.ha +2 -2
@@ 12,7 12,7 @@ use unix::signal;

let exit: bool	= false;

fn sigint(sig: int, info: *signal::siginfo, ucontext: *void) void = {
fn sigint(sig: signal::sig, info: *signal::siginfo, ucontext: *opaque) void = {
	exit = true;
};



@@ 57,7 57,7 @@ export fn main() void = {
	};
	defer net::close(sock)!;

	signal::handle(signal::SIGINT, &sigint);
	signal::handle(signal::sig::INT, &sigint);
	let buf = control::request {...};
	for (true) {
		const sz = match (udp::recvfrom(sock, buf.bytes, null, null)) {

M evdev/libevdev.ha => evdev/libevdev.ha +13 -12
@@ 2,6 2,7 @@ use errors;
use io;
use rt;
use strings;
use types::c;

export fn new_from_fd(fd: io::file) (errors::error | libevdev) = {
	let handle = null: libevdev;


@@ 13,11 14,11 @@ export fn new_from_fd(fd: io::file) (errors::error | libevdev) = {
};

export fn get_name(dev: libevdev) const str = {
	return strings::fromc(c_libevdev_get_name(dev));
	return c::tostr(c_libevdev_get_name(dev))!;
};

export fn set_name(dev: libevdev, name: str) void = {
	const cstr = strings::to_c(name);
	const cstr = c::fromstr(name);
	defer free(cstr);
	c_libevdev_set_name(dev, cstr);
};


@@ 35,7 36,7 @@ export fn enable_event_type(dev: libevdev, event_type: uint) (void | unknown_err
};

export fn enable_event_code(dev: libevdev, event_type: uint, code: uint,
		data: nullable *void) (void | unknown_error) = {
		data: nullable *opaque) (void | unknown_error) = {
	// TODO: wrap data with tagged union?
	return if (c_libevdev_enable_event_code(dev, event_type, code, data) != 0)
		unknown_error else void;


@@ 45,29 46,29 @@ export fn event_type_get_name(_type: u16) (const str | errors::invalid) =
	match (c_libevdev_event_type_get_name(_type)) {
	case null =>
		return errors::invalid;
	case let s: *const char =>
		return strings::fromc(s);
	case let s: *const c::char =>
		return c::tostr(s)!;
	};

export fn event_code_get_name(_type: u16, code: u16) (const str | errors::invalid) =
	match (c_libevdev_event_code_get_name(_type, code)) {
	case null =>
		return errors::invalid;
	case let s: *const char =>
		return strings::fromc(s);
	case let s: *const c::char =>
		return c::tostr(s)!;
	};

export @symbol("libevdev_new") fn new() libevdev;
export @symbol("libevdev_free") fn destroy(dev: libevdev) void;

@symbol("libevdev_new_from_fd") fn c_libevdev_new_from_fd(fd: int, dev: *libevdev) int;
@symbol("libevdev_get_name") fn c_libevdev_get_name(dev: libevdev) *const char;
@symbol("libevdev_set_name") fn c_libevdev_set_name(dev: libevdev, name: *const char) void;
@symbol("libevdev_get_name") fn c_libevdev_get_name(dev: libevdev) *const c::char;
@symbol("libevdev_set_name") fn c_libevdev_set_name(dev: libevdev, name: *const c::char) void;
@symbol("libevdev_next_event") fn c_libevdev_next_event(dev: libevdev,
	flags: uint, ev: *input_event) int;
@symbol("libevdev_enable_event_type") fn c_libevdev_enable_event_type(
	dev: libevdev, etype: uint) int;
@symbol("libevdev_enable_event_code") fn c_libevdev_enable_event_code(
	dev: libevdev, etype: uint, code: uint, data: nullable *void) int;
@symbol("libevdev_event_type_get_name") fn c_libevdev_event_type_get_name(_type: uint) nullable *const char;
@symbol("libevdev_event_code_get_name") fn c_libevdev_event_code_get_name(_type: uint, code: uint) nullable *const char;
	dev: libevdev, etype: uint, code: uint, data: nullable *opaque) int;
@symbol("libevdev_event_type_get_name") fn c_libevdev_event_type_get_name(_type: uint) nullable *const c::char;
@symbol("libevdev_event_code_get_name") fn c_libevdev_event_code_get_name(_type: uint, code: uint) nullable *const c::char;

M evdev/types.ha => evdev/types.ha +1 -1
@@ 1,6 1,6 @@
use rt;

export type libevdev = *void;
export type libevdev = *opaque;

export type input_event = struct {
	time:	rt::timeval,

M evdev/uinput/types.ha => evdev/uinput/types.ha +1 -1
@@ 1,5 1,5 @@
use io;

export type uinput = *void;
export type uinput = *opaque;

export def OPEN_MANAGED: io::file	= -2;

M sensors/ADXL345/ADXL345.ha => sensors/ADXL345/ADXL345.ha +1 -1
@@ 10,7 10,7 @@ use rt;
export fn new(bus: int) (ADXL345 | fs::error | errors::error) = {
	const path = fmt::asprintf("/dev/i2c-{}", bus);
	defer free(path);
	const file = os::open(path, fs::flags::RDONLY)?;
	const file = os::open(path, fs::flag::RDONLY)?;
	match (rt::ioctl(file, i2c::I2C_SLAVE, 0x53)) {
	case let e: rt::errno =>
		return errors::errno(e);

M sensors/L3G4200D/L3G4200D.ha => sensors/L3G4200D/L3G4200D.ha +1 -1
@@ 10,7 10,7 @@ use rt;
export fn new(bus: int) (L3G4200D | fs::error | errors::error) = {
	const path = fmt::asprintf("/dev/i2c-{}", bus);
	defer free(path);
	const file = os::open(path, fs::flags::RDONLY)?;
	const file = os::open(path, fs::flag::RDONLY)?;
	match (rt::ioctl(file, i2c::I2C_SLAVE, 0x69)) {
	case let e: rt::errno =>
		return errors::errno(e);

M sensors/joycon/joycon.ha => sensors/joycon/joycon.ha +10 -12
@@ 23,21 23,16 @@ export fn new(dev: (io::file | void)) (joycon | errors::error) = {
		const iter = fs::iter(fs, ".")!;
		let candidate = struct {
			fd: io::file = 0,
			dev: evdev::libevdev = 0: uintptr,
			dev: (evdev::libevdev | void) = void,
			preference: size = len(preferences),
		};
		let has_candidate = false;

		for (true) {
			const ent = match (fs::next(iter)) {
			case let e: fs::dirent =>
				if (!fs::ischdev(e.ftype)) {
					continue;
				};
				yield e.name;
			case void =>
				break;
		for (const e => fs::next(iter)!) {
			if (!fs::ischdev(e.ftype)) {
				continue;
			};
			const ent = e.name;
			const f = match (fs::open_file(fs, ent)) {
			case let f: io::file =>
				yield f;


@@ 74,7 69,7 @@ export fn new(dev: (io::file | void)) (joycon | errors::error) = {
		fmt::printfln("Picking {}", preferences[candidate.preference])!;
		return alloc(joycon_impl {
			fd = candidate.fd,
			dev = candidate.dev,
			dev = candidate.dev as evdev::libevdev,
			...
		});
	};


@@ 136,11 131,14 @@ export fn next_sample(joycon: joycon) (sample | errors::error) = {
				joycon.read |= READ_RZ;
				joycon.state.gyroscope.2 =
					-ev.value: f64 * GYRO_SCALE;
			case =>
				void;
			};
		case evdev::EV_MSC =>
			assert(ev.code == evdev::MSC_TIMESTAMP);
			joycon.state.timestamp = ev.value: u32;
		case =>
			void;
		};
	};
	abort("Unreachable");
};

M tools/buttonc/main.ha => tools/buttonc/main.ha +13 -16
@@ 9,6 9,7 @@ use os::exec;
use proto::control;
use strconv;
use unix::tty;
use unix::signal;

fn send(sock: net::socket, bytes: []u8) void = {
	match (udp::send(sock, bytes)) {


@@ 19,7 20,7 @@ fn send(sock: net::socket, bytes: []u8) void = {
	};
};

export fn main() int = {
export fn main() void = {
	const help: []getopt::help = [
		"control pointerd with buttons",
		('m', "pid", "motion-control pid, for attitude reset key combo"),


@@ 39,11 40,13 @@ export fn main() int = {
			case =>
				fmt::fatalf("Invalid pid {}", opt.1);
			};
		case =>
			abort();
		};
	};

	if (len(cmd.args) != 1) {
		getopt::printusage(os::stderr, os::args[0], help);
		getopt::printusage(os::stderr, os::args[0], help)!;
		os::exit(-1);
	};



@@ 64,20 67,14 @@ export fn main() int = {
		termios = &tty::termios_query(os::stdin_file)!;
		tty::makeraw(termios)!;
	};
	if (tty) defer tty::termios_restore(termios);
	defer if (tty) {
		tty::termios_restore(termios);
	};

	let left = false, right = false;
	let motion_blocked = false;
	for (true) {
		let i: []u8 = [0];
		match (io::read(os::stdin_file, i)) {
		case size =>
			yield;
		case io::EOF =>
			break;
		case let err: io::error =>
			fmt::fatalf("Cannot read(): {}", io::strerror(err));
		};
	let i: []u8 = [0];
	for (const sz => io::read(os::stdin_file, i)!) {
		switch (i[0]) {
		case 'A' =>
			buf.code = control::code::KEY_PRESSED;


@@ 101,15 98,15 @@ export fn main() int = {
			send(sock, buf.bytes);
		case 4 => // EOT
			break;
		case =>
			abort();
		};
		if (motion_pid != 0) {
			if ((!motion_blocked && left && right) ||
					(motion_blocked && (!left || !right))) {
				exec::kill(motion_pid, exec::signal::SIGUSR1)!;
				exec::sig(motion_pid, signal::sig::USR1)!;
				motion_blocked = !motion_blocked;
			};
		};
	};

	return 0;
};

M tools/evdev-dump-events/main.ha => tools/evdev-dump-events/main.ha +1 -1
@@ 10,7 10,7 @@ export fn main() void = {
	if (len(os::args) != 2) {
		fmt::fatalf("Usage: {} DEVICE", os::args[0]);
	};
	const file = match (os::open(os::args[1], fs::flags::RDONLY | fs::flags::NONBLOCK)) {
	const file = match (os::open(os::args[1], fs::flag::RDONLY | fs::flag::NONBLOCK)) {
	case let file: io::file =>
		yield file;
	case let err: fs::error =>

M tools/pointerc/main.ha => tools/pointerc/main.ha +1 -2
@@ 17,7 17,7 @@ fn send(sock: net::socket, bytes: []u8) void = {
	};
};

export fn main() int = {
export fn main() void = {
	if (len(os::args) > 4 || len(os::args) < 3) {
		fmt::fatalf("Usage: {} address (x y | left | right)", os::args[0]);
	};


@@ 60,5 60,4 @@ export fn main() int = {
		};
		send(sock, buf.bytes);
	};
	return 0;
};

M tools/sensors-dump/main+gy801.ha => tools/sensors-dump/main+gy801.ha +2 -2
@@ 16,7 16,7 @@ use unix::signal;

let exit: bool	= false;

fn sigint(sig: int, info: *signal::siginfo, ucontext: *void) void = {
fn sigint(sig: signal::sig, info: *signal::siginfo, ucontext: *opaque) void = {
	exit = true;
};



@@ 57,7 57,7 @@ export fn main() void = {
	const fd = timerfd::new(time::clock::MONOTONIC, 0)!;
	defer io::close(fd)!;
	timerfd::set(fd, (10 * time::MILLISECOND): timerfd::interval, 0)!;
	signal::handle(signal::SIGINT, &sigint, signal::flag::RESTART);
	signal::handle(signal::sig::INT, &sigint, signal::flag::RESTART);
	const integrator = integration::new();

	timerfd::read(fd)!;

M tools/sensors-dump/main+joycon.ha => tools/sensors-dump/main+joycon.ha +2 -2
@@ 10,7 10,7 @@ use unix::signal;

let exit: bool	= false;

fn sigint(sig: int, info: *signal::siginfo, ucontext: *void) void = {
fn sigint(sig: signal::sig, info: *signal::siginfo, ucontext: *opaque) void = {
	exit = true;
};



@@ 18,7 18,7 @@ export fn main() void = {
	const joycon = joycon::new(void)!;
	defer joycon::destroy(joycon);

	signal::handle(signal::SIGINT, &sigint, signal::flag::RESTART);
	signal::handle(signal::sig::INT, &sigint, signal::flag::RESTART);

	const sample = joycon::next_sample(joycon)!;
	let prev_us = sample.timestamp;