diff --git a/Source/Devices/AnalogIO.cpp b/Source/Devices/AnalogIO.cpp index 0e47eee..ba5138d 100644 --- a/Source/Devices/AnalogIO.cpp +++ b/Source/Devices/AnalogIO.cpp @@ -165,7 +165,7 @@ void AnalogIO::processFrames() currentAverageFrame = 0; - timestamps[currentFrame] = frame->time; + timestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time); sampleNumbers[currentFrame] = sampleNumber++; currentFrame++; diff --git a/Source/Devices/AnalogIO.h b/Source/Devices/AnalogIO.h index d74466a..e21eacb 100644 --- a/Source/Devices/AnalogIO.h +++ b/Source/Devices/AnalogIO.h @@ -99,6 +99,19 @@ class AnalogIO : public OnixDevice return channelDirection[channelNumber]; } + static String getChannelDirection(AnalogIODirection direction) + { + switch (direction) + { + case AnalogIODirection::Input: + return "Input"; + case AnalogIODirection::Output: + return "Output"; + default: + return ""; + } + } + void setChannelDirection(int channelNumber, AnalogIODirection direction) { if (channelNumber > numChannels || channelNumber < 0) @@ -121,21 +134,8 @@ class AnalogIO : public OnixDevice return channelVoltageRange[channelNumber]; } - void setChannelVoltageRange(int channelNumber, AnalogIOVoltageRange direction) - { - if (channelNumber > numChannels || channelNumber < 0) - { - LOGE("Channel number must be between 0 and " + String(channelNumber)); - return; - } - - channelVoltageRange[channelNumber] = direction; - } - AnalogIODataType getDataType() const { return dataType; } - void setDataType(AnalogIODataType type) { dataType = type; } - int getNumChannels() { return numChannels; } private: @@ -174,5 +174,18 @@ class AnalogIO : public OnixDevice static float getVoltsPerDivision(AnalogIOVoltageRange voltageRange); + void setChannelVoltageRange(int channelNumber, AnalogIOVoltageRange direction) + { + if (channelNumber > numChannels || channelNumber < 0) + { + LOGE("Channel number must be between 0 and " + String(channelNumber)); + return; + } + + channelVoltageRange[channelNumber] = direction; + } + + void setDataType(AnalogIODataType type) { dataType = type; } + JUCE_LEAK_DETECTOR(AnalogIO); }; diff --git a/Source/Devices/Bno055.cpp b/Source/Devices/Bno055.cpp index 636ee56..9fd92fa 100644 --- a/Source/Devices/Bno055.cpp +++ b/Source/Devices/Bno055.cpp @@ -151,7 +151,7 @@ void Bno055::processFrames() int16_t* dataPtr = (int16_t*)frame->data; - bnoTimestamps[currentFrame] = frame->time; + bnoTimestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time); int dataOffset = 4; diff --git a/Source/Devices/DigitalIO.cpp b/Source/Devices/DigitalIO.cpp index 8685ba2..5340024 100644 --- a/Source/Devices/DigitalIO.cpp +++ b/Source/Devices/DigitalIO.cpp @@ -82,7 +82,7 @@ void DigitalIO::processFrames() oni_frame_t* frame = frameArray.removeAndReturn(0); uint16_t* dataPtr = (uint16_t*)frame->data; - uint64_t timestamp = frame->time; + uint64_t timestamp = deviceContext->convertTimestampToSeconds(frame->time); int dataOffset = 4; diff --git a/Source/Devices/HarpSyncInput.cpp b/Source/Devices/HarpSyncInput.cpp index e7ec571..b9fd6c4 100644 --- a/Source/Devices/HarpSyncInput.cpp +++ b/Source/Devices/HarpSyncInput.cpp @@ -97,7 +97,7 @@ void HarpSyncInput::processFrames() uint32_t* dataPtr = (uint32_t*)frame->data; - timestamps[currentFrame] = frame->time; + timestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time); harpTimeSamples[currentFrame] = *(dataPtr + 2) + 1; diff --git a/Source/Devices/MemoryMonitor.cpp b/Source/Devices/MemoryMonitor.cpp index 6fc5da7..8229e31 100644 --- a/Source/Devices/MemoryMonitor.cpp +++ b/Source/Devices/MemoryMonitor.cpp @@ -147,9 +147,8 @@ void MemoryMonitor::processFrames() oni_frame_t* frame = frameArray.removeAndReturn(0); uint32_t* dataPtr = (uint32_t*)frame->data; - uint64_t timestamp = frame->time; - timestamps[currentFrame] = frame->time; + timestamps[currentFrame] = deviceContext->convertTimestampToSeconds(frame->time); percentUsedSamples[currentFrame] = 100.0f * float(*(dataPtr + 2)) / totalMemory; diff --git a/Source/Devices/Neuropixels2e.cpp b/Source/Devices/Neuropixels2e.cpp index e8b10d7..d733cce 100644 --- a/Source/Devices/Neuropixels2e.cpp +++ b/Source/Devices/Neuropixels2e.cpp @@ -621,7 +621,7 @@ void Neuropixels2e::processFrames() uint16_t* amplifierData = dataPtr + 9; sampleNumbers[frameCount] = sampleNumber; - timestamps[frameCount] = frame->time; + timestamps[frameCount] = deviceContext->convertTimestampToSeconds(frame->time); for (int i = 0; i < FramesPerSuperFrame; i++) { diff --git a/Source/Devices/Neuropixels_1.cpp b/Source/Devices/Neuropixels_1.cpp index 91f31ef..d1aa745 100644 --- a/Source/Devices/Neuropixels_1.cpp +++ b/Source/Devices/Neuropixels_1.cpp @@ -472,7 +472,7 @@ void Neuropixels_1::processFrames() uint16_t* dataPtr = (uint16_t*)frame->data; - apTimestamps[superFrameCount] = frame->time; + apTimestamps[superFrameCount] = deviceContext->convertTimestampToSeconds(frame->time); apSampleNumbers[superFrameCount] = apSampleNumber++; for (int i = 0; i < framesPerSuperFrame; i++) diff --git a/Source/Devices/OutputClock.h b/Source/Devices/OutputClock.h index 9c3ab5b..08a45a3 100644 --- a/Source/Devices/OutputClock.h +++ b/Source/Devices/OutputClock.h @@ -62,17 +62,17 @@ class OutputClock : public OnixDevice void processFrames() override {}; - float getFrequencyHz() const { return frequencyHz; } + double getFrequencyHz() const { return frequencyHz; } - void setFrequencyHz(float frequency) { frequencyHz = frequency; } + void setFrequencyHz(double frequency) { frequencyHz = frequency; } - uint32_t getDutyCycle() const { return dutyCycle; } + int32_t getDutyCycle() const { return dutyCycle; } - void setDutyCycle(uint32_t dutyCycle_) { dutyCycle = dutyCycle_; } + void setDutyCycle(int32_t dutyCycle_) { dutyCycle = dutyCycle_; } - uint32_t getDelay() const { return delay; } + int32_t getDelay() const { return delay; } - void setDelay(uint32_t delay_) { delay = delay_; } + void setDelay(int32_t delay_) { delay = delay_; } bool getGateRun() const { return gateRun; } @@ -85,8 +85,8 @@ class OutputClock : public OnixDevice private: double frequencyHz = 1e6; - uint32_t dutyCycle = 50; - uint32_t delay = 0; + int32_t dutyCycle = 50; + int32_t delay = 0; bool gateRun = true; diff --git a/Source/Devices/PolledBno055.cpp b/Source/Devices/PolledBno055.cpp index 4936f02..8de1482 100644 --- a/Source/Devices/PolledBno055.cpp +++ b/Source/Devices/PolledBno055.cpp @@ -261,7 +261,7 @@ void PolledBno055::hiResTimerCallback() rc = (uint64_t)deviceContext->readRegister(deviceIdx, DS90UB9x::LASTI2CH, ×tampH); if (rc != ONI_ESUCCESS) return; - bnoTimestamps[currentFrame] = (uint64_t(timestampH) << 32) | uint64_t(timestampL); + bnoTimestamps[currentFrame] = deviceContext->convertTimestampToSeconds((uint64_t(timestampH) << 32) | uint64_t(timestampL)); sampleNumbers[currentFrame] = sampleNumber++; diff --git a/Source/Onix1.cpp b/Source/Onix1.cpp index a63ac47..cdd99ac 100644 --- a/Source/Onix1.cpp +++ b/Source/Onix1.cpp @@ -35,6 +35,10 @@ Onix1::Onix1(int hostIndex) throw error_t(rc); oni_version(&major, &minor, &patch); + + rc = getOption(ONI_OPT_ACQCLKHZ, &ACQ_CLK_HZ); + if (rc != ONI_ESUCCESS) + throw error_t(rc); } Onix1::~Onix1() diff --git a/Source/Onix1.h b/Source/Onix1.h index dc7e9cd..9a0ec8f 100644 --- a/Source/Onix1.h +++ b/Source/Onix1.h @@ -88,7 +88,9 @@ class Onix1 int issueReset() { int val = 1; int rc = setOption(ONI_OPT_RESET, val); return rc; } - String getVersion() { return String(major) + "." + String(minor) + "." + String(patch); } + std::string getVersion() const { return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch); } + + double convertTimestampToSeconds(uint32_t timestamp) const { return static_cast(timestamp) / ACQ_CLK_HZ; } private: @@ -99,6 +101,8 @@ class Onix1 int minor; int patch; + uint32_t ACQ_CLK_HZ; + device_map_t deviceTable; template diff --git a/Source/OnixSourceCanvas.cpp b/Source/OnixSourceCanvas.cpp index 072f4d2..520a175 100644 --- a/Source/OnixSourceCanvas.cpp +++ b/Source/OnixSourceCanvas.cpp @@ -158,8 +158,10 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrgetDeviceIdx() == settingsInterfaces[j]->device->getDeviceIdx() && - compareDeviceNames(device->getName(), settingsInterfaces[j]->device->getName())) + auto selectedDevice = settingsInterfaces[j]->getDevice(); + + if (device->getDeviceIdx() == selectedDevice->getDeviceIdx() && + compareDeviceNames(device->getName(), selectedDevice->getName())) { ind = j; break; @@ -174,10 +176,12 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrgetDevice(); + if (device->type == OnixDeviceType::NEUROPIXELS_1) { auto npx1Found = std::static_pointer_cast(device); - auto npx1Selected = std::static_pointer_cast(settingsInterfaces[ind]->device); + auto npx1Selected = std::static_pointer_cast(selectedDevice); npx1Found->setSettings(npx1Selected->settings[0].get()); npx1Found->adcCalibrationFilePath = npx1Selected->adcCalibrationFilePath; npx1Found->gainCalibrationFilePath = npx1Selected->gainCalibrationFilePath; @@ -186,7 +190,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrtype == OnixDeviceType::OUTPUTCLOCK) { auto outputClockFound = std::static_pointer_cast(device); - auto outputClockSelected = std::static_pointer_cast(settingsInterfaces[ind]->device); + auto outputClockSelected = std::static_pointer_cast(selectedDevice); outputClockFound->setDelay(outputClockSelected->getDelay()); outputClockFound->setDutyCycle(outputClockSelected->getDutyCycle()); outputClockFound->setFrequencyHz(outputClockSelected->getFrequencyHz()); @@ -195,7 +199,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrtype == OnixDeviceType::ANALOGIO) { auto analogIOFound = std::static_pointer_cast(device); - auto analogIOSelected = std::static_pointer_cast(settingsInterfaces[ind]->device); + auto analogIOSelected = std::static_pointer_cast(selectedDevice); for (int i = 0; i < analogIOFound->getNumChannels(); i++) { analogIOFound->setChannelDirection(i, analogIOSelected->getChannelDirection(i)); @@ -204,7 +208,7 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptrtype == OnixDeviceType::NEUROPIXELSV2E) { auto npx2Found = std::static_pointer_cast(device); - auto npx2Selected = std::static_pointer_cast(settingsInterfaces[ind]->device); + auto npx2Selected = std::static_pointer_cast(selectedDevice); npx2Found->setSettings(npx2Selected->settings[0].get(), 0); npx2Found->setSettings(npx2Selected->settings[1].get(), 1); npx2Found->setGainCorrectionFile(0, npx2Selected->getGainCorrectionFile(0)); @@ -213,9 +217,8 @@ void OnixSourceCanvas::updateSettingsInterfaceDataSource(std::shared_ptr(settingsInterfaces[ind])->updateDevice(npx2Found); } - device->setEnabled(settingsInterfaces[ind]->device->isEnabled()); - settingsInterfaces[ind]->device.reset(); - settingsInterfaces[ind]->device = device; + device->setEnabled(selectedDevice->isEnabled()); + settingsInterfaces[ind]->setDevice(device); } String OnixSourceCanvas::getTopLevelTabName(PortName port, String headstage) @@ -263,7 +266,9 @@ void OnixSourceCanvas::removeTabs(PortName port) for (int i = settingsInterfaces.size() - 1; i >= 0; i -= 1) { - if ((settingsInterfaces[i]->device->getDeviceIdx() & offset) > 0) + auto selectedDevice = settingsInterfaces[i]->getDevice(); + + if ((selectedDevice->getDeviceIdx() & offset) > 0) { settingsInterfaces.erase(settingsInterfaces.begin() + i); tabExists = true; @@ -293,7 +298,9 @@ std::map OnixSourceCanvas::createSelectedMap(std::vectordevice->getDeviceIdx(), settings->device->type }); + auto device = settings->getDevice(); + + tabMap.insert({ device->getDeviceIdx(), device->type }); } return tabMap; @@ -512,10 +519,7 @@ void OnixSourceCanvas::startAcquisition() { for (const auto& settingsInterface : settingsInterfaces) { - if (settingsInterface->device != nullptr && settingsInterface->device->isEnabled()) - { - settingsInterface->startAcquisition(); - } + settingsInterface->startAcquisition(); } } @@ -523,21 +527,18 @@ void OnixSourceCanvas::stopAcquisition() { for (const auto& settingsInterface : settingsInterfaces) { - if (settingsInterface->device != nullptr && settingsInterface->device->isEnabled()) - { - settingsInterface->stopAcquisition(); - } + settingsInterface->stopAcquisition(); } } void OnixSourceCanvas::saveCustomParametersToXml(XmlElement* xml) { - //for (int i = 0; i < settingsInterfaces.size(); i++) - // settingsInterfaces[i]->saveParameters(xml); + for (int i = 0; i < settingsInterfaces.size(); i++) + settingsInterfaces[i]->saveParameters(xml); } void OnixSourceCanvas::loadCustomParametersFromXml(XmlElement* xml) { - //for (int i = 0; i < settingsInterfaces.size(); i++) - // settingsInterfaces[i]->loadParameters(xml); + for (int i = 0; i < settingsInterfaces.size(); i++) + settingsInterfaces[i]->loadParameters(xml); } diff --git a/Source/OnixSourceEditor.cpp b/Source/OnixSourceEditor.cpp index 963c7a0..f36b6ad 100644 --- a/Source/OnixSourceEditor.cpp +++ b/Source/OnixSourceEditor.cpp @@ -24,7 +24,7 @@ #include "OnixSource.h" OnixSourceEditor::OnixSourceEditor(GenericProcessor* parentNode, OnixSource* source_) - : VisualizerEditor(parentNode, "Onix Source", 240), source(source_) + : VisualizerEditor(parentNode, "Onix Source", 250), source(source_) { canvas = nullptr; @@ -38,8 +38,16 @@ OnixSourceEditor::OnixSourceEditor(GenericProcessor* parentNode, OnixSource* sou if (source->isContextInitialized()) { + portStatusA = std::make_unique(); + portStatusA->setRectangle(Rectangle(memoryUsage->getRight() + 4, memoryUsage->getY(), 10, 10)); + portStatusA->setCornerSize(Point(5,5)); + portStatusA->setFill(fillDisconnected); + portStatusA->setStrokeFill(statusIndicatorStrokeColor); + portStatusA->setStrokeThickness(statusIndicatorStrokeThickness); + addAndMakeVisible(portStatusA.get()); + portLabelA = std::make_unique