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");
|
||||
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
|
||||
// https://github.com/ziglang/zig/issues/14637#issuecomment-1428689051
|
||||
|
||||
|
@ -5,7 +5,7 @@ const UI = @import("./ui.zig");
|
||||
const Platform = @import("./platform.zig");
|
||||
const Assets = @import("./assets.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 remap = @import("./utils.zig").remap;
|
||||
const TaskPool = @import("./task-pool.zig");
|
||||
|
@ -153,7 +153,7 @@ pub fn main() !void {
|
||||
defer app.deinit();
|
||||
|
||||
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_IjStim.bin");
|
||||
}
|
||||
@ -191,5 +191,5 @@ pub fn main() !void {
|
||||
}
|
||||
|
||||
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");
|
||||
pub const c = @cImport({
|
||||
@cInclude("stdint.h");
|
||||
@cDefine("__int64", "long long");
|
||||
@cInclude("NIDAQmx.h");
|
||||
});
|
||||
const Api = @import("./api.zig");
|
||||
pub const c = Api.c;
|
||||
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.ni_daq);
|
||||
@ -38,6 +35,7 @@ pub const Options = struct {
|
||||
};
|
||||
|
||||
pub const Task = struct {
|
||||
ni_daq: *NIDaq,
|
||||
handle: TaskHandle,
|
||||
|
||||
name_buffer: [max_task_name_size]u8 = undefined,
|
||||
@ -45,19 +43,23 @@ pub const Task = struct {
|
||||
dropped_samples: u32 = 0,
|
||||
|
||||
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 {
|
||||
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);
|
||||
|
||||
if (required_size > self.name_buffer.len) {
|
||||
return error.BufferTooSmall;
|
||||
}
|
||||
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetTaskName(
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
api.DAQmxGetTaskName(
|
||||
self.handle,
|
||||
&self.name_buffer,
|
||||
self.name_buffer.len
|
||||
@ -69,29 +71,33 @@ pub const Task = struct {
|
||||
}
|
||||
|
||||
pub fn start(self: Task) !void {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxStartTask(self.handle),
|
||||
const api = self.ni_daq.api;
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
api.DAQmxStartTask(self.handle),
|
||||
error.DAQmxStartTask
|
||||
);
|
||||
}
|
||||
|
||||
pub fn stop(self: Task) !void {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxStopTask(self.handle),
|
||||
const api = self.ni_daq.api;
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
api.DAQmxStopTask(self.handle),
|
||||
error.DAQmxStopTask
|
||||
);
|
||||
}
|
||||
|
||||
pub fn setContinousSampleRate(self: Task, sample_rate: f64) !void {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_ContSamps, 0),
|
||||
const api = self.ni_daq.api;
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
api.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_ContSamps, 0),
|
||||
error.DAQmxCfgSampClkTiming
|
||||
);
|
||||
}
|
||||
|
||||
pub fn setFiniteSampleRate(self: Task, sample_rate: f64, samples_per_channel: u64) !void {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxCfgSampClkTiming(self.handle, null, sample_rate, c.DAQmx_Val_Rising, c.DAQmx_Val_FiniteSamps, samples_per_channel),
|
||||
const api = self.ni_daq.api;
|
||||
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
|
||||
);
|
||||
}
|
||||
@ -107,8 +113,9 @@ pub const Task = struct {
|
||||
};
|
||||
|
||||
pub fn createAIVoltageChannel(self: Task, options: AIVoltageChannelOptions) !void {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxCreateAIVoltageChan(
|
||||
const api = self.ni_daq.api;
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
api.DAQmxCreateAIVoltageChan(
|
||||
self.handle,
|
||||
options.channel,
|
||||
options.assigned_name,
|
||||
@ -132,7 +139,7 @@ pub const Task = struct {
|
||||
};
|
||||
|
||||
pub fn createAOVoltageChannel(self: Task, options: AOVoltageChannelOptions) !void {
|
||||
try checkDAQmxError(
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
c.DAQmxCreateAOVoltageChan(
|
||||
self.handle,
|
||||
options.channel,
|
||||
@ -155,8 +162,9 @@ pub const Task = struct {
|
||||
};
|
||||
|
||||
pub fn readAnalog(self: *Task, options: ReadAnalogOptions) !u32 {
|
||||
const api = self.ni_daq.api;
|
||||
var samples_per_channel: i32 = 0;
|
||||
const err = c.DAQmxReadAnalogF64(
|
||||
const err = api.DAQmxReadAnalogF64(
|
||||
self.handle,
|
||||
options.samples_per_channel,
|
||||
options.timeout,
|
||||
@ -171,7 +179,7 @@ pub const Task = struct {
|
||||
self.dropped_samples += 1;
|
||||
log.err("Dropped samples, not reading samples fast enough.", .{});
|
||||
} else if (err < 0) {
|
||||
try checkDAQmxError(err, error.DAQmxReadAnalogF64);
|
||||
try self.ni_daq.checkDAQmxError(err, error.DAQmxReadAnalogF64);
|
||||
}
|
||||
|
||||
return @intCast(samples_per_channel);
|
||||
@ -179,7 +187,7 @@ pub const Task = struct {
|
||||
|
||||
pub fn isDone(self: Task) !bool {
|
||||
var result: c.bool32 = 0;
|
||||
try checkDAQmxError(
|
||||
try self.ni_daq.checkDAQmxError(
|
||||
c.DAQmxIsTaskDone(self.handle, &result),
|
||||
error.DAQmxIsTaskDone
|
||||
);
|
||||
@ -365,12 +373,16 @@ const DeviceBuffers = struct {
|
||||
};
|
||||
|
||||
options: Options,
|
||||
api: Api,
|
||||
device_names_buffer: []u8,
|
||||
device_names: StringArrayListUnmanaged,
|
||||
|
||||
device_buffers: []DeviceBuffers,
|
||||
|
||||
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 = try allocator.alloc(u8, device_names_buffer_size);
|
||||
errdefer allocator.free(device_names_buffer);
|
||||
@ -388,6 +400,7 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !NIDaq {
|
||||
|
||||
return NIDaq{
|
||||
.options = options,
|
||||
.api = api,
|
||||
.device_names_buffer = device_names_buffer,
|
||||
.device_names = device_names,
|
||||
.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 {
|
||||
self.api.deinit();
|
||||
|
||||
self.device_names.deinit(allocator);
|
||||
allocator.free(self.device_names_buffer);
|
||||
|
||||
@ -423,33 +438,33 @@ test {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
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});
|
||||
} else {
|
||||
log.err("DAQmx ({}): Unknown (Buffer too small for message)", .{error_code});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checkDAQmxError(error_code: i32, err: anyerror) !void {
|
||||
logDAQmxError(error_code);
|
||||
pub fn checkDAQmxError(self: NIDaq, error_code: i32, err: anyerror) !void {
|
||||
self.logDAQmxError(error_code);
|
||||
|
||||
if (error_code < 0) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
try checkDAQmxError(error_code, err);
|
||||
try self.checkDAQmxError(error_code, err);
|
||||
}
|
||||
|
||||
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;
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetSysNIDAQMajorVersion(&major),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetSysNIDAQMajorVersion(&major),
|
||||
error.GetMajorVersion
|
||||
);
|
||||
|
||||
var minor: u32 = 0;
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetSysNIDAQMinorVersion(&minor),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetSysNIDAQMinorVersion(&minor),
|
||||
error.GetMinorVersion
|
||||
);
|
||||
|
||||
var update: u32 = 0;
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetSysNIDAQUpdateVersion(&update),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetSysNIDAQUpdateVersion(&update),
|
||||
error.GetUpdateVersion
|
||||
);
|
||||
|
||||
@ -501,8 +516,8 @@ pub fn listDeviceNames(self: *NIDaq) ![]const [:0]const u8 {
|
||||
self.device_names.clearRetainingCapacity();
|
||||
self.clearAllDeviceBuffers();
|
||||
|
||||
const required_size = c.DAQmxGetSysDevNames(null, 0);
|
||||
try checkDAQmxErrorIgnoreWarnings(required_size, error.DAQmxGetSysDevNames);
|
||||
const required_size = self.api.DAQmxGetSysDevNames(null, 0);
|
||||
try self.checkDAQmxErrorIgnoreWarnings(required_size, error.DAQmxGetSysDevNames);
|
||||
if (required_size == 0) {
|
||||
return self.device_names.items;
|
||||
}
|
||||
@ -511,8 +526,8 @@ pub fn listDeviceNames(self: *NIDaq) ![]const [:0]const u8 {
|
||||
return error.BufferTooSmall;
|
||||
}
|
||||
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetSysDevNames(self.device_names_buffer.ptr, @intCast(self.device_names_buffer.len)),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetSysDevNames(self.device_names_buffer.ptr, @intCast(self.device_names_buffer.len)),
|
||||
error.GetDeviceNames
|
||||
);
|
||||
|
||||
@ -549,6 +564,7 @@ fn clearAllDeviceBuffers(self: *NIDaq) void {
|
||||
}
|
||||
|
||||
fn listDevicePhysicalChannels(
|
||||
self: NIDaq,
|
||||
getPhysicalChannels: anytype,
|
||||
device: [:0]const u8,
|
||||
channel_names: *DeviceBuffers.ChannelNames,
|
||||
@ -559,7 +575,7 @@ fn listDevicePhysicalChannels(
|
||||
array_list.clearRetainingCapacity();
|
||||
|
||||
const required_size = getPhysicalChannels(device, null, 0);
|
||||
try checkDAQmxErrorIgnoreWarnings(required_size, error.GetPhysicalChannels);
|
||||
try self.checkDAQmxErrorIgnoreWarnings(required_size, error.GetPhysicalChannels);
|
||||
if (required_size == 0) {
|
||||
return array_list.items;
|
||||
}
|
||||
@ -568,7 +584,7 @@ fn listDevicePhysicalChannels(
|
||||
return error.BufferTooSmall;
|
||||
}
|
||||
|
||||
try checkDAQmxError(
|
||||
try self.checkDAQmxError(
|
||||
getPhysicalChannels(device, buffer.ptr, @intCast(buffer.len)),
|
||||
error.GetPhysicalChannels
|
||||
);
|
||||
@ -584,8 +600,8 @@ fn listDevicePhysicalChannels(
|
||||
pub fn listDeviceAIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const [:0]const u8 {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDevicePhysicalChannels(
|
||||
c.DAQmxGetDevAIPhysicalChans,
|
||||
return self.listDevicePhysicalChannels(
|
||||
self.api.DAQmxGetDevAIPhysicalChans,
|
||||
device,
|
||||
&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 {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDevicePhysicalChannels(
|
||||
c.DAQmxGetDevAOPhysicalChans,
|
||||
return self.listDevicePhysicalChannels(
|
||||
self.api.DAQmxGetDevAOPhysicalChans,
|
||||
device,
|
||||
&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 {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDevicePhysicalChannels(
|
||||
return self.listDevicePhysicalChannels(
|
||||
c.DAQmxGetDevCOPhysicalChans,
|
||||
device,
|
||||
&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 {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDevicePhysicalChannels(
|
||||
return self.listDevicePhysicalChannels(
|
||||
c.DAQmxGetDevCIPhysicalChans,
|
||||
device,
|
||||
&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 {
|
||||
_ = self;
|
||||
|
||||
var result: f64 = 0;
|
||||
|
||||
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
||||
switch (channel_type) {
|
||||
.analog_input => {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAIMinRate(channel, &result),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAIMinRate(channel, &result),
|
||||
error.DAQmxGetDevAIMinRate
|
||||
);
|
||||
},
|
||||
.analog_output => {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAOMinRate(channel, &result),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAOMinRate(channel, &result),
|
||||
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 {
|
||||
_ = self;
|
||||
|
||||
var result: f64 = 0;
|
||||
|
||||
const channel_type = getChannelType(channel) orelse return error.UnknownChannelType;
|
||||
switch (channel_type) {
|
||||
.analog_input => {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAIMaxSingleChanRate(channel, &result),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAIMaxSingleChanRate(channel, &result),
|
||||
error.DAQmxGetDevAIMaxSingleChanRate
|
||||
);
|
||||
},
|
||||
.analog_output => {
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAOMaxRate(channel, &result),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAOMaxRate(channel, &result),
|
||||
error.DAQmxGetDevAOMaxRate
|
||||
);
|
||||
},
|
||||
@ -702,6 +714,7 @@ pub fn getMaxSampleRate(self: NIDaq, channel: [:0]const u8) !f64 {
|
||||
}
|
||||
|
||||
fn listDeviceVoltageRanges(
|
||||
self: NIDaq,
|
||||
getVoltageRanges: anytype,
|
||||
device: [:0]const u8,
|
||||
voltage_ranges: *std.ArrayListUnmanaged(Range)
|
||||
@ -709,7 +722,7 @@ fn listDeviceVoltageRanges(
|
||||
voltage_ranges.clearRetainingCapacity();
|
||||
|
||||
const count = getVoltageRanges(device, null, 0);
|
||||
try checkDAQmxErrorIgnoreWarnings(count, error.GetVoltageRanges);
|
||||
try self.checkDAQmxErrorIgnoreWarnings(count, error.GetVoltageRanges);
|
||||
if (count == 0) {
|
||||
return voltage_ranges.items;
|
||||
}
|
||||
@ -722,7 +735,7 @@ fn listDeviceVoltageRanges(
|
||||
return error.BufferTooSmall;
|
||||
}
|
||||
|
||||
try checkDAQmxError(
|
||||
try self.checkDAQmxError(
|
||||
getVoltageRanges(device, buffer, @intCast(buffer_len)),
|
||||
error.GetVoltageRanges
|
||||
);
|
||||
@ -735,8 +748,8 @@ fn listDeviceVoltageRanges(
|
||||
pub fn listDeviceAIVoltageRanges(self: *NIDaq, device: [:0]const u8) ![]Range {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDeviceVoltageRanges(
|
||||
c.DAQmxGetDevAIVoltageRngs,
|
||||
return self.listDeviceVoltageRanges(
|
||||
self.api.DAQmxGetDevAIVoltageRngs,
|
||||
device,
|
||||
&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 {
|
||||
var device_buffers = try self.getDeviceBuffers(device);
|
||||
|
||||
return listDeviceVoltageRanges(
|
||||
c.DAQmxGetDevAOVoltageRngs,
|
||||
return self.listDeviceVoltageRanges(
|
||||
self.api.DAQmxGetDevAOVoltageRngs,
|
||||
device,
|
||||
&device_buffers.analog_output_voltage_ranges
|
||||
);
|
||||
}
|
||||
|
||||
pub fn createTask(self: NIDaq, name: ?[:0]const u8) !Task {
|
||||
_ = self;
|
||||
|
||||
pub fn createTask(self: *NIDaq, name: ?[:0]const u8) !Task {
|
||||
var handle: TaskHandle = undefined;
|
||||
|
||||
try checkDAQmxError(
|
||||
c.DAQmxCreateTask(name orelse "", &handle),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxCreateTask(name orelse "", &handle),
|
||||
error.DAQmxCreateTask
|
||||
);
|
||||
|
||||
return Task{ .handle = handle };
|
||||
return Task{ .ni_daq = self, .handle = handle };
|
||||
}
|
||||
|
||||
pub fn listDeviceAIMeasurementTypes(self: NIDaq, device: [:0]const u8) !AIMeasurementTypeList {
|
||||
var result = AIMeasurementTypeList.init(0) catch unreachable;
|
||||
_ = self;
|
||||
|
||||
const count = c.DAQmxGetDevAISupportedMeasTypes(device, null, 0);
|
||||
try checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAISupportedMeasTypes);
|
||||
const count = self.api.DAQmxGetDevAISupportedMeasTypes(device, null, 0);
|
||||
try self.checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAISupportedMeasTypes);
|
||||
assert(count <= result.buffer.len);
|
||||
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAISupportedMeasTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAISupportedMeasTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||
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 {
|
||||
var result = AOOutputTypeList.init(0) catch unreachable;
|
||||
_ = self;
|
||||
|
||||
const count = c.DAQmxGetDevAOSupportedOutputTypes(device, null, 0);
|
||||
try checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAOSupportedOutputTypes);
|
||||
const count = self.api.DAQmxGetDevAOSupportedOutputTypes(device, null, 0);
|
||||
try self.checkDAQmxErrorIgnoreWarnings(count, error.DAQmxGetDevAOSupportedOutputTypes);
|
||||
assert(count <= result.buffer.len);
|
||||
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevAOSupportedOutputTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevAOSupportedOutputTypes(device, @as([*c]c_int, @ptrCast(&result.buffer)), result.buffer.len),
|
||||
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 {
|
||||
_ = self;
|
||||
|
||||
var product_category = ProductCategory.Unknown;
|
||||
try checkDAQmxError(
|
||||
c.DAQmxGetDevProductCategory(device, @ptrCast(&product_category)),
|
||||
try self.checkDAQmxError(
|
||||
self.api.DAQmxGetDevProductCategory(device, @ptrCast(&product_category)),
|
||||
error.DAQmxGetDevProductCategory
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const NIDaq = @import("./ni-daq.zig");
|
||||
const NIDaq = @import("./ni-daq/root.zig");
|
||||
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.task_pool);
|
||||
|
Loading…
Reference in New Issue
Block a user