yaes/src/Config.zig
torque e639a17424
start writing control and config functionality
In theory, this will poll the feedback lines, but in practice, it
probably crashes or catches on fire or something.
2024-07-03 00:22:40 -07:00

113 lines
3.1 KiB
Zig

const std = @import("std");
const AzEl = @import("./LabjackYaesu.zig").AzEl;
const lj = @import("./labjack.zig");
const Config = @This();
var global_internal: Config = undefined;
pub const global: *const Config = &global_internal;
pub fn load(allocator: std.mem.Allocator, reader: anytype) !void {
var jread = std.json.Reader(1024, @TypeOf(reader)).init(allocator, reader);
defer jread.deinit();
global_internal = try std.json.parseFromTokenSourceLeaky(
Config,
allocator,
&jread,
.{},
);
}
pub fn loadDefault(allocator: std.mem.Allocator) void {
_ = allocator;
global_internal = .{};
}
pub fn destroy(allocator: std.mem.Allocator) void {
// TODO: implement this probably
_ = allocator;
}
rotctl: RotControlConfig = .{
.listen_address = "127.0.0.1",
.listen_port = 5432,
},
labjack: LabjackConfig = .{
.device = .autodetect,
.feedback_calibration = .{
.azimuth = .{
.minimum = .{ .voltage = 0.0, .angle = 0.0 },
.maximum = .{ .voltage = 5.0, .angle = 450.0 },
},
.elevation = .{
.minimum = .{ .voltage = 0.0, .angle = 0.0 },
.maximum = .{ .voltage = 5.0, .angle = 180.0 },
},
},
},
controller: ControllerConfig = .{
.azimuth_input = .{ .channel = .diff_01, .gain_index = 2 },
.elevation_input = .{ .channel = .diff_23, .gain_index = 2 },
.azimuth_outputs = .{ .increase = .{ .io = 0 }, .decrease = .{ .io = 1 } },
.elevation_outputs = .{ .increase = .{ .io = 2 }, .decrease = .{ .io = 3 } },
.loop_interval_ns = 50_000_000,
.parking_posture = .{ .azimuth = 180, .elevation = 90 },
.angle_tolerance = .{ .azimuth = 1, .elevation = 1 },
},
pub const VoltAngle = struct { voltage: f64, angle: f64 };
pub const MinMax = struct {
minimum: VoltAngle,
maximum: VoltAngle,
pub inline fn slope(self: MinMax) f64 {
return self.angleDiff() / self.voltDiff();
}
pub inline fn voltDiff(self: MinMax) f64 {
return self.maximum.voltage - self.minimum.voltage;
}
pub inline fn angleDiff(self: MinMax) f64 {
return self.maximum.angle - self.minimum.angle;
}
};
const RotControlConfig = struct {
listen_address: []const u8,
listen_port: u16,
};
const LabjackConfig = struct {
device: union(enum) {
autodetect,
serial_number: i32,
},
// Very basic two-point calibration for each degree of freedom. All other angles are
// linearly interpolated from these two points. This assumes the feedback is linear,
// which seems to be a mostly reasonable assumption in practice.
feedback_calibration: struct {
azimuth: MinMax,
elevation: MinMax,
},
};
const ControllerConfig = struct {
azimuth_input: lj.AnalogInput,
elevation_input: lj.AnalogInput,
azimuth_outputs: OutPair,
elevation_outputs: OutPair,
loop_interval_ns: u64,
parking_posture: AzEl,
angle_tolerance: AzEl,
const OutPair = struct {
increase: lj.DigitalOutputChannel,
decrease: lj.DigitalOutputChannel,
};
};