Skip to content
Snippets Groups Projects
Commit 0557473c authored by jsiegle's avatar jsiegle
Browse files

Now possible to dynamically select multiple headstages for the RHD2000Thread

parent f6178b69
No related branches found
No related tags found
No related merge requests found
...@@ -29,7 +29,7 @@ AudioNode::AudioNode() ...@@ -29,7 +29,7 @@ AudioNode::AudioNode()
: GenericProcessor("Audio Node"), audioEditor(0), volume(0.00001f) : GenericProcessor("Audio Node"), audioEditor(0), volume(0.00001f)
{ {
settings.numInputs = 128; settings.numInputs = 256;
settings.numOutputs = 2; settings.numOutputs = 2;
// 128 inputs, 2 outputs (left and right channel) // 128 inputs, 2 outputs (left and right channel)
......
...@@ -39,6 +39,15 @@ void DataBuffer::clear() ...@@ -39,6 +39,15 @@ void DataBuffer::clear()
buffer.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) void DataBuffer::addToBuffer(float* data, uint64* timestamps, int16* eventCodes, int numItems)
{ {
// writes one sample for all channels // writes one sample for all channels
......
...@@ -53,6 +53,9 @@ public: ...@@ -53,6 +53,9 @@ public:
/** Copies as many samples as possible from the DataBuffer to an AudioSampleBuffer.*/ /** Copies as many samples as possible from the DataBuffer to an AudioSampleBuffer.*/
int readAllFromBuffer(AudioSampleBuffer& data, uint64* ts, int16* eventCodes, int maxSize); int readAllFromBuffer(AudioSampleBuffer& data, uint64* ts, int16* eventCodes, int maxSize);
/** Resizes the data buffer */
void resize(int chans, int size);
private: private:
AbstractFifo abstractFifo; AbstractFifo abstractFifo;
AudioSampleBuffer buffer; AudioSampleBuffer buffer;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn)
{ {
evalBoard = new Rhd2000EvalBoard; evalBoard = new Rhd2000EvalBoard;
dataBlock = new Rhd2000DataBlock(1);
// Open Opal Kelly XEM6010 board. // Open Opal Kelly XEM6010 board.
int return_code = evalBoard->open(); int return_code = evalBoard->open();
...@@ -49,6 +50,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) ...@@ -49,6 +50,7 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn)
// Initialize board. // Initialize board.
evalBoard->initialize(); evalBoard->initialize();
evalBoard->setContinuousRunMode(false); evalBoard->setContinuousRunMode(false);
evalBoard->flush(); // flush in case it crashed with data remaining
// set defaults // set defaults
// 4 data sources : 0 -> PortA1 // 4 data sources : 0 -> PortA1
...@@ -70,10 +72,17 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) ...@@ -70,10 +72,17 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn)
numChannelsPerDataStream.add(0); numChannelsPerDataStream.add(0);
} }
dataBuffer = new DataBuffer(32, 10000);
enableHeadstage(0, true); enableHeadstage(0, true);
enableHeadstage(1, true); enableHeadstage(1, true);
enableHeadstage(2, true); // enableHeadstage(2, false);
enableHeadstage(3, 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. // Select per-channel amplifier sampling rate.
evalBoard->setSampleRate(Rhd2000EvalBoard::SampleRate10000Hz); evalBoard->setSampleRate(Rhd2000EvalBoard::SampleRate10000Hz);
...@@ -95,10 +104,6 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn) ...@@ -95,10 +104,6 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn)
chipRegisters->setLowerBandwidth(1.0); chipRegisters->setLowerBandwidth(1.0);
chipRegisters->setUpperBandwidth(7500.0); chipRegisters->setUpperBandwidth(7500.0);
dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams());
dataBuffer = new DataBuffer(getNumChannels(), 10000);
} }
} }
...@@ -114,6 +119,8 @@ RHD2000Thread::~RHD2000Thread() ...@@ -114,6 +119,8 @@ RHD2000Thread::~RHD2000Thread()
evalBoard->setLedDisplay(ledArray); evalBoard->setLedDisplay(ledArray);
} }
deleteAndZero(dataBlock);
} }
...@@ -171,10 +178,19 @@ void RHD2000Thread::enableHeadstage(int hsNum, bool enabled) ...@@ -171,10 +178,19 @@ void RHD2000Thread::enableHeadstage(int hsNum, bool enabled)
std::cout << "Enabled data streams: " << evalBoard->getNumEnabledDataStreams() << std::endl; 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) void RHD2000Thread::setCableLength(int hsNum, float length)
...@@ -204,6 +220,10 @@ void RHD2000Thread::setCableLength(int hsNum, float length) ...@@ -204,6 +220,10 @@ void RHD2000Thread::setCableLength(int hsNum, float length)
bool RHD2000Thread::startAcquisition() bool RHD2000Thread::startAcquisition()
{ {
dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams());
std::cout << "Expecting " << getNumChannels() << " channels." << std::endl;
//memset(filter_states,0,256*sizeof(double)); //memset(filter_states,0,256*sizeof(double));
int ledArray[8] = {1, 1, 0, 0, 0, 0, 0, 0}; int ledArray[8] = {1, 1, 0, 0, 0, 0, 0, 0};
...@@ -213,11 +233,6 @@ bool RHD2000Thread::startAcquisition() ...@@ -213,11 +233,6 @@ bool RHD2000Thread::startAcquisition()
cout << "Is eval board running: " << evalBoard->isRunning() << endl; 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; //std::cout << "Setting max timestep." << std::endl;
//evalBoard->setMaxTimeStep(100); //evalBoard->setMaxTimeStep(100);
evalBoard->setContinuousRunMode(true); evalBoard->setContinuousRunMode(true);
...@@ -245,10 +260,20 @@ bool RHD2000Thread::stopAcquisition() ...@@ -245,10 +260,20 @@ bool RHD2000Thread::stopAcquisition()
if (isThreadRunning()) if (isThreadRunning())
{ {
signalThreadShouldExit(); 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->setContinuousRunMode(false);
evalBoard->setMaxTimeStep(0); evalBoard->setMaxTimeStep(0);
std::cout << "Flushing FIFO." << std::endl;
evalBoard->flush();
cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl;
...@@ -279,23 +304,23 @@ bool RHD2000Thread::updateBuffer() ...@@ -279,23 +304,23 @@ bool RHD2000Thread::updateBuffer()
for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++) for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++)
{ {
int ds = -1; int streamNumber = -1;
int channel = -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) if (numChannelsPerDataStream[dataStream] > 0)
{ {
ds++; streamNumber++;
for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++) for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++)
{ {
channel++; channel++;
int value = dataBlock->amplifierData[ds][chan][samp]; int value = dataBlock->amplifierData[streamNumber][chan][samp];
thisSample[channel] = float(value-32768)*0.195f; thisSample[channel] = float(value-32768)*0.195f;
} }
...@@ -303,6 +328,8 @@ bool RHD2000Thread::updateBuffer() ...@@ -303,6 +328,8 @@ bool RHD2000Thread::updateBuffer()
} }
// std::cout << channel << std::endl;
timestamp = dataBlock->timeStamp[samp]; timestamp = dataBlock->timeStamp[samp];
eventCode = dataBlock->ttlIn[samp]; eventCode = dataBlock->ttlIn[samp];
...@@ -313,6 +340,8 @@ bool RHD2000Thread::updateBuffer() ...@@ -313,6 +340,8 @@ bool RHD2000Thread::updateBuffer()
} }
return true; return true;
} }
\ No newline at end of file
...@@ -61,6 +61,8 @@ public: ...@@ -61,6 +61,8 @@ public:
float getSampleRate(); float getSampleRate();
float getBitVolts(); float getBitVolts();
bool isHeadstageEnabled(int hsNum);
void enableHeadstage(int hsNum, bool enabled); void enableHeadstage(int hsNum, bool enabled);
void setCableLength(int hsNum, float length); void setCableLength(int hsNum, float length);
void setNumChannels(int hsNum, int nChannels); void setNumChannels(int hsNum, int nChannels);
...@@ -71,7 +73,7 @@ private: ...@@ -71,7 +73,7 @@ private:
ScopedPointer<Rhd2000EvalBoard> evalBoard; ScopedPointer<Rhd2000EvalBoard> evalBoard;
ScopedPointer<Rhd2000Registers> chipRegisters; ScopedPointer<Rhd2000Registers> chipRegisters;
ScopedPointer<Rhd2000DataBlock> dataBlock; Rhd2000DataBlock* dataBlock;
Array<int> numChannelsPerDataStream; Array<int> numChannelsPerDataStream;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#include "RHD2000Editor.h" #include "RHD2000Editor.h"
#include "../../UI/EditorViewport.h"
#include "../DataThreads/RHD2000Thread.h" #include "../DataThreads/RHD2000Thread.h"
...@@ -37,7 +38,7 @@ RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode, ...@@ -37,7 +38,7 @@ RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode,
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(i); HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(board, this, i);
headstageOptionsInterfaces.add(hsOptions); headstageOptionsInterfaces.add(hsOptions);
addAndMakeVisible(hsOptions); addAndMakeVisible(hsOptions);
...@@ -55,8 +56,10 @@ RHD2000Editor::~RHD2000Editor() ...@@ -55,8 +56,10 @@ RHD2000Editor::~RHD2000Editor()
// -------------------------------------------------------------------- // --------------------------------------------------------------------
HeadstageOptionsInterface::HeadstageOptionsInterface(int hsNum) : HeadstageOptionsInterface::HeadstageOptionsInterface(RHD2000Thread* board_,
hsNumber(hsNum) RHD2000Editor* editor_,
int hsNum) :
board(board_), editor(editor_), hsNumber(hsNum), isEnabled(false)
{ {
switch (hsNumber) switch (hsNumber)
...@@ -77,23 +80,67 @@ HeadstageOptionsInterface::HeadstageOptionsInterface(int hsNum) : ...@@ -77,23 +80,67 @@ HeadstageOptionsInterface::HeadstageOptionsInterface(int hsNum) :
name = "X"; 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() 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) void HeadstageOptionsInterface::paint(Graphics& g)
{ {
g.setColour(Colours::lightgrey); g.setColour(Colours::lightgrey);
g.fillRoundedRectangle(5,0,getWidth()-10,getHeight(),4.0f); 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
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
class HeadstageOptionsInterface; class HeadstageOptionsInterface;
class RHD2000Thread; class RHD2000Thread;
class UtilityButton;
class RHD2000Editor : public GenericEditor class RHD2000Editor : public GenericEditor
...@@ -57,19 +58,30 @@ private: ...@@ -57,19 +58,30 @@ private:
}; };
class HeadstageOptionsInterface : public Component class HeadstageOptionsInterface : public Component,
public Button::Listener
{ {
public: public:
HeadstageOptionsInterface(int hsNum); HeadstageOptionsInterface(RHD2000Thread*, RHD2000Editor*, int hsNum);
~HeadstageOptionsInterface(); ~HeadstageOptionsInterface();
//void mouseUp(const MouseEvent& event);
void paint(Graphics& g); void paint(Graphics& g);
void buttonClicked(Button* button);
private: private:
int hsNumber; int hsNumber;
String name; String name;
bool isEnabled;
RHD2000Thread* board;
RHD2000Editor* editor;
ScopedPointer<UtilityButton> enabledButton;
}; };
......
...@@ -37,7 +37,7 @@ RecordNode::RecordNode() ...@@ -37,7 +37,7 @@ RecordNode::RecordNode()
continuousDataFloatBuffer = new float[10000]; continuousDataFloatBuffer = new float[10000];
signalFilesShouldClose = false; signalFilesShouldClose = false;
settings.numInputs = 128; settings.numInputs = 256;
settings.numOutputs = 0; settings.numOutputs = 0;
eventChannel = new Channel(this, 0); eventChannel = new Channel(this, 0);
......
...@@ -325,6 +325,8 @@ void LfpDisplay::setNumChannels(int numChannels) ...@@ -325,6 +325,8 @@ void LfpDisplay::setNumChannels(int numChannels)
channels.clear(); channels.clear();
totalHeight = 0;
for (int i = 0; i < numChans; i++) for (int i = 0; i < numChans; i++)
{ {
...@@ -420,6 +422,8 @@ LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, int channelNumber) : ...@@ -420,6 +422,8 @@ LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, int channelNumber) :
canvas(c), isSelected(false), chan(channelNumber) canvas(c), isSelected(false), chan(channelNumber)
{ {
channelFont = Font("Default", 50, Font::plain);
} }
LfpChannelDisplay::~LfpChannelDisplay() LfpChannelDisplay::~LfpChannelDisplay()
...@@ -448,6 +452,12 @@ void LfpChannelDisplay::paint(Graphics& g) ...@@ -448,6 +452,12 @@ void LfpChannelDisplay::paint(Graphics& g)
(canvas->getYCoord(chan, i+stepSize)+0.5f)*getHeight()); (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() void LfpChannelDisplay::select()
......
...@@ -170,6 +170,8 @@ private: ...@@ -170,6 +170,8 @@ private:
int chan; int chan;
Font channelFont;
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment