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

First workings towards RHD2164 support

parent 77143beb
No related branches found
No related tags found
No related merge requests found
...@@ -34,19 +34,21 @@ ...@@ -34,19 +34,21 @@
#define okLIB_NAME "./libokFrontPanel.so" #define okLIB_NAME "./libokFrontPanel.so"
#define okLIB_EXTENSION "*.so" #define okLIB_EXTENSION "*.so"
#endif #endif
#define CHIP_ID_RHD2164_B 1000
// Allocates memory for a 3-D array of doubles. // Allocates memory for a 3-D array of doubles.
void allocateDoubleArray3D(std::vector<std::vector<std::vector<double> > > &array3D, void allocateDoubleArray3D(std::vector<std::vector<std::vector<double> > >& array3D,
int xSize, int ySize, int zSize) int xSize, int ySize, int zSize)
{ {
int i, j; int i, j;
if (xSize == 0) return; if (xSize == 0) return;
array3D.resize(xSize); array3D.resize(xSize);
for (i = 0; i < xSize; ++i) { for (i = 0; i < xSize; ++i)
{
array3D[i].resize(ySize); array3D[i].resize(ySize);
for (j = 0; j < ySize; ++j) { for (j = 0; j < ySize; ++j)
{
array3D[i][j].resize(zSize); array3D[i][j].resize(zSize);
} }
} }
...@@ -81,25 +83,25 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn), ...@@ -81,25 +83,25 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
// Returns 1 if successful, -1 if FrontPanel cannot be loaded, and -2 if XEM6010 can't be found. // Returns 1 if successful, -1 if FrontPanel cannot be loaded, and -2 if XEM6010 can't be found.
File executable = File::getSpecialLocation(File::currentExecutableFile); File executable = File::getSpecialLocation(File::currentExecutableFile);
#if defined(__APPLE__) #if defined(__APPLE__)
const String executableDirectory = const String executableDirectory =
executable.getParentDirectory().getParentDirectory().getParentDirectory().getParentDirectory().getFullPathName(); executable.getParentDirectory().getParentDirectory().getParentDirectory().getParentDirectory().getFullPathName();
#else #else
const String executableDirectory = executable.getParentDirectory().getFullPathName(); const String executableDirectory = executable.getParentDirectory().getFullPathName();
#endif
#endif
std::cout << executableDirectory << std::endl; std::cout << executableDirectory << std::endl;
String dirName = executableDirectory; String dirName = executableDirectory;
libraryFilePath = dirName; libraryFilePath = dirName;
libraryFilePath += File::separatorString; libraryFilePath += File::separatorString;
libraryFilePath += okLIB_NAME; libraryFilePath += okLIB_NAME;
dacStream = nullptr; dacStream = nullptr;
dacChannels = nullptr; dacChannels = nullptr;
dacThresholds = nullptr; dacThresholds = nullptr;
dacChannelsToUpdate = nullptr; dacChannelsToUpdate = nullptr;
if (openBoard(libraryFilePath)) if (openBoard(libraryFilePath))
...@@ -111,23 +113,23 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn), ...@@ -111,23 +113,23 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
// automatically find connected headstages // automatically find connected headstages
scanPorts(); // things would appear to run more smoothly if this were done after the editor has been created scanPorts(); // things would appear to run more smoothly if this were done after the editor has been created
// to perform electrode impedance measurements at very low frequencies. // to perform electrode impedance measurements at very low frequencies.
const int maxNumBlocks = 120; const int maxNumBlocks = 120;
int numStreams = 8; int numStreams = 8;
allocateDoubleArray3D(amplifierPreFilter, numStreams, 32, SAMPLES_PER_DATA_BLOCK * maxNumBlocks); allocateDoubleArray3D(amplifierPreFilter, numStreams, 32, SAMPLES_PER_DATA_BLOCK * maxNumBlocks);
// probably better to do this with a thread, but a timer works for now: // probably better to do this with a thread, but a timer works for now:
// startTimer(10); // initialize the board in the background // startTimer(10); // initialize the board in the background
dacStream = new int[8]; dacStream = new int[8];
dacChannels = new int[8]; dacChannels = new int[8];
dacThresholds = new float[8]; dacThresholds = new float[8];
dacChannelsToUpdate = new bool[8]; dacChannelsToUpdate = new bool[8];
for (int k = 0; k < 8; k++) for (int k = 0; k < 8; k++)
{ {
dacChannelsToUpdate[k] = true; dacChannelsToUpdate[k] = true;
dacStream[k] = 0; dacStream[k] = 0;
setDACthreshold(k, 65534); setDACthreshold(k, 65534);
} }
evalBoard->getDacInformation(dacChannels,dacThresholds); evalBoard->getDacInformation(dacChannels,dacThresholds);
setDefaultChannelNamesAndType(); setDefaultChannelNamesAndType();
...@@ -170,7 +172,7 @@ void RHD2000Thread::setDACthreshold(int dacOutput, float threshold) ...@@ -170,7 +172,7 @@ void RHD2000Thread::setDACthreshold(int dacOutput, float threshold)
dacChannelsToUpdate[dacOutput] = true; dacChannelsToUpdate[dacOutput] = true;
dacOutputShouldChange = true; dacOutputShouldChange = true;
// evalBoard->setDacThresholdVoltage(dacOutput,threshold); // evalBoard->setDacThresholdVoltage(dacOutput,threshold);
} }
void RHD2000Thread::setDACchannel(int dacOutput, int stream, int channel) void RHD2000Thread::setDACchannel(int dacOutput, int stream, int channel)
...@@ -202,17 +204,17 @@ bool RHD2000Thread::openBoard(String pathToLibrary) ...@@ -202,17 +204,17 @@ bool RHD2000Thread::openBoard(String pathToLibrary)
} }
else if (return_code == -1) // dynamic library not found else if (return_code == -1) // dynamic library not found
{ {
bool response = AlertWindow::showOkCancelBox (AlertWindow::NoIcon, bool response = AlertWindow::showOkCancelBox(AlertWindow::NoIcon,
"Opal Kelly library not found.", "Opal Kelly library not found.",
"The Opal Kelly library file was not found in the directory of the executable. Would you like to browse for it?", "The Opal Kelly library file was not found in the directory of the executable. Would you like to browse for it?",
"Yes", "No", 0, 0); "Yes", "No", 0, 0);
if (response) if (response)
{ {
// browse for file // browse for file
FileChooser fc("Select the library file...", FileChooser fc("Select the library file...",
File::getCurrentWorkingDirectory(), File::getCurrentWorkingDirectory(),
okLIB_EXTENSION, okLIB_EXTENSION,
true); true);
if (fc.browseForFileToOpen()) if (fc.browseForFileToOpen())
{ {
...@@ -226,20 +228,25 @@ bool RHD2000Thread::openBoard(String pathToLibrary) ...@@ -226,20 +228,25 @@ bool RHD2000Thread::openBoard(String pathToLibrary)
deviceFound = false; deviceFound = false;
} }
} else { }
else
{
deviceFound = false; deviceFound = false;
} }
} else if (return_code == -2) // board could not be opened }
else if (return_code == -2) // board could not be opened
{ {
bool response = AlertWindow::showOkCancelBox (AlertWindow::NoIcon, bool response = AlertWindow::showOkCancelBox(AlertWindow::NoIcon,
"Acquisition board not found.", "Acquisition board not found.",
"An acquisition board could not be found. Please connect one now.", "An acquisition board could not be found. Please connect one now.",
"OK", "Cancel", 0, 0); "OK", "Cancel", 0, 0);
if (response) if (response)
{ {
openBoard(libraryFilePath.getCharPointer()); // call recursively openBoard(libraryFilePath.getCharPointer()); // call recursively
} else { }
else
{
deviceFound = false; deviceFound = false;
} }
...@@ -251,24 +258,24 @@ bool RHD2000Thread::openBoard(String pathToLibrary) ...@@ -251,24 +258,24 @@ bool RHD2000Thread::openBoard(String pathToLibrary)
bool RHD2000Thread::uploadBitfile(String bitfilename) bool RHD2000Thread::uploadBitfile(String bitfilename)
{ {
deviceFound = true; deviceFound = true;
if (!evalBoard->uploadFpgaBitfile(bitfilename.toStdString())) if (!evalBoard->uploadFpgaBitfile(bitfilename.toStdString()))
{ {
std::cout << "Couldn't upload bitfile from " << bitfilename << std::endl; std::cout << "Couldn't upload bitfile from " << bitfilename << std::endl;
bool response = AlertWindow::showOkCancelBox (AlertWindow::NoIcon, bool response = AlertWindow::showOkCancelBox(AlertWindow::NoIcon,
"FPGA bitfile not found.", "FPGA bitfile not found.",
"The rhd2000.bit file was not found in the directory of the executable. Would you like to browse for it?", "The rhd2000.bit file was not found in the directory of the executable. Would you like to browse for it?",
"Yes", "No", 0, 0); "Yes", "No", 0, 0);
if (response) if (response)
{ {
// browse for file // browse for file
FileChooser fc("Select the FPGA bitfile...", FileChooser fc("Select the FPGA bitfile...",
File::getCurrentWorkingDirectory(), File::getCurrentWorkingDirectory(),
"*.bit", "*.bit",
true); true);
if (fc.browseForFileToOpen()) if (fc.browseForFileToOpen())
{ {
...@@ -282,12 +289,14 @@ bool RHD2000Thread::uploadBitfile(String bitfilename) ...@@ -282,12 +289,14 @@ bool RHD2000Thread::uploadBitfile(String bitfilename)
deviceFound = false; deviceFound = false;
} }
} else { }
else
{
deviceFound = false; deviceFound = false;
} }
} }
return deviceFound; return deviceFound;
} }
...@@ -298,12 +307,12 @@ void RHD2000Thread::initializeBoard() ...@@ -298,12 +307,12 @@ void RHD2000Thread::initializeBoard()
File executable = File::getSpecialLocation(File::currentExecutableFile); File executable = File::getSpecialLocation(File::currentExecutableFile);
#if defined(__APPLE__) #if defined(__APPLE__)
const String executableDirectory = const String executableDirectory =
executable.getParentDirectory().getParentDirectory().getParentDirectory().getParentDirectory().getFullPathName(); executable.getParentDirectory().getParentDirectory().getParentDirectory().getParentDirectory().getFullPathName();
#else #else
const String executableDirectory = executable.getParentDirectory().getFullPathName(); const String executableDirectory = executable.getParentDirectory().getFullPathName();
#endif #endif
bitfilename = executableDirectory; bitfilename = executableDirectory;
bitfilename += File::separatorString; bitfilename += File::separatorString;
...@@ -354,7 +363,7 @@ void RHD2000Thread::initializeBoard() ...@@ -354,7 +363,7 @@ void RHD2000Thread::initializeBoard()
Rhd2000DataBlock* dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); Rhd2000DataBlock* dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams());
// evalBoard->readDataBlock(dataBlock); // evalBoard->readDataBlock(dataBlock);
// Now that ADC calibration has been performed, we switch to the command sequence // Now that ADC calibration has been performed, we switch to the command sequence
// that does not execute ADC calibration. // that does not execute ADC calibration.
...@@ -386,21 +395,44 @@ void RHD2000Thread::scanPorts() ...@@ -386,21 +395,44 @@ void RHD2000Thread::scanPorts()
int delay, stream, id; int delay, stream, id;
//int numChannelsOnPort[4] = {0, 0, 0, 0}; //int numChannelsOnPort[4] = {0, 0, 0, 0};
Rhd2000EvalBoard::BoardDataSource initStreamPorts[8] =
{
Rhd2000EvalBoard::PortA1,
Rhd2000EvalBoard::PortA2,
Rhd2000EvalBoard::PortB1,
Rhd2000EvalBoard::PortB2,
Rhd2000EvalBoard::PortC1,
Rhd2000EvalBoard::PortC2,
Rhd2000EvalBoard::PortD1,
Rhd2000EvalBoard::PortD2
};
Rhd2000EvalBoard::BoardDataSource initStreamDdrPorts[8] =
{
Rhd2000EvalBoard::PortA1Ddr,
Rhd2000EvalBoard::PortA2Ddr,
Rhd2000EvalBoard::PortB1Ddr,
Rhd2000EvalBoard::PortB2Ddr,
Rhd2000EvalBoard::PortC1Ddr,
Rhd2000EvalBoard::PortC2Ddr,
Rhd2000EvalBoard::PortD1Ddr,
Rhd2000EvalBoard::PortD2Ddr
};
chipId.insertMultiple(0,-1,8); chipId.insertMultiple(0,-1,8);
setSampleRate(16, true); // set to 30 kHz temporarily setSampleRate(16, true); // set to 30 kHz temporarily
// Enable all data streams, and set sources to cover one or two chips // Enable all data streams, and set sources to cover one or two chips
// on Ports A-D. // on Ports A-D.
evalBoard->setDataSource(0, Rhd2000EvalBoard::PortA1); evalBoard->setDataSource(0, initStreamPorts[0]);
evalBoard->setDataSource(1, Rhd2000EvalBoard::PortA2); evalBoard->setDataSource(1, initStreamPorts[1]);
evalBoard->setDataSource(2, Rhd2000EvalBoard::PortB1); evalBoard->setDataSource(2, initStreamPorts[2]);
evalBoard->setDataSource(3, Rhd2000EvalBoard::PortB2); evalBoard->setDataSource(3, initStreamPorts[3]);
evalBoard->setDataSource(4, Rhd2000EvalBoard::PortC1); evalBoard->setDataSource(4, initStreamPorts[4]);
evalBoard->setDataSource(5, Rhd2000EvalBoard::PortC2); evalBoard->setDataSource(5, initStreamPorts[5]);
evalBoard->setDataSource(6, Rhd2000EvalBoard::PortD1); evalBoard->setDataSource(6, initStreamPorts[6]);
evalBoard->setDataSource(7, Rhd2000EvalBoard::PortD2); evalBoard->setDataSource(7, initStreamPorts[7]);
evalBoard->enableDataStream(0, true); evalBoard->enableDataStream(0, true);
evalBoard->enableDataStream(1, true); evalBoard->enableDataStream(1, true);
...@@ -506,7 +538,18 @@ void RHD2000Thread::scanPorts() ...@@ -506,7 +538,18 @@ void RHD2000Thread::scanPorts()
if (chipId[stream] > 0) if (chipId[stream] > 0)
{ {
//std::cout << "Enabling headstage on stream " << stream << std::endl; //std::cout << "Enabling headstage on stream " << stream << std::endl;
enableHeadstage(stream, true); if (chipId[stream] == 4) //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++;
}
else
enableHeadstage(stream, true);
} }
else else
{ {
...@@ -606,20 +649,20 @@ int RHD2000Thread::getNumADCchannels() ...@@ -606,20 +649,20 @@ int RHD2000Thread::getNumADCchannels()
{ {
if (acquireAdcChannels) if (acquireAdcChannels)
return 8; return 8;
else else
return 0; return 0;
} }
void RHD2000Thread::getEventChannelNames(StringArray &Names) void RHD2000Thread::getEventChannelNames(StringArray& Names)
{ {
Names.clear(); Names.clear();
for (int k=0;k<8;k++) for (int k=0; k<8; k++)
{ {
Names.add("TTL"+String(k+1)); Names.add("TTL"+String(k+1));
} }
} }
void RHD2000Thread::getChannelsInfo(StringArray &Names_, Array<channelType> &type_, Array<int> &stream_, Array<int> &originalChannelNumber_,Array<float> &gains_) void RHD2000Thread::getChannelsInfo(StringArray& Names_, Array<channelType>& type_, Array<int>& stream_, Array<int>& originalChannelNumber_,Array<float>& gains_)
{ {
Names_ = Names; Names_ = Names;
type_ = type; type_ = type;
...@@ -635,11 +678,11 @@ void RHD2000Thread::updateChannelNames() ...@@ -635,11 +678,11 @@ void RHD2000Thread::updateChannelNames()
/* go over the old names and tests whether this particular channel name was changed. /* go over the old names and tests whether this particular channel name was changed.
if so, return the old name */ if so, return the old name */
bool RHD2000Thread::channelModified(channelType t, int str, int ch, String &oldName, float &oldGain, int &index) bool RHD2000Thread::channelModified(channelType t, int str, int ch, String& oldName, float& oldGain, int& index)
{ {
for (int k=0;k<oldNames.size();k++) for (int k=0; k<oldNames.size(); k++)
{ {
if (oldType[k] == t && oldStream[k] == str && oldChannelNumber[k] == ch) if (oldType[k] == t && oldStream[k] == str && oldChannelNumber[k] == ch)
{ {
oldName = oldNames[k]; oldName = oldNames[k];
oldGain = oldGains[k]; oldGain = oldGains[k];
...@@ -659,7 +702,8 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN ...@@ -659,7 +702,8 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN
if (channelModified(t, str, ch, dummy, dummyFloat, index)) if (channelModified(t, str, ch, dummy, dummyFloat, index))
{ {
oldNames.set(index, newName); oldNames.set(index, newName);
} else }
else
{ {
oldNames.add(newName); oldNames.add(newName);
oldType.add(t); oldType.add(t);
...@@ -668,9 +712,9 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN ...@@ -668,9 +712,9 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN
oldGains.add(dummyFloat); oldGains.add(dummyFloat);
} }
for (int k=0;k<Names.size();k++) for (int k=0; k<Names.size(); k++)
{ {
if (type[k] == t && stream[k] == str && originalChannelNumber[k] == ch) if (type[k] == t && stream[k] == str && originalChannelNumber[k] == ch)
{ {
Names.set(k,newName); Names.set(k,newName);
return k; return k;
...@@ -687,7 +731,8 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain) ...@@ -687,7 +731,8 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain)
if (channelModified(t, str, ch, dummy, dummyFloat, index)) if (channelModified(t, str, ch, dummy, dummyFloat, index))
{ {
oldGains.set(index, gain); oldGains.set(index, gain);
} else }
else
{ {
oldNames.add(dummy); oldNames.add(dummy);
oldType.add(t); oldType.add(t);
...@@ -696,9 +741,9 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain) ...@@ -696,9 +741,9 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain)
oldGains.add(gain); oldGains.add(gain);
} }
for (int k=0;k<Names.size();k++) for (int k=0; k<Names.size(); k++)
{ {
if (type[k] == t && stream[k] == str && originalChannelNumber[k] == ch) if (type[k] == t && stream[k] == str && originalChannelNumber[k] == ch)
{ {
gains.set(k,gain); gains.set(k,gain);
return k; return k;
...@@ -727,49 +772,57 @@ void RHD2000Thread::setDefaultChannelNamesAndType() ...@@ -727,49 +772,57 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
stream.clear(); stream.clear();
gains.clear(); gains.clear();
originalChannelNumber.clear(); originalChannelNumber.clear();
int aux_counter=1; int aux_counter=1;
int data_counter = 1; int data_counter = 1;
String oldName; String oldName;
int dummy; int dummy;
float oldGain; float oldGain;
StringArray stream_prefix; StringArray stream_prefix;
stream_prefix.add("A1");stream_prefix.add("A2"); stream_prefix.add("A1");
stream_prefix.add("B1");stream_prefix.add("B2"); stream_prefix.add("A2");
stream_prefix.add("C1");stream_prefix.add("C2"); stream_prefix.add("B1");
stream_prefix.add("D1");stream_prefix.add("D2"); stream_prefix.add("B2");
stream_prefix.add("C1");
stream_prefix.add("C2");
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_DATA_STREAMS; i++)
{ {
if (numChannelsPerDataStream[i] > 0) if (numChannelsPerDataStream[i] > 0)
{ {
for (int k=0;k<numChannelsPerDataStream[i];k++) for (int k=0; k<numChannelsPerDataStream[i]; k++)
{ {
if (channelModified(DATA_CHANNEL,i,k, oldName,oldGain,dummy)) { if (channelModified(DATA_CHANNEL,i,k, oldName,oldGain,dummy))
{
Names.add(oldName); Names.add(oldName);
gains.add(oldGain); gains.add(oldGain);
data_counter++; data_counter++;
} else }
else
{ {
if (numberingScheme == 1) if (numberingScheme == 1)
Names.add("CH"+String(data_counter++)); Names.add("CH"+String(data_counter++));
else else
Names.add("CH_"+stream_prefix[i]+"_"+String(1+k)); Names.add("CH_"+stream_prefix[i]+"_"+String(1+k));
gains.add(getBitVolts()); gains.add(getBitVolts());
} }
type.add(DATA_CHANNEL); type.add(DATA_CHANNEL);
stream.add(i); stream.add(i);
originalChannelNumber.add(k); originalChannelNumber.add(k);
} }
for (int k=0;k<3;k++) for (int k=0; k<3; k++)
{ {
if (channelModified(AUX_CHANNEL,i,numChannelsPerDataStream[i]+k, oldName,oldGain, dummy)) { if (channelModified(AUX_CHANNEL,i,numChannelsPerDataStream[i]+k, oldName,oldGain, dummy))
{
Names.add(oldName); Names.add(oldName);
gains.add(oldGain); gains.add(oldGain);
aux_counter++; aux_counter++;
} else }
else
{ {
if (numberingScheme == 1) if (numberingScheme == 1)
Names.add("AUX"+String(aux_counter++)); Names.add("AUX"+String(aux_counter++));
...@@ -782,27 +835,29 @@ void RHD2000Thread::setDefaultChannelNamesAndType() ...@@ -782,27 +835,29 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
type.add(AUX_CHANNEL); type.add(AUX_CHANNEL);
stream.add(i); stream.add(i);
originalChannelNumber.add(numChannelsPerDataStream[i]+k); originalChannelNumber.add(numChannelsPerDataStream[i]+k);
} }
} }
} }
if (acquireAdcChannels) if (acquireAdcChannels)
{ {
for (int k=0;k<8;k++) for (int k=0; k<8; k++)
{ {
if (channelModified(ADC_CHANNEL,MAX_NUM_DATA_STREAMS,k, oldName,oldGain,dummy)) { if (channelModified(ADC_CHANNEL,MAX_NUM_DATA_STREAMS,k, oldName,oldGain,dummy))
{
Names.add(oldName); Names.add(oldName);
gains.add(oldGain); gains.add(oldGain);
} else }
else
{ {
Names.add("ADC"+String(k+1)); Names.add("ADC"+String(k+1));
gains.add(getBitVolts()); gains.add(getBitVolts());
} }
type.add(ADC_CHANNEL); type.add(ADC_CHANNEL);
stream.add(MAX_NUM_DATA_STREAMS); stream.add(MAX_NUM_DATA_STREAMS);
originalChannelNumber.add(k); originalChannelNumber.add(k);
} }
} }
...@@ -871,7 +926,7 @@ void RHD2000Thread::setTTLoutputMode(bool state) ...@@ -871,7 +926,7 @@ void RHD2000Thread::setTTLoutputMode(bool state)
{ {
ttlMode = state; ttlMode = state;
dacOutputShouldChange = true; dacOutputShouldChange = true;
} }
void RHD2000Thread::setDAChpf(float cutoff, bool enabled) void RHD2000Thread::setDAChpf(float cutoff, bool enabled)
...@@ -892,13 +947,13 @@ int RHD2000Thread::setNoiseSlicerLevel(int level) ...@@ -892,13 +947,13 @@ int RHD2000Thread::setNoiseSlicerLevel(int level)
{ {
desiredNoiseSlicerLevel = level; desiredNoiseSlicerLevel = level;
if (deviceFound) if (deviceFound)
evalBoard->setAudioNoiseSuppress(desiredNoiseSlicerLevel); evalBoard->setAudioNoiseSuppress(desiredNoiseSlicerLevel);
// Level has been checked once before this and then is checked again in setAudioNoiseSuppress. // Level has been checked once before this and then is checked again in setAudioNoiseSuppress.
// This may be overkill - maybe API should change so that the final function returns the value? // This may be overkill - maybe API should change so that the final function returns the value?
actualNoiseSlicerLevel = level; actualNoiseSlicerLevel = level;
return actualNoiseSlicerLevel; return actualNoiseSlicerLevel;
} }
...@@ -1163,9 +1218,9 @@ void RHD2000Thread::updateRegisters() ...@@ -1163,9 +1218,9 @@ void RHD2000Thread::updateRegisters()
evalBoard->selectAuxCommandLength(Rhd2000EvalBoard::AuxCmd3, 0, evalBoard->selectAuxCommandLength(Rhd2000EvalBoard::AuxCmd3, 0,
commandSequenceLength - 1); commandSequenceLength - 1);
chipRegisters.setFastSettle(true); chipRegisters.setFastSettle(true);
commandSequenceLength = chipRegisters.createCommandListRegisterConfig(commandList, false); commandSequenceLength = chipRegisters.createCommandListRegisterConfig(commandList, false);
// Upload version with fast settle enabled to AuxCmd3 RAM Bank 2. // Upload version with fast settle enabled to AuxCmd3 RAM Bank 2.
evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 2); evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 2);
...@@ -1225,13 +1280,13 @@ bool RHD2000Thread::startAcquisition() ...@@ -1225,13 +1280,13 @@ bool RHD2000Thread::startAcquisition()
//std::cout << "Setting max timestep." << std::endl; //std::cout << "Setting max timestep." << std::endl;
//evalBoard->setMaxTimeStep(100); //evalBoard->setMaxTimeStep(100);
std::cout << "Starting acquisition." << std::endl; std::cout << "Starting acquisition." << std::endl;
if (1) if (1)
{ {
// evalBoard->setContinuousRunMode(false); // evalBoard->setContinuousRunMode(false);
// evalBoard->setMaxTimeStep(0); // evalBoard->setMaxTimeStep(0);
std::cout << "Flushing FIFO." << std::endl; std::cout << "Flushing FIFO." << std::endl;
evalBoard->flush(); evalBoard->flush();
evalBoard->setContinuousRunMode(true); evalBoard->setContinuousRunMode(true);
...@@ -1275,14 +1330,14 @@ bool RHD2000Thread::stopAcquisition() ...@@ -1275,14 +1330,14 @@ bool RHD2000Thread::stopAcquisition()
evalBoard->setMaxTimeStep(0); evalBoard->setMaxTimeStep(0);
std::cout << "Flushing FIFO." << std::endl; std::cout << "Flushing FIFO." << std::endl;
evalBoard->flush(); evalBoard->flush();
// evalBoard->setContinuousRunMode(true); // evalBoard->setContinuousRunMode(true);
// evalBoard->run(); // evalBoard->run();
} }
dataBuffer->clear(); dataBuffer->clear();
if(deviceFound) if (deviceFound)
{ {
cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl;
...@@ -1324,9 +1379,9 @@ bool RHD2000Thread::updateBuffer() ...@@ -1324,9 +1379,9 @@ bool RHD2000Thread::updateBuffer()
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[streamNumber][chan][samp];
...@@ -1350,19 +1405,19 @@ bool RHD2000Thread::updateBuffer() ...@@ -1350,19 +1405,19 @@ bool RHD2000Thread::updateBuffer()
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++; channel++;
thisSample[channel] = 0.0374 * thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+0] - 45000.0f) ; float(dataBlock->auxiliaryData[streamNumber][1][samp+0] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer // constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel]; auxBuffer[channel] = thisSample[channel];
channel++; channel++;
thisSample[channel] = 0.0374 * thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+1] - 45000.0f) ; float(dataBlock->auxiliaryData[streamNumber][1][samp+1] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer // constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel]; auxBuffer[channel] = thisSample[channel];
...@@ -1370,7 +1425,7 @@ bool RHD2000Thread::updateBuffer() ...@@ -1370,7 +1425,7 @@ bool RHD2000Thread::updateBuffer()
channel++; channel++;
thisSample[channel] = 0.0374 * thisSample[channel] = 0.0374 *
float(dataBlock->auxiliaryData[streamNumber][1][samp+2] - 45000.0f) ; float(dataBlock->auxiliaryData[streamNumber][1][samp+2] - 45000.0f) ;
// constant offset keeps the values visible in the LFP Viewer // constant offset keeps the values visible in the LFP Viewer
auxBuffer[channel] = thisSample[channel]; auxBuffer[channel] = thisSample[channel];
...@@ -1419,7 +1474,7 @@ bool RHD2000Thread::updateBuffer() ...@@ -1419,7 +1474,7 @@ bool RHD2000Thread::updateBuffer()
if (dacOutputShouldChange) if (dacOutputShouldChange)
{ {
for (int k=0;k<8;k++) for (int k=0; k<8; k++)
{ {
if (dacChannelsToUpdate[k]) if (dacChannelsToUpdate[k])
{ {
...@@ -1440,9 +1495,9 @@ bool RHD2000Thread::updateBuffer() ...@@ -1440,9 +1495,9 @@ bool RHD2000Thread::updateBuffer()
evalBoard->setTtlMode(ttlMode); evalBoard->setTtlMode(ttlMode);
evalBoard->setFastSettleByTTL(fastTTLSettleEnabled); evalBoard->setFastSettleByTTL(fastTTLSettleEnabled);
evalBoard->setFastSettleByTTLchannel(fastSettleTTLChannel); evalBoard->setFastSettleByTTLchannel(fastSettleTTLChannel);
evalBoard->setDacHighpassFilter(desiredDAChpf); evalBoard->setDacHighpassFilter(desiredDAChpf);
evalBoard->enableDacHighpassFilter(desiredDAChpfState); evalBoard->enableDacHighpassFilter(desiredDAChpfState);
dacOutputShouldChange = false; dacOutputShouldChange = false;
} }
...@@ -1455,7 +1510,7 @@ bool RHD2000Thread::updateBuffer() ...@@ -1455,7 +1510,7 @@ bool RHD2000Thread::updateBuffer()
/***********************************/ /***********************************/
/* Below is code for impedance measurements */ /* Below is code for impedance measurements */
#define CHIP_ID_RHD2164_B 1000
...@@ -1463,7 +1518,7 @@ bool RHD2000Thread::updateBuffer() ...@@ -1463,7 +1518,7 @@ bool RHD2000Thread::updateBuffer()
// requested test frequency lies within acceptable ranges based on the // requested test frequency lies within acceptable ranges based on the
// amplifier bandwidth and the sampling rate. See impedancefreqdialog.cpp // amplifier bandwidth and the sampling rate. See impedancefreqdialog.cpp
// for more information. // for more information.
float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool &impedanceFreqValid) float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool& impedanceFreqValid)
{ {
int impedancePeriod; int impedancePeriod;
double lowerBandwidthLimit, upperBandwidthLimit; double lowerBandwidthLimit, upperBandwidthLimit;
...@@ -1471,24 +1526,32 @@ float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool & ...@@ -1471,24 +1526,32 @@ float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool &
upperBandwidthLimit = actualUpperBandwidth / 1.5; upperBandwidthLimit = actualUpperBandwidth / 1.5;
lowerBandwidthLimit = actualLowerBandwidth * 1.5; lowerBandwidthLimit = actualLowerBandwidth * 1.5;
if (dspEnabled) { if (dspEnabled)
if (actualDspCutoffFreq > actualLowerBandwidth) { {
if (actualDspCutoffFreq > actualLowerBandwidth)
{
lowerBandwidthLimit = actualDspCutoffFreq * 1.5; lowerBandwidthLimit = actualDspCutoffFreq * 1.5;
} }
} }
if (desiredImpedanceFreq > 0.0) { if (desiredImpedanceFreq > 0.0)
{
impedancePeriod = (boardSampleRate / desiredImpedanceFreq); impedancePeriod = (boardSampleRate / desiredImpedanceFreq);
if (impedancePeriod >= 4 && impedancePeriod <= 1024 && if (impedancePeriod >= 4 && impedancePeriod <= 1024 &&
desiredImpedanceFreq >= lowerBandwidthLimit && desiredImpedanceFreq >= lowerBandwidthLimit &&
desiredImpedanceFreq <= upperBandwidthLimit) { desiredImpedanceFreq <= upperBandwidthLimit)
{
actualImpedanceFreq = boardSampleRate / impedancePeriod; actualImpedanceFreq = boardSampleRate / impedancePeriod;
impedanceFreqValid = true; impedanceFreqValid = true;
} else { }
else
{
actualImpedanceFreq = 0.0; actualImpedanceFreq = 0.0;
impedanceFreqValid = false; impedanceFreqValid = false;
} }
} else { }
else
{
actualImpedanceFreq = 0.0; actualImpedanceFreq = 0.0;
impedanceFreqValid = false; impedanceFreqValid = false;
} }
...@@ -1500,10 +1563,10 @@ float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool & ...@@ -1500,10 +1563,10 @@ float RHD2000Thread::updateImpedanceFrequency(float desiredImpedanceFreq, bool &
// Reads numBlocks blocks of raw USB data stored in a queue of Rhd2000DataBlock // Reads numBlocks blocks of raw USB data stored in a queue of Rhd2000DataBlock
// objects, loads this data into this SignalProcessor object, scaling the raw // objects, loads this data into this SignalProcessor object, scaling the raw
// data to generate waveforms with units of volts or microvolts. // data to generate waveforms with units of volts or microvolts.
int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue, int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock>& dataQueue,
int numBlocks, int numDataStreams) int numBlocks, int numDataStreams)
{ {
int block, t, channel, stream, i, j; int block, t, channel, stream, i, j;
int indexAmp = 0; int indexAmp = 0;
int indexAux = 0; int indexAux = 0;
...@@ -1520,17 +1583,21 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue, ...@@ -1520,17 +1583,21 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue,
bool triggerFound = false; bool triggerFound = false;
const double AnalogTriggerThreshold = 1.65; const double AnalogTriggerThreshold = 1.65;
for (block = 0; block < numBlocks; ++block) { for (block = 0; block < numBlocks; ++block)
{
// Load and scale RHD2000 amplifier waveforms // Load and scale RHD2000 amplifier waveforms
// (sampled at amplifier sampling rate) // (sampled at amplifier sampling rate)
for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t) { for (t = 0; t < SAMPLES_PER_DATA_BLOCK; ++t)
for (channel = 0; channel < 32; ++channel) { {
for (stream = 0; stream < numDataStreams; ++stream) { for (channel = 0; channel < 32; ++channel)
{
for (stream = 0; stream < numDataStreams; ++stream)
{
// Amplifier waveform units = microvolts // Amplifier waveform units = microvolts
amplifierPreFilter[stream][channel][indexAmp] = 0.195 * amplifierPreFilter[stream][channel][indexAmp] = 0.195 *
(dataQueue.front().amplifierData[stream][channel][t] - 32768); (dataQueue.front().amplifierData[stream][channel][t] - 32768);
} }
} }
++indexAmp; ++indexAmp;
...@@ -1539,7 +1606,7 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue, ...@@ -1539,7 +1606,7 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue,
dataQueue.pop(); dataQueue.pop();
} }
return 0; return 0;
} }
#define PI 3.14159265359 #define PI 3.14159265359
...@@ -1549,17 +1616,18 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue, ...@@ -1549,17 +1616,18 @@ int RHD2000Thread::loadAmplifierData(queue<Rhd2000DataBlock> &dataQueue,
// Return the magnitude and phase (in degrees) of a selected frequency component (in Hz) // Return the magnitude and phase (in degrees) of a selected frequency component (in Hz)
// for a selected amplifier channel on the selected USB data stream. // for a selected amplifier channel on the selected USB data stream.
void RHD2000Thread::measureComplexAmplitude(std::vector<std::vector<std::vector<double>>> &measuredMagnitude, void RHD2000Thread::measureComplexAmplitude(std::vector<std::vector<std::vector<double>>>& measuredMagnitude,
std::vector<std::vector<std::vector<double>>> &measuredPhase, std::vector<std::vector<std::vector<double>>>& measuredPhase,
int capIndex, int stream, int chipChannel, int numBlocks, int capIndex, int stream, int chipChannel, int numBlocks,
double sampleRate, double frequency, int numPeriods) double sampleRate, double frequency, int numPeriods)
{ {
int period = (sampleRate / frequency); int period = (sampleRate / frequency);
int startIndex = 0; int startIndex = 0;
int endIndex = startIndex + numPeriods * period - 1; int endIndex = startIndex + numPeriods * period - 1;
// Move the measurement window to the end of the waveform to ignore start-up transient. // Move the measurement window to the end of the waveform to ignore start-up transient.
while (endIndex < SAMPLES_PER_DATA_BLOCK * numBlocks - period) { while (endIndex < SAMPLES_PER_DATA_BLOCK * numBlocks - period)
{
startIndex += period; startIndex += period;
endIndex += period; endIndex += period;
} }
...@@ -1571,16 +1639,16 @@ void RHD2000Thread::measureComplexAmplitude(std::vector<std::vector<std::vector< ...@@ -1571,16 +1639,16 @@ void RHD2000Thread::measureComplexAmplitude(std::vector<std::vector<std::vector<
startIndex, endIndex, sampleRate, frequency); startIndex, endIndex, sampleRate, frequency);
// Calculate magnitude and phase from real (I) and imaginary (Q) components. // Calculate magnitude and phase from real (I) and imaginary (Q) components.
measuredMagnitude[stream][chipChannel][capIndex] = measuredMagnitude[stream][chipChannel][capIndex] =
sqrt(iComponent * iComponent + qComponent * qComponent); sqrt(iComponent * iComponent + qComponent * qComponent);
measuredPhase[stream][chipChannel][capIndex] = measuredPhase[stream][chipChannel][capIndex] =
RADIANS_TO_DEGREES *atan2(qComponent, iComponent); RADIANS_TO_DEGREES *atan2(qComponent, iComponent);
} }
// Returns the real and imaginary amplitudes of a selected frequency component in the vector // Returns the real and imaginary amplitudes of a selected frequency component in the vector
// data, between a start index and end index. // data, between a start index and end index.
void RHD2000Thread::amplitudeOfFreqComponent(double &realComponent, double &imagComponent, void RHD2000Thread::amplitudeOfFreqComponent(double& realComponent, double& imagComponent,
const std::vector<double> &data, int startIndex, const std::vector<double>& data, int startIndex,
int endIndex, double sampleRate, double frequency) int endIndex, double sampleRate, double frequency)
{ {
int length = endIndex - startIndex + 1; int length = endIndex - startIndex + 1;
const double k = TWO_PI * frequency / sampleRate; // precalculate for speed const double k = TWO_PI * frequency / sampleRate; // precalculate for speed
...@@ -1588,7 +1656,8 @@ void RHD2000Thread::amplitudeOfFreqComponent(double &realComponent, double &imag ...@@ -1588,7 +1656,8 @@ void RHD2000Thread::amplitudeOfFreqComponent(double &realComponent, double &imag
// Perform correlation with sine and cosine waveforms. // Perform correlation with sine and cosine waveforms.
double meanI = 0.0; double meanI = 0.0;
double meanQ = 0.0; double meanQ = 0.0;
for (int t = startIndex; t <= endIndex; ++t) { for (int t = startIndex; t <= endIndex; ++t)
{
meanI += data.at(t) * cos(k * t); meanI += data.at(t) * cos(k * t);
meanQ += data.at(t) * -1.0 * sin(k * t); meanQ += data.at(t) * -1.0 * sin(k * t);
} }
...@@ -1605,8 +1674,8 @@ void RHD2000Thread::amplitudeOfFreqComponent(double &realComponent, double &imag ...@@ -1605,8 +1674,8 @@ void RHD2000Thread::amplitudeOfFreqComponent(double &realComponent, double &imag
// with a parasitic capacitance (i.e., due to the amplifier input capacitance and other // with a parasitic capacitance (i.e., due to the amplifier input capacitance and other
// capacitances associated with the chip bondpads), this function factors out the effect of the // capacitances associated with the chip bondpads), this function factors out the effect of the
// parasitic capacitance to return the acutal electrode impedance. // parasitic capacitance to return the acutal electrode impedance.
void RHD2000Thread::factorOutParallelCapacitance(double &impedanceMagnitude, double &impedancePhase, void RHD2000Thread::factorOutParallelCapacitance(double& impedanceMagnitude, double& impedancePhase,
double frequency, double parasiticCapacitance) double frequency, double parasiticCapacitance)
{ {
// First, convert from polar coordinates to rectangular coordinates. // First, convert from polar coordinates to rectangular coordinates.
double measuredR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase); double measuredR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase);
...@@ -1629,8 +1698,8 @@ void RHD2000Thread::factorOutParallelCapacitance(double &impedanceMagnitude, dou ...@@ -1629,8 +1698,8 @@ void RHD2000Thread::factorOutParallelCapacitance(double &impedanceMagnitude, dou
// 2-pole lowpass filter. This function attempts to somewhat correct for this, but a better // 2-pole lowpass filter. This function attempts to somewhat correct for this, but a better
// solution is to always run impedance measurements at 20 kS/s, where they seem to be most // solution is to always run impedance measurements at 20 kS/s, where they seem to be most
// accurate. // accurate.
void RHD2000Thread::empiricalResistanceCorrection(double &impedanceMagnitude, double &impedancePhase, void RHD2000Thread::empiricalResistanceCorrection(double& impedanceMagnitude, double& impedancePhase,
double boardSampleRate) double boardSampleRate)
{ {
// First, convert from polar coordinates to rectangular coordinates. // First, convert from polar coordinates to rectangular coordinates.
double impedanceR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase); double impedanceR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase);
...@@ -1644,7 +1713,7 @@ void RHD2000Thread::empiricalResistanceCorrection(double &impedanceMagnitude, do ...@@ -1644,7 +1713,7 @@ void RHD2000Thread::empiricalResistanceCorrection(double &impedanceMagnitude, do
impedancePhase = RADIANS_TO_DEGREES * atan2(impedanceX, impedanceR); impedancePhase = RADIANS_TO_DEGREES * atan2(impedanceX, impedanceR);
} }
void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, Array<float> &magnitudes, Array<float> &phases) void RHD2000Thread::runImpedanceTest(Array<int>& streams, Array<int>& channels, Array<float>& magnitudes, Array<float>& phases)
{ {
int commandSequenceLength, stream, channel, capRange; int commandSequenceLength, stream, channel, capRange;
double cSeries; double cSeries;
...@@ -1652,17 +1721,19 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1652,17 +1721,19 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
int triggerIndex; // dummy reference variable; not used int triggerIndex; // dummy reference variable; not used
queue<Rhd2000DataBlock> bufferQueue; // dummy reference variable; not used queue<Rhd2000DataBlock> bufferQueue; // dummy reference variable; not used
int numdataStreams = evalBoard->getNumEnabledDataStreams(); int numdataStreams = evalBoard->getNumEnabledDataStreams();
bool rhd2164ChipPresent = false; bool rhd2164ChipPresent = false;
Array<int> enabledStreams; Array<int> enabledStreams;
for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream) { for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
{
if (evalBoard->isStreamEnabled(stream)) if (evalBoard->isStreamEnabled(stream))
{ {
enabledStreams.add(stream); enabledStreams.add(stream);
} }
if (chipId[stream] == CHIP_ID_RHD2164_B) { if (chipId[stream] == CHIP_ID_RHD2164_B)
{
rhd2164ChipPresent = true; rhd2164ChipPresent = true;
} }
} }
...@@ -1724,10 +1795,12 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1724,10 +1795,12 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
measuredMagnitude.resize(evalBoard->getNumEnabledDataStreams()); measuredMagnitude.resize(evalBoard->getNumEnabledDataStreams());
measuredPhase.resize(evalBoard->getNumEnabledDataStreams()); measuredPhase.resize(evalBoard->getNumEnabledDataStreams());
for (int i = 0; i < evalBoard->getNumEnabledDataStreams(); ++i) { for (int i = 0; i < evalBoard->getNumEnabledDataStreams(); ++i)
{
measuredMagnitude[i].resize(32); measuredMagnitude[i].resize(32);
measuredPhase[i].resize(32); measuredPhase[i].resize(32);
for (int j = 0; j < 32; ++j) { for (int j = 0; j < 32; ++j)
{
measuredMagnitude[i][j].resize(3); measuredMagnitude[i][j].resize(3);
measuredPhase[i][j].resize(3); measuredPhase[i][j].resize(3);
} }
...@@ -1739,10 +1812,10 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1739,10 +1812,10 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
double impedanceMagnitude, impedancePhase; double impedanceMagnitude, impedancePhase;
const double bestAmplitude = 250.0; // we favor voltage readings that are closest to 250 uV: not too large, const double bestAmplitude = 250.0; // we favor voltage readings that are closest to 250 uV: not too large,
// and not too small. // and not too small.
const double dacVoltageAmplitude = 128 * (1.225 / 256); // this assumes the DAC amplitude was set to 128 const double dacVoltageAmplitude = 128 * (1.225 / 256); // this assumes the DAC amplitude was set to 128
const double parasiticCapacitance = 14.0e-12; // 14 pF: an estimate of on-chip parasitic capacitance, const double parasiticCapacitance = 14.0e-12; // 14 pF: an estimate of on-chip parasitic capacitance,
// including 10 pF of amplifier input capacitance. // including 10 pF of amplifier input capacitance.
double relativeFreq = actualImpedanceFreq / boardSampleRate; double relativeFreq = actualImpedanceFreq / boardSampleRate;
int bestAmplitudeIndex; int bestAmplitudeIndex;
...@@ -1750,75 +1823,83 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1750,75 +1823,83 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
// We execute three complete electrode impedance measurements: one each with // We execute three complete electrode impedance measurements: one each with
// Cseries set to 0.1 pF, 1 pF, and 10 pF. Then we select the best measurement // Cseries set to 0.1 pF, 1 pF, and 10 pF. Then we select the best measurement
// for each channel so that we achieve a wide impedance measurement range. // for each channel so that we achieve a wide impedance measurement range.
for (capRange = 0; capRange < 3; ++ capRange) for (capRange = 0; capRange < 3; ++ capRange)
{ {
switch (capRange) {
case 0: switch (capRange)
chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs100fF); {
cSeries = 0.1e-12; case 0:
cout << "setting capacitance to 0.1pF" << endl; chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs100fF);
break; cSeries = 0.1e-12;
case 1: cout << "setting capacitance to 0.1pF" << endl;
chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs1pF); break;
cSeries = 1.0e-12; case 1:
cout << "setting capacitance to 1pF" << endl; chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs1pF);
break; cSeries = 1.0e-12;
case 2: cout << "setting capacitance to 1pF" << endl;
chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs10pF); break;
cSeries = 10.0e-12; case 2:
cout << "setting capacitance to 10pF" << endl; chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs10pF);
break; cSeries = 10.0e-12;
cout << "setting capacitance to 10pF" << endl;
break;
} }
// Check all 32 channels across all active data streams. // Check all 32 channels across all active data streams.
for (channel = 0; channel < 32; ++channel) for (channel = 0; channel < 32; ++channel)
{ {
cout << "running impedance on channel " << channel << endl; cout << "running impedance on channel " << channel << endl;
chipRegisters.setZcheckChannel(channel); chipRegisters.setZcheckChannel(channel);
commandSequenceLength = commandSequenceLength =
chipRegisters.createCommandListRegisterConfig(commandList, false); chipRegisters.createCommandListRegisterConfig(commandList, false);
// Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1.
evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 3); evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 3);
evalBoard->run(); evalBoard->run();
while (evalBoard->isRunning() ) { while (evalBoard->isRunning())
{
} }
queue<Rhd2000DataBlock> dataQueue; queue<Rhd2000DataBlock> dataQueue;
evalBoard->readDataBlocks(numBlocks, dataQueue); evalBoard->readDataBlocks(numBlocks, dataQueue);
loadAmplifierData(dataQueue, numBlocks, numdataStreams); loadAmplifierData(dataQueue, numBlocks, numdataStreams);
for (stream = 0; stream < numdataStreams; ++stream) { for (stream = 0; stream < numdataStreams; ++stream)
if (chipId[stream] != CHIP_ID_RHD2164_B) { {
if (chipId[stream] != CHIP_ID_RHD2164_B)
{
measureComplexAmplitude(measuredMagnitude, measuredPhase, measureComplexAmplitude(measuredMagnitude, measuredPhase,
capRange, stream, channel, numBlocks, boardSampleRate, capRange, stream, channel, numBlocks, boardSampleRate,
actualImpedanceFreq, numPeriods); actualImpedanceFreq, numPeriods);
} }
} }
// If an RHD2164 chip is plugged in, we have to set the Zcheck select register to channels 32-63 // If an RHD2164 chip is plugged in, we have to set the Zcheck select register to channels 32-63
// and repeat the previous steps. // and repeat the previous steps.
if (rhd2164ChipPresent) { if (rhd2164ChipPresent)
{
chipRegisters.setZcheckChannel(channel + 32); // address channels 32-63 chipRegisters.setZcheckChannel(channel + 32); // address channels 32-63
commandSequenceLength = commandSequenceLength =
chipRegisters.createCommandListRegisterConfig(commandList, false); chipRegisters.createCommandListRegisterConfig(commandList, false);
// Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1.
evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 3); evalBoard->uploadCommandList(commandList, Rhd2000EvalBoard::AuxCmd3, 3);
evalBoard->run(); evalBoard->run();
while (evalBoard->isRunning() ) { while (evalBoard->isRunning())
{
} }
evalBoard->readDataBlocks(numBlocks, dataQueue); evalBoard->readDataBlocks(numBlocks, dataQueue);
loadAmplifierData(dataQueue, numBlocks, numdataStreams); loadAmplifierData(dataQueue, numBlocks, numdataStreams);
for (stream = 0; stream < evalBoard->getNumEnabledDataStreams(); ++stream) { for (stream = 0; stream < evalBoard->getNumEnabledDataStreams(); ++stream)
if (chipId[stream] == CHIP_ID_RHD2164_B) { {
if (chipId[stream] == CHIP_ID_RHD2164_B)
{
measureComplexAmplitude(measuredMagnitude, measuredPhase, measureComplexAmplitude(measuredMagnitude, measuredPhase,
capRange, stream, channel, numBlocks, boardSampleRate, capRange, stream, channel, numBlocks, boardSampleRate,
actualImpedanceFreq, numPeriods); actualImpedanceFreq, numPeriods);
} }
} }
} }
...@@ -1830,28 +1911,34 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1830,28 +1911,34 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
magnitudes.clear(); magnitudes.clear();
phases.clear(); phases.clear();
for (stream = 0; stream < evalBoard->getNumEnabledDataStreams(); ++stream) { for (stream = 0; stream < evalBoard->getNumEnabledDataStreams(); ++stream)
for (channel = 0; channel < 32; ++channel) { {
if (1) { for (channel = 0; channel < 32; ++channel)
{
if (1)
{
minDistance = 9.9e99; // ridiculously large number minDistance = 9.9e99; // ridiculously large number
for (capRange = 0; capRange < 3; ++capRange) { for (capRange = 0; capRange < 3; ++capRange)
{
// Find the measured amplitude that is closest to bestAmplitude on a logarithmic scale // Find the measured amplitude that is closest to bestAmplitude on a logarithmic scale
distance = abs(log(measuredMagnitude[stream][channel][capRange] / bestAmplitude)); distance = abs(log(measuredMagnitude[stream][channel][capRange] / bestAmplitude));
if (distance < minDistance) { if (distance < minDistance)
{
bestAmplitudeIndex = capRange; bestAmplitudeIndex = capRange;
minDistance = distance; minDistance = distance;
} }
} }
switch (bestAmplitudeIndex) { switch (bestAmplitudeIndex)
case 0: {
Cseries = 0.1e-12; case 0:
break; Cseries = 0.1e-12;
case 1: break;
Cseries = 1.0e-12; case 1:
break; Cseries = 1.0e-12;
case 2: break;
Cseries = 10.0e-12; case 2:
break; Cseries = 10.0e-12;
break;
} }
// Calculate current amplitude produced by on-chip voltage DAC // Calculate current amplitude produced by on-chip voltage DAC
...@@ -1859,7 +1946,7 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1859,7 +1946,7 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
// Calculate impedance magnitude from calculated current and measured voltage. // Calculate impedance magnitude from calculated current and measured voltage.
impedanceMagnitude = 1.0e-6 * (measuredMagnitude[stream][channel][bestAmplitudeIndex] / current) * impedanceMagnitude = 1.0e-6 * (measuredMagnitude[stream][channel][bestAmplitudeIndex] / current) *
(18.0 * relativeFreq * relativeFreq + 1.0); (18.0 * relativeFreq * relativeFreq + 1.0);
// Calculate impedance phase, with small correction factor accounting for the // Calculate impedance phase, with small correction factor accounting for the
// 3-command SPI pipeline delay. // 3-command SPI pipeline delay.
...@@ -1881,9 +1968,9 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels, ...@@ -1881,9 +1968,9 @@ void RHD2000Thread::runImpedanceTest(Array<int> &streams, Array<int> &channels,
if (impedanceMagnitude > 1000000) if (impedanceMagnitude > 1000000)
cout << "stream " << stream << " channel " << 1+channel << " magnitude: " << String(impedanceMagnitude/1e6,2) << " mOhm , phase : " <<impedancePhase << endl; cout << "stream " << stream << " channel " << 1+channel << " magnitude: " << String(impedanceMagnitude/1e6,2) << " mOhm , phase : " <<impedancePhase << endl;
else else
cout << "stream " << stream << " channel " << 1+channel << " magnitude: " << String(impedanceMagnitude/1e3,2) << " kOhm , phase : " <<impedancePhase << endl; cout << "stream " << stream << " channel " << 1+channel << " magnitude: " << String(impedanceMagnitude/1e3,2) << " kOhm , phase : " <<impedancePhase << endl;
} }
} }
} }
......
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