Remove system dependency on nidaqmx
This commit is contained in:
parent
4db4b9fa81
commit
6eea7329c8
@ -27,11 +27,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const external_compiler_support_dir = try std.process.getEnvVarOwned(b.allocator, "NIEXTCCOMPILERSUPP");
|
const external_compiler_support_dir = try std.process.getEnvVarOwned(b.allocator, "NIEXTCCOMPILERSUPP");
|
||||||
exe.addSystemIncludePath(.{ .cwd_relative = try std.fs.path.join(b.allocator, &.{ external_compiler_support_dir, "include" }) });
|
exe.addSystemIncludePath(.{ .cwd_relative = try std.fs.path.join(b.allocator, &.{ external_compiler_support_dir, "include" }) });
|
||||||
|
|
||||||
const lib_folder_name = if (target.result.ptrBitWidth() == 64) "lib64" else "lib32";
|
|
||||||
exe.addLibraryPath(.{ .cwd_relative = try std.fs.path.join(b.allocator, &.{ external_compiler_support_dir, lib_folder_name, "msvc" }) });
|
|
||||||
|
|
||||||
exe.linkSystemLibrary("nidaqmx");
|
|
||||||
|
|
||||||
// TODO: Emebed all assets using build.zig
|
// TODO: Emebed all assets using build.zig
|
||||||
// https://github.com/ziglang/zig/issues/14637#issuecomment-1428689051
|
// https://github.com/ziglang/zig/issues/14637#issuecomment-1428689051
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ const UI = @import("./ui.zig");
|
|||||||
const Platform = @import("./platform.zig");
|
const Platform = @import("./platform.zig");
|
||||||
const Assets = @import("./assets.zig");
|
const Assets = @import("./assets.zig");
|
||||||
const Graph = @import("./graph.zig");
|
const Graph = @import("./graph.zig");
|
||||||
const NIDaq = @import("ni-daq.zig");
|
const NIDaq = @import("ni-daq/root.zig");
|
||||||
const rect_utils = @import("./rect-utils.zig");
|
const rect_utils = @import("./rect-utils.zig");
|
||||||
const remap = @import("./utils.zig").remap;
|
const remap = @import("./utils.zig").remap;
|
||||||
const TaskPool = @import("./task-pool.zig");
|
const TaskPool = @import("./task-pool.zig");
|
||||||
|
@ -153,7 +153,7 @@ pub fn main() !void {
|
|||||||
defer app.deinit();
|
defer app.deinit();
|
||||||
|
|
||||||
if (builtin.mode == .Debug) {
|
if (builtin.mode == .Debug) {
|
||||||
try app.appendChannelFromDevice("Dev1/ai0");
|
// try app.appendChannelFromDevice("Dev1/ai0");
|
||||||
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin");
|
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin");
|
||||||
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_IjStim.bin");
|
||||||
}
|
}
|
||||||
@ -191,5 +191,5 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("./ni-daq.zig");
|
_ = @import("./ni-daq/root.zig");
|
||||||
}
|
}
|
59
src/ni-daq/api.zig
Normal file
59
src/ni-daq/api.zig
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cInclude("stdint.h");
|
||||||
|
@cDefine("__int64", "long long");
|
||||||
|
@cInclude("NIDAQmx.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
const Api = @This();
|
||||||
|
|
||||||
|
const log = std.log.scoped(.ni_daq_api);
|
||||||
|
|
||||||
|
lib: std.DynLib, // This MUST be the first field of `Api` struct
|
||||||
|
|
||||||
|
DAQmxGetSysNIDAQMajorVersion: *const @TypeOf(c.DAQmxGetSysNIDAQMajorVersion),
|
||||||
|
DAQmxGetSysNIDAQMinorVersion: *const @TypeOf(c.DAQmxGetSysNIDAQMinorVersion),
|
||||||
|
DAQmxGetSysNIDAQUpdateVersion: *const @TypeOf(c.DAQmxGetSysNIDAQUpdateVersion),
|
||||||
|
DAQmxGetErrorString: *const @TypeOf(c.DAQmxGetErrorString),
|
||||||
|
DAQmxStopTask: *const @TypeOf(c.DAQmxStopTask),
|
||||||
|
DAQmxStartTask: *const @TypeOf(c.DAQmxStartTask),
|
||||||
|
DAQmxClearTask: *const @TypeOf(c.DAQmxClearTask),
|
||||||
|
DAQmxGetTaskName: *const @TypeOf(c.DAQmxGetTaskName),
|
||||||
|
DAQmxCfgSampClkTiming: *const @TypeOf(c.DAQmxCfgSampClkTiming),
|
||||||
|
DAQmxCreateTask: *const @TypeOf(c.DAQmxCreateTask),
|
||||||
|
DAQmxCreateAIVoltageChan: *const @TypeOf(c.DAQmxCreateAIVoltageChan),
|
||||||
|
DAQmxGetSysDevNames: *const @TypeOf(c.DAQmxGetSysDevNames),
|
||||||
|
DAQmxGetDevAIVoltageRngs: *const @TypeOf(c.DAQmxGetDevAIVoltageRngs),
|
||||||
|
DAQmxGetDevAOVoltageRngs: *const @TypeOf(c.DAQmxGetDevAOVoltageRngs),
|
||||||
|
DAQmxGetDevAIMaxSingleChanRate: *const @TypeOf(c.DAQmxGetDevAIMaxSingleChanRate),
|
||||||
|
DAQmxGetDevAOMaxRate: *const @TypeOf(c.DAQmxGetDevAOMaxRate),
|
||||||
|
DAQmxGetDevAIMinRate: *const @TypeOf(c.DAQmxGetDevAIMinRate),
|
||||||
|
DAQmxGetDevAOMinRate: *const @TypeOf(c.DAQmxGetDevAOMinRate),
|
||||||
|
DAQmxGetDevAISupportedMeasTypes: *const @TypeOf(c.DAQmxGetDevAISupportedMeasTypes),
|
||||||
|
DAQmxGetDevAOSupportedOutputTypes: *const @TypeOf(c.DAQmxGetDevAOSupportedOutputTypes),
|
||||||
|
DAQmxGetDevProductCategory: *const @TypeOf(c.DAQmxGetDevProductCategory),
|
||||||
|
DAQmxGetDevAIPhysicalChans: *const @TypeOf(c.DAQmxGetDevAIPhysicalChans),
|
||||||
|
DAQmxGetDevAOPhysicalChans: *const @TypeOf(c.DAQmxGetDevAOPhysicalChans),
|
||||||
|
DAQmxReadAnalogF64: *const @TypeOf(c.DAQmxReadAnalogF64),
|
||||||
|
|
||||||
|
pub fn init() !Api {
|
||||||
|
var api: Api = undefined;
|
||||||
|
|
||||||
|
api.lib = try std.DynLib.open("nicaiu");
|
||||||
|
errdefer api.lib.close();
|
||||||
|
|
||||||
|
inline for (@typeInfo(Api).Struct.fields[1..]) |field| {
|
||||||
|
const name = std.fmt.comptimePrint("{s}\x00", .{field.name});
|
||||||
|
const name_z = name[0 .. (name.len - 1) :0];
|
||||||
|
@field(api, field.name) = api.lib.lookup(field.type, name_z) orelse {
|
||||||
|
log.err("Symbol lookup failed for {s}", .{name});
|
||||||
|
return error.SymbolLookup;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Api) void {
|
||||||
|
self.lib.close();
|
||||||
|
}
|
@ -1,9 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
pub const c = @cImport({
|
const Api = @import("./api.zig");
|
||||||
@cInclude("stdint.h");
|
pub const c = Api.c;
|
||||||
@cDefine("__int64", "long long");
|
|
||||||
@cInclude("NIDAQmx.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const log = std.log.scoped(.ni_daq);
|
const log = std.log.scoped(.ni_daq);
|
||||||
@ -38,6 +35,7 @@ pub const Options = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Task = struct {
|
pub const Task = struct {
|
||||||
|
ni_daq: *NIDaq,
|
||||||
handle: TaskHandle,
|
handle: TaskHandle,
|
||||||
|
|
||||||
name_buffer: [max_task_name_size]u8 = undefined,
|
name_buffer: [max_task_name_size]u8 = undefined,
|
||||||
@ -45,19 +43,23 @@ pub const Task = struct {
|
|||||||
dropped_samples: u32 = 0,
|
dropped_samples: u32 = 0,
|
||||||
|
|
||||||
pub fn clear(self: Task) void {
|
pub fn clear(self: Task) void {
|
||||||
logDAQmxError(c.DAQmxClearTask(self.handle));
|
// Ignore error
|
||||||
|
const api = self.ni_daq.api;
|
||||||
|
self.ni_daq.logDAQmxError(api.DAQmxClearTask(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self: *Task) ![]const u8 {
|
pub fn name(self: *Task) ![]const u8 {
|
||||||
const required_size = c.DAQmxGetTaskName(self.handle, null, 0);
|
const api = self.ni_daq.api;
|
||||||
|
|
||||||
|
const required_size = api.DAQmxGetTaskName(self.handle, null, 0);
|
||||||
assert(required_size >= 0);
|
assert(required_size >= 0);
|
||||||
|
|
||||||
if (required_size > self.name_buffer.len) {
|
if (required_size > self.name_buffer.len) {
|
||||||
return error.BufferTooSmall;
|
return error.BufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.ni_daq.checkDAQmxError(
|
||||||
c.DAQmxGetTaskName(
|
api.DAQmxGetTaskName(
|
||||||
self.handle,
|
self.handle,
|
||||||
&self.name_buffer,
|
&self.name_buffer,
|
||||||
self.name_buffer.len
|
self.name_buffer.len
|
||||||
@ -69,29 +71,33 @@ pub const Task = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self: Task) !void {
|
pub fn start(self: Task) !void {
|
||||||
try checkDAQmxError(
|
const api = self.ni_daq.api;
|
||||||
c.DAQmxStartTask(self.handle),
|
try self.ni_daq.checkDAQmxError(
|
||||||
|
api.DAQmxStartTask(self.handle),
|
||||||
error.DAQmxStartTask
|
error.DAQmxStartTask
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(self: Task) !void {
|
pub fn stop(self: Task) !void {
|
||||||
try checkDAQmxError(
|
const api = self.ni_daq.api;
|
||||||
c.DAQmxStopTask(self.handle),
|
try self.ni_daq.checkDAQmxError(
|
||||||
|
api.DAQmxStopTask(self.handle),
|
||||||
error.DAQmxStopTask
|
error.DAQmxStopTask
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setContinousSampleRate(self: Task, sample_rate: f64) !void {
|
pub fn setContinousSampleRate(self: Task, sample_rate: f64) !void {
|
||||||
try checkDAQmxError(
|
const api = self.ni_daq.api;
|
||||||
c.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_ContSamps, 0),
|
try self.ni_daq.checkDAQmxError(
|
||||||
|
api.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_ContSamps, 0),
|
||||||
error.DAQmxCfgSampClkTiming
|
error.DAQmxCfgSampClkTiming
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setFiniteSampleRate(self: Task, sample_rate: f64, samples_per_channel: u64) !void {
|
pub fn setFiniteSampleRate(self: Task, sample_rate: f64, samples_per_channel: u64) !void {
|
||||||
try checkDAQmxError(
|
const api = self.ni_daq.api;
|
||||||
c.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_FiniteSamps, samples_per_channel),
|
try self.ni_daq.checkDAQmxError(
|
||||||
|
api.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_FiniteSamps, samples_per_channel),
|
||||||
error.DAQmxCfgSampClkTiming
|
error.DAQmxCfgSampClkTiming
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -107,8 +113,9 @@ pub const Task = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn createAIVoltageChannel(self: Task, options: AIVoltageChannelOptions) !void {
|
pub fn createAIVoltageChannel(self: Task, options: AIVoltageChannelOptions) !void {
|
||||||
try checkDAQmxError(
|
const api = self.ni_daq.api;
|
||||||
c.DAQmxCreateAIVoltageChan(
|
try self.ni_daq.checkDAQmxError(
|
||||||
|
api.DAQmxCreateAIVoltageChan(
|
||||||
self.handle,
|
self.handle,
|
||||||
options.channel,
|
options.channel,
|
||||||
options.assigned_name,
|
options.assigned_name,
|
||||||
@ -132,7 +139,7 @@ pub const Task = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn createAOVoltageChannel(self: Task, options: AOVoltageChannelOptions) !void {
|
pub fn createAOVoltageChannel(self: Task, options: AOVoltageChannelOptions) !void {
|
||||||
try checkDAQmxError(
|
try self.ni_daq.checkDAQmxError(
|
||||||
c.DAQmxCreateAOVoltageChan(
|
c.DAQmxCreateAOVoltageChan(
|
||||||
self.handle,
|
self.handle,
|
||||||
options.channel,
|
options.channel,
|
||||||
@ -155,8 +162,9 @@ pub const Task = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn readAnalog(self: *Task, options: ReadAnalogOptions) !u32 {
|
pub fn readAnalog(self: *Task, options: ReadAnalogOptions) !u32 {
|
||||||
|
const api = self.ni_daq.api;
|
||||||
var samples_per_channel: i32 = 0;
|
var samples_per_channel: i32 = 0;
|
||||||
const err = c.DAQmxReadAnalogF64(
|
const err = api.DAQmxReadAnalogF64(
|
||||||
self.handle,
|
self.handle,
|
||||||
options.samples_per_channel,
|
options.samples_per_channel,
|
||||||
options.timeout,
|
options.timeout,
|
||||||
@ -171,7 +179,7 @@ pub const Task = struct {
|
|||||||
self.dropped_samples += 1;
|
self.dropped_samples += 1;
|
||||||
log.err("Dropped samples, not reading samples fast enough.", .{});
|
log.err("Dropped samples, not reading samples fast enough.", .{});
|
||||||
} else if (err < 0) {
|
} else if (err < 0) {
|
||||||
try checkDAQmxError(err, error.DAQmxReadAnalogF64);
|
try self.ni_daq.checkDAQmxError(err, error.DAQmxReadAnalogF64);
|
||||||
}
|
}
|
||||||
|
|
||||||
return @intCast(samples_per_channel);
|
return @intCast(samples_per_channel);
|
||||||
@ -179,7 +187,7 @@ pub const Task = struct {
|
|||||||
|
|
||||||
pub fn isDone(self: Task) !bool {
|
pub fn isDone(self: Task) !bool {
|
||||||
var result: c.bool32 = 0;
|
var result: c.bool32 = 0;
|
||||||
try checkDAQmxError(
|
try self.ni_daq.checkDAQmxError(
|
||||||
c.DAQmxIsTaskDone(self.handle, &result),
|
c.DAQmxIsTaskDone(self.handle, &result),
|
||||||
error.DAQmxIsTaskDone
|
error.DAQmxIsTaskDone
|
||||||
);
|
);
|
||||||
@ -365,12 +373,16 @@ const DeviceBuffers = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
options: Options,
|
options: Options,
|
||||||
|
api: Api,
|
||||||
device_names_buffer: []u8,
|
device_names_buffer: []u8,
|
||||||
device_names: StringArrayListUnmanaged,
|
device_names: StringArrayListUnmanaged,
|
||||||
|
|
||||||
device_buffers: []DeviceBuffers,
|
device_buffers: []DeviceBuffers,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, options: Options) !NIDaq {
|
pub fn init(allocator: std.mem.Allocator, options: Options) !NIDaq {
|
||||||
|
var api = try Api.init();
|
||||||
|
errdefer api.deinit();
|
||||||
|
|
||||||
const device_names_buffer_size = options.max_devices * (max_device_name_size + 2);
|
const device_names_buffer_size = options.max_devices * (max_device_name_size + 2);
|
||||||
const device_names_buffer = try allocator.alloc(u8, device_names_buffer_size);
|
const device_names_buffer = try allocator.alloc(u8, device_names_buffer_size);
|
||||||
errdefer allocator.free(device_names_buffer);
|
errdefer allocator.free(device_names_buffer);
|
||||||
@ -388,6 +400,7 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !NIDaq {
|
|||||||
|
|
||||||
return NIDaq{
|
return NIDaq{
|
||||||
.options = options,
|
.options = options,
|
||||||
|
.api = api,
|
||||||
.device_names_buffer = device_names_buffer,
|
.device_names_buffer = device_names_buffer,
|
||||||
.device_names = device_names,
|
.device_names = device_names,
|
||||||
.device_buffers = device_buffers
|
.device_buffers = device_buffers
|
||||||
@ -395,6 +408,8 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !NIDaq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *NIDaq, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *NIDaq, allocator: std.mem.Allocator) void {
|
||||||
|
self.api.deinit();
|
||||||
|
|
||||||
self.device_names.deinit(allocator);
|
self.device_names.deinit(allocator);
|
||||||
allocator.free(self.device_names_buffer);
|
allocator.free(self.device_names_buffer);
|
||||||
|
|
||||||
@ -423,33 +438,33 @@ test {
|
|||||||
try std.testing.expectEqual(3, maxIndexStringLength(101));
|
try std.testing.expectEqual(3, maxIndexStringLength(101));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logDAQmxError(error_code: i32) void {
|
pub fn logDAQmxError(self: NIDaq, error_code: i32) void {
|
||||||
if (error_code == 0) {
|
if (error_code == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg: [512:0]u8 = .{ 0 } ** 512;
|
var msg: [512:0]u8 = .{ 0 } ** 512;
|
||||||
if (c.DAQmxGetErrorString(error_code, &msg, msg.len) == 0) {
|
if (self.api.DAQmxGetErrorString(error_code, &msg, msg.len) == 0) {
|
||||||
log.err("DAQmx ({}): {s}", .{error_code, msg});
|
log.err("DAQmx ({}): {s}", .{error_code, msg});
|
||||||
} else {
|
} else {
|
||||||
log.err("DAQmx ({}): Unknown (Buffer too small for message)", .{error_code});
|
log.err("DAQmx ({}): Unknown (Buffer too small for message)", .{error_code});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkDAQmxError(error_code: i32, err: anyerror) !void {
|
pub fn checkDAQmxError(self: NIDaq, error_code: i32, err: anyerror) !void {
|
||||||
logDAQmxError(error_code);
|
self.logDAQmxError(error_code);
|
||||||
|
|
||||||
if (error_code < 0) {
|
if (error_code < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checkDAQmxErrorIgnoreWarnings(error_code: i32, err: anyerror) !void {
|
pub fn checkDAQmxErrorIgnoreWarnings(self: NIDaq, error_code: i32, err: anyerror) !void {
|
||||||
if (error_code > 0) {
|
if (error_code > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkDAQmxError(error_code, err);
|
try self.checkDAQmxError(error_code, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn splitCommaDelimitedList(array_list: *std.ArrayListUnmanaged([:0]const u8), buffer: []u8) !void {
|
fn splitCommaDelimitedList(array_list: *std.ArrayListUnmanaged([:0]const u8), buffer: []u8) !void {
|
||||||
@ -471,22 +486,22 @@ fn splitCommaDelimitedList(array_list: *std.ArrayListUnmanaged([:0]const u8), bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn version() !std.SemanticVersion {
|
pub fn version(self: NIDaq) !std.SemanticVersion {
|
||||||
var major: u32 = 0;
|
var major: u32 = 0;
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetSysNIDAQMajorVersion(&major),
|
self.api.DAQmxGetSysNIDAQMajorVersion(&major),
|
||||||
error.GetMajorVersion
|
error.GetMajorVersion
|
||||||
);
|
);
|
||||||
|
|
||||||
var minor: u32 = 0;
|
var minor: u32 = 0;
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetSysNIDAQMinorVersion(&minor),
|
self.api.DAQmxGetSysNIDAQMinorVersion(&minor),
|
||||||
error.GetMinorVersion
|
error.GetMinorVersion
|
||||||
);
|
);
|
||||||
|
|
||||||
var update: u32 = 0;
|
var update: u32 = 0;
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetSysNIDAQUpdateVersion(&update),
|
self.api.DAQmxGetSysNIDAQUpdateVersion(&update),
|
||||||
error.GetUpdateVersion
|
error.GetUpdateVersion
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -501,8 +516,8 @@ pub fn listDeviceNames(self: *NIDaq) ![]const [:0]const u8 {
|
|||||||
self.device_names.clearRetainingCapacity();
|
self.device_names.clearRetainingCapacity();
|
||||||
self.clearAllDeviceBuffers();
|
self.clearAllDeviceBuffers();
|
||||||
|
|
||||||
const required_size = c.DAQmxGetSysDevNames(null, 0);
|
const required_size = self.api.DAQmxGetSysDevNames(null, 0);
|
||||||
try checkDAQmxErrorIgnoreWarnings(required_size, error.DAQmxGetSysDevNames);
|
try self.checkDAQmxErrorIgnoreWarnings(required_size, error.DAQmxGetSysDevNames);
|
||||||
if (required_size == 0) {
|
if (required_size == 0) {
|
||||||
return self.device_names.items;
|
return self.device_names.items;
|
||||||
}
|
}
|
||||||
@ -511,8 +526,8 @@ pub fn listDeviceNames(self: *NIDaq) ![]const [:0]const u8 {
|
|||||||
return error.BufferTooSmall;
|
return error.BufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetSysDevNames(self.device_names_buffer.ptr, @intCast(self.device_names_buffer.len)),
|
self.api.DAQmxGetSysDevNames(self.device_names_buffer.ptr, @intCast(self.device_names_buffer.len)),
|
||||||
error.GetDeviceNames
|
error.GetDeviceNames
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -549,6 +564,7 @@ fn clearAllDeviceBuffers(self: *NIDaq) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn listDevicePhysicalChannels(
|
fn listDevicePhysicalChannels(
|
||||||
|
self: NIDaq,
|
||||||
getPhysicalChannels: anytype,
|
getPhysicalChannels: anytype,
|
||||||
device: [:0]const u8,
|
device: [:0]const u8,
|
||||||
channel_names: *DeviceBuffers.ChannelNames,
|
channel_names: *DeviceBuffers.ChannelNames,
|
||||||
@ -559,7 +575,7 @@ fn listDevicePhysicalChannels(
|
|||||||
array_list.clearRetainingCapacity();
|
array_list.clearRetainingCapacity();
|
||||||
|
|
||||||
const required_size = getPhysicalChannels(device, null, 0);
|
const required_size = getPhysicalChannels(device, null, 0);
|
||||||
try checkDAQmxErrorIgnoreWarnings(required_size, error.GetPhysicalChannels);
|
try self.checkDAQmxErrorIgnoreWarnings(required_size, error.GetPhysicalChannels);
|
||||||
if (required_size == 0) {
|
if (required_size == 0) {
|
||||||
return array_list.items;
|
return array_list.items;
|
||||||
}
|
}
|
||||||
@ -568,7 +584,7 @@ fn listDevicePhysicalChannels(
|
|||||||
return error.BufferTooSmall;
|
return error.BufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
getPhysicalChannels(device, buffer.ptr, @intCast(buffer.len)),
|
getPhysicalChannels(device, buffer.ptr, @intCast(buffer.len)),
|
||||||
error.GetPhysicalChannels
|
error.GetPhysicalChannels
|
||||||
);
|
);
|
||||||
@ -584,8 +600,8 @@ fn listDevicePhysicalChannels(
|
|||||||
pub fn listDeviceAIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
pub fn listDeviceAIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDevicePhysicalChannels(
|
return self.listDevicePhysicalChannels(
|
||||||
c.DAQmxGetDevAIPhysicalChans,
|
self.api.DAQmxGetDevAIPhysicalChans,
|
||||||
device,
|
device,
|
||||||
&device_buffers.analog_input_names
|
&device_buffers.analog_input_names
|
||||||
);
|
);
|
||||||
@ -594,8 +610,8 @@ pub fn listDeviceAIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const
|
|||||||
pub fn listDeviceAOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
pub fn listDeviceAOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDevicePhysicalChannels(
|
return self.listDevicePhysicalChannels(
|
||||||
c.DAQmxGetDevAOPhysicalChans,
|
self.api.DAQmxGetDevAOPhysicalChans,
|
||||||
device,
|
device,
|
||||||
&device_buffers.analog_output_names
|
&device_buffers.analog_output_names
|
||||||
);
|
);
|
||||||
@ -604,7 +620,7 @@ pub fn listDeviceAOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const
|
|||||||
pub fn listDeviceCOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
pub fn listDeviceCOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDevicePhysicalChannels(
|
return self.listDevicePhysicalChannels(
|
||||||
c.DAQmxGetDevCOPhysicalChans,
|
c.DAQmxGetDevCOPhysicalChans,
|
||||||
device,
|
device,
|
||||||
&device_buffers.counter_output_names
|
&device_buffers.counter_output_names
|
||||||
@ -614,7 +630,7 @@ pub fn listDeviceCOPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const
|
|||||||
pub fn listDeviceCIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
pub fn listDeviceCIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDevicePhysicalChannels(
|
return self.listDevicePhysicalChannels(
|
||||||
c.DAQmxGetDevCIPhysicalChans,
|
c.DAQmxGetDevCIPhysicalChans,
|
||||||
device,
|
device,
|
||||||
&device_buffers.counter_input_names
|
&device_buffers.counter_input_names
|
||||||
@ -646,21 +662,19 @@ fn getChannelType(device: [:0]const u8) ?ChannelType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getMinSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
pub fn getMinSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
||||||
_ = self;
|
|
||||||
|
|
||||||
var result: f64 = 0;
|
var result: f64 = 0;
|
||||||
|
|
||||||
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
||||||
switch (channel_type) {
|
switch (channel_type) {
|
||||||
.analog_input => {
|
.analog_input => {
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAIMinRate(channel, &result),
|
self.api.DAQmxGetDevAIMinRate(channel, &result),
|
||||||
error.DAQmxGetDevAIMinRate
|
error.DAQmxGetDevAIMinRate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.analog_output => {
|
.analog_output => {
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAOMinRate(channel, &result),
|
self.api.DAQmxGetDevAOMinRate(channel, &result),
|
||||||
error.DAQmxGetDevAOMinRate
|
error.DAQmxGetDevAOMinRate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -674,21 +688,19 @@ pub fn getMinSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getMaxSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
pub fn getMaxSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
||||||
_ = self;
|
|
||||||
|
|
||||||
var result: f64 = 0;
|
var result: f64 = 0;
|
||||||
|
|
||||||
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
||||||
switch (channel_type) {
|
switch (channel_type) {
|
||||||
.analog_input => {
|
.analog_input => {
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAIMaxSingleChanRate(channel, &result),
|
self.api.DAQmxGetDevAIMaxSingleChanRate(channel, &result),
|
||||||
error.DAQmxGetDevAIMaxSingleChanRate
|
error.DAQmxGetDevAIMaxSingleChanRate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.analog_output => {
|
.analog_output => {
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAOMaxRate(channel, &result),
|
self.api.DAQmxGetDevAOMaxRate(channel, &result),
|
||||||
error.DAQmxGetDevAOMaxRate
|
error.DAQmxGetDevAOMaxRate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -702,6 +714,7 @@ pub fn getMaxSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn listDeviceVoltageRanges(
|
fn listDeviceVoltageRanges(
|
||||||
|
self: NIDaq,
|
||||||
getVoltageRanges: anytype,
|
getVoltageRanges: anytype,
|
||||||
device: [:0]const u8,
|
device: [:0]const u8,
|
||||||
voltage_ranges: *std.ArrayListUnmanaged(Range)
|
voltage_ranges: *std.ArrayListUnmanaged(Range)
|
||||||
@ -709,7 +722,7 @@ fn listDeviceVoltageRanges(
|
|||||||
voltage_ranges.clearRetainingCapacity();
|
voltage_ranges.clearRetainingCapacity();
|
||||||
|
|
||||||
const count = getVoltageRanges(device, null, 0);
|
const count = getVoltageRanges(device, null, 0);
|
||||||
try checkDAQmxErrorIgnoreWarnings(count, error.GetVoltageRanges);
|
try self.checkDAQmxErrorIgnoreWarnings(count, error.GetVoltageRanges);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return voltage_ranges.items;
|
return voltage_ranges.items;
|
||||||
}
|
}
|
||||||
@ -722,7 +735,7 @@ fn listDeviceVoltageRanges(
|
|||||||
return error.BufferTooSmall;
|
return error.BufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
getVoltageRanges(device, buffer, @intCast(buffer_len)),
|
getVoltageRanges(device, buffer, @intCast(buffer_len)),
|
||||||
error.GetVoltageRanges
|
error.GetVoltageRanges
|
||||||
);
|
);
|
||||||
@ -735,8 +748,8 @@ fn listDeviceVoltageRanges(
|
|||||||
pub fn listDeviceAIVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
pub fn listDeviceAIVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDeviceVoltageRanges(
|
return self.listDeviceVoltageRanges(
|
||||||
c.DAQmxGetDevAIVoltageRngs,
|
self.api.DAQmxGetDevAIVoltageRngs,
|
||||||
device,
|
device,
|
||||||
&device_buffers.analog_input_voltage_ranges
|
&device_buffers.analog_input_voltage_ranges
|
||||||
);
|
);
|
||||||
@ -745,36 +758,33 @@ pub fn listDeviceAIVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
|||||||
pub fn listDeviceAOVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
pub fn listDeviceAOVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
||||||
var device_buffers = try self.getDeviceBuffers(device);
|
var device_buffers = try self.getDeviceBuffers(device);
|
||||||
|
|
||||||
return listDeviceVoltageRanges(
|
return self.listDeviceVoltageRanges(
|
||||||
c.DAQmxGetDevAOVoltageRngs,
|
self.api.DAQmxGetDevAOVoltageRngs,
|
||||||
device,
|
device,
|
||||||
&device_buffers.analog_output_voltage_ranges
|
&device_buffers.analog_output_voltage_ranges
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createTask(self: NIDaq, name: ?[:0]const u8) !Task {
|
pub fn createTask(self: *NIDaq, name: ?[:0]const u8) !Task {
|
||||||
_ = self;
|
|
||||||
|
|
||||||
var handle: TaskHandle = undefined;
|
var handle: TaskHandle = undefined;
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxCreateTask(name orelse "", &handle),
|
self.api.DAQmxCreateTask(name orelse "", &handle),
|
||||||
error.DAQmxCreateTask
|
error.DAQmxCreateTask
|
||||||
);
|
);
|
||||||
|
|
||||||
return Task{ .handle = handle };
|
return Task{ .ni_daq = self, .handle = handle };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listDeviceAIMeasurementTypes(self: NIDaq, device: [:0]const u8) !AIMeasurementTypeList {
|
pub fn listDeviceAIMeasurementTypes(self: NIDaq, device: [:0]const u8) !AIMeasurementTypeList {
|
||||||
var result = AIMeasurementTypeList.init(0) catch unreachable;
|
var result = AIMeasurementTypeList.init(0) catch unreachable;
|
||||||
_ = self;
|
|
||||||
|
|
||||||
const count = c.DAQmxGetDevAISupportedMeasTypes(device, null, 0);
|
const count = self.api.DAQmxGetDevAISupportedMeasTypes(device, null, 0);
|
||||||
try checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAISupportedMeasTypes);
|
try self.checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAISupportedMeasTypes);
|
||||||
assert(count <= result.buffer.len);
|
assert(count <= result.buffer.len);
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAISupportedMeasTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
self.api.DAQmxGetDevAISupportedMeasTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||||
error.DAQmxGetDevAISupportedMeasTypes
|
error.DAQmxGetDevAISupportedMeasTypes
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -790,14 +800,13 @@ pub fn checkDeviceAIMeasurementType(self: NIDaq, device: [:0]const u8, measureme
|
|||||||
|
|
||||||
pub fn listDeviceAOOutputTypes(self: NIDaq, device: [:0]const u8) !AOOutputTypeList {
|
pub fn listDeviceAOOutputTypes(self: NIDaq, device: [:0]const u8) !AOOutputTypeList {
|
||||||
var result = AOOutputTypeList.init(0) catch unreachable;
|
var result = AOOutputTypeList.init(0) catch unreachable;
|
||||||
_ = self;
|
|
||||||
|
|
||||||
const count = c.DAQmxGetDevAOSupportedOutputTypes(device, null, 0);
|
const count = self.api.DAQmxGetDevAOSupportedOutputTypes(device, null, 0);
|
||||||
try checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAOSupportedOutputTypes);
|
try self.checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAOSupportedOutputTypes);
|
||||||
assert(count <= result.buffer.len);
|
assert(count <= result.buffer.len);
|
||||||
|
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevAOSupportedOutputTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
self.api.DAQmxGetDevAOSupportedOutputTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||||
error.DAQmxGetDevAOSupportedOutputTypes
|
error.DAQmxGetDevAOSupportedOutputTypes
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -812,11 +821,9 @@ pub fn checkDeviceAOOutputType(self: NIDaq, device: [:0]const u8, output_type: A
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getDeviceProductCategory(self: NIDaq, device: [:0]const u8) !ProductCategory {
|
pub fn getDeviceProductCategory(self: NIDaq, device: [:0]const u8) !ProductCategory {
|
||||||
_ = self;
|
|
||||||
|
|
||||||
var product_category = ProductCategory.Unknown;
|
var product_category = ProductCategory.Unknown;
|
||||||
try checkDAQmxError(
|
try self.checkDAQmxError(
|
||||||
c.DAQmxGetDevProductCategory(device, @ptrCast(&product_category)),
|
self.api.DAQmxGetDevProductCategory(device, @ptrCast(&product_category)),
|
||||||
error.DAQmxGetDevProductCategory
|
error.DAQmxGetDevProductCategory
|
||||||
);
|
);
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const NIDaq = @import("./ni-daq.zig");
|
const NIDaq = @import("./ni-daq/root.zig");
|
||||||
|
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const log = std.log.scoped(.task_pool);
|
const log = std.log.scoped(.task_pool);
|
||||||
|
Loading…
Reference in New Issue
Block a user