prototype labjack API wrapper
The Labjack API provided by ljacklm is, quite frankly, dog doodoo. I say this as disrespectfully as possible. A lot of the API calls take specific (implictly sized) arrays that must be 0-filled just so the API can loop over them and fill them with a different number. Everything parameter is either long or a float (and I think the use of long is a carryover from the insane Win32 ABI where long is a 32 bit integer rather than 64 bit, which it is on most Posix platforms). The functions have a tendency to do 15 different things in a single call, and most of the function parameters are out parameters or even better, inout parameters. Some functions take arrays where other ones require the user to manually bitpack an integer. I've got the source for it right here and could rewrite it, but I don't hate myself enough to do that. The API surface I need is minimal, so I've just wrapped the parts I will be using. Ideally I will not need to touch this again, but it does still need to be tested with actual hardware, so we're not out of the woods yet.
This commit is contained in:
parent
eace0bf8db
commit
7275d1c30e
222
deps/labjack/ljacklm/libljacklm/ljacklm.c
vendored
222
deps/labjack/ljacklm/libljacklm/ljacklm.c
vendored
@ -1471,6 +1471,84 @@ float GetDriverVersion( void)
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
const char *StaticErrorString(long errorcode) {
|
||||
if(BitTst(errorcode,8))
|
||||
{
|
||||
errorcode -= STREAMBUFF_ERROR_OFFSET_LJ;
|
||||
}
|
||||
switch(errorcode)
|
||||
{
|
||||
case 0: return "No error";
|
||||
case 1: return "Unknown error";
|
||||
case 2: return "No LabJacks found";
|
||||
case 3: return "LabJack n not found";
|
||||
case 4: return "Set USB buffer error";
|
||||
case 5: return "Open handle error";
|
||||
case 6: return "Close handle error";
|
||||
case 7: return "Invalid ID";
|
||||
case 8: return "Invalid array size or value";
|
||||
case 9: return "Invalid power index";
|
||||
case 10: return "FCDD size too big";
|
||||
case 11: return "HVC size too big";
|
||||
case 12: return "Read error";
|
||||
case 13: return "Read timeout error";
|
||||
case 14: return "Write error";
|
||||
case 15: return "Turbo error";
|
||||
case 16: return "Illegal channel index";
|
||||
case 17: return "Illegal gain index";
|
||||
case 18: return "Illegal AI command";
|
||||
case 19: return "Illegal AO command";
|
||||
case 20: return "Bits out of range";
|
||||
case 21: return "Illegal number of channels";
|
||||
case 22: return "Illegal scan rate";
|
||||
case 23: return "Illegal number of samples";
|
||||
case 24: return "AI response error";
|
||||
case 25: return "LabJack RAM checksum error";
|
||||
case 26: return "AI sequence error";
|
||||
case 27: return "Maximum number of streams reached";
|
||||
case 28: return "AI stream start error";
|
||||
case 29: return "PC buffer overflow";
|
||||
case 30: return "LabJack buffer overflow";
|
||||
case 31: return "Stream read timeout";
|
||||
case 32: return "Illegal number of scans";
|
||||
case 33: return "No stream was found";
|
||||
case 40: return "Illegal input";
|
||||
case 41: return "Echo error";
|
||||
case 42: return "Data echo error";
|
||||
case 43: return "Response error";
|
||||
case 44: return "Asynch timeout error";
|
||||
case 45: return "Asynch start bit error";
|
||||
case 46: return "Asynch framing error";
|
||||
case 47: return "Asynch digital I/O state or tris error";
|
||||
case 48: return "Caps error";
|
||||
case 49: return "Caps error";
|
||||
case 50: return "Caps error";
|
||||
case 51: return "HID number caps error";
|
||||
case 52: return "HID get attributes warning";
|
||||
case 57: return "Wrong firmware version error";
|
||||
case 58: return "Digital I/O state or tris error";
|
||||
case 64: return "Could not claim all LabJacks";
|
||||
case 65: return "Error releasing all LabJacks";
|
||||
case 66: return "Could not claim LabJack";
|
||||
case 67: return "Error releasing LabJack";
|
||||
case 68: return "Claimed abandoned LabJack";
|
||||
case 69: return "Local ID -1 thread stopped";
|
||||
case 70: return "Stop thread timeout";
|
||||
case 71: return "Thread termination failed";
|
||||
case 72: return "Feature handle creation failed";
|
||||
case 73: return "Mutex creation failed";
|
||||
case 80: return "Synch CS state or tris error";
|
||||
case 81: return "Synch SCK tris error";
|
||||
case 82: return "Synch MISO tris error";
|
||||
case 83: return "Synch MOSI tris error";
|
||||
case 89: return "SHT1X communication error - CRC";
|
||||
case 90: return "SHT1X communication error - MeasReady";
|
||||
case 91: return "SHT1X communication error - ACK";
|
||||
case 92: return "SHT1X serial reset error";
|
||||
default: return "Unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//======================================================================
|
||||
//GetErrorString
|
||||
@ -1485,149 +1563,7 @@ float GetDriverVersion( void)
|
||||
void GetErrorString( long errorcode,
|
||||
char *errorString)
|
||||
{
|
||||
if(BitTst(errorcode,8))
|
||||
{
|
||||
errorcode -= STREAMBUFF_ERROR_OFFSET_LJ;
|
||||
}
|
||||
switch(errorcode)
|
||||
{
|
||||
case 0: errorString = strcpy(errorString,"No error");
|
||||
break;
|
||||
case 1: errorString = strcpy(errorString,"Unknown error");
|
||||
break;
|
||||
case 2: errorString = strcpy(errorString,"No LabJacks found");
|
||||
break;
|
||||
case 3: errorString = strcpy(errorString,"LabJack n not found");
|
||||
break;
|
||||
case 4: errorString = strcpy(errorString,"Set USB buffer error");
|
||||
break;
|
||||
case 5: errorString = strcpy(errorString,"Open handle error");
|
||||
break;
|
||||
case 6: errorString = strcpy(errorString,"Close handle error");
|
||||
break;
|
||||
case 7: errorString = strcpy(errorString,"Invalid ID");
|
||||
break;
|
||||
case 8: errorString = strcpy(errorString,"Invalid array size or value");
|
||||
break;
|
||||
case 9: errorString = strcpy(errorString,"Invalid power index");
|
||||
break;
|
||||
case 10: errorString = strcpy(errorString,"FCDD size too big");
|
||||
break;
|
||||
case 11: errorString = strcpy(errorString,"HVC size too big");
|
||||
break;
|
||||
case 12: errorString = strcpy(errorString,"Read error");
|
||||
break;
|
||||
case 13: errorString = strcpy(errorString,"Read timeout error");
|
||||
break;
|
||||
case 14: errorString = strcpy(errorString,"Write error");
|
||||
break;
|
||||
case 15: errorString = strcpy(errorString,"Turbo error");
|
||||
break;
|
||||
case 16: errorString = strcpy(errorString,"Illegal channel index");
|
||||
break;
|
||||
case 17: errorString = strcpy(errorString,"Illegal gain index");
|
||||
break;
|
||||
case 18: errorString = strcpy(errorString,"Illegal AI command");
|
||||
break;
|
||||
case 19: errorString = strcpy(errorString,"Illegal AO command");
|
||||
break;
|
||||
case 20: errorString = strcpy(errorString,"Bits out of range");
|
||||
break;
|
||||
case 21: errorString = strcpy(errorString,"Illegal number of channels");
|
||||
break;
|
||||
case 22: errorString = strcpy(errorString,"Illegal scan rate");
|
||||
break;
|
||||
case 23: errorString = strcpy(errorString,"Illegal number of samples");
|
||||
break;
|
||||
case 24: errorString = strcpy(errorString,"AI response error");
|
||||
break;
|
||||
case 25: errorString = strcpy(errorString,"LabJack RAM checksum error");
|
||||
break;
|
||||
case 26: errorString = strcpy(errorString,"AI sequence error");
|
||||
break;
|
||||
case 27: errorString = strcpy(errorString,"Maximum number of streams reached");
|
||||
break;
|
||||
case 28: errorString = strcpy(errorString,"AI stream start error");
|
||||
break;
|
||||
case 29: errorString = strcpy(errorString,"PC buffer overflow");
|
||||
break;
|
||||
case 30: errorString = strcpy(errorString,"LabJack buffer overflow");
|
||||
break;
|
||||
case 31: errorString = strcpy(errorString,"Stream read timeout");
|
||||
break;
|
||||
case 32: errorString = strcpy(errorString,"Illegal number of scans");
|
||||
break;
|
||||
case 33: errorString = strcpy(errorString,"No stream was found");
|
||||
break;
|
||||
case 40: errorString = strcpy(errorString,"Illegal input");
|
||||
break;
|
||||
case 41: errorString = strcpy(errorString,"Echo error");
|
||||
break;
|
||||
case 42: errorString = strcpy(errorString,"Data echo error");
|
||||
break;
|
||||
case 43: errorString = strcpy(errorString,"Response error");
|
||||
break;
|
||||
case 44: errorString = strcpy(errorString,"Asynch timeout error");
|
||||
break;
|
||||
case 45: errorString = strcpy(errorString,"Asynch start bit error");
|
||||
break;
|
||||
case 46: errorString = strcpy(errorString,"Asynch framing error");
|
||||
break;
|
||||
case 47: errorString = strcpy(errorString,"Asynch digital I/O state or tris error");
|
||||
break;
|
||||
case 48: errorString = strcpy(errorString,"Caps error");
|
||||
break;
|
||||
case 49: errorString = strcpy(errorString,"Caps error");
|
||||
break;
|
||||
case 50: errorString = strcpy(errorString,"Caps error");
|
||||
break;
|
||||
case 51: errorString = strcpy(errorString,"HID number caps error");
|
||||
break;
|
||||
case 52: errorString = strcpy(errorString,"HID get attributes warning");
|
||||
break;
|
||||
case 57: errorString = strcpy(errorString,"Wrong firmware version error");
|
||||
break;
|
||||
case 58: errorString = strcpy(errorString,"Digital I/O state or tris error");
|
||||
break;
|
||||
case 64: errorString = strcpy(errorString,"Could not claim all LabJacks");
|
||||
break;
|
||||
case 65: errorString = strcpy(errorString,"Error releasing all LabJacks");
|
||||
break;
|
||||
case 66: errorString = strcpy(errorString,"Could not claim LabJack");
|
||||
break;
|
||||
case 67: errorString = strcpy(errorString,"Error releasing LabJack");
|
||||
break;
|
||||
case 68: errorString = strcpy(errorString,"Claimed abandoned LabJack");
|
||||
break;
|
||||
case 69: errorString = strcpy(errorString,"Local ID -1 thread stopped");
|
||||
break;
|
||||
case 70: errorString = strcpy(errorString,"Stop thread timeout");
|
||||
break;
|
||||
case 71: errorString = strcpy(errorString,"Thread termination failed");
|
||||
break;
|
||||
case 72: errorString = strcpy(errorString,"Feature handle creation failed");
|
||||
break;
|
||||
case 73: errorString = strcpy(errorString,"Mutex creation failed");
|
||||
break;
|
||||
case 80: errorString = strcpy(errorString,"Synch CS state or tris error");
|
||||
break;
|
||||
case 81: errorString = strcpy(errorString,"Synch SCK tris error");
|
||||
break;
|
||||
case 82: errorString = strcpy(errorString,"Synch MISO tris error");
|
||||
break;
|
||||
case 83: errorString = strcpy(errorString,"Synch MOSI tris error");
|
||||
break;
|
||||
case 89: errorString = strcpy(errorString,"SHT1X communication error - CRC");
|
||||
break;
|
||||
case 90: errorString = strcpy(errorString,"SHT1X communication error - MeasReady");
|
||||
break;
|
||||
case 91: errorString = strcpy(errorString,"SHT1X communication error - ACK");
|
||||
break;
|
||||
case 92: errorString = strcpy(errorString,"SHT1X serial reset error");
|
||||
break;
|
||||
|
||||
default: errorString=strcpy(errorString,"Unknown error code");
|
||||
}
|
||||
errorString = strcpy(errorString, StaticErrorString(errorcode));
|
||||
return;
|
||||
}
|
||||
|
||||
|
2
deps/labjack/ljacklm/libljacklm/ljacklm.h
vendored
2
deps/labjack/ljacklm/libljacklm/ljacklm.h
vendored
@ -798,6 +798,8 @@ long DigitalIO( long *idnum,
|
||||
float GetDriverVersion( void);
|
||||
|
||||
|
||||
const char *StaticErrorString(long errorcode);
|
||||
|
||||
//======================================================================
|
||||
//GetErrorString
|
||||
//
|
||||
|
626
src/ljacklm.zig
626
src/ljacklm.zig
@ -1,3 +1,219 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn getDriverVersion() f32 {
|
||||
return c_api.GetDriverVersion();
|
||||
}
|
||||
|
||||
pub const Labjack = struct {
|
||||
id: ?u32 = null,
|
||||
demo: bool = false,
|
||||
|
||||
pub fn autodetect() Labjack {
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn firmwareVersion(self: Labjack) LabjackError!f32 {
|
||||
var id = self.cId();
|
||||
const version = c_api.GetFirmwareVersion(&id);
|
||||
|
||||
return if (version == 0)
|
||||
@as(c_api.LabjackCError, @bitCast(id)).toError()
|
||||
else
|
||||
version;
|
||||
}
|
||||
|
||||
/// Read one analog input channel, either single-ended or differential
|
||||
pub fn analogReadOne(self: Labjack, input: AnalogInput) LabjackError!AnalogReadResult {
|
||||
if (!input.channel.isDifferential() and input.gain != 0) {
|
||||
return error.InvalidGain;
|
||||
}
|
||||
|
||||
var id = self.cId();
|
||||
var over_v: c_long = 0;
|
||||
var res: AnalogReadResult = undefined;
|
||||
|
||||
const status = c_api.EAnalogIn(
|
||||
&id,
|
||||
@intFromBool(self.demo),
|
||||
input.channelNumber(),
|
||||
input.gain,
|
||||
&over_v,
|
||||
&res.voltage,
|
||||
);
|
||||
|
||||
if (status.okay()) {
|
||||
res.over_voltage = over_v > 0;
|
||||
return res;
|
||||
} else {
|
||||
return status.toError();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn digitalWriteOne(self: Labjack, output: DigitalOutput) LabjackError!void {
|
||||
var id = self.cId();
|
||||
const status = c_api.EDigitalOut(
|
||||
&id,
|
||||
@intFromBool(self.demo),
|
||||
output.channelNumber(),
|
||||
@intFromBool(output.isDLine()),
|
||||
@intFromBool(output.level),
|
||||
);
|
||||
|
||||
if (!status.okay())
|
||||
return status.toError();
|
||||
}
|
||||
|
||||
pub fn readAnalogWriteDigital(
|
||||
self: Labjack,
|
||||
comptime incount: u3,
|
||||
inputs: [incount]AnalogInput,
|
||||
outputs: ?[4]bool,
|
||||
ledOn: bool,
|
||||
) LabjackError![incount]AnalogReadResult {
|
||||
var id = self.cId();
|
||||
var out_states: c_long = if (outputs) |out|
|
||||
PackedOutput.fromBoolArray(out).toCLong()
|
||||
else
|
||||
0;
|
||||
var in_channels: [incount]c_long = undefined;
|
||||
var gains: [incount]c_long = undefined;
|
||||
for (inputs, &in_channels, &gains) |from, *inc, *gain| {
|
||||
inc.* = from.channelNumber();
|
||||
gain.* = from.gain;
|
||||
}
|
||||
var v_out: [4]f32 = .{0} ** 4;
|
||||
var over_v: c_long = 0;
|
||||
|
||||
const status = c_api.AISample(
|
||||
&id,
|
||||
@intFromBool(self.demo),
|
||||
&out_states,
|
||||
@intFromBool(outputs != null),
|
||||
@intFromBool(ledOn),
|
||||
incount,
|
||||
&in_channels,
|
||||
&gains,
|
||||
@intFromBool(false),
|
||||
&over_v,
|
||||
&v_out,
|
||||
);
|
||||
|
||||
if (!status.okay())
|
||||
return status.toError();
|
||||
|
||||
var result: [incount]AnalogReadResult = undefined;
|
||||
for (v_out[0..incount], &result) |raw, *res| {
|
||||
res.voltage = raw;
|
||||
// there's no information about which channel had over voltage, so
|
||||
// maybe we should return a different type
|
||||
res.over_voltage = over_v > 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn cId(self: Labjack) c_long {
|
||||
return self.id orelse -1;
|
||||
}
|
||||
};
|
||||
|
||||
pub const AnalogInput = struct {
|
||||
channel: AnalogInputChannel,
|
||||
gain: Gain = 0,
|
||||
|
||||
pub fn channelNumber(self: AnalogInput) u4 {
|
||||
return @intFromEnum(self.channel);
|
||||
}
|
||||
};
|
||||
|
||||
pub const AnalogReadResult = struct {
|
||||
voltage: f32,
|
||||
over_voltage: bool,
|
||||
};
|
||||
|
||||
pub const DigitalOutput = struct {
|
||||
channel: DigitalOutputChannel,
|
||||
level: bool,
|
||||
|
||||
pub fn channelNumber(self: DigitalOutput) u4 {
|
||||
return self.channel.channelNumber();
|
||||
}
|
||||
|
||||
pub fn isDLine(self: DigitalOutput) bool {
|
||||
return self.channel.isDLine();
|
||||
}
|
||||
};
|
||||
|
||||
pub const AnalogInputChannel = enum(u4) {
|
||||
ai0 = 0,
|
||||
ai1 = 1,
|
||||
ai2 = 2,
|
||||
ai3 = 3,
|
||||
ai4 = 4,
|
||||
ai5 = 5,
|
||||
ai6 = 6,
|
||||
ai7 = 7,
|
||||
|
||||
diff_01 = 8,
|
||||
diff_23 = 9,
|
||||
diff_45 = 10,
|
||||
diff_67 = 11,
|
||||
|
||||
pub fn isDifferential(self: AnalogInputChannel) bool {
|
||||
return switch (self) {
|
||||
.diff_01, .diff_23, .diff_45, .diff_67 => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const DigitalOutputChannel = union(enum) {
|
||||
io: u2,
|
||||
d: u4,
|
||||
|
||||
pub fn channelNumber(self: DigitalOutputChannel) u4 {
|
||||
return switch (self) {
|
||||
inline else => |val| val,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isDLine(self: DigitalOutputChannel) bool {
|
||||
return self == .d;
|
||||
}
|
||||
};
|
||||
|
||||
// differential only
|
||||
// 0 => G=1 ±20 volts
|
||||
// 1 => G=2 ±10 volts
|
||||
// 2 => G=4 ±5 volts
|
||||
// 3 => G=5 ±4 volts
|
||||
// 4 => G=8 ±2.5 volts
|
||||
// 5 => G=10 ±2 volts
|
||||
// 6 => G=16 ±1.25 volts
|
||||
// 7 => G=20 ±1 volt
|
||||
pub const Gain = u3;
|
||||
|
||||
pub const PackedOutput = packed struct(u4) {
|
||||
io0: bool,
|
||||
io1: bool,
|
||||
io2: bool,
|
||||
io3: bool,
|
||||
|
||||
pub fn fromBoolArray(states: [4]bool) PackedOutput {
|
||||
return .{
|
||||
.io0 = states[0],
|
||||
.io1 = states[1],
|
||||
.io2 = states[2],
|
||||
.io3 = states[3],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toCLong(self: PackedOutput) c_long {
|
||||
return @as(u4, @bitCast(self));
|
||||
}
|
||||
};
|
||||
|
||||
pub const c_api = struct {
|
||||
pub extern fn EAnalogIn(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
@ -5,14 +221,14 @@ pub extern fn EAnalogIn(
|
||||
gain: c_long,
|
||||
overVoltage: *c_long,
|
||||
voltage: *f32,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn EAnalogOut(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
analogOut0: f32,
|
||||
analogOut1: f32,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn ECount(
|
||||
idnum: *c_long,
|
||||
@ -20,15 +236,15 @@ pub extern fn ECount(
|
||||
resetCounter: c_long,
|
||||
count: *f64,
|
||||
ms: *f64,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn EDigitalIn(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
channel: c_long,
|
||||
readD: c_long,
|
||||
state: [*c]c_long,
|
||||
) c_long;
|
||||
state: *c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn EDigitalOut(
|
||||
idnum: *c_long,
|
||||
@ -36,7 +252,7 @@ pub extern fn EDigitalOut(
|
||||
channel: c_long,
|
||||
writeD: c_long,
|
||||
state: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AsynchConfig(
|
||||
idnum: *c_long,
|
||||
@ -51,7 +267,7 @@ pub extern fn AsynchConfig(
|
||||
halfA: c_long,
|
||||
halfB: c_long,
|
||||
halfC: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn Asynch(
|
||||
idnum: *c_long,
|
||||
@ -63,22 +279,22 @@ pub extern fn Asynch(
|
||||
baudrate: c_long,
|
||||
numWrite: c_long,
|
||||
numRead: c_long,
|
||||
data: [*c]c_long,
|
||||
) c_long;
|
||||
data: [*]c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AISample(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
stateIO: [*c]c_long,
|
||||
stateIO: *c_long,
|
||||
updateIO: c_long,
|
||||
ledOn: c_long,
|
||||
numChannels: c_long,
|
||||
channels: [*c]c_long,
|
||||
gains: [*c]c_long,
|
||||
channels: [*]c_long, // numChannels length
|
||||
gains: [*]c_long, // numChannels length
|
||||
disableCal: c_long,
|
||||
overVoltage: [*c]c_long,
|
||||
voltages: [*c]f32,
|
||||
) c_long;
|
||||
overVoltage: *c_long,
|
||||
voltages: *[4]f32,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AIBurst(
|
||||
idnum: *c_long,
|
||||
@ -87,19 +303,19 @@ pub extern fn AIBurst(
|
||||
updateIO: c_long,
|
||||
ledOn: c_long,
|
||||
numChannels: c_long,
|
||||
channels: [*c]c_long,
|
||||
gains: [*c]c_long,
|
||||
scanRate: [*c]f32,
|
||||
channels: [*]c_long, // numChannels length
|
||||
gains: [*]c_long, // numChannels length
|
||||
scanRate: *f32,
|
||||
disableCal: c_long,
|
||||
triggerIO: c_long,
|
||||
triggerIO: c_long, // 0=none, 1=IO0, or 2=IO1
|
||||
triggerState: c_long,
|
||||
numScans: c_long,
|
||||
timeout: c_long,
|
||||
voltages: [*c][4]f32,
|
||||
stateIOout: [*c]c_long,
|
||||
overVoltage: [*c]c_long,
|
||||
transferMode: c_long,
|
||||
) c_long;
|
||||
voltages: *[4096][4]f32,
|
||||
stateIOout: *[4096]c_long,
|
||||
overVoltage: *c_long,
|
||||
transferMode: c_long, // 0=auto,1=normal,2=turbo
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AIStreamStart(
|
||||
idnum: *c_long,
|
||||
@ -108,28 +324,28 @@ pub extern fn AIStreamStart(
|
||||
updateIO: c_long,
|
||||
ledOn: c_long,
|
||||
numChannels: c_long,
|
||||
channels: [*c]c_long,
|
||||
gains: [*c]c_long,
|
||||
scanRate: [*c]f32,
|
||||
channels: [*]c_long, // numChannels length
|
||||
gains: [*]c_long, // numChannels length
|
||||
scanRate: *f32,
|
||||
disableCal: c_long,
|
||||
reserved1: c_long,
|
||||
reserved1: c_long, // always 0
|
||||
readCount: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AIStreamRead(
|
||||
localID: c_long,
|
||||
numScans: c_long,
|
||||
timeout: c_long,
|
||||
voltages: [*c][4]f32,
|
||||
stateIOout: [*c]c_long,
|
||||
reserved: [*c]c_long,
|
||||
ljScanBacklog: [*c]c_long,
|
||||
overVoltage: [*c]c_long,
|
||||
) c_long;
|
||||
voltages: *[4096][4]f32,
|
||||
stateIOout: *[4096]c_long,
|
||||
reserved: ?*c_long, // unused
|
||||
ljScanBacklog: *c_long,
|
||||
overVoltage: *c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AIStreamClear(
|
||||
localID: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn AOUpdate(
|
||||
idnum: *c_long,
|
||||
@ -143,21 +359,21 @@ pub extern fn AOUpdate(
|
||||
count: [*c]c_ulong,
|
||||
analogOut0: f32,
|
||||
analogOut1: f32,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn BitsToVolts(
|
||||
chnum: c_long,
|
||||
chgain: c_long,
|
||||
bits: c_long,
|
||||
volts: [*c]f32,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn VoltsToBits(
|
||||
chnum: c_long,
|
||||
chgain: c_long,
|
||||
volts: f32,
|
||||
bits: [*c]c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn Counter(
|
||||
idnum: *c_long,
|
||||
@ -167,26 +383,22 @@ pub extern fn Counter(
|
||||
resetCounter: c_long,
|
||||
enableSTB: c_long,
|
||||
count: [*c]c_ulong,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn DigitalIO(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
trisD: [*c]c_long,
|
||||
trisIO: c_long,
|
||||
stateD: [*c]c_long,
|
||||
stateIO: [*c]c_long,
|
||||
trisD: *c_long, // 16 bits
|
||||
trisIO: c_long, // 4 bits
|
||||
stateD: *c_long, // 16 bits
|
||||
stateIO: *c_long, // 4 bits
|
||||
updateDigital: c_long,
|
||||
outputD: [*c]c_long,
|
||||
) c_long;
|
||||
outputD: *c_long, // 16 bits
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn GetDriverVersion() f32;
|
||||
|
||||
pub extern fn GetErrorString(
|
||||
errorcode: c_long,
|
||||
errorString: *[50]u8,
|
||||
) void;
|
||||
|
||||
pub extern fn StaticErrorString(errorcode: c_long) [*:0]const u8;
|
||||
pub extern fn GetErrorString(errorcode: c_long, errorString: *[50]u8) void;
|
||||
pub extern fn GetFirmwareVersion(idnum: *c_long) f32;
|
||||
|
||||
pub extern fn ListAll(
|
||||
@ -198,12 +410,12 @@ pub extern fn ListAll(
|
||||
numberFound: *c_long,
|
||||
fcddMaxSize: *c_long,
|
||||
hvcMaxSize: *c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn LocalID(
|
||||
idnum: *c_long,
|
||||
localID: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn PulseOut(
|
||||
idnum: *c_long,
|
||||
@ -215,7 +427,7 @@ pub extern fn PulseOut(
|
||||
timeC1: c_long,
|
||||
timeB2: c_long,
|
||||
timeC2: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn PulseOutStart(
|
||||
idnum: *c_long,
|
||||
@ -227,31 +439,24 @@ pub extern fn PulseOutStart(
|
||||
timeC1: c_long,
|
||||
timeB2: c_long,
|
||||
timeC2: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn PulseOutFinish(
|
||||
idnum: *c_long,
|
||||
demo: c_long,
|
||||
timeoutMS: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn PulseOutCalc(
|
||||
frequency: [*c]f32,
|
||||
timeB: [*c]c_long,
|
||||
timeC: [*c]c_long,
|
||||
) c_long;
|
||||
frequency: *f32,
|
||||
timeB: *c_long,
|
||||
timeC: *c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn ReEnum(
|
||||
idnum: *c_long,
|
||||
) c_long;
|
||||
|
||||
pub extern fn Reset(
|
||||
idnum: *c_long,
|
||||
) c_long;
|
||||
|
||||
pub extern fn ResetLJ(
|
||||
idnum: *c_long,
|
||||
) c_long;
|
||||
pub extern fn ReEnum(idnum: *c_long) LabjackCError;
|
||||
pub extern fn Reset(idnum: *c_long) LabjackCError;
|
||||
pub extern fn ResetLJ(idnum: *c_long) LabjackCError;
|
||||
pub extern fn CloseLabJack(localID: c_long) LabjackCError;
|
||||
|
||||
pub extern fn SHT1X(
|
||||
idnum: *c_long,
|
||||
@ -259,10 +464,10 @@ pub extern fn SHT1X(
|
||||
softComm: c_long,
|
||||
mode: c_long,
|
||||
statusReg: c_long,
|
||||
tempC: [*c]f32,
|
||||
tempF: [*c]f32,
|
||||
rh: [*c]f32,
|
||||
) c_long;
|
||||
tempC: *f32,
|
||||
tempF: *f32,
|
||||
rh: *f32,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn SHTComm(
|
||||
idnum: *c_long,
|
||||
@ -272,17 +477,17 @@ pub extern fn SHTComm(
|
||||
dataRate: c_long,
|
||||
numWrite: c_long,
|
||||
numRead: c_long,
|
||||
datatx: [*c]u8,
|
||||
datarx: [*c]u8,
|
||||
) c_long;
|
||||
datatx: [*]u8, // numWrite length
|
||||
datarx: [*]u8, // numRead length
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn SHTCRC(
|
||||
statusReg: c_long,
|
||||
numWrite: c_long,
|
||||
numRead: c_long,
|
||||
datatx: [*c]u8,
|
||||
datarx: [*c]u8,
|
||||
) c_long;
|
||||
datatx: *[4]u8,
|
||||
datarx: *[4]u8,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn Synch(
|
||||
idnum: *c_long,
|
||||
@ -295,8 +500,8 @@ pub extern fn Synch(
|
||||
csState: c_long,
|
||||
configD: c_long,
|
||||
numWriteRead: c_long,
|
||||
data: [*c]c_long,
|
||||
) c_long;
|
||||
data: *[18]c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn Watchdog(
|
||||
idnum: *c_long,
|
||||
@ -310,16 +515,16 @@ pub extern fn Watchdog(
|
||||
stateD0: c_long,
|
||||
stateD1: c_long,
|
||||
stateD8: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn ReadMem(
|
||||
idnum: *c_long,
|
||||
address: c_long,
|
||||
data3: [*c]c_long,
|
||||
data2: [*c]c_long,
|
||||
data1: [*c]c_long,
|
||||
data0: [*c]c_long,
|
||||
) c_long;
|
||||
data3: *c_long,
|
||||
data2: *c_long,
|
||||
data1: *c_long,
|
||||
data0: *c_long,
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn WriteMem(
|
||||
idnum: *c_long,
|
||||
@ -329,8 +534,241 @@ pub extern fn WriteMem(
|
||||
data2: c_long,
|
||||
data1: c_long,
|
||||
data0: c_long,
|
||||
) c_long;
|
||||
) LabjackCError;
|
||||
|
||||
pub extern fn CloseLabJack(
|
||||
localID: c_long,
|
||||
) c_long;
|
||||
pub const LabjackCError = packed struct(c_ulong) {
|
||||
code: LabjackErrorCode,
|
||||
stream_thread_error_flag: u1,
|
||||
firmware_version_error_flag: u1,
|
||||
_unused: switch (@typeInfo(c_ulong).Int.bits) {
|
||||
32 => u22,
|
||||
64 => u54,
|
||||
else => @compileError("c_ulong has a mystery number of bits"),
|
||||
},
|
||||
|
||||
pub fn okay(self: LabjackCError) bool {
|
||||
return self.code == .no_error;
|
||||
}
|
||||
|
||||
pub fn toError(self: LabjackCError) LabjackError {
|
||||
return switch (self.code) {
|
||||
.no_error => error.UnknownError,
|
||||
.unknown_error => error.UnknownError,
|
||||
.no_devices_found => error.NoDevicesFound,
|
||||
.device_n_not_found => error.DeviceNNotFound,
|
||||
.set_buffer_error => error.SetBufferError,
|
||||
.open_handle_error => error.OpenHandleError,
|
||||
.close_handle_error => error.CloseHandleError,
|
||||
.invalid_id => error.InvalidId,
|
||||
.array_size_or_value_error => error.ArraySizeOrValueError,
|
||||
.invalid_power_index => error.InvalidPowerIndex,
|
||||
.fcdd_size => error.FcddSize,
|
||||
.hvc_size => error.HvcSize,
|
||||
.read_error => error.ReadError,
|
||||
.read_timeout_error => error.ReadTimeoutError,
|
||||
.write_error => error.WriteError,
|
||||
.feature_error => error.FeatureError,
|
||||
.illegal_channel => error.IllegalChannel,
|
||||
.illegal_gain_index => error.IllegalGainIndex,
|
||||
.illegal_ai_command => error.IllegalAiCommand,
|
||||
.illegal_ao_command => error.IllegalAoCommand,
|
||||
.bits_out_of_range => error.BitsOutOfRange,
|
||||
.illegal_number_of_channels => error.IllegalNumberOfChannels,
|
||||
.illegal_scan_rate => error.IllegalScanRate,
|
||||
.illegal_num_samples => error.IllegalNumSamples,
|
||||
.ai_response_error => error.AiResponseError,
|
||||
.ram_cs_error => error.RamCsError,
|
||||
.ai_sequence_error => error.AiSequenceError,
|
||||
.num_streams_error => error.NumStreamsError,
|
||||
.ai_stream_start => error.AiStreamStart,
|
||||
.pc_buff_overflow => error.PcBuffOverflow,
|
||||
.lj_buff_overflow => error.LjBuffOverflow,
|
||||
.stream_read_timeout => error.StreamReadTimeout,
|
||||
.illegal_num_scans => error.IllegalNumScans,
|
||||
.no_stream_found => error.NoStreamFound,
|
||||
.illegal_input_error => error.IllegalInput,
|
||||
.echo_error => error.EchoError,
|
||||
.data_echo_error => error.DataEchoError,
|
||||
.response_error => error.ResponseError,
|
||||
.asynch_timeout_error => error.AsynchTimeout,
|
||||
.asynch_start_error => error.AsynchStartError,
|
||||
.asynch_frame_error => error.AsynchFrameError,
|
||||
.asynch_dio_config_error => error.AsynchDioConfigError,
|
||||
.input_caps_error => error.InputCapsError,
|
||||
.output_caps_error => error.OutputCapsError,
|
||||
.feature_caps_error => error.FeatureCapsError,
|
||||
.num_caps_error => error.NumCapsError,
|
||||
.get_attributes_warning => error.GetAttributesWarning,
|
||||
.wrong_firmware_version => error.WrongFirmwareVersion,
|
||||
.dio_config_error => error.DioConfigError,
|
||||
.claim_all_devices => error.ClaimAllDevices,
|
||||
.release_all_devices => error.ReleaseAllDevices,
|
||||
.claim_device => error.ClaimDevice,
|
||||
.release_device => error.ReleaseDevice,
|
||||
.claimed_abandoned => error.ClaimedAbandoned,
|
||||
.localid_neg => error.LocalidNeg,
|
||||
.stop_thread_timeout => error.StopThreadTimeout,
|
||||
.terminate_thread => error.TerminateThread,
|
||||
.feature_handle => error.FeatureHandle,
|
||||
.create_mutex => error.CreateMutex,
|
||||
.synch_csstatetris_error => error.SynchCsstatetrisError,
|
||||
.synch_scktris_error => error.SynchScktrisError,
|
||||
.synch_misotris_error => error.SynchMisotrisError,
|
||||
.synch_mositris_error => error.SynchMositrisError,
|
||||
.sht1x_crc_error => error.Sht1xCrcError,
|
||||
.sht1x_measready_error => error.Sht1xMeasreadyError,
|
||||
.sht1x_ack_error => error.Sht1xAckError,
|
||||
.sht1x_serial_reset_error => error.Sht1xSerialResetError,
|
||||
_ => error.UnknownErrorCode,
|
||||
};
|
||||
}
|
||||
|
||||
pub const LabjackErrorCode = enum(u8) {
|
||||
no_error = 0, // must be 0
|
||||
unknown_error = 1,
|
||||
no_devices_found = 2,
|
||||
device_n_not_found = 3,
|
||||
set_buffer_error = 4,
|
||||
open_handle_error = 5,
|
||||
close_handle_error = 6,
|
||||
invalid_id = 7,
|
||||
array_size_or_value_error = 8,
|
||||
invalid_power_index = 9,
|
||||
fcdd_size = 10,
|
||||
hvc_size = 11,
|
||||
read_error = 12,
|
||||
read_timeout_error = 13,
|
||||
write_error = 14,
|
||||
feature_error = 15,
|
||||
illegal_channel = 16,
|
||||
illegal_gain_index = 17,
|
||||
illegal_ai_command = 18,
|
||||
illegal_ao_command = 19,
|
||||
bits_out_of_range = 20,
|
||||
illegal_number_of_channels = 21,
|
||||
illegal_scan_rate = 22,
|
||||
illegal_num_samples = 23,
|
||||
ai_response_error = 24,
|
||||
ram_cs_error = 25,
|
||||
ai_sequence_error = 26,
|
||||
num_streams_error = 27,
|
||||
ai_stream_start = 28,
|
||||
pc_buff_overflow = 29,
|
||||
lj_buff_overflow = 30,
|
||||
stream_read_timeout = 31,
|
||||
illegal_num_scans = 32,
|
||||
no_stream_found = 33,
|
||||
illegal_input_error = 40,
|
||||
echo_error = 41,
|
||||
data_echo_error = 42,
|
||||
response_error = 43,
|
||||
asynch_timeout_error = 44,
|
||||
asynch_start_error = 45,
|
||||
asynch_frame_error = 46,
|
||||
asynch_dio_config_error = 47,
|
||||
input_caps_error = 48,
|
||||
output_caps_error = 49,
|
||||
feature_caps_error = 50,
|
||||
num_caps_error = 51,
|
||||
get_attributes_warning = 52,
|
||||
wrong_firmware_version = 57,
|
||||
dio_config_error = 58,
|
||||
claim_all_devices = 64,
|
||||
release_all_devices = 65,
|
||||
claim_device = 66,
|
||||
release_device = 67,
|
||||
claimed_abandoned = 68,
|
||||
localid_neg = 69,
|
||||
stop_thread_timeout = 70,
|
||||
terminate_thread = 71,
|
||||
feature_handle = 72,
|
||||
create_mutex = 73,
|
||||
synch_csstatetris_error = 80,
|
||||
synch_scktris_error = 81,
|
||||
synch_misotris_error = 82,
|
||||
synch_mositris_error = 83,
|
||||
sht1x_crc_error = 89,
|
||||
sht1x_measready_error = 90,
|
||||
sht1x_ack_error = 91,
|
||||
sht1x_serial_reset_error = 92,
|
||||
_,
|
||||
|
||||
pub fn describe(self: LabjackErrorCode) []const u8 {
|
||||
const res = StaticErrorString(@intFromEnum(self));
|
||||
return std.mem.sliceTo(res, 0);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pub const LabjackError = error{
|
||||
UnknownError,
|
||||
NoDevicesFound,
|
||||
DeviceNNotFound,
|
||||
SetBufferError,
|
||||
OpenHandleError,
|
||||
CloseHandleError,
|
||||
InvalidId,
|
||||
ArraySizeOrValueError,
|
||||
InvalidPowerIndex,
|
||||
FcddSize,
|
||||
HvcSize,
|
||||
ReadError,
|
||||
ReadTimeoutError,
|
||||
WriteError,
|
||||
FeatureError,
|
||||
IllegalChannel,
|
||||
IllegalGainIndex,
|
||||
IllegalAiCommand,
|
||||
IllegalAoCommand,
|
||||
BitsOutOfRange,
|
||||
IllegalNumberOfChannels,
|
||||
IllegalScanRate,
|
||||
IllegalNumSamples,
|
||||
AiResponseError,
|
||||
RamCsError,
|
||||
AiSequenceError,
|
||||
NumStreamsError,
|
||||
AiStreamStart,
|
||||
PcBuffOverflow,
|
||||
LjBuffOverflow,
|
||||
StreamReadTimeout,
|
||||
IllegalNumScans,
|
||||
NoStreamFound,
|
||||
IllegalInput,
|
||||
EchoError,
|
||||
DataEchoError,
|
||||
ResponseError,
|
||||
AsynchTimeout,
|
||||
AsynchStartError,
|
||||
AsynchFrameError,
|
||||
AsynchDioConfigError,
|
||||
InputCapsError,
|
||||
OutputCapsError,
|
||||
FeatureCapsError,
|
||||
NumCapsError,
|
||||
GetAttributesWarning,
|
||||
WrongFirmwareVersion,
|
||||
DioConfigError,
|
||||
ClaimAllDevices,
|
||||
ReleaseAllDevices,
|
||||
ClaimDevice,
|
||||
ReleaseDevice,
|
||||
ClaimedAbandoned,
|
||||
LocalidNeg,
|
||||
StopThreadTimeout,
|
||||
TerminateThread,
|
||||
FeatureHandle,
|
||||
CreateMutex,
|
||||
SynchCsstatetrisError,
|
||||
SynchScktrisError,
|
||||
SynchMisotrisError,
|
||||
SynchMositrisError,
|
||||
Sht1xCrcError,
|
||||
Sht1xMeasreadyError,
|
||||
Sht1xAckError,
|
||||
Sht1xSerialResetError,
|
||||
UnknownErrorCode,
|
||||
//
|
||||
InvalidGain,
|
||||
};
|
||||
|
19
src/main.zig
19
src/main.zig
@ -3,6 +3,23 @@ const std = @import("std");
|
||||
const ljack = @import("./ljacklm.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
const ver = ljack.GetDriverVersion();
|
||||
const ver = ljack.getDriverVersion();
|
||||
std.debug.print("Driver version: {d}\n", .{ver});
|
||||
|
||||
const device = ljack.Labjack.autodetect();
|
||||
|
||||
const in = try device.analogReadOne(.{ .channel = .diff_01, .gain = 2 });
|
||||
std.debug.print("Read voltage: {d}. Overvolt: {}\n", .{ in.voltage, in.over_voltage });
|
||||
try device.digitalWriteOne(.{ .channel = .{ .io = 0 }, .level = true });
|
||||
|
||||
const sample = try device.readAnalogWriteDigital(
|
||||
2,
|
||||
.{ .{ .channel = .diff_01, .gain = 2 }, .{ .channel = .diff_23, .gain = 2 } },
|
||||
.{false} ** 4,
|
||||
true,
|
||||
);
|
||||
|
||||
for (sample, 0..) |input, idx| {
|
||||
std.debug.print(" channel {d}: {d} V\n", .{ idx, input.voltage });
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user