-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adi:Generic: Add a generic driver #13
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
classdef Rx < adi.common.Rx & matlabshared.libiio.base & ... | ||
adi.common.Attribute & adi.common.DeviceAttribute & adi.common.Channel | ||
% Generic Precision ADC Class | ||
% adi.Generic.Rx Receives data from the connected ADC | ||
% The adi.Generic.Rx System object is a signal source that can receive | ||
% data from any generic ADI precision ADC. | ||
% | ||
% rx = adi.Generic.Rx('adxxxx', 'ip:analog.local'); | ||
% | ||
|
||
properties | ||
ribdp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
% DeviceAttributeNames Device Attribute Names | ||
% Array of device IIO attribute names as defined in the | ||
% driver/firmware, and queried from the hardware | ||
% at initialization time | ||
DeviceAttributeNames | ||
|
||
% ChannelAttributeNames Device Attribute Names | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: Channel attributes names |
||
% Array of channel IIO attribute names as defined in the | ||
% driver/firmware, and queried from the hardware | ||
% at initialization time | ||
ChannelAttributeNames | ||
end | ||
|
||
properties (Nontunable) | ||
mphalke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
% SamplesPerFrame Samples Per Frame | ||
% Number of samples per frame, specified as an even positive | ||
% integer. | ||
SamplesPerFrame = 1024 | ||
end | ||
|
||
properties (Nontunable, Hidden) | ||
ribdp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
channel_names = {'voltage0'} | ||
Timeout = Inf | ||
kernelBuffersCount = 1 | ||
dataTypeStr = 'int32' | ||
phyDevName = 'adxxxx' | ||
devName = 'adxxxx' | ||
end | ||
|
||
properties (Nontunable, Hidden, Constant) | ||
Type = 'Rx' | ||
ComplexData = false | ||
end | ||
|
||
properties (Hidden, Nontunable, Access = protected) | ||
isOutput = false | ||
end | ||
|
||
properties(Hidden, Access = protected) | ||
cachedAttrWrites = {} | ||
end | ||
|
||
methods | ||
|
||
%% Constructor | ||
function obj = Rx(Args) | ||
arguments | ||
Args.devName | ||
Args.phyDevName | ||
Args.uri | ||
end | ||
|
||
obj = [email protected](); | ||
obj.enableExplicitPolling = false; | ||
obj.EnabledChannels = 1; | ||
obj.BufferTypeConversionEnable = true; | ||
mphalke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
% Set device name, phyDevName, uri from input arguments | ||
try | ||
obj.devName = Args.devName; | ||
obj.phyDevName = Args.phyDevName; | ||
obj.uri = Args.uri; | ||
catch | ||
e = MException('MATLAB:notEnoughInputs',['Not enough input ' ... | ||
'arguments. Specify devName, phyDevName and uri']); | ||
throw(e) | ||
end | ||
|
||
% Determine datatype using trial and error | ||
possibleDataTypeStr = {'int8', 'int16', 'int32', 'int64'}; | ||
for k = 1:length(possibleDataTypeStr) | ||
try | ||
obj.dataTypeStr = possibleDataTypeStr{k}; | ||
obj.setup(); | ||
break; | ||
catch | ||
end | ||
end | ||
assert(obj.ConnectedToDevice == 1, "Connection could not be established with the specified device") | ||
|
||
% Check is the platform is running ADI Kuiper Linux. | ||
% Presence of 'local,kernel' context attribute would | ||
% indicate usage of Linux platform | ||
isLinuxPLatform = false; | ||
try | ||
obj.iio_context_get_attr_value(obj.iioCtx, 'local,kernel'); | ||
isLinuxPLatform = true; | ||
catch | ||
end | ||
|
||
release(obj); | ||
|
||
% If platform is running ADI Kuiper Linux, kernelBuffersCount | ||
% can be increased | ||
if isLinuxPLatform | ||
obj.kernelBuffersCount = 4; | ||
mphalke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
disp("Detected ADI Kuiper Linux platform. Changing buffer count to 4..") | ||
end | ||
|
||
end | ||
|
||
function flush(obj) | ||
% Flush the buffer contents | ||
flushBuffers(obj); | ||
end | ||
|
||
function SetDeviceAttrValue(obj, attr, val) | ||
% Apply the device attribute value when device is | ||
% connected | ||
% rx.SetDeviceAttrValue('sampling_frequency', '1000000') | ||
obj.cachedAttrWrites{end+1} = {attr, val}; | ||
end | ||
|
||
|
||
function val = GetDeviceAttrValue(obj, attr) | ||
% Fetch the device attribute value if device is | ||
% connected. | ||
% rx.GetDeviceAttrValue('sampling_frequency') | ||
if obj.ConnectedToDevice | ||
val = obj.getDeviceAttributeRAW(attr, 128); | ||
end | ||
end | ||
|
||
function SetChannelAttrValue(obj, chnID, attr, val) | ||
% Apply the channel attribute value when device is | ||
% connected. To write to the first channel attribute use | ||
% rx.SetChannelAttrValue('voltage0', 'scale', '2') or | ||
% rx.SetChannelAttrValue(1, 'scale', '2') | ||
if isnumeric(chnID) | ||
chnID = obj.channel_names(chanID); | ||
end | ||
obj.cachedAttrWrites{end+1} = {chnID, attr, val}; | ||
end | ||
|
||
function val = GetChannelAttrValue(obj, chnID, attr) | ||
% Fetch the channel attribute value if device is | ||
% connected. To get the first channel attribute value, use | ||
% rx.GetChannelAttrValue('voltage0', 'scale') or | ||
% rx.GetChannelAttrValue(1, 'scale') | ||
if obj.ConnectedToDevice | ||
if isnumeric(chnID) | ||
chnID = obj.channel_names(chanID); | ||
end | ||
val = obj.getAttributeRAW(attr, chnID, obj.isOutput); | ||
end | ||
end | ||
|
||
end | ||
|
||
%% API Functions | ||
methods (Hidden, Access = protected) | ||
|
||
function setupInit(obj) | ||
|
||
% Write all attributes to device once connected through set | ||
ribdp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
% methods | ||
% Do writes directly to hardware without using set methods. | ||
% This is required since Simulink support doesn't support | ||
% modification to nontunable variables at SetupImpl | ||
|
||
%Fetch all the attributes and channel names | ||
if ~isempty(obj.channel_names) | ||
obj.fetch_channel_names(); | ||
end | ||
|
||
if isempty(obj.DeviceAttributeNames) | ||
obj.fetch_device_attributes(); | ||
end | ||
|
||
if isempty(obj.ChannelAttributeNames) | ||
obj.fetch_channel_attributes(); | ||
end | ||
|
||
% Apply attribute settings in hardware | ||
if ~isempty(obj.cachedAttrWrites) | ||
for i = 1:length(obj.cachedAttrWrites) | ||
if length(obj.cachedAttrWrites{i}) == 2 | ||
% Apply device attribute | ||
attr = obj.cachedAttrWrites{i}{1}; | ||
val = obj.cachedAttrWrites{i}{2}; | ||
obj.setDeviceAttributeRAW(attr, val); | ||
elseif length(obj.cachedAttrWrites{i}) == 3 | ||
% Apply channel attribute | ||
chan = obj.cachedAttrWrites{i}{1}; | ||
attr = obj.cachedAttrWrites{i}{2}; | ||
val = obj.cachedAttrWrites{i}{3}; | ||
obj.setAttributeRAW(chan, attr, val, obj.isOutput); | ||
end | ||
end | ||
end | ||
|
||
obj.cachedAttrWrites = {}; | ||
|
||
end | ||
|
||
function fetch_channel_names(obj) | ||
% Update the channel names | ||
obj.channel_names = {}; | ||
phydev = getDev(obj, obj.devName); | ||
chanCount = obj.iio_device_get_channels_count(phydev); | ||
for c = 1:chanCount | ||
chanPtr = obj.iio_device_get_channel(phydev, c - 1); | ||
obj.channel_names{end + 1} = obj.iio_channel_get_name(chanPtr); | ||
end | ||
end | ||
|
||
function fetch_device_attributes(obj) | ||
% Store the attribute names | ||
devPtr = obj.getDev(obj.phyDevName); | ||
devAttrCnt = obj.iio_device_get_attrs_count(devPtr); | ||
for i=1:devAttrCnt | ||
obj.DeviceAttributeNames{end+1} = obj.iio_device_get_attr(devPtr, i-1); | ||
end | ||
end | ||
|
||
function fetch_channel_attributes(obj) | ||
% Store channel attribute names, if there's channels present | ||
devPtr = obj.getDev(obj.phyDevName); | ||
|
||
if ~isempty(obj.channel_names) | ||
% Fetch first channel | ||
chanPtr = calllib(obj.libName, 'iio_device_get_channel', devPtr, 0); | ||
|
||
% Fetch count of channel attributes | ||
chanAttrCnt = obj.iio_channel_get_attrs_count(chanPtr); | ||
|
||
% Fetch each attribute for the channel | ||
for j=1:chanAttrCnt | ||
obj.ChannelAttributeNames{j} = obj.iio_channel_get_attr(chanPtr, j-1); | ||
end | ||
end | ||
|
||
end | ||
|
||
|
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
%% Script for capturing buffers of data from a connected IIO device | ||
|
||
% Instantiate the Generic Rx system object, and specify the device name, uri | ||
% and phyDevName in the manner shown below | ||
rx = adi.Generic.Rx("devName", 'ad4630-24', 'phyDevName', 'ad4630-24',... | ||
'uri', 'ip:analog.local'); | ||
|
||
rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should comment be at top of expression similar to other comments? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will update this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious how did we come up with value 3660? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's just a heuristic obtained from testing parts in the HSX/TRX toolbox, and I thought to adopt the same here. @tfcollins - is this comment valid in only specific conditions/parts? Is it okay to keep it here? |
||
% performance, generally | ||
|
||
% Enable channels for data capture | ||
rx.EnabledChannels = [1]; | ||
|
||
% Display device and channel attribute names | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are attributes always displayed and is it necessary to display them? Should this be enabled just for debug purpose? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought to leave these here so that when running the example script out of the box for a specific part, the attributes are also printed out for the user to take note of and use subsequently. Anyone using the generic example would definitely also be able to modify the flow as per their needs. |
||
rx.DeviceAttributeNames | ||
rx.ChannelAttributeNames | ||
|
||
% Read and write attribute values | ||
% For example, with ad4630-24 | ||
% rx.GetDeviceAttrValue('sampling_frequency') | ||
% rx.SetDeviceAttrValue('sampling_frequency', '2000000'); | ||
% rx.SetChannelAttrValue('differential0', 'hardwaregain', '2'); | ||
|
||
% Capture data | ||
data = rx(); | ||
|
||
% Plot samples | ||
enabledChannels = size(data, 2); | ||
figure(1); | ||
for i = 1:enabledChannels | ||
subplot(enabledChannels, 1, i); | ||
plot(data(1:rx.SamplesPerFrame, i)); | ||
mphalke marked this conversation as resolved.
Show resolved
Hide resolved
|
||
title("Channel " + num2str(rx.EnabledChannels(i))); | ||
end | ||
|
||
% Delete the system object | ||
release(rx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this extra comment specifier needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be needed for generating the documentation using the scripts in CI/scripts/gen_docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, do you mean line no. 9 specifically? I guess it's not required. Will remove it and see if documentation generates fine without it.