Skip to content

Commit

Permalink
Fix channel duplication on 64ch headstage
Browse files Browse the repository at this point in the history
  • Loading branch information
jsiegle committed Aug 6, 2022
1 parent 73151e0 commit 5eddd69
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 22 deletions.
34 changes: 21 additions & 13 deletions Source/DeviceThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ DeviceThread::DeviceThread(SourceNode* sn, BoardType boardType_) : DataThread(sn
int maxNumHeadstages = (boardType == RHD_RECORDING_CONTROLLER) ? 16 : 8;

for (int i = 0; i < maxNumHeadstages; i++)
headstages.add(new Headstage(static_cast<Rhd2000EvalBoard::BoardDataSource>(i)));
headstages.add(new Headstage(static_cast<Rhd2000EvalBoard::BoardDataSource>(i), maxNumHeadstages));

evalBoard = new Rhd2000EvalBoard;

Expand Down Expand Up @@ -106,14 +106,19 @@ DeviceThread::DeviceThread(SourceNode* sn, BoardType boardType_) : DataThread(sn

if (openBoard(libraryFilePath))
{
dataBlock = new Rhd2000DataBlock(1,evalBoard->isUSB3());
dataBlock = new Rhd2000DataBlock(1, evalBoard->isUSB3());

// upload bitfile and restore default settings
initializeBoard();

if (evalBoard->isUSB3())
LOGD("USB3 board mode enabled");

MAX_NUM_DATA_STREAMS = evalBoard->MAX_NUM_DATA_STREAMS;
MAX_NUM_HEADSTAGES = MAX_NUM_DATA_STREAMS / 2;

//std::cout << "MAX NUM STREAMS: " << MAX_NUM_DATA_STREAMS << ", MAX NUM HEADSTAGES: " << MAX_NUM_HEADSTAGES << std::endl;

// automatically find connected headstages
scanPorts(); // things would appear to run more smoothly if this were done after the editor has been created

Expand Down Expand Up @@ -1251,6 +1256,8 @@ bool DeviceThread::foundInputSource()

bool DeviceThread::enableHeadstage(int hsNum, bool enabled, int nStr, int strChans)
{
LOGD("Headstage ", hsNum, ", enabled: ", enabled, ", num streams: ", nStr, ", stream channels: ", strChans);
LOGD("Max num headstages: ", MAX_NUM_HEADSTAGES);

if (enabled)
{
Expand Down Expand Up @@ -1301,6 +1308,7 @@ void DeviceThread::updateBoardStreams()
{
if (i < enabledStreams.size())
{
//std::cout << "Enabling stream " << i << " with source " << enabledStreams[i] << std::endl;
evalBoard->enableDataStream(i,true);
evalBoard->setDataSource(i,enabledStreams[i]);
}
Expand Down Expand Up @@ -1741,19 +1749,15 @@ bool DeviceThread::stopAcquisition()

bool DeviceThread::updateBuffer()
{
//int chOffset;
unsigned char* bufferPtr;
double ts;
//cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl;
//cout << "Block size: " << blockSize << endl;

//LOGD( "Current number of words: " << evalBoard->numWordsInFifo() << " for " << blockSize );
if (evalBoard->isUSB3() || evalBoard->numWordsInFifo() >= blockSize)
{
bool return_code;

return_code = evalBoard->readRawDataBlock(&bufferPtr);
// see Rhd2000DataBlock::fillFromUsbBuffer() for an idea of data order in bufferPtr
// see Rhd2000DataBlock::fillFromUsbBuffer() for documentation of buffer structure

int index = 0;
int auxIndex, chanIndex;
Expand All @@ -1775,23 +1779,27 @@ bool DeviceThread::updateBuffer()
int64 timestamp = Rhd2000DataBlock::convertUsbTimeStamp(bufferPtr, index);
index += 4; // timestamp width
auxIndex = index; // aux chans start at this offset
// skip aux channels for now
index += 6 * numStreams; // width of the 3 aux chans
// copy 64 neural data channels

for (int dataStream = 0; dataStream < numStreams; dataStream++)
{
{

int nChans = numChannelsPerDataStream[dataStream];

chanIndex = index + 2*dataStream;

if ((chipId[dataStream] == CHIP_ID_RHD2132) && (nChans == 16)) //RHD2132 16ch. headstage
{
chanIndex += 2 * RHD2132_16CH_OFFSET*numStreams;
chanIndex += 2 * RHD2132_16CH_OFFSET * numStreams;
}

for (int chan = 0; chan < nChans; chan++)
{
channel++;
thisSample[channel] = float(*(uint16*)(bufferPtr + chanIndex) - 32768)*0.195f;
chanIndex += 2*numStreams; // single chan width (2 bytes)
thisSample[channel] = float(*(uint16*)(bufferPtr + chanIndex) - 32768) * 0.195f;
chanIndex += 2 * numStreams; // single chan width (2 bytes)
}

}
index += 64 * numStreams; // neural data width
auxIndex += 2 * numStreams; // skip AuxCmd1 slots (see updateRegisters())
Expand Down
9 changes: 5 additions & 4 deletions Source/DeviceThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@
#define REGISTER_59_MISO_B 58
#define RHD2132_16CH_OFFSET 8

#define MAX_NUM_CHANNELS MAX_NUM_DATA_STREAMS * 35

#define MAX_NUM_HEADSTAGES MAX_NUM_DATA_STREAMS / 2
#define MAX_NUM_CHANNELS MAX_NUM_DATA_STREAMS_USB3 * 35

namespace RhythmNode
{
Expand Down Expand Up @@ -245,6 +243,9 @@ namespace RhythmNode
int ttlLine,
bool state);

int MAX_NUM_HEADSTAGES;
int MAX_NUM_DATA_STREAMS;

private:

std::queue<DigitalOutputCommand> digitalOutputCommands;
Expand Down Expand Up @@ -280,7 +281,7 @@ namespace RhythmNode
float auxBuffer[MAX_NUM_CHANNELS]; // aux inputs are only sampled every 4th sample, so use this to buffer the
// samples so they can be handles just like the regular neural channels later

float auxSamples[MAX_NUM_DATA_STREAMS][3];
float auxSamples[MAX_NUM_DATA_STREAMS_USB3][3];

unsigned int blockSize;

Expand Down
3 changes: 2 additions & 1 deletion Source/Headstage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@

using namespace RhythmNode;

Headstage::Headstage(Rhd2000EvalBoard::BoardDataSource dataSource_) :
Headstage::Headstage(Rhd2000EvalBoard::BoardDataSource dataSource_, int MAX_H) :
dataSource(dataSource_),
MAX_NUM_HEADSTAGES(MAX_H),
numStreams(0),
channelsPerStream(32),
halfChannels(false),
Expand Down
4 changes: 3 additions & 1 deletion Source/Headstage.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace RhythmNode
public:

/** Constructor */
Headstage(Rhd2000EvalBoard::BoardDataSource dataSource);
Headstage(Rhd2000EvalBoard::BoardDataSource dataSource, int MAX_NUM_HEADSTAGES);

/** Destructor*/
~Headstage() { }
Expand Down Expand Up @@ -137,6 +137,8 @@ namespace RhythmNode

bool halfChannels;

int MAX_NUM_HEADSTAGES;

ChannelNamingScheme namingScheme;

StringArray channelNames;
Expand Down
2 changes: 1 addition & 1 deletion Source/ImpedanceMeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void ImpedanceMeter::runImpedanceMeasurement(Impedances& impedances)

Array<int> enabledStreams;

for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream)
for (stream = 0; stream < board->MAX_NUM_DATA_STREAMS; ++stream)
{
CHECK_EXIT;

Expand Down
2 changes: 2 additions & 0 deletions Source/rhythm-api/rhd2000datablock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
// Constructor. Allocates memory for data block.
Rhd2000DataBlock::Rhd2000DataBlock(int numDataStreams, bool usb3) : samplesPerBlock(SAMPLES_PER_DATA_BLOCK(usb3)), usb3(usb3)
{

//std::cout << "New data block with " << numDataStreams << " streams." << std::endl;
allocateUIntArray1D(timeStamp, samplesPerBlock);
allocateIntArray3D(amplifierData, numDataStreams, 32, samplesPerBlock);
allocateIntArray3D(auxiliaryData, numDataStreams, 3, samplesPerBlock);
Expand Down
4 changes: 4 additions & 0 deletions Source/rhythm-api/rhd2000evalboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Rhd2000EvalBoard::Rhd2000EvalBoard()
dev = 0;
usb3 = false;

MAX_NUM_DATA_STREAMS = MAX_NUM_DATA_STREAMS_USB3;

for (i = 0; i < MAX_NUM_DATA_STREAMS; ++i) {
dataStreamEnabled[i] = 0;
}
Expand Down Expand Up @@ -123,6 +125,8 @@ int Rhd2000EvalBoard::open(const char* libname)
return -2;
}

MAX_NUM_DATA_STREAMS = usb3 ? MAX_NUM_DATA_STREAMS_USB3 : MAX_NUM_DATA_STREAMS_USB2;

// Configure the on-board PLL appropriately.
dev->LoadDefaultPLLConfiguration();

Expand Down
7 changes: 5 additions & 2 deletions Source/rhythm-api/rhd2000evalboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#define RHYTHM_BOARD_ID_USB3 600
#define MAX_NUM_DATA_STREAMS_USB2 8
#define MAX_NUM_DATA_STREAMS_USB3 16
#define MAX_NUM_DATA_STREAMS 32

#define FIFO_CAPACITY_WORDS 67108864

//#define MAX_NUM_DATA_STREAMS(u3) ( u3 ? MAX_NUM_DATA_STREAMS_USB3 : MAX_NUM_DATA_STREAMS_USB2 )
Expand Down Expand Up @@ -177,11 +177,13 @@ class Rhd2000EvalBoard
void printFIFOmetrics();
bool readRawDataBlock(unsigned char** bufferPtr, int nSamples = -1);

int MAX_NUM_DATA_STREAMS;

private:
OpalKellyLegacy::okCFrontPanel *dev;
AmplifierSampleRate sampleRate;
int numDataStreams; // total number of data streams currently enabled
int dataStreamEnabled[MAX_NUM_DATA_STREAMS]; // 0 (disabled) or 1 (enabled), set for maximum stream number
int dataStreamEnabled[MAX_NUM_DATA_STREAMS_USB3]; // 0 (disabled) or 1 (enabled), set for maximum stream number
std::vector<int> cableDelay;

// Buffer for reading bytes from USB interface
Expand Down Expand Up @@ -250,6 +252,7 @@ class Rhd2000EvalBoard
bool isDataClockLocked() const;

bool usb3; //Open-Ephys addition for USB3 support

};

#endif // RHD2000EVALBOARD_H

0 comments on commit 5eddd69

Please sign in to comment.