Skip to content

Commit c9894d7

Browse files
committed
Successfully stream data from one ONIX device
1 parent eb7ee41 commit c9894d7

File tree

2 files changed

+199
-58
lines changed

2 files changed

+199
-58
lines changed

Source/OnixSource.cpp

Lines changed: 186 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,88 @@
2626
#include "OnixSourceEditor.h"
2727

2828

29+
OnixSource::OnixSource(SourceNode* sn) :
30+
DataThread(sn),
31+
ctx(NULL),
32+
devicesFound(false)
33+
{
34+
LOGD("ONIX Source creating ONI context.");
35+
36+
ctx = oni_create_ctx("riffa"); // "riffa" is the PCIe driver name
37+
38+
if (!ctx) { LOGE("Failed to create context."); return; }
39+
40+
// Initialize context and discover hardware
41+
int errorCode = oni_init_ctx(ctx, 0);
42+
43+
if (errorCode) { LOGE(oni_error_str(errorCode)); return; }
44+
45+
oni_size_t num_devs = 0;
46+
oni_device_t* devices = NULL;
47+
48+
// Examine device table
49+
size_t num_devs_sz = sizeof(num_devs);
50+
oni_get_opt(ctx, ONI_OPT_NUMDEVICES, &num_devs, &num_devs_sz);
51+
52+
size_t devices_sz = sizeof(oni_device_t) * num_devs;
53+
devices = (oni_device_t *)realloc(devices, devices_sz);
54+
if (devices == NULL) { LOGE("No devices found."); return; }
55+
oni_get_opt(ctx, ONI_OPT_DEVICETABLE, devices, &devices_sz);
56+
57+
devicesFound = true;
58+
59+
// print device info
60+
printf(" +--------------------+-------+-------+-------+-------+---------------------\n");
61+
printf(" | \t\t| \t|Firm.\t|Read\t|Wrt. \t| \n");
62+
printf(" |Dev. idx\t\t|ID\t|ver. \t|size\t|size \t|Desc.\n");
63+
printf(" +--------------------+-------+-------+-------+-------+---------------------\n");
64+
65+
for (size_t dev_idx = 0; dev_idx < num_devs; dev_idx++) {
66+
if (devices[dev_idx].id != ONIX_NULL) {
67+
68+
const char* dev_str = onix_device_str(devices[dev_idx].id);
69+
70+
printf("%02zd |%05zd: 0x%02x.0x%02x\t|%d\t|%d\t|%u\t|%u\t|%s\n",
71+
dev_idx,
72+
devices[dev_idx].idx,
73+
(uint8_t)(devices[dev_idx].idx >> 8),
74+
(uint8_t)devices[dev_idx].idx,
75+
devices[dev_idx].id,
76+
devices[dev_idx].version,
77+
devices[dev_idx].read_size,
78+
devices[dev_idx].write_size,
79+
dev_str);
80+
}
81+
}
82+
83+
oni_size_t frame_size = 0;
84+
size_t frame_size_sz = sizeof(frame_size);
85+
oni_get_opt(ctx, ONI_OPT_MAXREADFRAMESIZE, &frame_size, &frame_size_sz);
86+
printf("Max. read frame size: %u bytes\n", frame_size);
87+
88+
oni_get_opt(ctx, ONI_OPT_MAXWRITEFRAMESIZE, &frame_size, &frame_size_sz);
89+
printf("Max. write frame size: %u bytes\n", frame_size);
90+
91+
size_t block_size_sz = sizeof(block_read_size);
92+
93+
// oni_set_opt(ctx, ONI_OPT_RESET, &val, sizeof(val));
94+
oni_set_opt(ctx, ONI_OPT_BLOCKREADSIZE, &block_read_size, block_size_sz);
95+
96+
// Enable memory usage device
97+
oni_write_reg(ctx, DEVICE_MEMORY, 0, 1);
98+
99+
oni_reg_val_t hzVal = 0;
100+
oni_read_reg(ctx, DEVICE_MEMORY, 2, &hzVal);
101+
102+
// set memory device refresh rate to 100 Hz
103+
oni_write_reg(ctx, DEVICE_MEMORY, 1, hzVal/100);
104+
105+
oni_reg_val_t memSize = 0;
106+
oni_read_reg(ctx, DEVICE_MEMORY, 3, &memSize);
107+
108+
LOGD ("Hardware buffer size in 32-bit words: ", (int)memSize);
109+
}
110+
29111
DataThread* OnixSource::createDataThread(SourceNode *sn)
30112
{
31113
return new OnixSource(sn);
@@ -44,7 +126,7 @@ void OnixSource::updateSettings(OwnedArray<ContinuousChannel>* continuousChannel
44126
OwnedArray<EventChannel>* eventChannels,
45127
OwnedArray<SpikeChannel>* spikeChannels,
46128
OwnedArray<DataStream>* dataStreams,
47-
OwnedArray<DeviceInfo>* devices,
129+
OwnedArray<DeviceInfo>* deviceInfos,
48130
OwnedArray<ConfigurationObject>* configurationObjects)
49131
{
50132

@@ -54,87 +136,138 @@ void OnixSource::updateSettings(OwnedArray<ContinuousChannel>* continuousChannel
54136
eventChannels->clear();
55137
continuousChannels->clear();
56138
spikeChannels->clear();
57-
devices->clear();
139+
deviceInfos->clear();
58140
configurationObjects->clear();
59141

60142
sources.clear();
61143
sourceBuffers.clear();
62144

63-
if (ctx == NULL)
145+
if (devicesFound)
64146
{
65-
LOGD("ONIX Source creating ONI context.");
66-
67-
ctx = oni_create_ctx("riffa"); // "riffa" is the PCIe driver name
68-
69-
if (!ctx) { LOGE("Failed to create context."); return; }
70-
71-
// Initialize context and discover hardware
72-
int errorCode = oni_init_ctx(ctx, 0);
73-
74-
if (errorCode) { LOGE(oni_error_str(errorCode)); return; }
75-
76-
oni_size_t num_devs = 0;
77-
oni_device_t* devices = NULL;
78-
79-
// Examine device table
80-
size_t num_devs_sz = sizeof(num_devs);
81-
oni_get_opt(ctx, ONI_OPT_NUMDEVICES, &num_devs, &num_devs_sz);
82-
83-
size_t devices_sz = sizeof(oni_device_t) * num_devs;
84-
devices = (oni_device_t *)realloc(devices, devices_sz);
85-
if (devices == NULL) { LOGE("No devices found."); return; }
86-
oni_get_opt(ctx, ONI_OPT_DEVICETABLE, devices, &devices_sz);
87-
88-
// print device info
89-
for (size_t dev_idx = 0; dev_idx < num_devs; dev_idx++) {
90-
if (devices[dev_idx].id != ONIX_NULL) {
91-
92-
const char* dev_str = onix_device_str(devices[dev_idx].id);
93-
94-
printf("%02zd |%05zd: 0x%02x.0x%02x\t|%d\t|%d\t|%u\t|%u\t|%s\n",
95-
dev_idx,
96-
devices[dev_idx].idx,
97-
(uint8_t)(devices[dev_idx].idx >> 8),
98-
(uint8_t)devices[dev_idx].idx,
99-
devices[dev_idx].id,
100-
devices[dev_idx].version,
101-
devices[dev_idx].read_size,
102-
devices[dev_idx].write_size,
103-
dev_str);
104-
}
147+
sourceBuffers.add(new DataBuffer(1, 10000)); // Memory device
148+
// sourceBuffers.add(new DataBuffer(1, 10000)); // Heartbeat device
149+
150+
//Memory usage device
151+
DataStream::Settings memStreamSettings
152+
{
153+
"Memory Usage", // stream name
154+
"Hardware buffer usage on an acquisition board", // stream description
155+
"onix-pcie-device.memory", // stream identifier
156+
100 // sample rate
157+
158+
};
159+
160+
DataStream* stream = new DataStream(memStreamSettings);
161+
dataStreams->add(stream);
162+
163+
{
164+
ContinuousChannel::Settings channelSettings{
165+
ContinuousChannel::AUX,
166+
"MEM",
167+
"Hardware buffer usage",
168+
"onix-pcie-device.continuous.mem",
169+
1.0f,
170+
stream
171+
};
172+
continuousChannels->add(new ContinuousChannel(channelSettings));
105173
}
106174
}
107175

108-
109-
110-
111176
// detect available devices and create source objects for each
112177

113178
}
114179

115180

116181
bool OnixSource::foundInputSource()
117182
{
118-
return false;
183+
return devicesFound;
119184
}
120185

121186
bool OnixSource::startAcquisition()
122187
{
123188

124-
for (auto source : sources)
125-
source->buffer->clear();
189+
// for (auto source : sources)
190+
// source->buffer->clear();
191+
192+
// for (auto source : sources)
193+
// source->startThread();
194+
if (!devicesFound)
195+
return false;
196+
197+
oni_reg_val_t reg = 2;
198+
int res = oni_set_opt(ctx, ONI_OPT_RESETACQCOUNTER, &reg, sizeof(oni_size_t));
199+
if (res < ONI_ESUCCESS)
200+
{
201+
LOGE("Error starting acquisition: ", oni_error_str(res), " code ", res);
202+
return false;
203+
}
126204

127-
for (auto source : sources)
128-
source->startThread();
205+
startThread();
129206

130207
return true;
131208
}
132209

133210
bool OnixSource::stopAcquisition()
134211
{
212+
if (isThreadRunning())
213+
signalThreadShouldExit();
214+
215+
waitForThreadToExit(2000);
216+
217+
if (devicesFound)
218+
{
219+
oni_size_t reg = 0;
220+
int res = oni_set_opt(ctx, ONI_OPT_RUNNING, &reg, sizeof(reg));
221+
if (res < ONI_ESUCCESS)
222+
{
223+
LOGE("Error stopping acquisition: ", oni_error_str(res), " code ", res);
224+
return false;
225+
}
226+
227+
uint32_t val = 1;
228+
oni_set_opt(ctx, ONI_OPT_RESET, &val, sizeof(val));
229+
oni_set_opt(ctx, ONI_OPT_BLOCKREADSIZE, &block_read_size, sizeof(block_read_size));
230+
}
231+
sourceBuffers[0]->clear();
135232

136-
for (auto source : sources)
137-
source->signalThreadShouldExit();
233+
return true;
234+
}
235+
236+
bool OnixSource::updateBuffer()
237+
{
238+
const int nSamps = 192;
239+
oni_frame_t* frame;
240+
unsigned char* bufferPtr;
241+
242+
for (int samp = 0; samp < nSamps; samp++)
243+
{
244+
int res = oni_read_frame(ctx, &frame);
245+
246+
if (res < ONI_ESUCCESS)
247+
{
248+
LOGE("Error reading ONI frame: ", oni_error_str(res), " code ", res);
249+
return false;
250+
}
251+
252+
if (frame->dev_idx == DEVICE_MEMORY)
253+
{
254+
bufferPtr = (unsigned char*)frame->data + 8; //skip ONI timestamps
255+
uint32 membytes = (uint32(*(uint16*)bufferPtr) << 16) + (uint32(*(uint16*)(bufferPtr + 2)));
256+
float memf = membytes * sizeof(membytes);
257+
uint64 zero = 0;
258+
int64 tst = frame->time;
259+
double tsd = -1;
260+
sourceBuffers[0]->addToBuffer(
261+
&memf,
262+
&tst,
263+
&tsd,
264+
&zero,
265+
1
266+
);
267+
}
268+
269+
oni_destroy_frame(frame);
270+
}
138271

139272
return true;
140273
}

Source/OnixSource.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,17 @@ class OnixSource : public DataThread
5151
public:
5252

5353
/** Constructor */
54-
OnixSource(SourceNode* sn) : DataThread(sn)
55-
{
56-
ctx = NULL;
57-
}
54+
OnixSource(SourceNode* sn);
5855

5956
/** Destructor */
6057
~OnixSource()
6158
{
6259
if (ctx != NULL)
60+
{
61+
uint32_t val = 1;
62+
oni_set_opt(ctx, ONI_OPT_RESET, &val, sizeof(val));
6363
oni_destroy_ctx(ctx);
64+
}
6465
}
6566

6667
/** Static method to create DataThread */
@@ -70,7 +71,7 @@ class OnixSource : public DataThread
7071
std::unique_ptr<GenericEditor> createEditor(SourceNode* sn);
7172

7273
/** Not used -- data buffers are updated for each source stream */
73-
bool updateBuffer() { return true; }
74+
bool updateBuffer() override;
7475

7576
/** Returns true if the hardware is connected, false otherwise.*/
7677
bool foundInputSource();
@@ -89,6 +90,8 @@ class OnixSource : public DataThread
8990
OwnedArray<DeviceInfo>* devices,
9091
OwnedArray<ConfigurationObject>* configurationObjects);
9192

93+
private:
94+
9295
/** Available data sources */
9396
OwnedArray<OnixDevice> sources;
9497

@@ -98,6 +101,11 @@ class OnixSource : public DataThread
98101
/** The ONI context object */
99102
oni_ctx ctx;
100103

104+
static const oni_dev_idx_t DEVICE_MEMORY = 0x000a;
105+
const oni_size_t block_read_size = 2048;
106+
107+
bool devicesFound = false;
108+
101109
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OnixSource);
102110

103111
};

0 commit comments

Comments
 (0)