Skip to content

Commit

Permalink
WIP new interface
Browse files Browse the repository at this point in the history
  • Loading branch information
StoneLin0708 committed May 22, 2024
1 parent 513924c commit 7e8e3e9
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 433 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
!**/Build/CMAKE_README.txt

/.vscode
/.cache
/.venv
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/fmtlib/fmt.git
15 changes: 9 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ if (NOT CMAKE_LIBRARY_ARCHITECTURE)
endif()
endif()

target_compile_options(${PLUGIN_NAME} PRIVATE $<$<CONFIG:Debug>:-fsanitize=address>)
target_link_libraries(${PLUGIN_NAME} $<$<CONFIG:Debug>:-fsanitize=address>)
# target_compile_options(${PLUGIN_NAME} PRIVATE $<$<CONFIG:Debug>:-fsanitize=address>)
# target_link_libraries(${PLUGIN_NAME} $<$<CONFIG:Debug>:-fsanitize=address>)

#Libraries and compiler options
if(MSVC)
target_compile_definitions(${PLUGIN_NAME} PRIVATE NOMINMAX)
target_link_libraries(${PLUGIN_NAME} ${GUI_BIN_DIR}/open-ephys.lib)
target_compile_options(${PLUGIN_NAME} PRIVATE /sdl- /W0)

Expand Down Expand Up @@ -111,15 +112,17 @@ foreach( src_file IN ITEMS ${SRC_FILES})
endforeach()

# additional libraries
add_subdirectory(third_party/fmt EXCLUDE_FROM_ALL)

find_package(okFrontPanel REQUIRED)
find_package(xdaq REQUIRED)
find_package(fmt REQUIRED)
find_package(nlohmann_json REQUIRED)

target_link_libraries(${PLUGIN_NAME}
fmt::fmt-header-only
fmt::fmt
okFrontPanel::okFrontPanel
xdaq::xdaq
nlohmann_json::nlohmann_json
)

if (MSVC)
install(FILES $<TARGET_FILE:okFrontPanel::okFrontPanel> DESTINATION ${GUI_BIN_DIR}/shared CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES})
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Resources/xdaq.bit DESTINATION ${GUI_BIN_DIR}/shared)
Expand Down
185 changes: 72 additions & 113 deletions Source/DeviceThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,32 +1014,77 @@ bool DeviceThread::startAcquisition()
evalBoard->flush();
evalBoard->setContinuousRunMode(true);
evalBoard->run();
running = true;
data_thread = std::thread([this]() {
const int numStreams = evalBoard->getNumEnabledDataStreams();
std::vector<bool> isddrstream;

const int chunk_size = 1;
Rhd2000DataBlock current_block(numStreams, chunk_size, evalBoard->get_dio32());
int nonddr = 0;
for (int i = 0; i < evalBoard->ports.max_streams; ++i) {
if (!evalBoard->isStreamEnabled(i)) continue;
bool ddr = evalBoard->ports.is_ddr(i);
isddrstream.push_back(ddr);
nonddr += !ddr;
}
isddrstream.push_back(false);
const int current_aquisition_streams = evalBoard->getNumEnabledDataStreams();
const int current_aquisition_channels =
(32 * numStreams + nonddr * 3 * settings.acquireAux +
+settings.acquireAdc * evalBoard->ports.num_of_adc);
const int buffer_samples = 256;
std::vector<unsigned char> data_buffer(evalBoard->get_sample_size<char>() * buffer_samples);
std::vector<float> output_buffer(current_aquisition_channels * chunk_size);

while (running) {
for(auto begin = data_buffer.begin(); begin != data_buffer.end();){
auto r = evalBoard->read_raw_to_buffer(data_buffer.end() - begin, &*begin);
begin +=r;
if(r == 0) std::this_thread::sleep_for(std::chrono::milliseconds(1));
if(!running) return;
}
const auto chunk_buffer_size = evalBoard->get_sample_size<char>() * chunk_size;

for (int chunk = 0; chunk < data_buffer.size() / chunk_buffer_size; ++chunk) {
current_block.from_buffer(&data_buffer[chunk_buffer_size * chunk]);

// tranpose data from Time x Channel x Stream to Time x Stream x Channel
auto target = output_buffer.begin();
for (int s = 0; s < current_aquisition_streams; ++s) {
target =
std::copy(current_block.amp.begin() + s * 32 * chunk_size,
current_block.amp.begin() + (s + 1) * 32 * chunk_size, target);
if (!settings.acquireAux | (!isddrstream[s] && isddrstream[s + 1])) continue;

for (int c = 0; c < 3; ++c) {
auto &current_aux_buffer = auxBuffer[s * 3 + c];
for (int t = 0; t < chunk_size; ++t) {
// aux is offset by 1
const int aux = (current_block.timeStamp[t] + 3) % 4;
// update aux buffer with new value that sampled every 4th sample
if (aux == c)
current_aux_buffer =
IntanChip::aux2V(current_block.aux[1][s * chunk_size+ t]);
// oversampleing by 4 times
*target++ = current_aux_buffer;
}
}
}

// LOGD("Expecting blocksize of ", blockSize, " for ", evalBoard->getNumEnabledDataStreams(), "
// streams");

assert(current_block == nullptr);
const int numStreams = evalBoard->getNumEnabledDataStreams();

// const int chunk_size = 32;
const int chunk_size = 1;
current_block = new Rhd2000DataBlock(numStreams, chunk_size, evalBoard->get_dio32());
if (settings.acquireAdc) {
std::copy(current_block.adc.begin(), current_block.adc.end(), target);
}

assert(isddrstream.size() == 0);
int nonddr = 0;
for (int i = 0; i < evalBoard->ports.max_streams; ++i) {
if (!evalBoard->isStreamEnabled(i)) continue;
bool ddr = evalBoard->ports.is_ddr(i);
isddrstream.push_back(ddr);
nonddr += !ddr;
}
isddrstream.push_back(false);
current_aquisition_streams = evalBoard->getNumEnabledDataStreams();
current_aquisition_channels = (32 * numStreams + nonddr * 3 * settings.acquireAux +
+settings.acquireAdc * evalBoard->ports.num_of_adc);
data_buffer.resize(evalBoard->get_sample_size<char>() * SAMPLES_PER_DATA_BLOCK * 4);
output_buffer.resize(current_aquisition_channels * chunk_size);
// output_buffer.resize(current_aquisition_channels * 300);
auto ts = std::vector<double>(chunk_size, 0);
auto ttl = std::vector<uint64_t>(chunk_size);
std::transform(current_block.ttlIn.begin(), current_block.ttlIn.end(), ttl.begin(),
[](auto t) { return t; });
sourceBuffers[0]->addToBuffer(&output_buffer[0], &current_block.timeStamp[0],
&ts[0], &ttl[0], chunk_size, chunk_size);
}
}
});

startThread();

Expand All @@ -1051,6 +1096,9 @@ bool DeviceThread::startAcquisition()
bool DeviceThread::stopAcquisition()
{
// LOGD("RHD2000 data thread stopping acquisition.");
running = false;
if (data_thread.joinable())
data_thread.join();

if (isThreadRunning()) {
signalThreadShouldExit();
Expand Down Expand Up @@ -1080,101 +1128,12 @@ bool DeviceThread::stopAcquisition()
// remove commands
while (!digitalOutputCommands.empty()) digitalOutputCommands.pop();

delete current_block;
current_block = nullptr;
isddrstream.clear();
current_aquisition_channels = 0;
current_aquisition_streams = 0;
output_buffer.clear();

return true;
}

bool DeviceThread::updateBuffer()
{
// using Clock = std::chrono::high_resolution_clock;
// static auto sumtime = 0.0;
// static auto measurementCount = 0;
const int samples_available = evalBoard->get_num_samples_available(true);
if (samples_available > SAMPLES_PER_DATA_BLOCK * 4) {
evalBoard->read_to_buffer(SAMPLES_PER_DATA_BLOCK * 4, &data_buffer[0]);
const auto chunk_buffer_size =
evalBoard->get_sample_size<char>() * current_block->num_samples;
for (int chunk = 0; chunk < SAMPLES_PER_DATA_BLOCK * 4 / current_block->num_samples;
++chunk) {
// auto start_time = Clock::now();
// const auto all_start_time = start_time;

current_block->from_buffer(&data_buffer[chunk_buffer_size * chunk]);
// auto rbt =
// std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now() - start_time)
// .count();
// sumtime += rbt;
// ++measurementCount;
const int num_samples = current_block->num_samples;
// if (chunk == (SAMPLES_PER_DATA_BLOCK * 4 / current_block->num_samples - 1))
// fmt::print("read {} samples in {} ns avg {:.0f} us/samp, {} to go", num_samples,
// rbt, sumtime / measurementCount / num_samples, samples_available);
// start_time = Clock::now();


// tranpose data from Time x Channel x Stream to Time x Stream x Channel
auto target = output_buffer.begin();
const auto num_streams = isddrstream.size() - 1;
for (int s = 0; s < current_aquisition_streams; ++s) {
target = std::copy(current_block->amp.begin() + s * 32 * num_samples,
current_block->amp.begin() + (s + 1) * 32 * num_samples, target);
if (!settings.acquireAux | (!isddrstream[s] && isddrstream[s + 1])) continue;

for (int c = 0; c < 3; ++c) {
auto &current_aux_buffer = auxBuffer[s * 3 + c];
for (int t = 0; t < num_samples; ++t) {
// aux is offset by 1
const int aux = (current_block->timeStamp[t] + 3) % 4;
// update aux buffer with new value that sampled every 4th sample
if (aux == c)
current_aux_buffer =
IntanChip::aux2V(current_block->aux[1][s * num_samples + t]);
// oversampleing by 4 times
*target++ = current_aux_buffer;
}
}
}

if (settings.acquireAdc) {
std::copy(current_block->adc.begin(), current_block->adc.end(), target);
}

auto ts = std::vector<double>(num_samples, 0);
// Not ideal to cast into another vector, but it's more convenient to switch between
// 16 / 32 channels
auto ttl = std::vector<uint64_t>(num_samples);
std::transform(current_block->ttlIn.begin(), current_block->ttlIn.end(), ttl.begin(),
[](auto t) { return t; });

// if (chunk == (SAMPLES_PER_DATA_BLOCK * 4 / current_block->num_samples - 1))
// fmt::print("Trans {} ns ", std::chrono::duration_cast<std::chrono::nanoseconds>(
// Clock::now() - start_time)
// .count());
// start_time = Clock::now();

sourceBuffers[0]->addToBuffer(&output_buffer[0], &current_block->timeStamp[0], &ts[0],
&ttl[0], num_samples, num_samples);

// if (chunk == (SAMPLES_PER_DATA_BLOCK * 4 / current_block->num_samples - 1))
// fmt::print(
// "Added to buffer {} ns / sample , Total={}\n",
// std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now() -
// start_time)
// .count() /
// num_samples,
// std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now() -
// all_start_time)
// .count() /
// num_samples);
}
}

if (updateSettingsDuringAcquisition) {
LOGD("DAC");
for (int k = 0; k < 8; k++) {
Expand Down
9 changes: 3 additions & 6 deletions Source/DeviceThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,9 @@ class DeviceThread : public DataThread

StringArray channelNames;

Rhd2000DataBlock *current_block = nullptr;
std::vector<bool> isddrstream;
int current_aquisition_channels = 0;
int current_aquisition_streams = 0;
std::vector<unsigned char> data_buffer;
std::vector<float> output_buffer;
std::thread data_thread;
std::atomic_bool running;


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DeviceThread);
};
Expand Down
5 changes: 0 additions & 5 deletions Source/ImpedanceMeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,6 @@ std::optional<Impedances> ImpedanceMeter::runImpedanceMeasurement()
board->evalBoard->run();
while (board->evalBoard->isRunning())
;
if (board->evalBoard->get_num_samples_available(true) !=
SAMPLES_PER_DATA_BLOCK * numBlocks) {
std::cerr << "Error: Did not receive enough data from board.\n";
return std::nullopt;
}
auto db = board->evalBoard->read_samples(SAMPLES_PER_DATA_BLOCK * numBlocks);

for (int stream = 0; stream < numdataStreams; ++stream) {
Expand Down
Loading

0 comments on commit 7e8e3e9

Please sign in to comment.