diff --git a/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp b/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp index c3b02ff8b3f60688dcdd5117fec107672a64cb90..827d816bf7ae383b93e35b39f9c7383e289e89db 100644 --- a/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp +++ b/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp @@ -46,6 +46,7 @@ //#define DEBUG_EMULATE_HEADSTAGES 8 //#define DEBUG_EMULATE_64CH +//#define DEBUG_REAL_HEADSTAGE 5 #define INIT_STEP 256 @@ -277,6 +278,7 @@ void RHD2000Thread::initializeBoard() // Initialize the board std::cout << "Initializing acquisition board." << std::endl; + evalBoard->openPipe(); evalBoard->initialize(); // This applies the following settings: // - sample rate to 30 kHz @@ -319,7 +321,7 @@ void RHD2000Thread::initializeBoard() // Read the resulting single data block from the USB interface. We don't // need to do anything with this, since it was only used for ADC calibration - ScopedPointer<Rhd2000DataBlock> dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); + ScopedPointer<Rhd2000DataBlock> dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams(), INIT_STEP); evalBoard->readDataBlock(dataBlock, INIT_STEP); // Now that ADC calibration has been performed, we switch to the command sequence @@ -333,7 +335,7 @@ void RHD2000Thread::initializeBoard() evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, fastSettleEnabled ? 2 : 1); - + evalBoard->closePipe(); } @@ -347,7 +349,7 @@ void RHD2000Thread::scanPorts() impedanceThread->stopThreadSafely(); //Clear previous known streams enabledStreams.clear(); - + evalBoard->openPipe(); // Scan SPI ports int delay, hs, id; @@ -422,7 +424,7 @@ void RHD2000Thread::scanPorts() evalBoard->setContinuousRunMode(false); ScopedPointer<Rhd2000DataBlock> dataBlock = - new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); + new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams(), INIT_STEP); Array<int> sumGoodDelays; sumGoodDelays.insertMultiple(0, 0, 8); @@ -494,12 +496,12 @@ void RHD2000Thread::scanPorts() //std::cout << std::endl; #if DEBUG_EMULATE_HEADSTAGES > 0 - if (tmpChipId[0] > 0) + if (tmpChipId[DEBUG_REAL_HEADSTAGE] > 0) { int chipIdx = 0; for (int hs = 0; hs < DEBUG_EMULATE_HEADSTAGES && hs < MAX_NUM_HEADSTAGES ; ++hs) { - if (enabledStreams.size() < MAX_NUM_DATA_STREAMS(evalBoard->isUSB3())) + if (enabledStreams.size() < MAX_NUM_DATA_STREAMS) { #ifdef DEBUG_EMULATE_64CH chipId.set(chipIdx++,CHIP_ID_RHD2164); @@ -513,7 +515,7 @@ void RHD2000Thread::scanPorts() } for (int i = 0; i < enabledStreams.size(); i++) { - enabledStreams.set(i,Rhd2000EvalBoard::PortA1); + enabledStreams.set(i,(rhd2000PCIe::BoardDataSource)DEBUG_REAL_HEADSTAGE); } } @@ -591,6 +593,7 @@ void RHD2000Thread::scanPorts() evalBoard->estimateCableLengthMeters(max(optimumDelay[6],optimumDelay[7])); setSampleRate(savedSampleRateIndex); // restore saved sample rate + evalBoard->closePipe(); //updateRegisters(); newScan = true; } @@ -1321,7 +1324,7 @@ bool RHD2000Thread::startAcquisition() // evalBoard->setContinuousRunMode(false); // evalBoard->setMaxTimeStep(0); std::cout << "Flushing FIFO." << std::endl; - evalBoard->flush(); + evalBoard->openPipe(); evalBoard->setContinuousRunMode(true); //evalBoard->printFIFOmetrics(); evalBoard->run(); @@ -1365,7 +1368,7 @@ bool RHD2000Thread::stopAcquisition() evalBoard->setContinuousRunMode(false); evalBoard->setMaxTimeStep(0); std::cout << "Flushing FIFO." << std::endl; - evalBoard->flush(); + evalBoard->closePipe(); // evalBoard->setContinuousRunMode(true); // evalBoard->run(); @@ -2073,6 +2076,7 @@ void RHDImpedanceMeasure::run() ed = (RHD2000Editor*)board->sn->editor.get(); if (data == nullptr) return; + board->evalBoard->openPipe(); runImpedanceMeasurement(); restoreFPGA(); ed->triggerAsyncUpdate(); @@ -2159,7 +2163,7 @@ void RHDImpedanceMeasure::runImpedanceMeasurement() CHECK_EXIT; board->evalBoard->setContinuousRunMode(false); - board->evalBoard->setMaxTimeStep(SAMPLES_PER_DATA_BLOCK_PCIE * numBlocks); + board->evalBoard->setMaxTimeStep(INIT_STEP * numBlocks); // Create matrices of doubles of size (numStreams x 32 x 3) to store complex amplitudes // of all amplifier channels (32 on each data stream) at three different Cseries values. @@ -2361,7 +2365,7 @@ void RHDImpedanceMeasure::restoreFPGA() { board->evalBoard->setContinuousRunMode(false); board->evalBoard->setMaxTimeStep(0); - board->evalBoard->flush(); + board->evalBoard->closePipe(); // Switch back to flatline board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd1, 0); diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp index 923344b62b6bb42a582fe826566ec736f92f94be..bd898d827ebfd2fd31beb2dad4eb62a5c3779548 100644 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp +++ b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp @@ -67,6 +67,7 @@ void rhd2000PCIe::writeRegister(controlAddr reg, int16_t value, int16_t mask) { int16_t curVal; int rd = Read(fidControl, &curVal, 2); + if (rd < 2) { std::cerr << "Unsuccesful read to control addr " << regAddr << " code: " << rd << std::endl; return; @@ -125,25 +126,40 @@ bool rhd2000PCIe::open() return false; } + std::cout << "Device files opened" << std::endl; + return true; +} + +bool rhd2000PCIe::openPipe() +{ fidFIFO = Open("\\\\.\\xillybus_neural_data_32", O_RDONLY | O_BINARY); if (fidFIFO < 0) { std:cerr << "Error opening data FIFO" << std::endl; - Close(fidControl); - Close(fidStatus); - fidControl = -1; - fidStatus = -1; + return false; } - std::cout << "Device files opened" << std::endl; + std::cout << "Pipe opened" << std::endl; return true; } +void rhd2000PCIe::closePipe() +{ + if (fidFIFO >= 0) + { + Close(fidFIFO); + fidFIFO = -1; + std::cout << "Pipe closed" << std::endl; + } + else + std::cerr << "ERROR: pipe already closed" << std::endl; +} + // Initialize Rhythm FPGA to default starting values. void rhd2000PCIe::initialize() { int i; - resetBoard(); + //resetBoard(); setSampleRate(SampleRate30000Hz); selectAuxCommandBank(PortA, AuxCmd1, 0); selectAuxCommandBank(PortB, AuxCmd1, 0); @@ -255,76 +271,78 @@ bool rhd2000PCIe::setSampleRate(AmplifierSampleRate newSampleRate) // pulse DCM_prog_trigger high (e.g., using an okTriggerIn module). If this module is reset, it // reverts to a per-channel sampling rate of 30.0 kS/s. - unsigned long M, D; - + unsigned long M, O, D; + D = 0; switch (newSampleRate) { case SampleRate1000Hz: M = 7; - D = 125; + O = 125; break; case SampleRate1250Hz: M = 7; - D = 100; + O = 100; break; case SampleRate1500Hz: M = 21; - D = 250; + O = 125; + D = 0x8000; break; case SampleRate2000Hz: M = 14; - D = 125; + O = 125; break; case SampleRate2500Hz: M = 35; - D = 250; + O = 125; + D = 0x8000; break; case SampleRate3000Hz: M = 21; - D = 125; + O = 125; break; case SampleRate3333Hz: M = 14; - D = 75; + O = 75; break; case SampleRate4000Hz: M = 28; - D = 125; + O = 125; break; case SampleRate5000Hz: M = 7; - D = 25; + O = 25; break; case SampleRate6250Hz: M = 7; - D = 20; + O = 20; break; case SampleRate8000Hz: - M = 112; - D = 250; + M = 56; + O = 125; break; case SampleRate10000Hz: M = 14; - D = 25; + O = 25; break; case SampleRate12500Hz: M = 7; - D = 10; + O = 10; break; case SampleRate15000Hz: M = 21; - D = 25; + O = 25; break; case SampleRate20000Hz: M = 28; - D = 25; + O = 25; break; case SampleRate25000Hz: M = 35; - D = 25; + O = 25; break; case SampleRate30000Hz: M = 42; - D = 25; + O = 25; break; default: return(false); @@ -336,7 +354,7 @@ bool rhd2000PCIe::setSampleRate(AmplifierSampleRate newSampleRate) while (isDcmProgDone() == false) {} // Reprogram clock synthesizer - writeRegister(DataFreqPll, (256 * M + D)); + writeRegister(DataFreqPll, D+ ((M<<8)&0x7F00) + (O&0x00FF)); // Wait for DataClkLocked = 1 before allowing data acquisition to continue while (isDataClockLocked() == false) {} @@ -456,7 +474,7 @@ void rhd2000PCIe::uploadCommandList(const vector<int> &commandList, AuxCmdSlot a for (i = 0; i < commandList.size(); ++i) { int16_t value = commandList[i]; - int wd = Write(fidControl, &value, 2); + int wd = Write(fidMem, &value, 2); if (wd < 2) { std::cerr << "Error writing auxcmd " << auxCommandSlot << " index " << i << std::endl; @@ -865,6 +883,7 @@ bool rhd2000PCIe::isStreamEnabled(int streamIndex) bool rhd2000PCIe::readRawDataBlock(unsigned char** bufferPtr, int nSamples) { unsigned int numBytesToRead; + unsigned int numread = 0; numBytesToRead = 2 * Rhd2000DataBlock::calculateDataBlockSizeInWords(numDataStreams, nSamples); @@ -875,21 +894,20 @@ bool rhd2000PCIe::readRawDataBlock(unsigned char** bufferPtr, int nSamples) return false; } - int nr = Read(fidFIFO, dataBuffer, numBytesToRead); + do { + int nr = Read(fidFIFO, dataBuffer, numBytesToRead); - if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - } - else if (nr < numBytesToRead) - { - cerr << "CRITICAL: Timeout on pipe read. Check block and buffer sizes." << endl; - } + if (nr < 0) + { + std::cerr << "Error reading from pipe" << std::endl; + } + numread += nr; + } while (numread < numBytesToRead); *bufferPtr = dataBuffer; return true; } - +/* void rhd2000PCIe::flush() { int nr = 0; @@ -899,7 +917,7 @@ void rhd2000PCIe::flush() } while (nr > 0); -} +}*/ // Read data block from the USB interface, if one is available. Returns true if data block // was available. @@ -907,6 +925,7 @@ bool rhd2000PCIe::readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples) { unsigned int numBytesToRead; long res; + unsigned int numread = 0; numBytesToRead = 2 * dataBlock->calculateDataBlockSizeInWords(numDataStreams, nSamples); @@ -916,16 +935,17 @@ bool rhd2000PCIe::readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples) return false; } - int nr = Read(fidFIFO, dataBuffer, numBytesToRead); + do { + int nr = Read(fidFIFO, dataBuffer, numBytesToRead); - if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - } - else if (nr < numBytesToRead) - { - cerr << "CRITICAL: Timeout on pipe read. Check block and buffer sizes." << endl; - } + if (nr < 0) + { + std::cerr << "Error reading from pipe" << std::endl; + break; + } + numread += nr; + } while (numread < numBytesToRead); + dataBlock->fillFromUsbBuffer(dataBuffer, 0, numDataStreams, nSamples); @@ -934,14 +954,16 @@ bool rhd2000PCIe::readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples) // Reads a certain number of USB data blocks, if the specified number is available, and appends them // to queue. Returns true if data blocks were available. -bool rhd2000PCIe::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue) +bool rhd2000PCIe::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue, int nSamples) { unsigned int numWordsToRead, numBytesToRead; int i; + unsigned int numread = 0; Rhd2000DataBlock *dataBlock; + + if (nSamples < 1) nSamples = SAMPLES_PER_DATA_BLOCK_PCIE; - - numWordsToRead = numBlocks * dataBlock->calculateDataBlockSizeInWords(numDataStreams); + numWordsToRead = numBlocks * dataBlock->calculateDataBlockSizeInWords(numDataStreams, nSamples); numBytesToRead = 2 * numWordsToRead; @@ -952,18 +974,17 @@ bool rhd2000PCIe::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQue return false; } - int nr = Read(fidFIFO, dataBuffer, numBytesToRead); + do { + int nr = Read(fidFIFO, dataBuffer, numBytesToRead); - if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - } - else if (nr < numBytesToRead) - { - cerr << "CRITICAL: Timeout on pipe read. Check block and buffer sizes." << endl; - } + if (nr < 0) + { + std::cerr << "Error reading from pipe" << std::endl; + } + numread += nr; + } while (numread < numBytesToRead); - dataBlock = new Rhd2000DataBlock(numDataStreams); + dataBlock = new Rhd2000DataBlock(numDataStreams, nSamples); for (i = 0; i < numBlocks; ++i) { dataBlock->fillFromUsbBuffer(dataBuffer, i, numDataStreams); dataQueue.push(*dataBlock); diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h index 638728a7157d82933befdf61974771e9dbf855cf..255f2554de0eaa095701323c9eff4f18f4e3c366 100644 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h +++ b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h @@ -107,9 +107,12 @@ namespace PCIeRhythm { bool readRawDataBlock(unsigned char** bufferPtr, int nSamples = -1); bool readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples = -1); - bool readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue); + bool readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue, int nSamples = -1); - void flush(); + bool openPipe(); + void closePipe(); + + //void flush(); private: diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp index 9363fb196c41554ce5849249cce7448d1360119d..6d52e8b78ef80bd50f9a5f914f9bbfe102fc8054 100644 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp +++ b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp @@ -32,7 +32,7 @@ using namespace PCIeRhythm; // from a Rhythm FPGA interface controlling up to eight RHD2000 chips. // Constructor. Allocates memory for data block. -Rhd2000DataBlock::Rhd2000DataBlock(int numDataStreams) : samplesPerBlock(SAMPLES_PER_DATA_BLOCK_PCIE) +Rhd2000DataBlock::Rhd2000DataBlock(int numDataStreams, int nSamples) : samplesPerBlock(nSamples) { allocateUIntArray1D(timeStamp, samplesPerBlock); allocateIntArray3D(amplifierData, numDataStreams, 32, samplesPerBlock); diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h index b126b4f51fd135fa2115d2d6e1dc759250172705..d4aff22f4692c968b8dd5743fd74e1d6f7df3068 100644 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h +++ b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h @@ -33,7 +33,7 @@ namespace PCIeRhythm { class Rhd2000DataBlock { public: - Rhd2000DataBlock(int numDataStreams); + Rhd2000DataBlock(int numDataStreams, int nSamples = SAMPLES_PER_DATA_BLOCK_PCIE); vector<unsigned int> timeStamp; vector<vector<vector<int> > > amplifierData; diff --git a/Source/UI/EditorViewport.cpp b/Source/UI/EditorViewport.cpp index 3110f73e3cd0866e58043ec059a54e1f347778d0..b295b51bdb86a7e78eea44fd033635aeae11575f 100755 --- a/Source/UI/EditorViewport.cpp +++ b/Source/UI/EditorViewport.cpp @@ -80,8 +80,8 @@ EditorViewport::EditorViewport() EditorViewport::~EditorViewport() { + signalChainManager = nullptr; deleteAllChildren(); - delete signalChainManager; } void EditorViewport::signalChainCanBeEdited(bool t) diff --git a/Source/UI/EditorViewport.h b/Source/UI/EditorViewport.h index bcc3266159f1c145d3d59465e24bd3c2057f2c1d..dc94421f53bc2b6b97bbb8dd88175e5d035e167d 100755 --- a/Source/UI/EditorViewport.h +++ b/Source/UI/EditorViewport.h @@ -188,7 +188,7 @@ private: Array<GenericEditor*, CriticalSection> editorArray; Array<SignalChainTabButton*, CriticalSection> signalChainArray; - SignalChainManager* signalChainManager; + ScopedPointer<SignalChainManager> signalChainManager; Font font; Image sourceDropImage;