From 6e2fd1f1bfce58ac6fd89241b3ac7fa4c2aa9921 Mon Sep 17 00:00:00 2001 From: bparks13 Date: Thu, 24 Apr 2025 17:31:48 -0400 Subject: [PATCH 1/5] If automated discovery fails, set port voltage to zero --- Source/Devices/PortController.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Source/Devices/PortController.cpp b/Source/Devices/PortController.cpp index 1bbdea4..07133ac 100644 --- a/Source/Devices/PortController.cpp +++ b/Source/Devices/PortController.cpp @@ -66,8 +66,8 @@ void PortController::processFrames() int dataOffset = 8; - uint32_t code = (uint32_t) *(dataPtr + dataOffset); - uint32_t data = (uint32_t) *(dataPtr + dataOffset + 1); + uint32_t code = (uint32_t) * (dataPtr + dataOffset); + uint32_t data = (uint32_t) * (dataPtr + dataOffset + 1); errorFlag = errorFlag || ((uint32_t)data & LINKSTATE_SL) == 0; @@ -115,19 +115,29 @@ bool PortController::configureVoltage(double voltage) { if (voltage == defaultVoltage) { - if (discoveryParameters == DiscoveryParameters() || discoveryParameters.voltageIncrement <= 0) + if (discoveryParameters == DiscoveryParameters() || discoveryParameters.voltageIncrement <= 0) return false; ConfigureVoltageWithProgressBar progressBar = ConfigureVoltageWithProgressBar(discoveryParameters, this); progressBar.runThread(); - return progressBar.getResult(); + bool result = progressBar.getResult(); + + if (!result) + setVoltageOverride(0, false); + + return result; } else if (voltage >= 0.0 && voltage <= 7.0) { setVoltage(voltage); - return checkLinkState(); + bool result = checkLinkState(); + + if (!result) + setVoltageOverride(0, false); + + return result; } return false; From 18a243ed99b4403f11dabe31844e7709d044da45 Mon Sep 17 00:00:00 2001 From: bparks13 Date: Thu, 24 Apr 2025 17:38:42 -0400 Subject: [PATCH 2/5] Update stream/channel identifiers - All stream identifiers now follow the format "onix.[headstage|breakout].[device]" - All channel identifiers start the same as their corresponding stream, but with the addition of ".[continuous}event].[datatype].[subtype]". Not all channels have a subtype, so this part may be omitted --- Source/Devices/AnalogIO.cpp | 9 +- Source/Devices/Bno055.cpp | 36 +++++--- Source/Devices/DigitalIO.cpp | 2 +- Source/Devices/HarpSyncInput.cpp | 6 +- Source/Devices/MemoryMonitor.cpp | 6 +- Source/Devices/Neuropixels2e.cpp | 6 +- Source/Devices/Neuropixels_1.cpp | 14 +++- Source/Devices/PolledBno055.cpp | 42 +++++++--- Source/OnixDevice.cpp | 56 +++++++++++++ Source/OnixDevice.h | 136 ++++++++++++++++++------------- Source/OnixSource.cpp | 47 +++++++---- Source/OnixSource.h | 2 + Source/OnixSourceCanvas.cpp | 28 +++---- Source/OnixSourceEditor.cpp | 4 +- 14 files changed, 268 insertions(+), 126 deletions(-) diff --git a/Source/Devices/AnalogIO.cpp b/Source/Devices/AnalogIO.cpp index 0e47eee..f3ec655 100644 --- a/Source/Devices/AnalogIO.cpp +++ b/Source/Devices/AnalogIO.cpp @@ -28,14 +28,15 @@ AnalogIO::AnalogIO(String name, const oni_dev_idx_t deviceIdx_, std::shared_ptr< StreamInfo analogInputStream = StreamInfo( OnixDevice::createStreamName({ getHeadstageName(), name, "AnalogInput" }), "Analog Input data", - "onix-analogio.data.input", - 12, + getStreamIdentifier(), + getNumChannels(), std::floor(AnalogIOFrequencyHz / framesToAverage), "AnalogInput", ContinuousChannel::Type::ADC, 20.0f / numberOfDivisions, // NB: +/- 10 Volts "V", - {}); + {}, + { "input" }); streamInfos.add(analogInputStream); for (int i = 0; i < numFrames; i++) @@ -63,7 +64,7 @@ bool AnalogIO::updateSettings() for (int i = 0; i < numChannels; i += 1) { - rc = deviceContext->writeRegister(deviceIdx, (oni_reg_addr_t)AnalogIORegisters::CH00_IN_RANGE + i, (oni_reg_val_t)channelVoltageRange[i]); + rc = deviceContext->writeRegister(deviceIdx, (oni_reg_addr_t)AnalogIORegisters::CH00_IN_RANGE + i, (oni_reg_val_t)channelVoltageRange[i]); if (rc != ONI_ESUCCESS) return false; } diff --git a/Source/Devices/Bno055.cpp b/Source/Devices/Bno055.cpp index 636ee56..a3ad8cd 100644 --- a/Source/Devices/Bno055.cpp +++ b/Source/Devices/Bno055.cpp @@ -27,70 +27,86 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ { const float bitVolts = 1.0; + auto streamIdentifier = getStreamIdentifier(); + String port = PortController::getPortName(PortController::getPortFromIndex(deviceIdx)); StreamInfo eulerAngleStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Euler" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Euler angle", - "onix-bno055.data.euler", + streamIdentifier, 3, sampleRate, "Euler", ContinuousChannel::Type::AUX, bitVolts, "Degrees", - { "Yaw", "Roll", "Pitch" }); + { "Yaw", "Roll", "Pitch" }, + "euler", + { "y", "r", "p" } + ); streamInfos.add(eulerAngleStream); StreamInfo quaternionStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Quaternion" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Quaternion", - "onix-bno055.data.quat", + streamIdentifier, 4, sampleRate, "Quaternion", ContinuousChannel::Type::AUX, bitVolts, "u", - { "W", "X", "Y", "Z" }); + { "W", "X", "Y", "Z" }, + "quaternion", + { "w", "x", "y", "z" } + ); streamInfos.add(quaternionStream); StreamInfo accelerationStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Acceleration" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Acceleration", - "onix-bno055.data.acc", + streamIdentifier, 3, sampleRate, "Acceleration", ContinuousChannel::Type::AUX, bitVolts, "m / s ^ 2", - { "X", "Y", "Z" }); + { "X", "Y", "Z" }, + "acceleration", + { "x","y","z" } + ); streamInfos.add(accelerationStream); StreamInfo gravityStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Gravity" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Gravity", - "onix-bno055.data.grav", + streamIdentifier + ".gravity", 3, sampleRate, "Gravity", ContinuousChannel::Type::AUX, bitVolts, "m/s^2", - { "X", "Y", "Z" }); + { "X", "Y", "Z" }, + "gravity", + { "x", "y", "z" } + ); streamInfos.add(gravityStream); StreamInfo temperatureStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Temperature" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Temperature", - "onix-bno055.data.temp", + streamIdentifier, 1, sampleRate, "Temperature", ContinuousChannel::Type::AUX, bitVolts, "Celsius", - { "" }); + { "" }, + "temperature" + ); streamInfos.add(temperatureStream); // TODO: Add calibration stream here? diff --git a/Source/Devices/DigitalIO.cpp b/Source/Devices/DigitalIO.cpp index 8685ba2..6842510 100644 --- a/Source/Devices/DigitalIO.cpp +++ b/Source/Devices/DigitalIO.cpp @@ -59,7 +59,7 @@ EventChannel::Settings DigitalIO::getEventChannelSettings() EventChannel::Type::TTL, OnixDevice::createStreamName({getHeadstageName(), getName(), "Events"}), "Digital inputs and breakout button states coming from a DigitalIO device", - "onix-digitalio.events", + getStreamIdentifier() + ".event.digital", nullptr, numButtons + numDigitalInputs }; diff --git a/Source/Devices/HarpSyncInput.cpp b/Source/Devices/HarpSyncInput.cpp index e7ec571..1f3c693 100644 --- a/Source/Devices/HarpSyncInput.cpp +++ b/Source/Devices/HarpSyncInput.cpp @@ -30,14 +30,16 @@ HarpSyncInput::HarpSyncInput(String name, const oni_dev_idx_t deviceIdx_, std::s StreamInfo harpTimeStream = StreamInfo( OnixDevice::createStreamName({ getHeadstageName(), getName(), "HarpTime" }), "Harp clock time corresponding to the local acquisition ONIX clock count", - "onix-harpsyncinput.data.harptime", + getStreamIdentifier(), 1, 1, "HarpTime", ContinuousChannel::Type::AUX, 1.0f, "s", - {""}); + { "" }, + "harptime" + ); streamInfos.add(harpTimeStream); for (int i = 0; i < numFrames; i++) diff --git a/Source/Devices/MemoryMonitor.cpp b/Source/Devices/MemoryMonitor.cpp index 6fc5da7..ecd888d 100644 --- a/Source/Devices/MemoryMonitor.cpp +++ b/Source/Devices/MemoryMonitor.cpp @@ -61,14 +61,16 @@ MemoryMonitor::MemoryMonitor(String name, const oni_dev_idx_t deviceIdx_, std::s StreamInfo percentUsedStream = StreamInfo( OnixDevice::createStreamName({ getHeadstageName(), getName(), "PercentUsed" }), "Percent of available memory that is currently used", - "onix - memorymonitor.data.percentused", + getStreamIdentifier(), 1, samplesPerSecond, "Percent", ContinuousChannel::Type::AUX, 1.0f, "%", - { "" }); + { "" }, + "percent" + ); streamInfos.add(percentUsedStream); for (int i = 0; i < numFrames; i++) diff --git a/Source/Devices/Neuropixels2e.cpp b/Source/Devices/Neuropixels2e.cpp index e8b10d7..30316ee 100644 --- a/Source/Devices/Neuropixels2e.cpp +++ b/Source/Devices/Neuropixels2e.cpp @@ -44,14 +44,16 @@ void Neuropixels2e::createDataStream(int n) StreamInfo apStream = StreamInfo( OnixDevice::createStreamName({ PortController::getPortName(PortController::getPortFromIndex(deviceIdx)), getHeadstageName(), "Probe" + String(n) }), "Neuropixels 2.0 data stream", - "onix-neuropixels2.data", + getStreamIdentifier(), numberOfChannels, sampleRate, "CH", ContinuousChannel::Type::ELECTRODE, 0.195f, CharPointer_UTF8("\xc2\xb5V"), - {}); + {}, + "ap" + ); streamInfos.add(apStream); } diff --git a/Source/Devices/Neuropixels_1.cpp b/Source/Devices/Neuropixels_1.cpp index 91f31ef..2901a48 100644 --- a/Source/Devices/Neuropixels_1.cpp +++ b/Source/Devices/Neuropixels_1.cpp @@ -174,30 +174,36 @@ Neuropixels_1::Neuropixels_1(String name, const oni_dev_idx_t deviceIdx_, std::s INeuropixel(NeuropixelsV1fValues::numberOfSettings, NeuropixelsV1fValues::numberOfShanks) { String port = PortController::getPortName(PortController::getPortFromIndex(deviceIdx)); + auto streamIdentifier = getStreamIdentifier(); + StreamInfo apStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "AP" }), "Neuropixels 1.0 AP band data stream", - "onix-neuropixels1.data.ap", + streamIdentifier, numberOfChannels, apSampleRate, "AP", ContinuousChannel::Type::ELECTRODE, 0.195f, CharPointer_UTF8("\xc2\xb5V"), - {}); + {}, + "ap" + ); streamInfos.add(apStream); StreamInfo lfpStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "LFP" }), "Neuropixels 1.0 LFP band data stream", - "onix-neuropixels1.data.lfp", + streamIdentifier, numberOfChannels, lfpSampleRate, "LFP", ContinuousChannel::Type::ELECTRODE, 0.195f, CharPointer_UTF8("\xc2\xb5V"), - {}); + {}, + "lfp" + ); streamInfos.add(lfpStream); defineMetadata(settings[0].get()); diff --git a/Source/Devices/PolledBno055.cpp b/Source/Devices/PolledBno055.cpp index 4936f02..6a588e0 100644 --- a/Source/Devices/PolledBno055.cpp +++ b/Source/Devices/PolledBno055.cpp @@ -28,83 +28,101 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ { const float bitVolts = 1.0; + auto streamIdentifier = getStreamIdentifier(); + String port = PortController::getPortName(PortController::getPortFromIndex(deviceIdx)); StreamInfo eulerAngleStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Euler" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Euler angle", - "onix-bno055.data.euler", + streamIdentifier, 3, sampleRate, "Euler", ContinuousChannel::Type::AUX, bitVolts, "Degrees", - { "Yaw", "Roll", "Pitch" }); + { "Yaw", "Roll", "Pitch" }, + "euler", + { "y", "r", "p" } + ); streamInfos.add(eulerAngleStream); StreamInfo quaternionStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Quaternion" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Quaternion", - "onix-bno055.data.quat", + streamIdentifier, 4, sampleRate, "Quaternion", ContinuousChannel::Type::AUX, bitVolts, "", - { "W", "X", "Y", "Z" }); + { "W", "X", "Y", "Z" }, + "quaternion", + { "w", "x", "y", "z" } + ); streamInfos.add(quaternionStream); StreamInfo accelerationStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Acceleration" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Acceleration", - "onix-bno055.data.acc", + streamIdentifier, 3, sampleRate, "Acceleration", ContinuousChannel::Type::AUX, bitVolts, "m / s ^ 2", - { "X", "Y", "Z" }); + { "X", "Y", "Z" }, + "acceleration", + { "x","y","z" } + ); streamInfos.add(accelerationStream); StreamInfo gravityStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Gravity" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Gravity", - "onix-bno055.data.grav", + streamIdentifier, 3, sampleRate, "Gravity", ContinuousChannel::Type::AUX, bitVolts, "m/s^2", - { "X", "Y", "Z" }); + { "X", "Y", "Z" }, + "gravity", + { "x", "y", "z" } + ); streamInfos.add(gravityStream); StreamInfo temperatureStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Temperature" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Temperature", - "onix-bno055.data.temp", + streamIdentifier, 1, sampleRate, "Temperature", ContinuousChannel::Type::AUX, bitVolts, "Celsius", - { "" }); + { "" }, + "temperature" + ); streamInfos.add(temperatureStream); StreamInfo calibrationStatusStream = StreamInfo( OnixDevice::createStreamName({ port, getHeadstageName(), getName(), "Calibration" }), "Bosch Bno055 9-axis inertial measurement unit (IMU) Calibration", - "onix-bno055.data.cal", + streamIdentifier, 1, sampleRate, "Calibration", ContinuousChannel::Type::AUX, bitVolts, "", - { "" }); + { "" }, + "calibration" + ); streamInfos.add(calibrationStatusStream); for (int i = 0; i < numFrames; i++) diff --git a/Source/OnixDevice.cpp b/Source/OnixDevice.cpp index 9d84f71..8761ac3 100644 --- a/Source/OnixDevice.cpp +++ b/Source/OnixDevice.cpp @@ -50,3 +50,59 @@ oni_dev_idx_t OnixDevice::getDeviceIndexFromPassthroughIndex(oni_dev_idx_t passt return idx; } + +OnixDeviceType OnixDevice::getDeviceType() const +{ + return type; +} + +String OnixDevice::getStreamIdentifier() +{ + String streamIdentifier = "onix."; + + // Insert the headstage or breakout board + if (getHeadstageName() == NEUROPIXELSV1F_HEADSTAGE_NAME) + { + streamIdentifier += "npx1f."; + } + else if (getHeadstageName() == NEUROPIXELSV2E_HEADSTAGE_NAME) + { + streamIdentifier += "npx2e."; + } + else if (getHeadstageName() == BREAKOUT_BOARD_NAME) + { + streamIdentifier += "breakout."; + } + + // Insert the device + if (getDeviceType() == OnixDeviceType::ANALOGIO) + { + streamIdentifier += "analogio"; + } + else if (getDeviceType() == OnixDeviceType::BNO || getDeviceType() == OnixDeviceType::POLLEDBNO) + { + streamIdentifier += "9dof"; + } + else if (getDeviceType() == OnixDeviceType::DIGITALIO) + { + streamIdentifier += "digitalio"; + } + else if (getDeviceType() == OnixDeviceType::HARPSYNCINPUT) + { + streamIdentifier += "harp"; + } + else if (getDeviceType() == OnixDeviceType::MEMORYMONITOR) + { + streamIdentifier += "memory"; + } + else if (getDeviceType() == OnixDeviceType::NEUROPIXELS_1) + { + streamIdentifier += "npx1f"; + } + else if (getDeviceType() == OnixDeviceType::NEUROPIXELSV2E) + { + streamIdentifier += "npx2e"; + } + + return streamIdentifier; +} diff --git a/Source/OnixDevice.h b/Source/OnixDevice.h index b7e02a1..da1721e 100644 --- a/Source/OnixDevice.h +++ b/Source/OnixDevice.h @@ -42,12 +42,10 @@ enum class PortName }; enum class OnixDeviceType { - HS64, BNO, POLLEDBNO, NEUROPIXELS_1, NEUROPIXELSV2E, - ADC, PORT_CONTROL, MEMORYMONITOR, OUTPUTCLOCK, @@ -59,71 +57,88 @@ enum class OnixDeviceType { struct StreamInfo { public: - StreamInfo() - { - name_ = "name"; - description_ = "description"; - identifier_ = "identifier"; - numChannels_ = 0; - sampleRate_ = 0; - channelPrefix_ = "channelPrefix"; - channelType_ = ContinuousChannel::Type::INVALID; - bitVolts_ = 1.0f; - units_ = "units"; - suffixes_ = { "suffixes" }; - } + StreamInfo() {} - StreamInfo(String name, String description, String identifier, int numChannels, float sampleRate, String channelPrefix, ContinuousChannel::Type channelType, - float bitVolts, String units, StringArray suffixes) + StreamInfo(String name, String description, String streamIdentifier, int numChannels, float sampleRate, String channelPrefix, ContinuousChannel::Type channelType, + float bitVolts, String units, StringArray channelNameSuffixes, String channelIdentifierDataType, StringArray channelIdentifierSubTypes = {}) { - name_ = name; - description_ = description; - identifier_ = identifier; - numChannels_ = numChannels; - sampleRate_ = sampleRate; - channelPrefix_ = channelPrefix; - channelType_ = channelType; - bitVolts_ = bitVolts; - units_ = units; - suffixes_ = suffixes; - - if (numChannels_ != suffixes_.size()) + m_name = name; + m_description = description; + m_streamIdentifier = streamIdentifier; + m_numChannels = numChannels; + m_sampleRate = sampleRate; + m_channelPrefix = channelPrefix; + m_channelType = channelType; + m_bitVolts = bitVolts; + m_units = units; + m_channelNameSuffixes = channelNameSuffixes; + m_channelIdentifierDataType = channelIdentifierDataType; + m_channelIdentifierSubTypes = channelIdentifierSubTypes; + + if (m_numChannels != m_channelNameSuffixes.size()) { - if (suffixes_.size() != 0) - LOGE("Difference between number of channels and suffixes. Generating default suffixes instead."); + if (m_channelNameSuffixes.size() != 0) + LOGE("Difference between number of channels and channel name suffixes. Generating default suffixes instead."); + + m_channelNameSuffixes.clear(); + m_channelNameSuffixes.ensureStorageAllocated(numChannels); - suffixes_.clear(); - suffixes_.ensureStorageAllocated(numChannels); - - for (int i = 0; i < numChannels_; i += 1) + for (int i = 0; i < m_numChannels; i += 1) + { + m_channelNameSuffixes.add(String(i + 1)); + } + } + + if (m_channelIdentifierSubTypes.size() > 0 && m_numChannels != m_channelIdentifierSubTypes.size()) + { + if (m_channelIdentifierSubTypes.size() == 1) + { + for (int i = 1; i < m_numChannels; i++) + { + m_channelIdentifierSubTypes.add(m_channelIdentifierSubTypes[0]); + } + } + else { - suffixes_.add(String(i + 1)); + LOGE("Difference between number of channels and channel identifier subtypes. Generating default subtypes instead."); + + m_channelIdentifierSubTypes.clear(); + m_channelIdentifierSubTypes.ensureStorageAllocated(numChannels); + + for (int i = 0; i < m_numChannels; i += 1) + { + m_channelIdentifierSubTypes.add(String(i + 1)); + } } } }; - String getName() const { return name_; } - String getDescription() const { return description_; } - String getIdentifier() const { return identifier_; } - int getNumChannels() const { return numChannels_; } - float getSampleRate() const { return sampleRate_; } - String getChannelPrefix() const { return channelPrefix_; } - ContinuousChannel::Type getChannelType() const { return channelType_; } - float getBitVolts() const { return bitVolts_; } - String getUnits() const { return units_; } - StringArray getSuffixes() const { return suffixes_; } + String getName() const { return m_name; } + String getDescription() const { return m_description; } + String getStreamIdentifier() const { return m_streamIdentifier; } + int getNumChannels() const { return m_numChannels; } + float getSampleRate() const { return m_sampleRate; } + String getChannelPrefix() const { return m_channelPrefix; } + ContinuousChannel::Type getChannelType() const { return m_channelType; } + float getBitVolts() const { return m_bitVolts; } + String getUnits() const { return m_units; } + StringArray getChannelNameSuffixes() const { return m_channelNameSuffixes; } + String getChannelIdentifierDataType() const { return m_channelIdentifierDataType; } + StringArray getChannelIdentifierSubTypes() const { return m_channelIdentifierSubTypes; } private: - String name_; - String description_; - String identifier_; - int numChannels_; - float sampleRate_; - String channelPrefix_; - ContinuousChannel::Type channelType_; - float bitVolts_; - String units_; - StringArray suffixes_; + String m_name = "name"; + String m_description = "description"; + String m_streamIdentifier = "identifier"; + int m_numChannels = 0; + float m_sampleRate = 0; + String m_channelPrefix = "channelPrefix"; + ContinuousChannel::Type m_channelType = ContinuousChannel::Type::INVALID; + float m_bitVolts = 1.0f; + String m_units = "units"; + StringArray m_channelNameSuffixes = { "suffixes" }; + String m_channelIdentifierDataType = "datatype"; + StringArray m_channelIdentifierSubTypes = { "subtypes" }; }; /** @@ -179,8 +194,6 @@ class OnixDevice return streamName; } - const OnixDeviceType type; - Array streamInfos; const int bufferSizeInSeconds = 10; @@ -188,6 +201,11 @@ class OnixDevice String getHeadstageName() { return m_headstageName; } void setHeadstageName(String headstage) { m_headstageName = headstage; } + OnixDeviceType getDeviceType() const; + + /** Returns a string for this device that follows the pattern: onix.[headstage|breakout].[device] */ + String getStreamIdentifier(); + protected: oni_dev_idx_t getDeviceIndexFromPassthroughIndex(oni_dev_idx_t hubIndex); @@ -204,6 +222,8 @@ class OnixDevice String m_headstageName; + const OnixDeviceType type; + JUCE_LEAK_DETECTOR(OnixDevice); }; diff --git a/Source/OnixSource.cpp b/Source/OnixSource.cpp index 13315c2..337a4c2 100644 --- a/Source/OnixSource.cpp +++ b/Source/OnixSource.cpp @@ -404,7 +404,7 @@ std::shared_ptr OnixSource::getDevice(OnixDeviceType type) { for (const auto& device : sources) { - if (device->type == type) return device; + if (device->getDeviceType() == type) return device; } return nullptr; @@ -416,9 +416,9 @@ std::map OnixSource::createDeviceMap(OnixDeviceVector devic for (const auto& device : devices) { - if (filterDevices && (device->type == OnixDeviceType::HEARTBEAT || device->type == OnixDeviceType::MEMORYMONITOR)) continue; + if (filterDevices && (device->getDeviceType() == OnixDeviceType::HEARTBEAT || device->getDeviceType() == OnixDeviceType::MEMORYMONITOR)) continue; - deviceMap.insert({ device->getDeviceIdx(), device->type }); + deviceMap.insert({ device->getDeviceIdx(), device->getDeviceType() }); } return deviceMap; @@ -543,7 +543,7 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel { if (!source->isEnabled()) continue; - if (source->type == OnixDeviceType::NEUROPIXELS_1) + if (source->getDeviceType() == OnixDeviceType::NEUROPIXELS_1) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -557,7 +557,7 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel addIndividualStreams(source->streamInfos, dataStreams, deviceInfos, continuousChannels); } - else if (source->type == OnixDeviceType::BNO || source->type == OnixDeviceType::POLLEDBNO) + else if (source->getDeviceType() == OnixDeviceType::BNO || source->getDeviceType() == OnixDeviceType::POLLEDBNO) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -572,13 +572,13 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel DataStream::Settings dataStreamSettings{ OnixDevice::createStreamName({PortController::getPortName(PortController::getPortFromIndex(source->getDeviceIdx())), source->getHeadstageName(), source->getName()}), "Continuous data from a Bno055 9-axis IMU", - "onix-bno055.data", + source->getStreamIdentifier(), source->streamInfos[0].getSampleRate() }; addCombinedStreams(dataStreamSettings, source->streamInfos, dataStreams, deviceInfos, continuousChannels); } - else if (source->type == OnixDeviceType::NEUROPIXELSV2E) + else if (source->getDeviceType() == OnixDeviceType::NEUROPIXELSV2E) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -592,7 +592,7 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel addIndividualStreams(source->streamInfos, dataStreams, deviceInfos, continuousChannels); } - else if (source->type == OnixDeviceType::MEMORYMONITOR) + else if (source->getDeviceType() == OnixDeviceType::MEMORYMONITOR) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -615,7 +615,7 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel std::static_pointer_cast(source)->setDigitalIO(digitalIO); } } - else if (source->type == OnixDeviceType::ANALOGIO) + else if (source->getDeviceType() == OnixDeviceType::ANALOGIO) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -629,7 +629,7 @@ void OnixSource::updateSettings(OwnedArray* continuousChannel addIndividualStreams(source->streamInfos, dataStreams, deviceInfos, continuousChannels); } - else if (source->type == OnixDeviceType::HARPSYNCINPUT) + else if (source->getDeviceType() == OnixDeviceType::HARPSYNCINPUT) { DeviceInfo::Settings deviceSettings{ source->getName(), @@ -663,9 +663,9 @@ void OnixSource::addCombinedStreams(DataStream::Settings dataStreamSettings, { ContinuousChannel::Settings channelSettings{ streamInfo.getChannelType(), - streamInfo.getChannelPrefix() + streamInfo.getSuffixes()[chan], + streamInfo.getChannelPrefix() + streamInfo.getChannelNameSuffixes()[chan], streamInfo.getDescription(), - streamInfo.getIdentifier(), + createContinuousChannelIdentifier(streamInfo, chan), streamInfo.getBitVolts(), stream }; @@ -686,7 +686,7 @@ void OnixSource::addIndividualStreams(Array streamInfos, { streamInfo.getName(), streamInfo.getDescription(), - streamInfo.getIdentifier(), + streamInfo.getStreamIdentifier(), streamInfo.getSampleRate() }; @@ -694,14 +694,16 @@ void OnixSource::addIndividualStreams(Array streamInfos, dataStreams->add(stream); stream->device = deviceInfos->getLast(); + auto suffixes = streamInfo.getChannelNameSuffixes(); + // Add continuous channels for (int chan = 0; chan < streamInfo.getNumChannels(); chan++) { ContinuousChannel::Settings channelSettings{ streamInfo.getChannelType(), - streamInfo.getChannelPrefix() + streamInfo.getSuffixes()[chan], + streamInfo.getChannelPrefix() + suffixes[chan], streamInfo.getDescription(), - streamInfo.getIdentifier(), + createContinuousChannelIdentifier(streamInfo, chan), streamInfo.getBitVolts(), stream }; @@ -711,6 +713,21 @@ void OnixSource::addIndividualStreams(Array streamInfos, } } +String OnixSource::createContinuousChannelIdentifier(StreamInfo streamInfo, int channelNumber) +{ + auto dataType = streamInfo.getChannelIdentifierDataType(); + auto subTypes = streamInfo.getChannelIdentifierSubTypes(); + + auto channelIdentifier = streamInfo.getStreamIdentifier() + ".continuous." + dataType; + + if (subTypes.size() == streamInfo.getNumChannels()) + channelIdentifier += "." + subTypes[channelNumber]; + else if (subTypes.size() == 1) + channelIdentifier += "." + subTypes[0]; + + return channelIdentifier; +} + bool OnixSource::isDevicesReady() { auto tabMap = editor->createTabMapFromCanvas(); diff --git a/Source/OnixSource.h b/Source/OnixSource.h index 99ffbf1..df72b1f 100644 --- a/Source/OnixSource.h +++ b/Source/OnixSource.h @@ -150,5 +150,7 @@ class OnixSource : public DataThread void addCombinedStreams(DataStream::Settings, Array, OwnedArray*, OwnedArray*, OwnedArray*); + String createContinuousChannelIdentifier(StreamInfo streamInfo, int channelNumber); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OnixSource); }; diff --git a/Source/OnixSourceCanvas.cpp b/Source/OnixSourceCanvas.cpp index 072f4d2..4e526d4 100644 --- a/Source/OnixSourceCanvas.cpp +++ b/Source/OnixSourceCanvas.cpp @@ -91,42 +91,42 @@ void OnixSourceCanvas::populateSourceTabs(CustomTabComponent* tab, OnixDeviceVec for (const auto& device : devices) { - if (device->type == OnixDeviceType::NEUROPIXELS_1) + if (device->getDeviceType() == OnixDeviceType::NEUROPIXELS_1) { auto neuropixInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, neuropixInterface); } - else if (device->type == OnixDeviceType::BNO) + else if (device->getDeviceType() == OnixDeviceType::BNO) { auto bno055Interface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, bno055Interface); } - else if (device->type == OnixDeviceType::OUTPUTCLOCK) + else if (device->getDeviceType() == OnixDeviceType::OUTPUTCLOCK) { auto outputClockInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, outputClockInterface); } - else if (device->type == OnixDeviceType::HARPSYNCINPUT) + else if (device->getDeviceType() == OnixDeviceType::HARPSYNCINPUT) { auto harpSyncInputInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, harpSyncInputInterface); } - else if (device->type == OnixDeviceType::ANALOGIO) + else if (device->getDeviceType() == OnixDeviceType::ANALOGIO) { auto analogIOInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, analogIOInterface); } - else if (device->type == OnixDeviceType::DIGITALIO) + else if (device->getDeviceType() == OnixDeviceType::DIGITALIO) { auto digitalIOInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, digitalIOInterface); } - else if (device->type == OnixDeviceType::NEUROPIXELSV2E) + else if (device->getDeviceType() == OnixDeviceType::NEUROPIXELSV2E) { auto npxv2eInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getHeadstageName(), tab, npxv2eInterface); } - else if (device->type == OnixDeviceType::POLLEDBNO) + else if (device->getDeviceType() == OnixDeviceType::POLLEDBNO) { auto polledBnoInterface = std::make_shared(std::static_pointer_cast(device), editor, this); addInterfaceToTab(device->getName(), tab, polledBnoInterface); @@ -168,13 +168,13 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrtype != OnixDeviceType::MEMORYMONITOR && device->type != OnixDeviceType::HEARTBEAT) + if (device->getDeviceType() != OnixDeviceType::MEMORYMONITOR && device->getDeviceType() != OnixDeviceType::HEARTBEAT) LOGD("Unable to match " + device->getName() + " to an open tab."); return; } - if (device->type == OnixDeviceType::NEUROPIXELS_1) + if (device->getDeviceType() == OnixDeviceType::NEUROPIXELS_1) { auto npx1Found = std::static_pointer_cast(device); auto npx1Selected = std::static_pointer_cast(settingsInterfaces[ind]->device); @@ -183,7 +183,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrgainCalibrationFilePath = npx1Selected->gainCalibrationFilePath; npx1Found->setCorrectOffset(npx1Selected->getCorrectOffset()); } - else if (device->type == OnixDeviceType::OUTPUTCLOCK) + else if (device->getDeviceType() == OnixDeviceType::OUTPUTCLOCK) { auto outputClockFound = std::static_pointer_cast(device); auto outputClockSelected = std::static_pointer_cast(settingsInterfaces[ind]->device); @@ -192,7 +192,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrsetFrequencyHz(outputClockSelected->getFrequencyHz()); outputClockFound->setGateRun(outputClockSelected->getGateRun()); } - else if (device->type == OnixDeviceType::ANALOGIO) + else if (device->getDeviceType() == OnixDeviceType::ANALOGIO) { auto analogIOFound = std::static_pointer_cast(device); auto analogIOSelected = std::static_pointer_cast(settingsInterfaces[ind]->device); @@ -201,7 +201,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrsetChannelDirection(i, analogIOSelected->getChannelDirection(i)); } } - else if (device->type == OnixDeviceType::NEUROPIXELSV2E) + else if (device->getDeviceType() == OnixDeviceType::NEUROPIXELSV2E) { auto npx2Found = std::static_pointer_cast(device); auto npx2Selected = std::static_pointer_cast(settingsInterfaces[ind]->device); @@ -293,7 +293,7 @@ std::map OnixSourceCanvas::createSelectedMap(std::vectordevice->getDeviceIdx(), settings->device->type }); + tabMap.insert({ settings->device->getDeviceIdx(), settings->device->getDeviceType() }); } return tabMap; diff --git a/Source/OnixSourceEditor.cpp b/Source/OnixSourceEditor.cpp index 963c7a0..aa34ea6 100644 --- a/Source/OnixSourceEditor.cpp +++ b/Source/OnixSourceEditor.cpp @@ -334,7 +334,7 @@ void OnixSourceEditor::startAcquisition() for (const auto& source : source->getDataSources()) { - if (source->type == OnixDeviceType::MEMORYMONITOR) + if (source->getDeviceType() == OnixDeviceType::MEMORYMONITOR) { memoryUsage->setMemoryMonitor(std::static_pointer_cast(source)); memoryUsage->startAcquisition(); @@ -350,7 +350,7 @@ void OnixSourceEditor::stopAcquisition() for (const auto& source : source->getDataSources()) { - if (source->type == OnixDeviceType::MEMORYMONITOR) + if (source->getDeviceType() == OnixDeviceType::MEMORYMONITOR) { memoryUsage->stopAcquisition(); break; From 8c09e5d7a4a48cfd159aeb83a213c098f49a4a72 Mon Sep 17 00:00:00 2001 From: bparks13 Date: Mon, 28 Apr 2025 13:35:11 -0400 Subject: [PATCH 3/5] Ensure bitVolts are correctly set --- Source/Devices/AnalogIO.cpp | 16 ++++++++-------- Source/Devices/Bno055.cpp | 24 +++++++++++------------- Source/Devices/PolledBno055.cpp | 14 ++++++-------- Source/OnixDevice.h | 4 ++-- Source/UI/AnalogIOInterface.cpp | 4 ++-- 5 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Source/Devices/AnalogIO.cpp b/Source/Devices/AnalogIO.cpp index f3ec655..7580aee 100644 --- a/Source/Devices/AnalogIO.cpp +++ b/Source/Devices/AnalogIO.cpp @@ -33,7 +33,7 @@ AnalogIO::AnalogIO(String name, const oni_dev_idx_t deviceIdx_, std::shared_ptr< std::floor(AnalogIOFrequencyHz / framesToAverage), "AnalogInput", ContinuousChannel::Type::ADC, - 20.0f / numberOfDivisions, // NB: +/- 10 Volts + getVoltsPerDivision(AnalogIOVoltageRange::TenVolts), // NB: +/- 10 Volts "V", {}, { "input" }); @@ -42,7 +42,7 @@ AnalogIO::AnalogIO(String name, const oni_dev_idx_t deviceIdx_, std::shared_ptr< for (int i = 0; i < numFrames; i++) eventCodes[i] = 0; - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { channelDirection[i] = AnalogIODirection::Input; channelVoltageRange[i] = AnalogIOVoltageRange::TenVolts; @@ -62,7 +62,7 @@ bool AnalogIO::updateSettings() { int rc = 0; - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { rc = deviceContext->writeRegister(deviceIdx, (oni_reg_addr_t)AnalogIORegisters::CH00_IN_RANGE + i, (oni_reg_val_t)channelVoltageRange[i]); if (rc != ONI_ESUCCESS) return false; @@ -70,7 +70,7 @@ bool AnalogIO::updateSettings() uint32_t ioReg = 0; - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { ioReg = (ioReg & ~((uint32_t)1 << i)) | ((uint32_t)(channelDirection[i]) << i); } @@ -78,7 +78,7 @@ bool AnalogIO::updateSettings() rc = deviceContext->writeRegister(deviceIdx, (oni_reg_addr_t)AnalogIORegisters::CHDIR, ioReg); if (rc != ONI_ESUCCESS) return false; - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { voltsPerDivision[i] = getVoltsPerDivision(channelVoltageRange[i]); } @@ -147,7 +147,7 @@ void AnalogIO::processFrames() int dataOffset = 4; - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { if (dataType == AnalogIODataType::S16) analogInputSamples[currentFrame + i * numFrames] += *(dataPtr + dataOffset + i); @@ -155,11 +155,11 @@ void AnalogIO::processFrames() analogInputSamples[currentFrame + i * numFrames] += *(dataPtr + dataOffset + i) * voltsPerDivision[i]; } - currentAverageFrame += 1; + currentAverageFrame++; if (currentAverageFrame >= framesToAverage) { - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { analogInputSamples[currentFrame + i * numFrames] /= framesToAverage; } diff --git a/Source/Devices/Bno055.cpp b/Source/Devices/Bno055.cpp index a3ad8cd..b117e6e 100644 --- a/Source/Devices/Bno055.cpp +++ b/Source/Devices/Bno055.cpp @@ -25,8 +25,6 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_, std::shared_ptr ctx) : OnixDevice(name, headstageName, OnixDeviceType::BNO, deviceIdx_, ctx) { - const float bitVolts = 1.0; - auto streamIdentifier = getStreamIdentifier(); String port = PortController::getPortName(PortController::getPortFromIndex(deviceIdx)); @@ -38,7 +36,7 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ sampleRate, "Euler", ContinuousChannel::Type::AUX, - bitVolts, + eulerAngleScale, "Degrees", { "Yaw", "Roll", "Pitch" }, "euler", @@ -54,8 +52,8 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ sampleRate, "Quaternion", ContinuousChannel::Type::AUX, - bitVolts, - "u", + quaternionScale, + "u", // NB: Quaternion data is unitless by definition { "W", "X", "Y", "Z" }, "quaternion", { "w", "x", "y", "z" } @@ -70,8 +68,8 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ sampleRate, "Acceleration", ContinuousChannel::Type::AUX, - bitVolts, - "m / s ^ 2", + accelerationScale, + "m/s^2", { "X", "Y", "Z" }, "acceleration", { "x","y","z" } @@ -86,7 +84,7 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ sampleRate, "Gravity", ContinuousChannel::Type::AUX, - bitVolts, + accelerationScale, "m/s^2", { "X", "Y", "Z" }, "gravity", @@ -102,7 +100,7 @@ Bno055::Bno055(String name, String headstageName, const oni_dev_idx_t deviceIdx_ sampleRate, "Temperature", ContinuousChannel::Type::AUX, - bitVolts, + 1.0f, "Celsius", { "" }, "temperature" @@ -178,7 +176,7 @@ void Bno055::processFrames() { bnoSamples[currentFrame + channelOffset * numFrames] = float(*(dataPtr + dataOffset)) * eulerAngleScale; dataOffset++; - channelOffset += 1; + channelOffset++; } // Quaternion @@ -186,7 +184,7 @@ void Bno055::processFrames() { bnoSamples[currentFrame + channelOffset * numFrames] = float(*(dataPtr + dataOffset)) * quaternionScale; dataOffset++; - channelOffset += 1; + channelOffset++; } // Acceleration @@ -194,7 +192,7 @@ void Bno055::processFrames() { bnoSamples[currentFrame + channelOffset * numFrames] = float(*(dataPtr + dataOffset)) * accelerationScale; dataOffset++; - channelOffset += 1; + channelOffset++; } // Gravity @@ -202,7 +200,7 @@ void Bno055::processFrames() { bnoSamples[currentFrame + channelOffset * numFrames] = float(*(dataPtr + dataOffset)) * accelerationScale; dataOffset++; - channelOffset += 1; + channelOffset++; } // Temperature diff --git a/Source/Devices/PolledBno055.cpp b/Source/Devices/PolledBno055.cpp index 6a588e0..ce6360a 100644 --- a/Source/Devices/PolledBno055.cpp +++ b/Source/Devices/PolledBno055.cpp @@ -26,8 +26,6 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ : OnixDevice(name, headstageName, OnixDeviceType::POLLEDBNO, deviceIdx_, ctx), I2CRegisterContext(Bno055Address, deviceIdx_, ctx) { - const float bitVolts = 1.0; - auto streamIdentifier = getStreamIdentifier(); String port = PortController::getPortName(PortController::getPortFromIndex(deviceIdx)); @@ -39,7 +37,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Euler", ContinuousChannel::Type::AUX, - bitVolts, + eulerAngleScale, "Degrees", { "Yaw", "Roll", "Pitch" }, "euler", @@ -55,7 +53,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Quaternion", ContinuousChannel::Type::AUX, - bitVolts, + quaternionScale, "", { "W", "X", "Y", "Z" }, "quaternion", @@ -71,7 +69,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Acceleration", ContinuousChannel::Type::AUX, - bitVolts, + accelerationScale, "m / s ^ 2", { "X", "Y", "Z" }, "acceleration", @@ -87,7 +85,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Gravity", ContinuousChannel::Type::AUX, - bitVolts, + accelerationScale, "m/s^2", { "X", "Y", "Z" }, "gravity", @@ -103,7 +101,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Temperature", ContinuousChannel::Type::AUX, - bitVolts, + 1.0f, "Celsius", { "" }, "temperature" @@ -118,7 +116,7 @@ PolledBno055::PolledBno055(String name, String headstageName, const oni_dev_idx_ sampleRate, "Calibration", ContinuousChannel::Type::AUX, - bitVolts, + 1.0f, "", { "" }, "calibration" diff --git a/Source/OnixDevice.h b/Source/OnixDevice.h index da1721e..2d45a3e 100644 --- a/Source/OnixDevice.h +++ b/Source/OnixDevice.h @@ -83,7 +83,7 @@ struct StreamInfo { m_channelNameSuffixes.clear(); m_channelNameSuffixes.ensureStorageAllocated(numChannels); - for (int i = 0; i < m_numChannels; i += 1) + for (int i = 0; i < m_numChannels; i++) { m_channelNameSuffixes.add(String(i + 1)); } @@ -105,7 +105,7 @@ struct StreamInfo { m_channelIdentifierSubTypes.clear(); m_channelIdentifierSubTypes.ensureStorageAllocated(numChannels); - for (int i = 0; i < m_numChannels; i += 1) + for (int i = 0; i < m_numChannels; i++) { m_channelIdentifierSubTypes.add(String(i + 1)); } diff --git a/Source/UI/AnalogIOInterface.cpp b/Source/UI/AnalogIOInterface.cpp index 7d304c0..88af59c 100644 --- a/Source/UI/AnalogIOInterface.cpp +++ b/Source/UI/AnalogIOInterface.cpp @@ -55,7 +55,7 @@ AnalogIOInterface::AnalogIOInterface(std::shared_ptr d, OnixSourceEdit voltageRangeList.add("+/- 5.0 V"); voltageRangeList.add("+/- 10.0 V"); - for (int i = 0; i < numChannels; i += 1) + for (int i = 0; i < numChannels; i++) { channelDirectionLabels[i] = std::make_unique