Skip to content

Commit 35a6d2b

Browse files
authored
Merge pull request #86 from open-ephys-plugins/polled-bno-threading
Updated PolledBno055
2 parents 5895a9c + acf93f3 commit 35a6d2b

File tree

7 files changed

+189
-121
lines changed

7 files changed

+189
-121
lines changed

Source/Devices/PolledBno055.cpp

Lines changed: 97 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ using namespace OnixSourcePlugin;
2626

2727
PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_idx_t deviceIdx_, std::shared_ptr<Onix1> ctx)
2828
: OnixDevice(name, hubName, PolledBno055::getDeviceType(), deviceIdx_, ctx, true),
29-
I2CRegisterContext(Bno055Address, deviceIdx_, ctx)
29+
I2CRegisterContext(Bno055Address, deviceIdx_, ctx),
30+
Thread("Polled BNO: " + name)
3031
{
3132
auto streamIdentifier = getStreamIdentifier();
3233

@@ -36,10 +37,10 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
3637
"Bosch Bno055 9-axis inertial measurement unit (IMU) Euler angle",
3738
streamIdentifier,
3839
3,
39-
sampleRate,
40+
SampleRate,
4041
"Eul",
4142
ContinuousChannel::Type::AUX,
42-
eulerAngleScale,
43+
EulerAngleScale,
4344
"Degrees",
4445
{ "Y", "R", "P" },
4546
"euler",
@@ -52,10 +53,10 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
5253
"Bosch Bno055 9-axis inertial measurement unit (IMU) Quaternion",
5354
streamIdentifier,
5455
4,
55-
sampleRate,
56+
SampleRate,
5657
"Quat",
5758
ContinuousChannel::Type::AUX,
58-
quaternionScale,
59+
QuaternionScale,
5960
"",
6061
{ "W", "X", "Y", "Z" },
6162
"quaternion",
@@ -68,10 +69,10 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
6869
"Bosch Bno055 9-axis inertial measurement unit (IMU) Acceleration",
6970
streamIdentifier,
7071
3,
71-
sampleRate,
72+
SampleRate,
7273
"Acc",
7374
ContinuousChannel::Type::AUX,
74-
accelerationScale,
75+
AccelerationScale,
7576
"m / s ^ 2",
7677
{ "X", "Y", "Z" },
7778
"acceleration",
@@ -84,10 +85,10 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
8485
"Bosch Bno055 9-axis inertial measurement unit (IMU) Gravity",
8586
streamIdentifier,
8687
3,
87-
sampleRate,
88+
SampleRate,
8889
"Grav",
8990
ContinuousChannel::Type::AUX,
90-
accelerationScale,
91+
AccelerationScale,
9192
"m/s^2",
9293
{ "X", "Y", "Z" },
9394
"gravity",
@@ -100,7 +101,7 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
100101
"Bosch Bno055 9-axis inertial measurement unit (IMU) Temperature",
101102
streamIdentifier,
102103
1,
103-
sampleRate,
104+
SampleRate,
104105
"Temp",
105106
ContinuousChannel::Type::AUX,
106107
1.0f,
@@ -115,7 +116,7 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
115116
"Bosch Bno055 9-axis inertial measurement unit (IMU) Calibration status",
116117
streamIdentifier,
117118
4,
118-
sampleRate,
119+
SampleRate,
119120
"Cal",
120121
ContinuousChannel::Type::AUX,
121122
1.0f,
@@ -126,10 +127,15 @@ PolledBno055::PolledBno055(std::string name, std::string hubName, const oni_dev_
126127
);
127128
streamInfos.add(calibrationStatusStream);
128129

129-
for (int i = 0; i < numFrames; i++)
130+
for (int i = 0; i < NumFrames; i++)
130131
eventCodes[i] = 0;
131132
}
132133

134+
PolledBno055::~PolledBno055()
135+
{
136+
stopThread(500);
137+
}
138+
133139
OnixDeviceType PolledBno055::getDeviceType()
134140
{
135141
return OnixDeviceType::POLLEDBNO;
@@ -174,7 +180,7 @@ bool PolledBno055::updateSettings()
174180
rc = WriteByte(0x3D, 0x0C); // Operation mode is NDOF
175181
if (rc != ONI_ESUCCESS) return false;
176182

177-
rc = set933I2cRate(i2cRate);
183+
rc = set933I2cRate(I2cRate);
178184

179185
return rc == ONI_ESUCCESS;
180186
}
@@ -184,16 +190,36 @@ void PolledBno055::startAcquisition()
184190
sampleNumber = 0;
185191
currentFrame = 0;
186192

193+
previousTime = std::chrono::steady_clock::now();
194+
187195
if (isEnabled())
188-
startTimer(timerIntervalInMilliseconds);
196+
startThread();
189197
}
190198

191-
void PolledBno055::stopAcquisition()
199+
void PolledBno055::run()
192200
{
193-
stopTimer();
201+
while (!threadShouldExit())
202+
{
203+
time_point now = std::chrono::steady_clock::now();
194204

195-
while (isTimerRunning())
196-
std::this_thread::sleep_for(std::chrono::milliseconds(10));
205+
std::chrono::milliseconds dur = std::chrono::duration_cast<std::chrono::milliseconds>(now - previousTime);
206+
207+
// NB: If the interval has not passed yet, wait for the remaining duration
208+
if (dur < TimerIntervalInMilliseconds)
209+
{
210+
std::this_thread::sleep_for(TimerIntervalInMilliseconds - dur);
211+
}
212+
213+
pollFrame();
214+
215+
previousTime += TimerIntervalInMilliseconds;
216+
}
217+
}
218+
219+
void PolledBno055::stopAcquisition()
220+
{
221+
if (isThreadRunning())
222+
stopThread(500);
197223
}
198224

199225
void PolledBno055::addFrame(oni_frame_t* frame)
@@ -203,63 +229,75 @@ void PolledBno055::addFrame(oni_frame_t* frame)
203229

204230
void PolledBno055::addSourceBuffers(OwnedArray<DataBuffer>& sourceBuffers)
205231
{
206-
sourceBuffers.add(new DataBuffer(numberOfChannels, (int)sampleRate * bufferSizeInSeconds));
232+
sourceBuffers.add(new DataBuffer(NumberOfChannels, (int)SampleRate * bufferSizeInSeconds));
207233
bnoBuffer = sourceBuffers.getLast();
208234
}
209235

210-
int16_t PolledBno055::readInt16(uint32_t startAddress)
236+
void PolledBno055::processFrames()
211237
{
212-
uint32_t value = 0;
213-
int rc = ReadWord(startAddress, 2, &value);
214-
215-
if (rc != ONI_ESUCCESS)
216-
return 0;
238+
}
217239

218-
return static_cast<int16_t>(value);
240+
int16_t PolledBno055::getInt16FromUint32(uint32_t value, bool getLowerValue)
241+
{
242+
return getLowerValue ?
243+
static_cast<int16_t>(value & 0xFFFFu) :
244+
static_cast<int16_t>((value & 0xFFFF0000u) >> 16);
219245
}
220246

221-
void PolledBno055::hiResTimerCallback()
247+
void PolledBno055::pollFrame()
222248
{
223249
size_t offset = 0;
250+
uint32_t value;
251+
224252

225253
// Euler
226-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress) * eulerAngleScale;
227-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 2) * eulerAngleScale;
228-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 4) * eulerAngleScale;
254+
ReadWord(EulerHeadingLsbAddress, 4, &value);
255+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * EulerAngleScale;
256+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * EulerAngleScale;
257+
258+
ReadWord(EulerHeadingLsbAddress + 4, 4, &value);
259+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * EulerAngleScale;
229260

230261
// Quaternion
231-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 6) * quaternionScale;
232-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 8) * quaternionScale;
233-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 10) * quaternionScale;
234-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 12) * quaternionScale;
262+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * QuaternionScale;
263+
264+
ReadWord(EulerHeadingLsbAddress + 8, 4, &value);
265+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * QuaternionScale;
266+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * QuaternionScale;
267+
268+
ReadWord(EulerHeadingLsbAddress + 12, 4, &value);
269+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * QuaternionScale;
235270

236271
// Acceleration
237272

238-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 14) * accelerationScale;
239-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 16) * accelerationScale;
240-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 18) * accelerationScale;
273+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * AccelerationScale;
274+
275+
ReadWord(EulerHeadingLsbAddress + 16, 4, &value);
276+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * AccelerationScale;
277+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * AccelerationScale;
241278

242279
// Gravity
243280

244-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 20) * accelerationScale;
245-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 22) * accelerationScale;
246-
bnoSamples[offset++ * numFrames + currentFrame] = readInt16(EulerHeadingLsbAddress + 24) * accelerationScale;
281+
ReadWord(EulerHeadingLsbAddress + 20, 4, &value);
282+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * AccelerationScale;
283+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, false) * AccelerationScale;
284+
285+
ReadWord(EulerHeadingLsbAddress + 24, 4, &value);
286+
bnoSamples[offset++ * NumFrames + currentFrame] = getInt16FromUint32(value, true) * AccelerationScale;
247287

248288
// Temperature
249289

250-
oni_reg_val_t byte;
251-
ReadByte(EulerHeadingLsbAddress + 26, &byte);
252-
bnoSamples[offset++ * numFrames + currentFrame] = static_cast<uint8_t>(byte);
290+
bnoSamples[offset++ * NumFrames + currentFrame] = static_cast<uint8_t>((value & 0xFF0000u) >> 16);
253291

254292
// Calibration Status
255293

256-
ReadByte(EulerHeadingLsbAddress + 27, &byte);
257-
294+
oni_reg_val_t byte = static_cast<uint8_t>((value & 0xFF000000u) >> 24);
295+
258296
constexpr uint8_t statusMask = 0b11;
259297

260298
for (int i = 0; i < 4; i++)
261299
{
262-
bnoSamples[currentFrame + (offset + i) * numFrames] = (byte & (statusMask << (2 * i))) >> (2 * i);
300+
bnoSamples[currentFrame + (offset + i) * NumFrames] = (byte & (statusMask << (2 * i))) >> (2 * i);
263301
}
264302

265303
oni_reg_val_t timestampL = 0, timestampH = 0;
@@ -274,13 +312,24 @@ void PolledBno055::hiResTimerCallback()
274312

275313
currentFrame++;
276314

277-
if (currentFrame >= numFrames)
315+
if (currentFrame >= NumFrames)
278316
{
279-
bnoBuffer->addToBuffer(bnoSamples.data(), sampleNumbers, bnoTimestamps, eventCodes, numFrames);
317+
bnoBuffer->addToBuffer(bnoSamples.data(), sampleNumbers, bnoTimestamps, eventCodes, NumFrames);
280318
currentFrame = 0;
281319
}
282320
}
283321

322+
int16_t PolledBno055::readInt16(uint32_t startAddress)
323+
{
324+
uint32_t value = 0;
325+
int rc = ReadWord(startAddress, 2, &value);
326+
327+
if (rc != ONI_ESUCCESS)
328+
return 0;
329+
330+
return static_cast<int16_t>(value);
331+
}
332+
284333
void PolledBno055::setBnoAxisMap(Bno055AxisMap map)
285334
{
286335
axisMap = map;

0 commit comments

Comments
 (0)