diff --git a/Source/Processors/DataThreads/RHD2000Thread.cpp b/Source/Processors/DataThreads/RHD2000Thread.cpp index 2c66ea353bf3884fc23d721e788a1bb939f897d3..9e1b9c6fba3f0a672541192f97a8c8cdecefd495 100644 --- a/Source/Processors/DataThreads/RHD2000Thread.cpp +++ b/Source/Processors/DataThreads/RHD2000Thread.cpp @@ -48,23 +48,36 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) // Initialize board. evalBoard->initialize(); + evalBoard->setContinuousRunMode(false); + + // set defaults + // 4 data sources : 0 -> PortA1 + // 1 -> PortB1 + // 2 -> PortC1 + // 3 -> PortD1 + // + // source 0 is enabled with 32 channels; the rest are disabled + // + // sample rate is 10 kHz + evalBoard->setDataSource(0, Rhd2000EvalBoard::PortA1); evalBoard->setDataSource(1, Rhd2000EvalBoard::PortB1); - evalBoard->setContinuousRunMode(false); + evalBoard->setDataSource(2, Rhd2000EvalBoard::PortC1); + evalBoard->setDataSource(3, Rhd2000EvalBoard::PortD1); - numChannelsPerDataStream.add(32); - numChannelsPerDataStream.add(32); + for (int i = 0; i < 4; i++) + { + numChannelsPerDataStream.add(0); + } - numChannels = 64; + enableHeadstage(0, true); + enableHeadstage(1, true); + enableHeadstage(2, false); + enableHeadstage(3, false); // Select per-channel amplifier sampling rate. evalBoard->setSampleRate(Rhd2000EvalBoard::SampleRate10000Hz); - // Now that we have set our sampling rate, we can set the MISO sampling delay - // which is dependent on the sample rate. We assume a 3-foot cable. - evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortA, 3.0); - evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortB, 3.0); - // Let's turn one LED on to indicate that the program is running. int ledArray[8] = {1, 0, 0, 0, 0, 0, 0, 0}; evalBoard->setLedDisplay(ledArray); @@ -84,8 +97,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); - dataBuffer = new DataBuffer(numChannels, 10000); - + dataBuffer = new DataBuffer(getNumChannels(), 10000); } @@ -107,6 +119,14 @@ RHD2000Thread::~RHD2000Thread() int RHD2000Thread::getNumChannels() { + + numChannels = 0; + + for (int i = 0; i < numChannelsPerDataStream.size(); i++) + { + numChannels += numChannelsPerDataStream[i]; + } + return numChannels; } @@ -132,6 +152,55 @@ bool RHD2000Thread::foundInputSource() } +void RHD2000Thread::enableHeadstage(int hsNum, bool enabled) +{ + + evalBoard->enableDataStream(hsNum, enabled); + + if (enabled) + { + numChannelsPerDataStream.set(hsNum, 32); + } else { + numChannelsPerDataStream.set(hsNum, 0); + } + + std::cout << "Enabled channels: " << numChannelsPerDataStream[0] << + " " << numChannelsPerDataStream[1] << + " " << numChannelsPerDataStream[2] << + " " << numChannelsPerDataStream[3] << std::endl; + + std::cout << "Enabled data streams: " << evalBoard->getNumEnabledDataStreams() << std::endl; + + delete(dataBlock); + + dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); + +} + +void RHD2000Thread::setCableLength(int hsNum, float length) +{ + // Set the MISO sampling delay, which is dependent on the sample rate. + + switch (hsNum) + { + case 0: + evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortA, length); + break; + case 1: + evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortB, length); + break; + case 2: + evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortC, length); + break; + case 3: + evalBoard->setCableLengthFeet(Rhd2000EvalBoard::PortD, length); + break; + default: + break; + } + +} + bool RHD2000Thread::startAcquisition() { @@ -210,15 +279,26 @@ bool RHD2000Thread::updateBuffer() for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++) { - for (int dataStream = 0; dataStream < 1; dataStream++) + int ds = -1; + int channel = -1; + + for (int dataStream = 0; dataStream < 2; dataStream++) //numChannelsPerDataStream.size(); dataStream++) { - for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++) + if (numChannelsPerDataStream[dataStream] > 0) { - int value = dataBlock->amplifierData[dataStream][chan][samp]; + ds++; + + for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++) + { + + channel++; + + int value = dataBlock->amplifierData[ds][chan][samp]; - thisSample[chan] = float(value-32768)*0.195f; + thisSample[channel] = float(value-32768)*0.195f; + } } } diff --git a/Source/Processors/DataThreads/RHD2000Thread.h b/Source/Processors/DataThreads/RHD2000Thread.h index 40859a4e3ebcaa092fbab634c8b5032c15c781eb..ef8cc760a39e085c4e28a4ba9167495911b2e354 100644 --- a/Source/Processors/DataThreads/RHD2000Thread.h +++ b/Source/Processors/DataThreads/RHD2000Thread.h @@ -61,6 +61,10 @@ public: float getSampleRate(); float getBitVolts(); + void enableHeadstage(int hsNum, bool enabled); + void setCableLength(int hsNum, float length); + void setNumChannels(int hsNum, int nChannels); + int getNumEventChannels(); private: diff --git a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h index 9f2ddab578ae6d65ee0bdb93a756db2aaa09119a..d27a2c3eede0b4785c0b110e874b6d707bc0b48f 100755 --- a/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h +++ b/Source/Processors/DataThreads/rhythm-api/rhd2000datablock.h @@ -20,7 +20,7 @@ #ifndef RHD2000DATABLOCK_H #define RHD2000DATABLOCK_H -#define SAMPLES_PER_DATA_BLOCK 200 +#define SAMPLES_PER_DATA_BLOCK 300 #define RHD2000_HEADER_MAGIC_NUMBER 0xc691199927021942 using namespace std; diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp index a99c588d965f6d3c55a9ebd5cb1bce350092ce10..215ad007dfa8d14df5ae053fdc637fbbc7bbfd37 100755 --- a/Source/Processors/Editors/GenericEditor.cpp +++ b/Source/Processors/Editors/GenericEditor.cpp @@ -72,6 +72,8 @@ void GenericEditor::constructorInitialize(GenericProcessor* owner, bool useDefau if (!owner->isMerger() && !owner->isSplitter()) { + std::cout << "Adding drawer button." << std::endl; + drawerButton = new DrawerButton("name"); drawerButton->addListener(this); addAndMakeVisible(drawerButton); diff --git a/Source/Processors/Editors/RHD2000Editor.cpp b/Source/Processors/Editors/RHD2000Editor.cpp index 159e04001115c5fbde164099e87a08d2e3e20e6d..d6e5edacefc2e1b222428462ec4a0e2f88ef3601 100644 --- a/Source/Processors/Editors/RHD2000Editor.cpp +++ b/Source/Processors/Editors/RHD2000Editor.cpp @@ -23,17 +23,26 @@ #include "RHD2000Editor.h" -RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode, bool useDefaultParameterEditors=true) - : GenericEditor(parentNode, useDefaultParameterEditors) +#include "../DataThreads/RHD2000Thread.h" + +RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode, + RHD2000Thread* board_, + bool useDefaultParameterEditors=true + ) + : GenericEditor(parentNode, useDefaultParameterEditors), board(board_) { desiredWidth = 400; + int width = desiredWidth/4 - 10; + for (int i = 0; i < 4; i++) { HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(i); headstageOptionsInterfaces.add(hsOptions); addAndMakeVisible(hsOptions); + + hsOptions->setBounds(8+i*width,30, width, 85); } } @@ -43,16 +52,6 @@ RHD2000Editor::~RHD2000Editor() } -void RHD2000Editor::resized() -{ - - int width = getWidth()/4 - 20; - - for (int i = 0; i < headstageOptionsInterfaces.size(); i++) - { - headstageOptionsInterfaces[i]->setBounds(10+i*width,30, width,getHeight()-50); - } -} // -------------------------------------------------------------------- @@ -91,4 +90,10 @@ void HeadstageOptionsInterface::paint(Graphics& g) g.fillRoundedRectangle(5,0,getWidth()-10,getHeight(),4.0f); + g.setColour(Colours::grey); + + g.setFont(Font("Small Text",10,Font::plain)); + + g.drawText("Headstage " + name, 8, 5, 200, 15, Justification::left, false); + } \ No newline at end of file diff --git a/Source/Processors/Editors/RHD2000Editor.h b/Source/Processors/Editors/RHD2000Editor.h index b6140c1c8f7f17900e78ada32edcbe38520f5d7e..44ec1629ced6cd8ecb39dde5e44740c721052899 100644 --- a/Source/Processors/Editors/RHD2000Editor.h +++ b/Source/Processors/Editors/RHD2000Editor.h @@ -36,21 +36,22 @@ */ class HeadstageOptionsInterface; +class RHD2000Thread; class RHD2000Editor : public GenericEditor { public: - RHD2000Editor(GenericProcessor* parentNode, bool useDefaultParameterEditors); + RHD2000Editor(GenericProcessor* parentNode, RHD2000Thread*, bool useDefaultParameterEditors); ~RHD2000Editor(); - void resized(); - private: OwnedArray<HeadstageOptionsInterface> headstageOptionsInterfaces; + RHD2000Thread* board; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHD2000Editor); }; @@ -69,6 +70,7 @@ private: int hsNumber; String name; + }; diff --git a/Source/Processors/SourceNode.cpp b/Source/Processors/SourceNode.cpp index 7d263a23128543de08e2f4e0a13033c5e12c0c01..2a043bcab73a487b7d8affe028ce498330dda3d5 100755 --- a/Source/Processors/SourceNode.cpp +++ b/Source/Processors/SourceNode.cpp @@ -90,6 +90,14 @@ SourceNode::SourceNode(const String& name_) SourceNode::~SourceNode() { + + if (dataThread->isThreadRunning()) + { + std::cout << "Forcing thread to stop." << std::endl; + dataThread->stopThread(500); + } + + if (eventChannelState) delete[] eventChannelState; } @@ -198,7 +206,7 @@ AudioProcessorEditor* SourceNode::createEditor() if (getName().equalsIgnoreCase("RHD2000 USB Board")) { - editor = new RHD2000Editor(this, true); + editor = new RHD2000Editor(this, (RHD2000Thread*) dataThread.get(), true); } else {