Compare commits

..

No commits in common. "b0aac111a2a581c2d06fabc70ec7c6812031b844" and "bd465af30d0ba0495e6de3f8973a46ffa6f0d7ba" have entirely different histories.

4 changed files with 8 additions and 70 deletions

View File

@ -32,20 +32,11 @@ pub fn destroy(allocator: std.mem.Allocator) void {
rotctl: RotControlConfig = .{ rotctl: RotControlConfig = .{
.listen_address = "127.0.0.1", .listen_address = "127.0.0.1",
.listen_port = 4533, .listen_port = 5432,
}, },
labjack: LabjackConfig = .{ labjack: LabjackConfig = .{
.device = .autodetect, .device = .autodetect,
.feedback_calibration = .{ .feedback_calibration = .{
// NOTE: these min and max angles are treated as hardware limits. This serves
// two purposes: first, it means that feedback is always interpolated,
// never extrapolated (though with a two point calibration, that doesn't
// matter much). Second, it prevents having a redundant set of bounds
// values that could potentially desync from these and cause problems.
//
// The functional min and max are these plus the angle offset values. For
// example, given controller.angle_offset.azimuth = -6, the practical minimum
// azimuth would be -6 deg and the practical maximum would be 444 deg.
.azimuth = .{ .azimuth = .{
.minimum = .{ .voltage = 0.0, .angle = 0.0 }, .minimum = .{ .voltage = 0.0, .angle = 0.0 },
.maximum = .{ .voltage = 5.0, .angle = 450.0 }, .maximum = .{ .voltage = 5.0, .angle = 450.0 },
@ -57,17 +48,14 @@ labjack: LabjackConfig = .{
}, },
}, },
controller: ControllerConfig = .{ controller: ControllerConfig = .{
.azimuth_input = .{ .channel = .diff_01, .range = .@"5 V" }, .azimuth_input = .{ .channel = .diff_01, .gain_index = 2 },
.elevation_input = .{ .channel = .diff_23, .range = .@"5 V" }, .elevation_input = .{ .channel = .diff_23, .gain_index = 2 },
.azimuth_outputs = .{ .increase = .{ .io = 0 }, .decrease = .{ .io = 1 } }, .azimuth_outputs = .{ .increase = .{ .io = 0 }, .decrease = .{ .io = 1 } },
.elevation_outputs = .{ .increase = .{ .io = 2 }, .decrease = .{ .io = 3 } }, .elevation_outputs = .{ .increase = .{ .io = 2 }, .decrease = .{ .io = 3 } },
.loop_interval_ns = 50_000_000, .loop_interval_ns = 50_000_000,
.parking_posture = .{ .azimuth = 180, .elevation = 90 }, .parking_posture = .{ .azimuth = 180, .elevation = 90 },
.angle_tolerance = .{ .azimuth = 1, .elevation = 1 }, .angle_tolerance = .{ .azimuth = 1, .elevation = 1 },
.angle_offset = .{ .azimuth = 0, .elevation = 0 }, .angle_offset = .{ .azimuth = 0, .elevation = 0 },
// this is a symmetric mask, so the minimum usable elevation is elevation_mask deg
// and the maximum usable elevation is 180 - elevation_mask deg
.elevation_mask = 0.0,
}, },
pub const VoltAngle = struct { voltage: f64, angle: f64 }; pub const VoltAngle = struct { voltage: f64, angle: f64 };
@ -118,7 +106,6 @@ const ControllerConfig = struct {
parking_posture: AzEl, parking_posture: AzEl,
angle_tolerance: AzEl, angle_tolerance: AzEl,
angle_offset: AzEl, angle_offset: AzEl,
elevation_mask: f64,
const OutPair = struct { const OutPair = struct {
increase: lj.DigitalOutputChannel, increase: lj.DigitalOutputChannel,

View File

@ -40,13 +40,7 @@ pub fn setTarget(self: LabjackYaesu, target: AzEl) void {
defer self.lock.unlock(); defer self.lock.unlock();
const controller = @constCast(self.controller); const controller = @constCast(self.controller);
controller.target = .{ controller.target = target;
.azimuth = target.azimuth,
.elevation = @min(
@max(target.elevation, config.controller.elevation_mask),
180.0 - config.controller.elevation_mask,
),
};
controller.requested_state = .running; controller.requested_state = .running;
} }

View File

@ -1,7 +1,6 @@
const std = @import("std"); const std = @import("std");
const Config = @import("./Config.zig"); const config = @import("./Config.zig").global;
const config = Config.global;
const LabjackYaesu = @import("./LabjackYaesu.zig"); const LabjackYaesu = @import("./LabjackYaesu.zig");
const RotCtl = @This(); const RotCtl = @This();
@ -114,27 +113,6 @@ fn getPosition(self: *RotCtl, _: []const u8, tokens: *TokenIter) CommandError!vo
self.printReply("{d:.1}\n{d:.1}", .{ pos.azimuth, pos.elevation }) catch return error.BadOutput; self.printReply("{d:.1}\n{d:.1}", .{ pos.azimuth, pos.elevation }) catch return error.BadOutput;
} }
fn inRange(request: f64, comptime dof: enum { azimuth, elevation }) bool {
return switch (dof) {
// zig fmt: off
.azimuth => request >= (
config.labjack.feedback_calibration.azimuth.minimum.angle
+ config.controller.angle_offset.azimuth
) and request <= (
config.labjack.feedback_calibration.azimuth.maximum.angle
+ config.controller.angle_offset.azimuth
),
.elevation => request >= (
config.labjack.feedback_calibration.elevation.minimum.angle
+ config.controller.angle_offset.elevation
) and request <= (
config.labjack.feedback_calibration.elevation.maximum.angle
+ config.controller.angle_offset.elevation
),
// zig fmt: on
};
}
fn setPosition(self: *RotCtl, _: []const u8, tokens: *TokenIter) CommandError!void { fn setPosition(self: *RotCtl, _: []const u8, tokens: *TokenIter) CommandError!void {
const azimuth = std.fmt.parseFloat(f64, tokens.next() orelse { const azimuth = std.fmt.parseFloat(f64, tokens.next() orelse {
return self.replyStatus(.invalid_parameter) catch error.BadOutput; return self.replyStatus(.invalid_parameter) catch error.BadOutput;
@ -142,18 +120,12 @@ fn setPosition(self: *RotCtl, _: []const u8, tokens: *TokenIter) CommandError!vo
return self.replyStatus(.invalid_parameter) catch error.BadOutput; return self.replyStatus(.invalid_parameter) catch error.BadOutput;
}; };
if (!inRange(azimuth, .azimuth))
return self.replyStatus(.invalid_parameter) catch error.BadOutput;
const elevation = std.fmt.parseFloat(f64, tokens.next() orelse { const elevation = std.fmt.parseFloat(f64, tokens.next() orelse {
return self.replyStatus(.invalid_parameter) catch error.BadOutput; return self.replyStatus(.invalid_parameter) catch error.BadOutput;
}) catch { }) catch {
return self.replyStatus(.invalid_parameter) catch error.BadOutput; return self.replyStatus(.invalid_parameter) catch error.BadOutput;
}; };
if (!inRange(elevation, .elevation))
return self.replyStatus(.invalid_parameter) catch error.BadOutput;
self.rotator.setTarget(.{ .azimuth = azimuth, .elevation = elevation }); self.rotator.setTarget(.{ .azimuth = azimuth, .elevation = elevation });
return self.replyStatus(.okay) catch error.BadOutput; return self.replyStatus(.okay) catch error.BadOutput;
} }

View File

@ -50,7 +50,7 @@ pub const Labjack = struct {
&id, &id,
@intFromBool(self.demo), @intFromBool(self.demo),
input.channelNumber(), input.channelNumber(),
input.gainIndex(), input.gain_index,
&over_v, &over_v,
&res.voltage, &res.voltage,
); );
@ -93,7 +93,7 @@ pub const Labjack = struct {
var gains: [incount]c_long = undefined; var gains: [incount]c_long = undefined;
for (inputs, &in_channels, &gains) |from, *inc, *gain| { for (inputs, &in_channels, &gains) |from, *inc, *gain| {
inc.* = from.channelNumber(); inc.* = from.channelNumber();
gain.* = from.gainIndex(); gain.* = from.gain_index;
} }
var v_out: [4]f32 = .{0} ** 4; var v_out: [4]f32 = .{0} ** 4;
var over_v: c_long = 0; var over_v: c_long = 0;
@ -133,15 +133,11 @@ pub const Labjack = struct {
pub const AnalogInput = struct { pub const AnalogInput = struct {
channel: AnalogInputChannel, channel: AnalogInputChannel,
range: InputRange = .@"20 V", gain_index: GainIndex = 0,
pub fn channelNumber(self: AnalogInput) u4 { pub fn channelNumber(self: AnalogInput) u4 {
return @intFromEnum(self.channel); return @intFromEnum(self.channel);
} }
pub fn gainIndex(self: AnalogInput) GainIndex {
return @intFromEnum(self.range);
}
}; };
pub const AnalogReadResult = struct { pub const AnalogReadResult = struct {
@ -211,17 +207,6 @@ pub const DigitalOutputChannel = union(enum) {
// 7 => G=20 ±1 volt // 7 => G=20 ±1 volt
pub const GainIndex = u3; pub const GainIndex = u3;
pub const InputRange = enum(GainIndex) {
@"20 V" = 0,
@"10 V" = 1,
@"5 V" = 2,
@"4 V" = 3,
@"2.5 V" = 4,
@"2 V" = 5,
@"1.25 V" = 6,
@"1 V" = 7,
};
pub const PackedOutput = packed struct(u4) { pub const PackedOutput = packed struct(u4) {
io0: bool, io0: bool,
io1: bool, io1: bool,