Skip to content

Commit bce0067

Browse files
authored
Merge pull request #133 from open-ephys-plugins/issue-130
Separate Analog and Digital data streams
2 parents 4dcf5dd + ebf9c00 commit bce0067

18 files changed

+259
-643
lines changed

Source/Devices/AnalogIO.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ AnalogIO::AnalogIO(std::string name, std::string hubName, const oni_dev_idx_t de
3131
OnixDevice::createStreamName({ getHubName(), name, "AnalogInput" }),
3232
"Analog Input data",
3333
getStreamIdentifier(),
34-
getNumChannels(),
34+
numChannels,
3535
getSampleRate(),
3636
"AnalogInput",
3737
ContinuousChannel::Type::ADC,
@@ -181,11 +181,6 @@ void AnalogIO::setDataType(AnalogIODataType type)
181181
dataType = type;
182182
}
183183

184-
int AnalogIO::getNumChannels()
185-
{
186-
return numChannels;
187-
}
188-
189184
void AnalogIO::startAcquisition()
190185
{
191186
currentFrame = 0;
@@ -247,22 +242,16 @@ void AnalogIO::processFrame(uint64_t eventWord)
247242

248243
if (currentFrame >= numFrames)
249244
{
250-
shouldAddToBuffer = true;
251-
currentFrame = 0;
252-
}
253-
254-
if (shouldAddToBuffer)
255-
{
256-
shouldAddToBuffer = false;
257245
analogInputBuffer->addToBuffer(analogInputSamples.data(), sampleNumbers, timestamps, eventCodes, numFrames);
258246

259247
analogInputSamples.fill(0);
248+
currentFrame = 0;
260249
}
261250
}
262251

263252
void AnalogIO::processFrames()
264253
{
265-
while (frameQueue.peek() != nullptr )
254+
while (frameQueue.peek() != nullptr)
266255
{
267256
processFrame();
268257
}

Source/Devices/AnalogIO.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,8 @@ namespace OnixSourcePlugin
8989
AnalogIODataType getDataType() const;
9090
void setDataType(AnalogIODataType type);
9191

92-
int getNumChannels();
93-
9492
static OnixDeviceType getDeviceType();
9593

96-
static constexpr int framesToAverage = 4; // NB: Downsampling from 100 kHz to 25 kHz
9794
static int getSampleRate();
9895

9996
int getNumberOfFrames();
@@ -103,6 +100,7 @@ namespace OnixSourcePlugin
103100
DataBuffer* analogInputBuffer = nullptr;
104101

105102
static constexpr int AnalogIOFrequencyHz = 100000;
103+
static constexpr int framesToAverage = 4; // NB: Downsampling from 100 kHz to 25 kHz
106104

107105
static constexpr int numFrames = 25;
108106
static constexpr int numChannels = 12;
@@ -119,8 +117,6 @@ namespace OnixSourcePlugin
119117
unsigned short currentAverageFrame = 0;
120118
int sampleNumber = 0;
121119

122-
bool shouldAddToBuffer = false;
123-
124120
std::array<float, numFrames* numChannels> analogInputSamples;
125121

126122
double timestamps[numFrames];

Source/Devices/AuxiliaryIO.cpp

Lines changed: 0 additions & 92 deletions
This file was deleted.

Source/Devices/AuxiliaryIO.h

Lines changed: 0 additions & 62 deletions
This file was deleted.

Source/Devices/DeviceList.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
2121
*/
2222

23-
#include "AuxiliaryIO.h"
2423
#include "AnalogIO.h"
2524
#include "Bno055.h"
2625
#include "DigitalIO.h"

Source/Devices/DigitalIO.cpp

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,37 @@
2626
using namespace OnixSourcePlugin;
2727

2828
DigitalIO::DigitalIO(std::string name, std::string hubName, const oni_dev_idx_t deviceIdx_, std::shared_ptr<Onix1> oni_ctx)
29-
: OnixDevice(name, hubName, DigitalIO::getDeviceType(), deviceIdx_, oni_ctx), eventWords(64)
29+
: OnixDevice(name, hubName, DigitalIO::getDeviceType(), deviceIdx_, oni_ctx)
3030
{
31+
StreamInfo digitalInputStream = StreamInfo(
32+
OnixDevice::createStreamName({ getHubName(), name, "DigitalInputs" }),
33+
"Digital Inputs data",
34+
getStreamIdentifier(),
35+
NumDigitalInputs,
36+
AnalogIO::getSampleRate(),
37+
"CH",
38+
ContinuousChannel::Type::AUX,
39+
1.0,
40+
"u", // NB: Digital data is unitless by definition
41+
{},
42+
{ "input" });
43+
streamInfos.add(digitalInputStream);
44+
45+
StreamInfo digitalButtonStream = StreamInfo(
46+
OnixDevice::createStreamName({ getHubName(), name, "DigitalButtons" }),
47+
"Digital Buttons data",
48+
getStreamIdentifier(),
49+
NumButtons,
50+
AnalogIO::getSampleRate(),
51+
"",
52+
ContinuousChannel::Type::AUX,
53+
1.0,
54+
"u", // NB: Digital data is unitless by definition
55+
{ "Moon", "Triangle", "X", "Check", "Circle", "Square" },
56+
{ "input" });
57+
streamInfos.add(digitalButtonStream);
58+
59+
eventCodes.fill(0);
3160
}
3261

3362
OnixDeviceType DigitalIO::getDeviceType()
@@ -49,7 +78,9 @@ int DigitalIO::configureDevice()
4978
if (rc != ONI_ESUCCESS)
5079
throw error_str("Could not read the base frequency register on the DigitalIO device.");
5180

52-
uint32_t periodTicks = baseFreqHz / (uint32_t)AnalogIO::getSampleRate();
81+
// NB: Two states are not accounted for when comparing clock ticks on the hardware,
82+
// therefore the periodTicks variable must be decreased by 2 to get the correct sample rate.
83+
uint32_t periodTicks = (baseFreqHz / (uint32_t)AnalogIO::getSampleRate()) - 2u;
5384
rc = deviceContext->writeRegister(deviceIdx, (uint32_t)DigitalIORegisters::SAMPLE_PERIOD, periodTicks);
5485
if (rc != ONI_ESUCCESS)
5586
throw error_str("Could not write the sample rate for polling to the DigitalIO device.");
@@ -64,10 +95,16 @@ bool DigitalIO::updateSettings()
6495

6596
void DigitalIO::startAcquisition()
6697
{
98+
currentFrame = 0;
99+
sampleNumber = 0;
100+
101+
digitalSamples.fill(0);
67102
}
68103

69104
void DigitalIO::addSourceBuffers(OwnedArray<DataBuffer>& sourceBuffers)
70105
{
106+
sourceBuffers.add(new DataBuffer(NumChannels, (int)streamInfos.getFirst().getSampleRate() * bufferSizeInSeconds));
107+
digitalBuffer = sourceBuffers.getLast();
71108
}
72109

73110
EventChannel::Settings DigitalIO::getEventChannelSettings(DataStream* stream)
@@ -78,48 +115,54 @@ EventChannel::Settings DigitalIO::getEventChannelSettings(DataStream* stream)
78115
"Digital inputs and breakout button states coming from a DigitalIO device",
79116
getStreamIdentifier() + ".event.digital",
80117
stream,
81-
numButtons + numDigitalInputs
118+
NumChannels
82119
};
83120

84121
return settings;
85122
}
86123

87-
int DigitalIO::getNumberOfWords()
124+
float DigitalIO::getChannelState(uint8_t state, int channel)
88125
{
89-
return eventWords.size_approx();
90-
}
126+
return (state & (1 << channel)) >> channel; // NB: Return the state of the specified channel
127+
};
91128

92129
void DigitalIO::processFrames()
93130
{
94131
oni_frame_t* frame;
95132
while (frameQueue.try_dequeue(frame))
96133
{
134+
size_t offset = 0;
97135

98136
uint16_t* dataPtr = (uint16_t*)frame->data;
99-
uint64_t timestamp = deviceContext->convertTimestampToSeconds(frame->time);
100137

101-
int dataOffset = 4;
138+
timestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time);
139+
sampleNumbers[currentFrame] = sampleNumber++;
102140

103-
uint64_t portState = *(dataPtr + dataOffset);
104-
uint64_t buttonState = *(dataPtr + dataOffset + 1);
141+
constexpr int inputDataOffset = 4;
142+
constexpr int buttonDataOffset = inputDataOffset + 1;
105143

106-
uint64_t ttlEventWord = (buttonState & 0x3F) << 8 | (portState & 0xFF);
107-
eventWords.enqueue(ttlEventWord);
144+
uint64_t inputState = *(dataPtr + inputDataOffset);
145+
uint64_t buttonState = *(dataPtr + buttonDataOffset);
108146

109-
oni_destroy_frame(frame);
110-
}
111-
}
147+
for (int i = 0; i < NumDigitalInputs; i++)
148+
{
149+
digitalSamples[currentFrame + offset++ * NumFrames] = getChannelState(inputState, i);
150+
}
112151

113-
uint64_t DigitalIO::getEventWord()
114-
{
115-
uint64_t eventWord;
116-
if (eventWords.try_dequeue(eventWord))
117-
return eventWord;
152+
for (int i = 0; i < NumButtons; i++)
153+
{
154+
digitalSamples[currentFrame + offset++ * NumFrames] = getChannelState(buttonState, i);
155+
}
118156

119-
return 0;
120-
}
157+
eventCodes[currentFrame] = (buttonState & 0x3F) << 8 | (inputState & 0xFF);
121158

122-
bool DigitalIO::hasEventWord()
123-
{
124-
return eventWords.peek() != nullptr;
159+
oni_destroy_frame(frame);
160+
161+
if (++currentFrame >= NumFrames)
162+
{
163+
digitalBuffer->addToBuffer(digitalSamples.data(), sampleNumbers.data(), timestamps.data(), eventCodes.data(), NumFrames);
164+
165+
currentFrame = 0;
166+
}
167+
}
125168
}

0 commit comments

Comments
 (0)