Skip to content

Commit d4ad0ce

Browse files
committed
Fix issues with usb transfer
1 parent 8f1f632 commit d4ad0ce

9 files changed

Lines changed: 199 additions & 26 deletions

File tree

Builds/VisualStudio2013/Plugins/IntanRecordingController/IntanRecordingController.vcxproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
<CharacterSet>MultiByte</CharacterSet>
3838
</PropertyGroup>
3939
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
40-
<ConfigurationType>Application</ConfigurationType>
40+
<ConfigurationType>DynamicLibrary</ConfigurationType>
4141
<UseDebugLibraries>false</UseDebugLibraries>
4242
<PlatformToolset>v120</PlatformToolset>
4343
<WholeProgramOptimization>true</WholeProgramOptimization>
4444
<CharacterSet>MultiByte</CharacterSet>
4545
</PropertyGroup>
4646
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
47-
<ConfigurationType>Application</ConfigurationType>
47+
<ConfigurationType>DynamicLibrary</ConfigurationType>
4848
<UseDebugLibraries>false</UseDebugLibraries>
4949
<PlatformToolset>v120</PlatformToolset>
5050
<WholeProgramOptimization>true</WholeProgramOptimization>
@@ -134,6 +134,7 @@
134134
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000datablockusb3.cpp" />
135135
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000evalboardusb3.cpp" />
136136
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000registersusb3.cpp" />
137+
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\USBThread.cpp" />
137138
</ItemGroup>
138139
<ItemGroup>
139140
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\RHD2000Editor.h" />
@@ -142,6 +143,7 @@
142143
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000datablockusb3.h" />
143144
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000evalboardusb3.h" />
144145
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000registersusb3.h" />
146+
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\USBThread.h" />
145147
</ItemGroup>
146148
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
147149
<ImportGroup Label="ExtensionTargets">

Builds/VisualStudio2013/Plugins/IntanRecordingController/IntanRecordingController.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000registersusb3.cpp">
3737
<Filter>Source Files\rhythm-api</Filter>
3838
</ClCompile>
39+
<ClCompile Include="..\..\..\..\Source\Plugins\IntanRecordingController\USBThread.cpp">
40+
<Filter>Source Files</Filter>
41+
</ClCompile>
3942
</ItemGroup>
4043
<ItemGroup>
4144
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\RHD2000Editor.h">
@@ -56,5 +59,8 @@
5659
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\rhythm-api\rhd2000registersusb3.h">
5760
<Filter>Source Files\rhythm-api</Filter>
5861
</ClInclude>
62+
<ClInclude Include="..\..\..\..\Source\Plugins\IntanRecordingController\USBThread.h">
63+
<Filter>Header Files</Filter>
64+
</ClInclude>
5965
</ItemGroup>
6066
</Project>

Source/Plugins/IntanRecordingController/RHD2000Thread.cpp

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "RHD2000Thread.h"
2525
#include "RHD2000Editor.h"
26+
#include "USBThread.h"
2627

2728
#if defined(_WIN32)
2829
#define okLIB_NAME "okFrontPanel.dll"
@@ -367,6 +368,10 @@ void RHD2000Thread::initializeBoard()
367368
{
368369
return;
369370
}
371+
372+
//Instantiate usb thread
373+
usbThread = new USBThread(evalBoard);
374+
370375
// Initialize the board
371376
std::cout << "Initializing acquisition board." << std::endl;
372377
evalBoard->initialize();
@@ -1403,24 +1408,31 @@ bool RHD2000Thread::startAcquisition()
14031408
//std::cout << "Setting max timestep." << std::endl;
14041409
//evalBoard->setMaxTimeStep(100);
14051410

1411+
blockSize = dataBlock->calculateDataBlockSizeInWords(evalBoard->getNumEnabledDataStreams());
1412+
std::cout << "Expecting blocksize of " << blockSize << " for " << evalBoard->getNumEnabledDataStreams() << " streams" << std::endl;
14061413

1407-
std::cout << "Starting acquisition." << std::endl;
1408-
if (1)
1409-
{
1410-
// evalBoard->setContinuousRunMode(false);
1411-
// evalBoard->setMaxTimeStep(0);
1412-
std::cout << "Flushing FIFO." << std::endl;
1413-
evalBoard->flush();
1414-
evalBoard->setContinuousRunMode(true);
1415-
//evalBoard->printFIFOmetrics();
1416-
evalBoard->run();
1417-
//evalBoard->printFIFOmetrics();
1418-
}
1414+
//evalBoard->printFIFOmetrics();
14191415

1420-
blockSize = dataBlock->calculateDataBlockSizeInWords(evalBoard->getNumEnabledDataStreams());
1421-
std::cout << "Expecting blocksize of " << blockSize << " for " << evalBoard->getNumEnabledDataStreams() << " streams" << std::endl;
1416+
// evalBoard->setContinuousRunMode(false);
1417+
// evalBoard->setMaxTimeStep(0);
1418+
std::cout << "Flushing FIFO." << std::endl;
1419+
evalBoard->flush();
1420+
std::cout << "FIFO count " << evalBoard->getNumWordsInFifo() << std::endl;
1421+
1422+
std::cout << "Starting usb thread with buffer of " << blockSize * 2 << " bytes" << std::endl;
1423+
usbThread->startAcquisition(blockSize * 2);
1424+
1425+
std::cout << "Starting acquisition." << std::endl;
1426+
evalBoard->setContinuousRunMode(true);
1427+
//evalBoard->printFIFOmetrics();
1428+
evalBoard->run();
14221429
//evalBoard->printFIFOmetrics();
1423-
startThread();
1430+
startThread();
1431+
1432+
1433+
1434+
1435+
14241436

14251437

14261438
isTransmitting = true;
@@ -1433,6 +1445,7 @@ bool RHD2000Thread::stopAcquisition()
14331445

14341446
// isTransmitting = false;
14351447
std::cout << "RHD2000 data thread stopping acquisition." << std::endl;
1448+
usbThread->stopAcquisition();
14361449

14371450
if (isThreadRunning())
14381451
{
@@ -1482,14 +1495,15 @@ bool RHD2000Thread::stopAcquisition()
14821495
bool RHD2000Thread::updateBuffer()
14831496
{
14841497
//int chOffset;
1485-
unsigned char* bufferPtr;
14861498
//cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl;
14871499
//cout << "Block size: " << blockSize << endl;
1488-
1500+
unsigned char* bufferPtr;
14891501
//std::cout << "Current number of words: " << evalBoard->numWordsInFifo() << " for " << blockSize << std::endl;
1490-
bool return_code;
1502+
long return_code;
14911503

1492-
return_code = evalBoard->readDataBlocksRaw(1,bufferPtr);
1504+
return_code = usbThread->usbRead(bufferPtr);
1505+
if (return_code == 0)
1506+
return true;
14931507

14941508
int index = 0;
14951509
int auxIndex, chanIndex;
@@ -1504,6 +1518,7 @@ bool RHD2000Thread::updateBuffer()
15041518
if (!Rhd2000DataBlockUsb3::checkUsbHeader(bufferPtr, index))
15051519
{
15061520
cerr << "Error in Rhd2000EvalBoard::readDataBlock: Incorrect header." << endl;
1521+
cerr << "Read code: " << return_code << endl;
15071522
break;
15081523
}
15091524

@@ -1584,7 +1599,6 @@ bool RHD2000Thread::updateBuffer()
15841599

15851600
if (dacOutputShouldChange)
15861601
{
1587-
std::cout << "DAC" << std::endl;
15881602
for (int k=0; k<8; k++)
15891603
{
15901604
if (dacChannelsToUpdate[k])

Source/Plugins/IntanRecordingController/RHD2000Thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
class SourceNode;
4242
class RHDHeadstage;
4343
class RHDImpedanceMeasure;
44+
class USBThread;
4445

4546
struct ImpedanceData
4647
{
@@ -212,6 +213,7 @@ class RHD2000Thread : public DataThread
212213
Array<float> adcBitVolts;
213214
bool newScan;
214215
ScopedPointer<RHDImpedanceMeasure> impedanceThread;
216+
ScopedPointer<USBThread> usbThread;
215217

216218
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHD2000Thread);
217219
};
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
------------------------------------------------------------------
3+
4+
This file is part of the Open Ephys GUI
5+
Copyright (C) 2016 Open Ephys
6+
7+
------------------------------------------------------------------
8+
9+
This program is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
24+
#include "USBThread.h"
25+
#include "rhythm-api/rhd2000evalboardusb3.h"
26+
27+
USBThread::USBThread(Rhd2000EvalBoardUsb3* b)
28+
: m_board(b), Thread("USBThread")
29+
{
30+
}
31+
32+
33+
USBThread::~USBThread()
34+
{
35+
}
36+
37+
void USBThread::startAcquisition(int nBytes)
38+
{
39+
ScopedLock lock(m_lock);
40+
for (int i = 0; i < 2; i++)
41+
{
42+
m_lastRead[i] = 0;
43+
m_buffers[i].malloc(nBytes);
44+
}
45+
m_curBuffer = 0;
46+
m_readBuffer = 0;
47+
m_canRead = true;
48+
startThread();
49+
}
50+
51+
void USBThread::stopAcquisition()
52+
{
53+
std::cout << "Stopping usb thread" << std::endl;
54+
if (!stopThread(1000))
55+
{
56+
std::cerr << "USB Thread could not stop cleanly. Force quitting it" << std::endl;
57+
}
58+
}
59+
60+
long USBThread::usbRead(unsigned char*& buffer)
61+
{
62+
ScopedLock lock(m_lock);
63+
if (m_readBuffer == m_curBuffer)
64+
return 0;
65+
buffer = m_buffers[m_readBuffer].getData();
66+
long read = m_lastRead[m_readBuffer];
67+
m_readBuffer = ++m_readBuffer % 2;
68+
m_canRead = true;
69+
notify();
70+
return read;
71+
}
72+
73+
void USBThread::run()
74+
{
75+
while (!threadShouldExit())
76+
{
77+
m_lock.enter();
78+
if (m_canRead)
79+
{
80+
m_lock.exit();
81+
long read;
82+
do
83+
{
84+
if (threadShouldExit())
85+
break;
86+
read = m_board->readDataBlocksRaw(1, m_buffers[m_curBuffer].getData());
87+
} while (read <= 0);
88+
{
89+
ScopedLock lock(m_lock);
90+
m_lastRead[m_curBuffer] = read;
91+
m_curBuffer = ++m_curBuffer % 2;
92+
m_canRead = false;
93+
}
94+
}
95+
else
96+
m_lock.exit();
97+
98+
if (!threadShouldExit())
99+
wait(100);
100+
}
101+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
------------------------------------------------------------------
3+
4+
This file is part of the Open Ephys GUI
5+
Copyright (C) 2016 Open Ephys
6+
7+
------------------------------------------------------------------
8+
9+
This program is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
#ifndef USBTHREAD_H
24+
#define USBTHREAD_H
25+
26+
#include <BasicJuceHeader.h>
27+
#include <atomic>
28+
class Rhd2000EvalBoardUsb3;
29+
30+
class USBThread : Thread
31+
{
32+
public:
33+
USBThread(Rhd2000EvalBoardUsb3*);
34+
~USBThread();
35+
void run() override;
36+
void startAcquisition(int nBytes);
37+
void stopAcquisition();
38+
long usbRead(unsigned char*&);
39+
private:
40+
Rhd2000EvalBoardUsb3* const m_board;
41+
HeapBlock<unsigned char> m_buffers[2];
42+
long m_lastRead[2];
43+
unsigned short m_curBuffer{ 0 };
44+
unsigned short m_readBuffer{ 0 };
45+
bool m_canRead{ false };
46+
CriticalSection m_lock;
47+
};
48+
49+
#endif

Source/Plugins/IntanRecordingController/rhythm-api/rhd2000datablockusb3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#ifndef RHD2000DATABLOCKUSB3_H
2222
#define RHD2000DATABLOCKUSB3_H
2323

24-
#define SAMPLES_PER_DATA_BLOCK 128
24+
#define SAMPLES_PER_DATA_BLOCK 256
2525
#define CHANNELS_PER_STREAM 32
2626
#define RHD2000_HEADER_MAGIC_NUMBER 0xd7a22aaa38132a53
2727

Source/Plugins/IntanRecordingController/rhythm-api/rhd2000evalboardusb3.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,8 +1494,7 @@ long Rhd2000EvalBoardUsb3::readDataBlocksRaw(int numBlocks, unsigned char* buffe
14941494
unsigned int numWordsToRead = numBlocks * Rhd2000DataBlockUsb3::calculateDataBlockSizeInWords(numDataStreams, nSamples);
14951495

14961496
if (numWordsInFifo() < numWordsToRead)
1497-
return 0;
1498-
1497+
return 0;
14991498
long result = dev->ReadFromBlockPipeOut(PipeOutData, USB3_BLOCK_SIZE, 2 * numWordsToRead, buffer);
15001499

15011500
if (result == ok_Failed) {

Source/Plugins/IntanRecordingController/rhythm-api/rhd2000evalboardusb3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
#define FIFO_CAPACITY_WORDS 67108864
3535

36-
#define USB3_BLOCK_SIZE 1024
36+
#define USB3_BLOCK_SIZE 2048
3737
#define RAM_BURST_SIZE 32
3838

3939
#include <queue>

0 commit comments

Comments
 (0)