diff --git a/Source/Processors/AudioNode.cpp b/Source/Processors/AudioNode.cpp index f13fffc366336f6a0132b3ffcf01549b05e07918..abcec0cdf7e84736f0ec3291689db07f8d01a5cc 100755 --- a/Source/Processors/AudioNode.cpp +++ b/Source/Processors/AudioNode.cpp @@ -29,7 +29,7 @@ AudioNode::AudioNode() : GenericProcessor("Audio Node"), audioEditor(0), volume(0.00001f) { - settings.numInputs = 128; + settings.numInputs = 256; settings.numOutputs = 2; // 128 inputs, 2 outputs (left and right channel) diff --git a/Source/Processors/DataThreads/DataBuffer.cpp b/Source/Processors/DataThreads/DataBuffer.cpp index be94870fb0e874c2d29757be9b73b139c64b2824..19bae80e262931b779465643d683f34818197873 100755 --- a/Source/Processors/DataThreads/DataBuffer.cpp +++ b/Source/Processors/DataThreads/DataBuffer.cpp @@ -39,6 +39,15 @@ void DataBuffer::clear() buffer.clear(); } +void DataBuffer::resize(int chans, int size) +{ + buffer.setSize(chans, size); + timestampBuffer = new uint64[size]; + eventCodeBuffer = new int16[size]; + + numChans = chans; +} + void DataBuffer::addToBuffer(float* data, uint64* timestamps, int16* eventCodes, int numItems) { // writes one sample for all channels diff --git a/Source/Processors/DataThreads/DataBuffer.h b/Source/Processors/DataThreads/DataBuffer.h index 08eb4efa0289e7189f1cb386f508decaf308e6da..be03599cd89b1cf56cc7183c4dfc698e7b3a4b91 100755 --- a/Source/Processors/DataThreads/DataBuffer.h +++ b/Source/Processors/DataThreads/DataBuffer.h @@ -53,6 +53,9 @@ public: /** Copies as many samples as possible from the DataBuffer to an AudioSampleBuffer.*/ int readAllFromBuffer(AudioSampleBuffer& data, uint64* ts, int16* eventCodes, int maxSize); + /** Resizes the data buffer */ + void resize(int chans, int size); + private: AbstractFifo abstractFifo; AudioSampleBuffer buffer; diff --git a/Source/Processors/DataThreads/RHD2000Thread.cpp b/Source/Processors/DataThreads/RHD2000Thread.cpp index 0c3edb40185ca4bf2bfb37da138ca140a4a60d7d..70c6d38b954edc8d8cad75009e3e7dc7c08e38b7 100644 --- a/Source/Processors/DataThreads/RHD2000Thread.cpp +++ b/Source/Processors/DataThreads/RHD2000Thread.cpp @@ -27,6 +27,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) { evalBoard = new Rhd2000EvalBoard; + dataBlock = new Rhd2000DataBlock(1); // Open Opal Kelly XEM6010 board. int return_code = evalBoard->open(); @@ -49,6 +50,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) // Initialize board. evalBoard->initialize(); evalBoard->setContinuousRunMode(false); + evalBoard->flush(); // flush in case it crashed with data remaining // set defaults // 4 data sources : 0 -> PortA1 @@ -70,10 +72,17 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) numChannelsPerDataStream.add(0); } + dataBuffer = new DataBuffer(32, 10000); + enableHeadstage(0, true); enableHeadstage(1, true); - enableHeadstage(2, true); - enableHeadstage(3, false); + // enableHeadstage(2, false); + // enableHeadstage(3, false); + + setCableLength(0, 3.0f); + setCableLength(1, 3.0f); + setCableLength(2, 3.0f); + setCableLength(3, 3.0f); // Select per-channel amplifier sampling rate. evalBoard->setSampleRate(Rhd2000EvalBoard::SampleRate10000Hz); @@ -95,10 +104,6 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) chipRegisters->setLowerBandwidth(1.0); chipRegisters->setUpperBandwidth(7500.0); - dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); - - dataBuffer = new DataBuffer(getNumChannels(), 10000); - } } @@ -114,6 +119,8 @@ RHD2000Thread::~RHD2000Thread() evalBoard->setLedDisplay(ledArray); } + deleteAndZero(dataBlock); + } @@ -171,10 +178,19 @@ void RHD2000Thread::enableHeadstage(int hsNum, bool enabled) std::cout << "Enabled data streams: " << evalBoard->getNumEnabledDataStreams() << std::endl; - delete(dataBlock); + dataBuffer->resize(getNumChannels(), 10000); +} + +bool RHD2000Thread::isHeadstageEnabled(int hsNum) +{ + + if (numChannelsPerDataStream[hsNum] > 0) + { + return true; + } + + return false; - dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); - } void RHD2000Thread::setCableLength(int hsNum, float length) @@ -204,6 +220,10 @@ void RHD2000Thread::setCableLength(int hsNum, float length) bool RHD2000Thread::startAcquisition() { + dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); + + std::cout << "Expecting " << getNumChannels() << " channels." << std::endl; + //memset(filter_states,0,256*sizeof(double)); int ledArray[8] = {1, 1, 0, 0, 0, 0, 0, 0}; @@ -213,11 +233,6 @@ bool RHD2000Thread::startAcquisition() cout << "Is eval board running: " << evalBoard->isRunning() << endl; - // If this happens too soon after acquisition is stopped, problems ensue - std::cout << "Flushing FIFO." << std::endl; - evalBoard->flush(); - - //std::cout << "Setting max timestep." << std::endl; //evalBoard->setMaxTimeStep(100); evalBoard->setContinuousRunMode(true); @@ -245,10 +260,20 @@ bool RHD2000Thread::stopAcquisition() if (isThreadRunning()) { signalThreadShouldExit(); + + } + + if (waitForThreadToExit(500)) + { + std::cout << "Thread exited." << std::endl; + } else { + std::cout << "Thread failed to exit, continuing anyway..." << std::endl; } evalBoard->setContinuousRunMode(false); evalBoard->setMaxTimeStep(0); + std::cout << "Flushing FIFO." << std::endl; + evalBoard->flush(); cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; @@ -279,23 +304,23 @@ bool RHD2000Thread::updateBuffer() for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++) { - int ds = -1; + int streamNumber = -1; int channel = -1; - for (int dataStream = 0; dataStream < 2; dataStream++) //numChannelsPerDataStream.size(); dataStream++) + for (int dataStream = 0; dataStream < numChannelsPerDataStream.size(); dataStream++) { if (numChannelsPerDataStream[dataStream] > 0) { - ds++; + streamNumber++; for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++) { channel++; - int value = dataBlock->amplifierData[ds][chan][samp]; + int value = dataBlock->amplifierData[streamNumber][chan][samp]; thisSample[channel] = float(value-32768)*0.195f; } @@ -303,6 +328,8 @@ bool RHD2000Thread::updateBuffer() } + // std::cout << channel << std::endl; + timestamp = dataBlock->timeStamp[samp]; eventCode = dataBlock->ttlIn[samp]; @@ -313,6 +340,8 @@ bool RHD2000Thread::updateBuffer() } + + return true; } \ No newline at end of file diff --git a/Source/Processors/DataThreads/RHD2000Thread.h b/Source/Processors/DataThreads/RHD2000Thread.h index ef8cc760a39e085c4e28a4ba9167495911b2e354..14c8293bbde2bf3a1dee6abdeb6ffab2b746ec05 100644 --- a/Source/Processors/DataThreads/RHD2000Thread.h +++ b/Source/Processors/DataThreads/RHD2000Thread.h @@ -61,6 +61,8 @@ public: float getSampleRate(); float getBitVolts(); + bool isHeadstageEnabled(int hsNum); + void enableHeadstage(int hsNum, bool enabled); void setCableLength(int hsNum, float length); void setNumChannels(int hsNum, int nChannels); @@ -71,7 +73,7 @@ private: ScopedPointer<Rhd2000EvalBoard> evalBoard; ScopedPointer<Rhd2000Registers> chipRegisters; - ScopedPointer<Rhd2000DataBlock> dataBlock; + Rhd2000DataBlock* dataBlock; Array<int> numChannelsPerDataStream; diff --git a/Source/Processors/Editors/RHD2000Editor.cpp b/Source/Processors/Editors/RHD2000Editor.cpp index d6e5edacefc2e1b222428462ec4a0e2f88ef3601..a10d65d6cbd83529d88d712acf59f96f68add886 100644 --- a/Source/Processors/Editors/RHD2000Editor.cpp +++ b/Source/Processors/Editors/RHD2000Editor.cpp @@ -22,6 +22,7 @@ */ #include "RHD2000Editor.h" +#include "../../UI/EditorViewport.h" #include "../DataThreads/RHD2000Thread.h" @@ -37,7 +38,7 @@ RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode, for (int i = 0; i < 4; i++) { - HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(i); + HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(board, this, i); headstageOptionsInterfaces.add(hsOptions); addAndMakeVisible(hsOptions); @@ -55,8 +56,10 @@ RHD2000Editor::~RHD2000Editor() // -------------------------------------------------------------------- -HeadstageOptionsInterface::HeadstageOptionsInterface(int hsNum) : - hsNumber(hsNum) +HeadstageOptionsInterface::HeadstageOptionsInterface(RHD2000Thread* board_, + RHD2000Editor* editor_, + int hsNum) : + board(board_), editor(editor_), hsNumber(hsNum), isEnabled(false) { switch (hsNumber) @@ -77,23 +80,67 @@ HeadstageOptionsInterface::HeadstageOptionsInterface(int hsNum) : name = "X"; } + isEnabled = board->isHeadstageEnabled(hsNumber); + + enabledButton = new UtilityButton("enabled", Font("Small Text", 13, Font::plain)); + enabledButton->addListener(this); + enabledButton->setRadius(3.0f); + enabledButton->setBounds(10,30,70,25); + addAndMakeVisible(enabledButton); + + + } HeadstageOptionsInterface::~HeadstageOptionsInterface() { +} + +void HeadstageOptionsInterface::buttonClicked(Button* button) +{ + if (~(board->isThreadRunning())) + { + if (isEnabled) + { + isEnabled = false; + } else { + isEnabled = true; + } + + board->enableHeadstage(hsNumber, isEnabled); + } + + repaint(); + + editor->getEditorViewport()->makeEditorVisible(editor, false, true); } +// void HeadstageOptionsInterface::mouseUp(const MouseEvent& event) +// { +// ///>>>> ???? WHY ISN"T THIS WORKING? + +// if (event.eventComponent == this) +// { + + +// } + +// } + void HeadstageOptionsInterface::paint(Graphics& g) { g.setColour(Colours::lightgrey); g.fillRoundedRectangle(5,0,getWidth()-10,getHeight(),4.0f); - g.setColour(Colours::grey); + if (isEnabled) + g.setColour(Colours::black); + else + g.setColour(Colours::grey); - g.setFont(Font("Small Text",10,Font::plain)); + g.setFont(Font("Small Text",20,Font::plain)); - g.drawText("Headstage " + name, 8, 5, 200, 15, Justification::left, false); + g.drawText(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 44ec1629ced6cd8ecb39dde5e44740c721052899..3367ed3d04ea886645122602b1e7f44663ef0ed4 100644 --- a/Source/Processors/Editors/RHD2000Editor.h +++ b/Source/Processors/Editors/RHD2000Editor.h @@ -38,6 +38,7 @@ class HeadstageOptionsInterface; class RHD2000Thread; +class UtilityButton; class RHD2000Editor : public GenericEditor @@ -57,19 +58,30 @@ private: }; -class HeadstageOptionsInterface : public Component +class HeadstageOptionsInterface : public Component, + public Button::Listener { public: - HeadstageOptionsInterface(int hsNum); + HeadstageOptionsInterface(RHD2000Thread*, RHD2000Editor*, int hsNum); ~HeadstageOptionsInterface(); + //void mouseUp(const MouseEvent& event); + void paint(Graphics& g); + void buttonClicked(Button* button); + private: int hsNumber; String name; + bool isEnabled; + + RHD2000Thread* board; + RHD2000Editor* editor; + + ScopedPointer<UtilityButton> enabledButton; }; diff --git a/Source/Processors/RecordNode.cpp b/Source/Processors/RecordNode.cpp index 0bd09520ed7d31a1655cf7e26fff155a73990382..52bab8f983c2d3aa078897cca4e1b653ac3c62b8 100755 --- a/Source/Processors/RecordNode.cpp +++ b/Source/Processors/RecordNode.cpp @@ -37,7 +37,7 @@ RecordNode::RecordNode() continuousDataFloatBuffer = new float[10000]; signalFilesShouldClose = false; - settings.numInputs = 128; + settings.numInputs = 256; settings.numOutputs = 0; eventChannel = new Channel(this, 0); diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.cpp b/Source/Processors/Visualization/LfpDisplayCanvas.cpp index 1164bc10950308b481e2bb860b27b867d0ef1c07..a87bd6bc667826ffad0d3cedec0edb57d14621c2 100755 --- a/Source/Processors/Visualization/LfpDisplayCanvas.cpp +++ b/Source/Processors/Visualization/LfpDisplayCanvas.cpp @@ -325,6 +325,8 @@ void LfpDisplay::setNumChannels(int numChannels) channels.clear(); + totalHeight = 0; + for (int i = 0; i < numChans; i++) { @@ -420,6 +422,8 @@ LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, int channelNumber) : canvas(c), isSelected(false), chan(channelNumber) { + channelFont = Font("Default", 50, Font::plain); + } LfpChannelDisplay::~LfpChannelDisplay() @@ -448,6 +452,12 @@ void LfpChannelDisplay::paint(Graphics& g) (canvas->getYCoord(chan, i+stepSize)+0.5f)*getHeight()); } + g.setColour(Colours::black.withAlpha(0.3f)); + g.setFont(channelFont); + + g.drawText(String(chan+1), 10, 50, 200, 50, Justification::left, false); + + } void LfpChannelDisplay::select() diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.h b/Source/Processors/Visualization/LfpDisplayCanvas.h index 7605a0142690cbdd711b60eafa8ef10eb01d6c8c..567fe72b861d00f61ebfac63a965621ff57fc7ff 100755 --- a/Source/Processors/Visualization/LfpDisplayCanvas.h +++ b/Source/Processors/Visualization/LfpDisplayCanvas.h @@ -170,6 +170,8 @@ private: int chan; + Font channelFont; + };