Skip to content
Snippets Groups Projects
Commit 5a5f2b16 authored by Aaron Cuevas Lopez's avatar Aaron Cuevas Lopez
Browse files

Add proper support for RHD2164

parent 0d8f92cf
No related branches found
No related tags found
No related merge requests found
......@@ -1199,7 +1199,7 @@ void HeadstageOptionsInterface::checkEnabledState()
if (board->isHeadstageEnabled(hsNumber1))
{
channelsOnHs1 = 32;
channelsOnHs1 = board->getChannelsInHeadstage(hsNumber1);
hsButton1->setLabel(String(channelsOnHs1));
hsButton1->setEnabledState(true);
}
......@@ -1212,7 +1212,7 @@ void HeadstageOptionsInterface::checkEnabledState()
if (board->isHeadstageEnabled(hsNumber2))
{
channelsOnHs2 = 32;
channelsOnHs2 = board->getChannelsInHeadstage(hsNumber2);
hsButton2->setLabel(String(channelsOnHs2));
hsButton2->setEnabledState(true);
}
......@@ -1230,7 +1230,7 @@ void HeadstageOptionsInterface::checkEnabledState()
void HeadstageOptionsInterface::buttonClicked(Button* button)
{
if (!(editor->acquisitionIsActive) && board->foundInputSource())
/* if (!(editor->acquisitionIsActive) && board->foundInputSource())
{
//std::cout << "Acquisition is not active" << std::endl;
......@@ -1265,7 +1265,7 @@ void HeadstageOptionsInterface::buttonClicked(Button* button)
editor->getEditorViewport()->makeEditorVisible(editor, false, true);
}
}*/
}
......
......@@ -81,6 +81,10 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
cableLengthPortA(0.914f), cableLengthPortB(0.914f), cableLengthPortC(0.914f), cableLengthPortD(0.914f), // default is 3 feet (0.914 m),
audioOutputL(-1), audioOutputR(-1) ,numberingScheme(1)
{
for (int i=0; i < MAX_NUM_HEADSTAGES; i++)
headstagesArray.add(new RHDHeadstage(static_cast<Rhd2000EvalBoard::BoardDataSource>(i)));
evalBoard = new Rhd2000EvalBoard;
dataBlock = new Rhd2000DataBlock(1);
dataBuffer = new DataBuffer(2, 10000); // start with 2 channels and automatically resize
......@@ -408,9 +412,13 @@ void RHD2000Thread::scanPorts()
{
return;
}
//Clear previous known streams
enabledStreams.clear();
// Scan SPI ports
int delay, stream, id;
int delay, hs, id;
int register59Value;
//int numChannelsOnPort[4] = {0, 0, 0, 0};
Rhd2000EvalBoard::BoardDataSource initStreamPorts[8] =
......@@ -438,6 +446,7 @@ void RHD2000Thread::scanPorts()
};
chipId.insertMultiple(0,-1,8);
Array<int> tmpChipId(chipId);
setSampleRate(Rhd2000EvalBoard::SampleRate30000Hz, true); // set to 30 kHz temporarily
......@@ -517,28 +526,28 @@ void RHD2000Thread::scanPorts()
// Read the Intan chip ID number from each RHD2000 chip found.
// Record delay settings that yield good communication with the chip.
for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)//MAX_NUM_DATA_STREAMS; ++stream)
for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)//MAX_NUM_DATA_STREAMS; ++stream)
{
// std::cout << "Stream number " << stream << ", delay = " << delay << std::endl;
id = deviceId(dataBlock, stream, register59Value);
id = deviceId(dataBlock, hs, register59Value);
if (id == CHIP_ID_RHD2132 || id == CHIP_ID_RHD2216 ||
(id == CHIP_ID_RHD2164 && register59Value == REGISTER_59_MISO_A))
{
// std::cout << "Device ID found: " << id << std::endl;
sumGoodDelays.set(stream,sumGoodDelays[stream] + 1);
sumGoodDelays.set(hs,sumGoodDelays[hs] + 1);
if (indexFirstGoodDelay[stream] == -1)
if (indexFirstGoodDelay[hs] == -1)
{
indexFirstGoodDelay.set(stream, delay);
chipId.set(stream,id);
indexFirstGoodDelay.set(hs, delay);
tmpChipId.set(hs,id);
}
else if (indexSecondGoodDelay[stream] == -1)
else if (indexSecondGoodDelay[hs] == -1)
{
indexSecondGoodDelay.set(stream,delay);
chipId.set(stream,id);
indexSecondGoodDelay.set(hs,delay);
tmpChipId.set(hs,id);
}
}
}
......@@ -554,7 +563,7 @@ void RHD2000Thread::scanPorts()
#if DEBUG_EMULATE_HEADSTAGES > 0
for (int nd = 0; nd < MAX_NUM_DATA_STREAMS; ++nd)
{
if ((nd < DEBUG_EMULATE_HEADSTAGES) &&(chipId[0] > 0))
if ((nd < DEBUG_EMULATE_HEADSTAGES) &&(tmpChipId[0] > 0))
{
evalBoard->setDataSource(nd,initStreamPorts[0]);
enableHeadstage(nd,true);
......@@ -566,29 +575,36 @@ void RHD2000Thread::scanPorts()
}
#else
// Now, disable data streams where we did not find chips present.
for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
int chipIdx = 0;
for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)
{
if (chipId[stream] > 0)
if ((tmpChipId[hs] > 0) && (enabledStreams.size() < MAX_NUM_DATA_STREAMS))
{
chipId.set(chipIdx++,chipId[hs]);
//std::cout << "Enabling headstage on stream " << stream << std::endl;
if (chipId[stream] == CHIP_ID_RHD2164) //RHD2164
if (tmpChipId[hs] == CHIP_ID_RHD2164) //RHD2164
{
//We just add it like a second headstage, allowing only one RHD2164 per channel
//This would need to change
evalBoard->setDataSource(stream+1,initStreamDdrPorts[stream]);
enableHeadstage(stream,true);
enableHeadstage(stream+1,true);
chipId.set(stream+1,CHIP_ID_RHD2164_B);
stream++;
if (enabledStreams.size() < MAX_NUM_DATA_STREAMS - 1)
{
enableHeadstage(hs,true,2,32);
chipId.set(chipIdx++,CHIP_ID_RHD2164_B);
}
else //just one stream left
{
enableHeadstage(hs,true,1,32);
}
}
else
enableHeadstage(stream, true);
{
enableHeadstage(hs, true,1,tmpChipId[hs] == 1 ? 32:16);
}
}
else
{
enableHeadstage(stream, false);
enableHeadstage(hs, false);
}
}
updateBoardStreams();
#endif
......@@ -600,15 +616,15 @@ void RHD2000Thread::scanPorts()
Array<int> optimumDelay;
optimumDelay.insertMultiple(0,0,8);
for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)
{
if (sumGoodDelays[stream] == 1 || sumGoodDelays[stream] == 2)
if (sumGoodDelays[hs] == 1 || sumGoodDelays[hs] == 2)
{
optimumDelay.set(stream,indexFirstGoodDelay[stream]);
optimumDelay.set(hs,indexFirstGoodDelay[hs]);
}
else if (sumGoodDelays[stream] > 2)
else if (sumGoodDelays[hs] > 2)
{
optimumDelay.set(stream,indexSecondGoodDelay[stream]);
optimumDelay.set(hs,indexSecondGoodDelay[hs]);
}
}
......@@ -669,11 +685,11 @@ bool RHD2000Thread::isAcquisitionActive()
return isTransmitting;
}
void RHD2000Thread::setNumChannels(int hsNum, int numChannels)
/*void RHD2000Thread::setNumChannels(int hsNum, int numChannels)
{
if (numChannelsPerDataStream[hsNum] > 0)
numChannelsPerDataStream.set(hsNum, numChannels);
}
}*/
void RHD2000Thread::getEventChannelNames(StringArray& Names)
......@@ -836,11 +852,11 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
stream_prefix.add("D1");
stream_prefix.add("D2");
for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
{
if (numChannelsPerDataStream[i] > 0)
if (headstagesArray[i]->isPlugged())
{
for (int k = 0; k < numChannelsPerDataStream[i]; k++)
for (int k = 0; k < headstagesArray[i]->getNumChannels(); k++)
{
type.add(HEADSTAGE_CHANNEL);
......@@ -867,16 +883,16 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
}
}
//Aux channels
for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
{
if (numChannelsPerDataStream[i] > 0)
if (headstagesArray[i]->isPlugged())
{
for (int k = 0; k < 3; k++)
{
type.add(AUX_CHANNEL);
if (channelModified(AUX_CHANNEL,i,numChannelsPerDataStream[i]+k, oldName,oldGain, dummy))
if (channelModified(AUX_CHANNEL,i,headstagesArray[i]->getNumChannels()+k, oldName,oldGain, dummy))
{
Names.add(oldName);
gains.add(oldGain);
......@@ -895,7 +911,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
}
stream.add(i);
originalChannelNumber.add(numChannelsPerDataStream[i]+k);
originalChannelNumber.add(headstagesArray[i]->getNumChannels()+k);
}
}
}
......@@ -908,7 +924,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
channelNumber++;
type.add(ADC_CHANNEL);
if (channelModified(ADC_CHANNEL,MAX_NUM_DATA_STREAMS,k, oldName,oldGain,dummy))
if (channelModified(ADC_CHANNEL,MAX_NUM_HEADSTAGES,k, oldName,oldGain,dummy))
{
Names.add(oldName);
gains.add(oldGain);
......@@ -919,7 +935,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
gains.add(getAdcBitVolts(k));
}
stream.add(MAX_NUM_DATA_STREAMS);
stream.add(MAX_NUM_HEADSTAGES);
originalChannelNumber.add(k);
}
......@@ -935,12 +951,12 @@ int RHD2000Thread::getNumChannels()
int RHD2000Thread::getNumHeadstageOutputs()
{
numChannels = 0;
for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
{
if (numChannelsPerDataStream[i] > 0)
if (headstagesArray[i]->isPlugged())
{
numChannels += numChannelsPerDataStream[i];
numChannels += headstagesArray[i]->getNumChannels();
}
}
......@@ -954,9 +970,9 @@ int RHD2000Thread::getNumAuxOutputs()
{
int numAuxOutputs = 0;
for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
for (int i = 0; i < MAX_NUM_HEADSTAGES; i++)
{
if (numChannelsPerDataStream[i] > 0)
if (headstagesArray[i]->isPlugged() > 0)
{
numAuxOutputs += 3;
}
......@@ -1089,45 +1105,82 @@ bool RHD2000Thread::foundInputSource()
}
bool RHD2000Thread::enableHeadstage(int hsNum, bool enabled)
bool RHD2000Thread::enableHeadstage(int hsNum, bool enabled, int nStr, int strChans)
{
evalBoard->enableDataStream(hsNum, enabled);
/* evalBoard->enableDataStream(hsNum, enabled);*/
if (enabled)
{
numChannelsPerDataStream.set(hsNum, 32);
}
else
{
numChannelsPerDataStream.set(hsNum, 0);
}
if (enabled)
{
headstagesArray[hsNum]->setNumStreams(nStr);
headstagesArray[hsNum]->setChannelsPerStream(strChans);
enabledStreams.add(headstagesArray[hsNum]->getDataStream(0));
numChannelsPerDataStream.add(strChans);
if (nStr > 1)
{
enabledStreams.add(headstagesArray[hsNum]->getDataStream(1));
numChannelsPerDataStream.add(strChans);
}
}
else
{
int idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(0));
if (idx >= 0)
{
enabledStreams.remove(idx);
numChannelsPerDataStream.remove(idx);
}
if (headstagesArray[hsNum]->getNumStreams() > 1)
{
idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(1));
if (idx >= 0)
{
enabledStreams.remove(idx);
numChannelsPerDataStream.remove(idx);
}
}
headstagesArray[hsNum]->setNumStreams(0);
}
std::cout << "Enabled channels: ";
/*
std::cout << "Enabled channels: ";
for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
{
std::cout << numChannelsPerDataStream[i] << " ";
}
}*/
std:: cout << std::endl;
dataBuffer->resize(getNumChannels(), 10000);
return true;
}
dataBuffer->resize(getNumChannels(), 10000);
return true;
void RHD2000Thread::updateBoardStreams()
{
for (int i=0; i < MAX_NUM_DATA_STREAMS; i++)
{
if (i < enabledStreams.size())
{
evalBoard->enableDataStream(i,true);
evalBoard->setDataSource(i,enabledStreams[i]);
}
else
{
evalBoard->enableDataStream(i,false);
}
}
}
bool RHD2000Thread::isHeadstageEnabled(int hsNum)
{
if (numChannelsPerDataStream[hsNum] > 0)
{
return true;
}
return headstagesArray[hsNum]->isPlugged();
return false;
}
int RHD2000Thread::getChannelsInHeadstage(int hsNum)
{
return headstagesArray[hsNum]->getNumChannels();
}
void RHD2000Thread::assignAudioOut(int dacChannel, int dataChannel)
......@@ -1497,82 +1550,73 @@ bool RHD2000Thread::updateBuffer()
for (int samp = 0; samp < dataBlock->getSamplesPerDataBlock(); samp++)
{
int streamNumber = -1;
int channel = -1;
// do the neural data channels first
for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
{
if (numChannelsPerDataStream[dataStream] > 0)
{
streamNumber++;
for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++)
{
for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++)
{
for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++)
{
// std::cout << "reading sample stream " << streamNumber << " chan " << chan << " sample "<< samp << std::endl;
// std::cout << "reading sample stream " << streamNumber << " chan " << chan << " sample "<< samp << std::endl;
channel++;
channel++;
int value = dataBlock->amplifierData[streamNumber][chan][samp];
int value = dataBlock->amplifierData[dataStream][chan][samp];
thisSample[channel] = float(value-32768)*0.195f;
}
thisSample[channel] = float(value-32768)*0.195f;
}
}
}
}
streamNumber = -1;
// then do the Intan AUX channels
for (int dataStream = 0; dataStream < MAX_NUM_DATA_STREAMS; dataStream++)
for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++)
{
if (numChannelsPerDataStream[dataStream] > 0)
{
streamNumber++;
if (samp % 4 == 1) // every 4th sample should have auxiliary input data
{
if (samp % 4 == 1) // every 4th sample should have auxiliary input data
{
// std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
// std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+0] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[dataStream][1][samp+0] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel];
auxBuffer[channel] = thisSample[channel];
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+1] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[dataStream][1][samp+1] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel];
auxBuffer[channel] = thisSample[channel];
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+2] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
channel++;
thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[dataStream][1][samp+2] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel];
auxBuffer[channel] = thisSample[channel];
}
else // repeat last values from buffer
{
}
else // repeat last values from buffer
{
//std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
//std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl;
channel++;
thisSample[channel] = auxBuffer[channel];
channel++;
thisSample[channel] = auxBuffer[channel];
channel++;
thisSample[channel] = auxBuffer[channel];
}
channel++;
thisSample[channel] = auxBuffer[channel];
channel++;
thisSample[channel] = auxBuffer[channel];
channel++;
thisSample[channel] = auxBuffer[channel];
}
}
}
......@@ -2130,3 +2174,44 @@ void RHD2000Thread::runImpedanceTest(Array<int>& streams, Array<int>& channels,
evalBoard->enableExternalFastSettle(true);
}
}
RHDHeadstage::RHDHeadstage(Rhd2000EvalBoard::BoardDataSource stream) :
numStreams(0), channelsPerStream(32), dataStream(stream)
{
}
RHDHeadstage::~RHDHeadstage()
{
}
void RHDHeadstage::setNumStreams(int num)
{
numStreams = num;
}
void RHDHeadstage::setChannelsPerStream(int nchan)
{
channelsPerStream = nchan;
}
int RHDHeadstage::getNumChannels()
{
return channelsPerStream*numStreams;
}
int RHDHeadstage::getNumStreams()
{
return numStreams;
}
Rhd2000EvalBoard::BoardDataSource RHDHeadstage::getDataStream(int index)
{
if (index < 0 || index > 1) index = 0;
return static_cast<Rhd2000EvalBoard::BoardDataSource>(dataStream+MAX_NUM_HEADSTAGES*index);
}
bool RHDHeadstage::isPlugged()
{
return (numStreams > 0);
}
\ No newline at end of file
......@@ -40,9 +40,10 @@
#include "../GenericProcessor/GenericProcessor.h"
#define MAX_NUM_DATA_STREAMS 8
#define MAX_NUM_HEADSTAGES 8
class SourceNode;
class RHDHeadstage;
/**
Communicates with the RHD2000 Evaluation Board from Intan Technologies
......@@ -68,12 +69,8 @@ public:
float getBitVolts(Channel* chan);
float getAdcBitVolts(int channelNum);
// for internal use:
bool isHeadstageEnabled(int hsNum);
bool enableHeadstage(int hsNum, bool enabled);
void setCableLength(int hsNum, float length);
void setNumChannels(int hsNum, int nChannels);
bool isHeadstageEnabled(int hsNum);
int getChannelsInHeadstage(int hsNum);
void setSampleRate(int index, bool temporary = false);
......@@ -122,6 +119,12 @@ public:
String getChannelName(ChannelType t, int str, int ch);
private:
bool enableHeadstage(int hsNum, bool enabled, int nStr = 1, int strChans = 32);
void updateBoardStreams();
void setCableLength(int hsNum, float length);
// void setNumChannels(int hsNum, int nChannels);
void setDefaultChannelNamesAndType();
bool channelModified(ChannelType t, int str, int k, String &oldName, float &oldGain, int &index);
......@@ -130,7 +133,6 @@ private:
Rhd2000DataBlock* dataBlock;
std::vector<std::vector<std::vector<double>>> amplifierPreFilter;
Array<int> numChannelsPerDataStream;
void factorOutParallelCapacitance(double &impedanceMagnitude, double &impedancePhase,
double frequency, double parasiticCapacitance);
void empiricalResistanceCorrection(double &impedanceMagnitude, double &impedancePhase,
......@@ -188,6 +190,9 @@ private:
float *dacThresholds;
bool *dacChannelsToUpdate;
Array<int> chipId;
OwnedArray<RHDHeadstage> headstagesArray;
Array<Rhd2000EvalBoard::BoardDataSource> enabledStreams;
Array<int> numChannelsPerDataStream;
// used for data stream names...
int numberingScheme ;
......@@ -203,4 +208,22 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHD2000Thread);
};
class RHDHeadstage
{
public:
RHDHeadstage(Rhd2000EvalBoard::BoardDataSource stream);
~RHDHeadstage();
void setNumStreams(int num);
void setChannelsPerStream(int nchan);
int getNumChannels();
int getNumStreams();
Rhd2000EvalBoard::BoardDataSource getDataStream(int index);
bool isPlugged();
private:
Rhd2000EvalBoard::BoardDataSource dataStream;
int numStreams;
int channelsPerStream;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHDHeadstage);
};
#endif // __RHD2000THREAD_H_2C4CBD67__
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