Skip to content
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

Remove Breakout prefix from classes where its redundant #301

Merged
merged 2 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,33 @@

namespace OpenEphys.Onix1
{
/// <inheritdoc cref = "AnalogInput"/>
[Obsolete("Use AnalogInput instead. This operator will be removed in version 1.0.0")]
public class BreakoutAnalogInput : AnalogInput { }
jonnew marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Produces a sequence of analog input frames from an ONIX breakout board.
/// </summary>
/// <remarks>
/// This data IO operator must be linked to an appropriate configuration, such as a <see
/// cref="ConfigureBreakoutAnalogIO"/>, using a shared <c>DeviceName</c>.
/// cref="ConfigureAnalogIO"/>, using a shared <c>DeviceName</c>.
/// </remarks>
[Description("Produces a sequence of analog input frames from an ONIX breakout board.")]
public class BreakoutAnalogInput : Source<BreakoutAnalogInputDataFrame>
public class AnalogInput : Source<AnalogInputDataFrame>
{
/// <inheritdoc cref = "SingleDeviceFactory.DeviceName"/>
[TypeConverter(typeof(BreakoutAnalogIO.NameConverter))]
[TypeConverter(typeof(AnalogIO.NameConverter))]
[Description(SingleDeviceFactory.DeviceNameDescription)]
[Category(DeviceFactory.ConfigurationCategory)]
public string DeviceName { get; set; }

/// <summary>
/// Gets or sets the number of samples collected for each channel that are use to create a single <see cref="BreakoutAnalogInputDataFrame"/>.
/// Gets or sets the number of samples collected for each channel that are use to create a single <see cref="AnalogInputDataFrame"/>.
/// </summary>
/// <remarks>
/// This property determines the number of analog samples that are buffered for each channel before data is propagated. For instance, if this
/// value is set to 100, then 100 samples, along with corresponding clock values, will be collected from each of the input channels
/// and packed into each <see cref="BreakoutAnalogInputDataFrame"/>. Because channels are sampled at 100 kHz, this is equivalent to 1
/// and packed into each <see cref="AnalogInputDataFrame"/>. Because channels are sampled at 100 kHz, this is equivalent to 1
/// millisecond of data from each channel.
/// </remarks>
[Description("The number of analog samples that are buffered for each channel before data is propagated.")]
Expand All @@ -42,15 +46,15 @@ public class BreakoutAnalogInput : Source<BreakoutAnalogInputDataFrame>
/// Gets or sets the data type used to represent analog samples.
/// </summary>
/// <remarks>
/// If <see cref="BreakoutAnalogIODataType.S16"/> is selected, each ADC sample is represented at a signed, twos-complement encoded
/// 16-bit integer. <see cref="BreakoutAnalogIODataType.S16"/> samples can be converted to a voltage using each channels'
/// <see cref="BreakoutAnalogIOVoltageRange"/> selection. For instance, channel 0 can be converted using <see cref="ConfigureBreakoutAnalogIO.InputRange0"/>.
/// When <see cref="BreakoutAnalogIODataType.Volts"/> is selected, the voltage conversion is performed automatically and samples
/// If <see cref="AnalogIODataType.S16"/> is selected, each ADC sample is represented at a signed, twos-complement encoded
/// 16-bit integer. <see cref="AnalogIODataType.S16"/> samples can be converted to a voltage using each channels'
/// <see cref="AnalogIOVoltageRange"/> selection. For instance, channel 0 can be converted using <see cref="ConfigureAnalogIO.InputRange0"/>.
/// When <see cref="AnalogIODataType.Volts"/> is selected, the voltage conversion is performed automatically and samples
/// are represented as 32-bit floating point voltages.
/// </remarks>
[Description("The data type used to represent analog samples.")]
[Category(DeviceFactory.ConfigurationCategory)]
public BreakoutAnalogIODataType DataType { get; set; } = BreakoutAnalogIODataType.S16;
public AnalogIODataType DataType { get; set; } = AnalogIODataType.S16;

static Mat CreateVoltageScale(int bufferSize, float[] voltsPerDivision)
{
Expand All @@ -66,47 +70,47 @@ static Mat CreateVoltageScale(int bufferSize, float[] voltsPerDivision)
}

/// <summary>
/// Generates a sequence of <see cref="BreakoutAnalogInputDataFrame"/>.
/// Generates a sequence of <see cref="AnalogInputDataFrame"/>.
/// </summary>
/// <returns>A sequence of <see cref="BreakoutAnalogInputDataFrame"/></returns>
public unsafe override IObservable<BreakoutAnalogInputDataFrame> Generate()
/// <returns>A sequence of <see cref="AnalogInputDataFrame"/></returns>
public unsafe override IObservable<AnalogInputDataFrame> Generate()
{
var bufferSize = BufferSize;
var dataType = DataType;
return DeviceManager.GetDevice(DeviceName).SelectMany(
deviceInfo => Observable.Create<BreakoutAnalogInputDataFrame>(observer =>
deviceInfo => Observable.Create<AnalogInputDataFrame>(observer =>
{
var device = deviceInfo.GetDeviceContext(typeof(BreakoutAnalogIO));
var ioDeviceInfo = (BreakoutAnalogIODeviceInfo)deviceInfo;
var device = deviceInfo.GetDeviceContext(typeof(AnalogIO));
var ioDeviceInfo = (AnalogIODeviceInfo)deviceInfo;

var sampleIndex = 0;
var voltageScale = dataType == BreakoutAnalogIODataType.Volts
var voltageScale = dataType == AnalogIODataType.Volts
? CreateVoltageScale(bufferSize, ioDeviceInfo.VoltsPerDivision)
: null;
var transposeBuffer = voltageScale != null
? new Mat(BreakoutAnalogIO.ChannelCount, bufferSize, Depth.S16, 1)
? new Mat(AnalogIO.ChannelCount, bufferSize, Depth.S16, 1)
: null;
var analogDataBuffer = new short[BreakoutAnalogIO.ChannelCount * bufferSize];
var analogDataBuffer = new short[AnalogIO.ChannelCount * bufferSize];
var hubClockBuffer = new ulong[bufferSize];
var clockBuffer = new ulong[bufferSize];

var frameObserver = Observer.Create<oni.Frame>(
frame =>
{
var payload = (BreakoutAnalogInputPayload*)frame.Data.ToPointer();
Marshal.Copy(new IntPtr(payload->AnalogData), analogDataBuffer, sampleIndex * BreakoutAnalogIO.ChannelCount, BreakoutAnalogIO.ChannelCount);
var payload = (AnalogInputPayload*)frame.Data.ToPointer();
Marshal.Copy(new IntPtr(payload->AnalogData), analogDataBuffer, sampleIndex * AnalogIO.ChannelCount, AnalogIO.ChannelCount);
hubClockBuffer[sampleIndex] = payload->HubClock;
clockBuffer[sampleIndex] = frame.Clock;
if (++sampleIndex >= bufferSize)
{
var analogData = BufferHelper.CopyTranspose(
analogDataBuffer,
bufferSize,
BreakoutAnalogIO.ChannelCount,
AnalogIO.ChannelCount,
Depth.S16,
voltageScale,
transposeBuffer);
observer.OnNext(new BreakoutAnalogInputDataFrame(clockBuffer, hubClockBuffer, analogData));
observer.OnNext(new AnalogInputDataFrame(clockBuffer, hubClockBuffer, analogData));
hubClockBuffer = new ulong[bufferSize];
clockBuffer = new ulong[bufferSize];
sampleIndex = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ namespace OpenEphys.Onix1
/// <summary>
/// Buffered analog data produced by the ONIX breakout board.
/// </summary>
public class BreakoutAnalogInputDataFrame : BufferedDataFrame
public class AnalogInputDataFrame : BufferedDataFrame
{
/// <summary>
/// Initializes a new instance of the <see cref="BreakoutAnalogInputDataFrame"/> class.
/// Initializes a new instance of the <see cref="AnalogInputDataFrame"/> class.
/// </summary>
/// <param name="clock">A buffered array of <see cref="DataFrame.Clock"/> values.</param>
/// <param name="hubClock"> A buffered array of hub clock counter values.</param>
/// <param name="analogData">A buffered array of multi-channel analog data.</param>
public BreakoutAnalogInputDataFrame(ulong[] clock, ulong[] hubClock, Mat analogData)
public AnalogInputDataFrame(ulong[] clock, ulong[] hubClock, Mat analogData)
: base(clock, hubClock)
{
AnalogData = analogData;
Expand All @@ -27,9 +27,9 @@ public BreakoutAnalogInputDataFrame(ulong[] clock, ulong[] hubClock, Mat analogD
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct BreakoutAnalogInputPayload
unsafe struct AnalogInputPayload
{
public ulong HubClock;
public fixed short AnalogData[BreakoutAnalogIO.ChannelCount];
public fixed short AnalogData[AnalogIO.ChannelCount];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@

namespace OpenEphys.Onix1
{
/// <inheritdoc cref = "AnalogOutput"/>
[Obsolete("Use AnalogOutput instead. This operator will be removed in version 1.0.0")]
public class BreakoutAnalogOutput : AnalogOutput { }
jonnew marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Sends analog output data to an ONIX breakout board.
/// </summary>
/// <remarks>
/// This data IO operator must be linked to an appropriate configuration, such as a <see
/// cref="ConfigureBreakoutAnalogIO"/>, using a shared <c>DeviceName</c>.
/// cref="ConfigureAnalogIO"/>, using a shared <c>DeviceName</c>.
/// </remarks>
[Description("Sends analog output data to an ONIX breakout board.")]
public class BreakoutAnalogOutput : Sink<Mat>
public class AnalogOutput : Sink<Mat>
{
const BreakoutAnalogIOVoltageRange OutputRange = BreakoutAnalogIOVoltageRange.TenVolts;
const AnalogIOVoltageRange OutputRange = AnalogIOVoltageRange.TenVolts;

/// <inheritdoc cref = "SingleDeviceFactory.DeviceName"/>
[TypeConverter(typeof(BreakoutAnalogIO.NameConverter))]
[TypeConverter(typeof(AnalogIO.NameConverter))]
[Description(SingleDeviceFactory.DeviceNameDescription)]
[Category(DeviceFactory.ConfigurationCategory)]
public string DeviceName { get; set; }
Expand All @@ -29,24 +33,24 @@ public class BreakoutAnalogOutput : Sink<Mat>
/// Gets or sets the data type used to represent analog samples.
/// </summary>
/// <remarks>
/// If <see cref="BreakoutAnalogIODataType.S16"/> is selected, each DAC value is represented by a
/// If <see cref="AnalogIODataType.S16"/> is selected, each DAC value is represented by a
/// signed, twos-complement encoded 16-bit integer. In this case, the output voltage always
/// corresponds to <see cref="BreakoutAnalogIOVoltageRange.TenVolts"/>. When <see
/// cref="BreakoutAnalogIODataType.Volts"/> is selected, 32-bit floating point voltages between -10
/// corresponds to <see cref="AnalogIOVoltageRange.TenVolts"/>. When <see
/// cref="AnalogIODataType.Volts"/> is selected, 32-bit floating point voltages between -10
/// and 10 volts are sent directly to the DACs.
/// </remarks>
[Description("The data type used to represent analog samples.")]
[Category(DeviceFactory.ConfigurationCategory)]
public BreakoutAnalogIODataType DataType { get; set; } = BreakoutAnalogIODataType.S16;
public AnalogIODataType DataType { get; set; } = AnalogIODataType.S16;

/// <summary>
/// Send an matrix of samples to all enabled analog outputs.
/// </summary>
/// <remarks>
/// If a matrix contains multiple samples, they will be written to hardware as quickly as
/// communication allows. The data within each input matrix must have <see cref="Depth.S16"/> when
/// <c>DataType</c> is set to <see cref="BreakoutAnalogIODataType.S16"/> or <see cref="Depth.F32"/>
/// when <c>DataType</c> is set to <see cref="BreakoutAnalogIODataType.Volts"/>.
/// <c>DataType</c> is set to <see cref="AnalogIODataType.S16"/> or <see cref="Depth.F32"/>
/// when <c>DataType</c> is set to <see cref="AnalogIODataType.Volts"/>.
/// </remarks>
/// <param name="source"> A sequence of 12xN sample matrices containing the analog data to write to
/// channels 0 to 11.</param>
Expand All @@ -60,14 +64,14 @@ public override unsafe IObservable<Mat> Process(IObservable<Mat> source)
var bufferSize = 0;
var scaleBuffer = default(Mat);
var transposeBuffer = default(Mat);
var sampleScale = dataType == BreakoutAnalogIODataType.Volts
? 1 / BreakoutAnalogIODeviceInfo.GetVoltsPerDivision(OutputRange)
var sampleScale = dataType == AnalogIODataType.Volts
? 1 / AnalogIODeviceInfo.GetVoltsPerDivision(OutputRange)
: 1;
var device = deviceInfo.GetDeviceContext(typeof(BreakoutAnalogIO));
var device = deviceInfo.GetDeviceContext(typeof(AnalogIO));
return source.Do(data =>
{
if (dataType == BreakoutAnalogIODataType.S16 && data.Depth != Depth.S16 ||
dataType == BreakoutAnalogIODataType.Volts && data.Depth != Depth.F32)
if (dataType == AnalogIODataType.S16 && data.Depth != Depth.S16 ||
dataType == AnalogIODataType.Volts && data.Depth != Depth.F32)
{
ThrowDataTypeException(data.Depth);
}
Expand Down Expand Up @@ -116,7 +120,7 @@ public override unsafe IObservable<Mat> Process(IObservable<Mat> source)
/// </summary>
/// <remarks>
/// This overload should be used when <c>DataType</c> is set to <see
/// cref="BreakoutAnalogIODataType.S16"/> and values should be within -32,768 to 32,767, which
/// cref="AnalogIODataType.S16"/> and values should be within -32,768 to 32,767, which
/// correspond to -10.0 to 10.0 volts.
/// </remarks>
/// <param name="source"> A sequence of 12x1 element arrays each containing the analog data to write
Expand All @@ -125,12 +129,12 @@ public override unsafe IObservable<Mat> Process(IObservable<Mat> source)
/// to 11.</returns>
public IObservable<short[]> Process(IObservable<short[]> source)
{
if (DataType != BreakoutAnalogIODataType.S16)
if (DataType != AnalogIODataType.S16)
ThrowDataTypeException(Depth.S16);

return DeviceManager.GetDevice(DeviceName).SelectMany(deviceInfo =>
{
var device = deviceInfo.GetDeviceContext(typeof(BreakoutAnalogIO));
var device = deviceInfo.GetDeviceContext(typeof(AnalogIO));
return source.Do(data =>
{
AssertChannelCount(data.Length);
Expand All @@ -150,28 +154,28 @@ public IObservable<short[]> Process(IObservable<short[]> source)
/// </summary>
/// <remarks>
/// This overload should be used when <c>DataType</c> is set to <see
/// cref="BreakoutAnalogIODataType.Volts"/> and values should be within -10.0 to 10.0 volts.
/// cref="AnalogIODataType.Volts"/> and values should be within -10.0 to 10.0 volts.
/// </remarks>
/// <param name="source"> A sequence of 12x1 element arrays each containing the analog data to write
/// to channels 0 to 11.</param>
/// <returns> A sequence of 12x1 element arrays each containing the analog data to write to channels 0
/// to 11.</returns>
public IObservable<float[]> Process(IObservable<float[]> source)
{
if (DataType != BreakoutAnalogIODataType.Volts)
if (DataType != AnalogIODataType.Volts)
ThrowDataTypeException(Depth.F32);

return DeviceManager.GetDevice(DeviceName).SelectMany(deviceInfo =>
{
var device = deviceInfo.GetDeviceContext(typeof(BreakoutAnalogIO));
var divisionsPerVolt = 1 / BreakoutAnalogIODeviceInfo.GetVoltsPerDivision(OutputRange);
var device = deviceInfo.GetDeviceContext(typeof(AnalogIO));
var divisionsPerVolt = 1 / AnalogIODeviceInfo.GetVoltsPerDivision(OutputRange);
return source.Do(data =>
{
AssertChannelCount(data.Length);
var samples = new ushort[data.Length];
for (int i = 0; i < samples.Length; i++)
{
samples[i] = (ushort)(data[i] * divisionsPerVolt + BreakoutAnalogIO.DacMidScale);
samples[i] = (ushort)(data[i] * divisionsPerVolt + AnalogIO.DacMidScale);
}

device.Write(samples);
Expand All @@ -181,10 +185,10 @@ public IObservable<float[]> Process(IObservable<float[]> source)

static void AssertChannelCount(int channels)
{
if (channels != BreakoutAnalogIO.ChannelCount)
if (channels != AnalogIO.ChannelCount)
{
throw new InvalidOperationException(
$"The input data must have exactly {BreakoutAnalogIO.ChannelCount} channels."
$"The input data must have exactly {AnalogIO.ChannelCount} channels."
);
}
}
Expand Down
Loading