Skip to content

Commit

Permalink
Picoscope: use offset into driver buffer
Browse files Browse the repository at this point in the history
This changes the streaming callback and process bulk to also take into
account the data offset in the buffer that the driver is writing the
data into.
Also since the callback is executed on the driver thread, it uses
atomics to exchange the indices.

While this works for now, the picoscope programmer's guide instructs to
copy the data out of the buffer inside of the callback, which suggests
that the data might be overwritten once the callback returns (and
potentially before the processBulk method has actually copied the data).
This should be investigated further.

Signed-off-by: Alexander Krimm <A.Krimm@gsi.de>
  • Loading branch information
wirew0rm committed Oct 25, 2024
1 parent be5baa2 commit 587b291
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions blocklib/picoscope/Picoscope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ class Picoscope : public PicoscopeBlockingHelper<TPSImpl, acquisitionMode == Acq

private:
std::mutex g_init_mutex;
std::size_t streamingSamples = 0Z;
std::atomic<std::size_t> streamingSamples = 0Z;
std::atomic<std::size_t> streamingOffset = 0Z;
std::queue<gr::property_map> timingMessages;

public:
Expand Down Expand Up @@ -465,12 +466,13 @@ class Picoscope : public PicoscopeBlockingHelper<TPSImpl, acquisitionMode == Acq
ps_state.produced_worker += availableSamples;
}

void streamingCallback(int32_t nrSamplesSigned, uint32_t, int16_t overflow)
void streamingCallback(int32_t nrSamplesSigned, uint32_t idx, int16_t overflow)
requires(acquisitionMode == AcquisitionMode::Streaming)
{
streamingSamples = static_cast<std::size_t>(nrSamplesSigned);
streamingOffset = static_cast<std::size_t>(idx);
// NOTE: according to the programmer's guide the data should be copied-out inside the callback function. Not sure if the driver might overwrite the buffer with new data after the callback has returned
assert(nrSamplesSigned >= 0);
const auto nrSamples = static_cast<std::size_t>(nrSamplesSigned);

// According to well-informed sources, the driver indicates the buffer overrun by setting all the bits of the overflow argument to true.
if (static_cast<uint16_t>(overflow) == 0xffff) {
Expand All @@ -491,16 +493,16 @@ class Picoscope : public PicoscopeBlockingHelper<TPSImpl, acquisitionMode == Acq
template<gr::OutputSpanLike TOutSpan>
gr::work::Status processBulk(std::span<TOutSpan>& outputs) {
if constexpr (acquisitionMode == AcquisitionMode::Streaming) {
if (const auto ec = self().driver_poll()) {
this->emitErrorMessage("PicoscopeError", ec.message());
return gr::work::Status::ERROR;
}
if (streamingSamples == 0) {
for (auto& output : outputs) {
output.publish(0);
}
if (const auto ec = self().driver_poll()) {
this->emitErrorMessage("PicoscopeError", ec.message());
return gr::work::Status::ERROR;
}
} else {
processDriverData(streamingSamples, 0, outputs);
processDriverData(streamingSamples, streamingOffset, outputs);
streamingSamples = 0;
}
} else {
Expand Down

0 comments on commit 587b291

Please sign in to comment.