Skip to content

Commit 26c2999

Browse files
committed
Separate digital data from analog data
- Digital data is now saved as a continuous data stream with fourteen channels, and also as an event in the same stream
1 parent 4dcf5dd commit 26c2999

File tree

8 files changed

+131
-75
lines changed

8 files changed

+131
-75
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: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
using namespace OnixSourcePlugin;
2828

2929
AuxiliaryIO::AuxiliaryIO(std::string name, std::string hubName, const oni_dev_idx_t analogIndex, const oni_dev_idx_t digitalIndex, std::shared_ptr<Onix1> oni_ctx)
30-
: CompositeDevice(name, hubName, AuxiliaryIO::getCompositeDeviceType(), createAuxiliaryIODevices(hubName, analogIndex, digitalIndex, oni_ctx), oni_ctx)
30+
: CompositeDevice(name, hubName, AuxiliaryIO::getCompositeDeviceType(), analogIndex, createAuxiliaryIODevices(hubName, analogIndex, digitalIndex, oni_ctx), oni_ctx)
3131
{
3232
analogIO = getDevice<AnalogIO>(OnixDeviceType::ANALOGIO);
3333
digitalIO = getDevice<DigitalIO>(OnixDeviceType::DIGITALIO);
@@ -43,8 +43,8 @@ OnixDeviceVector AuxiliaryIO::createAuxiliaryIODevices(std::string hubName, cons
4343
{
4444
OnixDeviceVector devices;
4545

46-
devices.emplace_back(std::make_shared<AnalogIO>("AnalogIO", hubName, analogIndex, oni_ctx));
4746
devices.emplace_back(std::make_shared<DigitalIO>("DigitalIO", hubName, digitalIndex, oni_ctx));
47+
devices.emplace_back(std::make_shared<AnalogIO>("AnalogIO", hubName, analogIndex, oni_ctx));
4848

4949
return devices;
5050
}
@@ -57,18 +57,7 @@ bool AuxiliaryIO::isEnabled() const
5757
void AuxiliaryIO::processFrames()
5858
{
5959
digitalIO->processFrames();
60-
61-
while (digitalIO->hasEventWord() && analogIO->getNumberOfFrames() >= AnalogIO::framesToAverage)
62-
{
63-
auto eventWord = digitalIO->getEventWord();
64-
65-
for (int i = 0; i < AnalogIO::framesToAverage; i++)
66-
{
67-
analogIO->processFrame(eventWord);
68-
}
69-
70-
digitalIO->processFrames();
71-
}
60+
analogIO->processFrames();
7261
}
7362

7463
OnixDeviceType AuxiliaryIO::getDeviceType()

Source/Devices/DigitalIO.cpp

Lines changed: 65 additions & 24 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()
@@ -64,10 +93,16 @@ bool DigitalIO::updateSettings()
6493

6594
void DigitalIO::startAcquisition()
6695
{
96+
currentFrame = 0;
97+
sampleNumber = 0;
98+
99+
digitalSamples.fill(0);
67100
}
68101

69102
void DigitalIO::addSourceBuffers(OwnedArray<DataBuffer>& sourceBuffers)
70103
{
104+
sourceBuffers.add(new DataBuffer(NumChannels, (int)streamInfos.getFirst().getSampleRate() * bufferSizeInSeconds));
105+
digitalBuffer = sourceBuffers.getLast();
71106
}
72107

73108
EventChannel::Settings DigitalIO::getEventChannelSettings(DataStream* stream)
@@ -78,48 +113,54 @@ EventChannel::Settings DigitalIO::getEventChannelSettings(DataStream* stream)
78113
"Digital inputs and breakout button states coming from a DigitalIO device",
79114
getStreamIdentifier() + ".event.digital",
80115
stream,
81-
numButtons + numDigitalInputs
116+
NumChannels
82117
};
83118

84119
return settings;
85120
}
86121

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

92127
void DigitalIO::processFrames()
93128
{
94129
oni_frame_t* frame;
95130
while (frameQueue.try_dequeue(frame))
96131
{
132+
size_t offset = 0;
97133

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

101-
int dataOffset = 4;
136+
timestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time);
137+
sampleNumbers[currentFrame] = sampleNumber++;
102138

103-
uint64_t portState = *(dataPtr + dataOffset);
104-
uint64_t buttonState = *(dataPtr + dataOffset + 1);
139+
constexpr int inputDataOffset = 4;
140+
constexpr int buttonDataOffset = inputDataOffset + 1;
105141

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

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

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

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

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

Source/Devices/DigitalIO.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,30 @@ namespace OnixSourcePlugin
7979

8080
EventChannel::Settings getEventChannelSettings(DataStream* stream);
8181

82-
int getNumberOfWords();
83-
uint64_t getEventWord();
84-
bool hasEventWord();
85-
8682
static OnixDeviceType getDeviceType();
8783

8884
private:
8985

90-
static constexpr int numDigitalInputs = 8;
91-
static constexpr int numButtons = 6;
86+
DataBuffer* digitalBuffer = nullptr;
87+
88+
static float getChannelState(uint8_t state, int channel);
89+
90+
static constexpr int NumFrames = 25;
91+
92+
static constexpr int NumDigitalInputs = 8;
93+
static constexpr int NumButtons = 6;
94+
static constexpr int NumChannels = NumDigitalInputs + NumButtons;
95+
96+
static constexpr int NumSamples = NumFrames * NumChannels;
97+
98+
unsigned short currentFrame = 0;
99+
int64_t sampleNumber = 0;
100+
101+
std::array<float, NumSamples> digitalSamples;
92102

93-
ReaderWriterQueue<uint64_t> eventWords;
103+
std::array<double, NumFrames> timestamps;
104+
std::array<int64_t, NumFrames> sampleNumbers;
105+
std::array<uint64_t, NumFrames> eventCodes;
94106

95107
JUCE_LEAK_DETECTOR(DigitalIO);
96108
};

Source/OnixDevice.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ void OnixDevice::stopAcquisition()
242242
}
243243
}
244244

245-
CompositeDevice::CompositeDevice(std::string name_, std::string hubName, CompositeDeviceType type_, OnixDeviceVector devices_, std::shared_ptr<Onix1> oni_ctx)
246-
: OnixDevice(name_, hubName, OnixDeviceType::COMPOSITE, devices_.at(0)->getDeviceIdx(), oni_ctx)
245+
CompositeDevice::CompositeDevice(std::string name_, std::string hubName, CompositeDeviceType type_, const oni_dev_idx_t devIdx, OnixDeviceVector devices_, std::shared_ptr<Onix1> oni_ctx)
246+
: OnixDevice(name_, hubName, OnixDeviceType::COMPOSITE, devIdx, oni_ctx)
247247
{
248248
compositeType = type_;
249249
devices = devices_;

Source/OnixDevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ namespace OnixSourcePlugin
243243
{
244244
public:
245245

246-
CompositeDevice(std::string name_, std::string hubName, CompositeDeviceType type_, OnixDeviceVector devices_, std::shared_ptr<Onix1> oni_ctx);
246+
CompositeDevice(std::string name_, std::string hubName, CompositeDeviceType type_, const oni_dev_idx_t, OnixDeviceVector devices_, std::shared_ptr<Onix1> oni_ctx);
247247

248248
CompositeDeviceType getCompositeDeviceType() const;
249249

Source/OnixSource.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -892,22 +892,46 @@ void OnixSource::updateSettings(OwnedArray<ContinuousChannel>* continuousChannel
892892

893893
if (compositeDevice->getCompositeDeviceType() == CompositeDeviceType::AUXILIARYIO)
894894
{
895-
DeviceInfo::Settings deviceSettings{
895+
auto auxiliaryIO = std::static_pointer_cast<AuxiliaryIO>(compositeDevice);
896+
897+
// NB: DigitalIO
898+
DeviceInfo::Settings digitalIODeviceSettings{
896899
source->getName(),
897-
"Auxiliary device containing analog and digital IO data",
898-
"auxiliaryio",
900+
"DigitalIO",
901+
"digitalio",
899902
"0000000",
900903
""
901904
};
902905

903-
deviceInfos->add(new DeviceInfo(deviceSettings));
906+
deviceInfos->add(new DeviceInfo(digitalIODeviceSettings));
904907

905-
auto auxiliaryIO = std::static_pointer_cast<AuxiliaryIO>(compositeDevice);
908+
auto digitalIO = auxiliaryIO->getDigitalIO();
906909

907-
addIndividualStreams(auxiliaryIO->getAnalogIO()->streamInfos, dataStreams, deviceInfos, continuousChannels);
910+
DataStream::Settings dataStreamSettings{
911+
OnixDevice::createStreamName({digitalIO->getHubName(), digitalIO->getName()}),
912+
"Digital inputs and buttons",
913+
digitalIO->getStreamIdentifier(),
914+
digitalIO->streamInfos[0].getSampleRate(),
915+
true
916+
};
908917

909-
auto eventChannelSettings = auxiliaryIO->getDigitalIO()->getEventChannelSettings(dataStreams->getLast());
918+
addCombinedStreams(dataStreamSettings, digitalIO->streamInfos, dataStreams, deviceInfos, continuousChannels);
919+
920+
auto eventChannelSettings = digitalIO->getEventChannelSettings(dataStreams->getLast());
910921
eventChannels->add(new EventChannel(eventChannelSettings));
922+
923+
// NB: AnalogIO
924+
DeviceInfo::Settings analogIODeviceSettings{
925+
source->getName(),
926+
"AnalogIO",
927+
"analogio",
928+
"0000000",
929+
""
930+
};
931+
932+
deviceInfos->add(new DeviceInfo(analogIODeviceSettings));
933+
934+
addIndividualStreams(auxiliaryIO->getAnalogIO()->streamInfos, dataStreams, deviceInfos, continuousChannels);
911935
}
912936
else
913937
{
@@ -947,7 +971,12 @@ void OnixSource::addCombinedStreams(DataStream::Settings dataStreamSettings,
947971
auto prefix = streamInfo.getChannelPrefix();
948972

949973
if (suffixes[chan] != "")
950-
prefix += "-" + suffixes[chan];
974+
{
975+
if (prefix != "")
976+
prefix += "-" + suffixes[chan];
977+
else
978+
prefix = suffixes[chan];
979+
}
951980

952981
ContinuousChannel::Settings channelSettings{
953982
streamInfo.getChannelType(),

0 commit comments

Comments
 (0)