Skip to content

Commit

Permalink
ref-ARRUS-102: Implemented MANUAL work mode. (#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjarosik authored Oct 10, 2021
1 parent 012f141 commit 4a6441a
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 30 deletions.
2 changes: 1 addition & 1 deletion api/python/arrus/ops/us4r.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Scheme:
:param rx_buffer_size: number of elements the rx buffer (allocated on \
us4r ddr internal memory) should consists of
:param output_buffer: specification of the output buffer
:param work_mode: determines the system work mode, available values: 'ASYNC', 'HOST'
:param work_mode: determines the system work mode, available values: 'ASYNC', 'HOST', 'MANUAL'
:param processing: data processing to perform on the raw channel RF data \
currently only arrus.utils.imaging is supported
"""
Expand Down
11 changes: 11 additions & 0 deletions api/python/arrus/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ def stop_scheme(self):
if self._current_processing is not None:
self._current_processing.stop()

def run(self):
"""
Runs the uploaded scheme.
The behaviour of this method depends on the work mode:
- MANUAL: triggers execution of batch of sequences only ONCE,
- HOST, ASYNC: triggers execution of batch of sequences IN A LOOP (Host: trigger is on buffer element release).
The run function can be called only once (before the scheme is stopped).
"""
self._session_handle.run()

def get_device(self, path: str):
"""
Returns a device identified by a given id.
Expand Down
3 changes: 2 additions & 1 deletion api/python/arrus/utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ def convert_to_core_scheme(scheme):

core_work_mode = {
"ASYNC": arrus.core.Scheme.WorkMode_ASYNC,
"HOST": arrus.core.Scheme.WorkMode_HOST
"HOST": arrus.core.Scheme.WorkMode_HOST,
"MANUAL": arrus.core.Scheme.WorkMode_MANUAL
}[scheme.work_mode]

return arrus.core.Scheme(core_seq, rx_buffer_size, data_buffer_spec,
Expand Down
4 changes: 3 additions & 1 deletion arrus/core/api/ops/us4r/Scheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class Scheme {
/** Trigger generated by us4r, error on overflow. */
ASYNC,
/** Trigger generated by host, no error on overflow. */
HOST
HOST,
/** New data acquisition and processing is manually triggered by user. */
MANUAL
};

/**
Expand Down
10 changes: 10 additions & 0 deletions arrus/core/api/session/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ class Session {
*/
virtual void stopScheme() = 0;

/**
* Runs the uploaded scheme.
*
* The behaviour of this method depends on the work mode:
* - MANUAL: triggers execution of batch of sequences only ONCE,
* - HOST, ASYNC: triggers execution of batch of sequences IN A LOOP (Host: trigger is on buffer element release).
* The run function can be called only once (before the scheme is stopped).
*/
virtual void run() = 0;

virtual ~Session() = default;
};

Expand Down
4 changes: 2 additions & 2 deletions arrus/core/devices/probe/ProbeImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ void ProbeImpl::syncTrigger() {

void ProbeImpl::registerOutputBuffer(Us4ROutputBuffer *buffer,
const Us4RBuffer::Handle &us4rBuffer,
bool isTriggerSync) {
adapter->registerOutputBuffer(buffer, us4rBuffer, isTriggerSync);
::arrus::ops::us4r::Scheme::WorkMode workMode) {
adapter->registerOutputBuffer(buffer, us4rBuffer, workMode);
}

// Remaps FCM according to given rx aperture active channels mappings.
Expand Down
3 changes: 2 additions & 1 deletion arrus/core/devices/probe/ProbeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class ProbeImpl : public ProbeImplBase {

void syncTrigger() override;

void registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4RBuffer::Handle &us4rBuffer, bool isTriggerSync) override;
void registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4RBuffer::Handle &us4rBuffer,
::arrus::ops::us4r::Scheme::WorkMode workMode) override;

static FrameChannelMapping::Handle remapFcm(const FrameChannelMapping::Handle &adapterFcm,
const std::vector<std::vector<ChannelIdx>> &adapterActiveChannels,
Expand Down
4 changes: 3 additions & 1 deletion arrus/core/devices/probe/ProbeImplBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define ARRUS_CORE_DEVICES_PROBE_PROBEIMPLBASE_H

#include "arrus/core/api/devices/probe/Probe.h"
#include "arrus/core/api/ops/us4r/Scheme.h"
#include "arrus/core/devices/us4r/Us4RBuffer.h"
#include "arrus/core/devices/UltrasoundDevice.h"

Expand All @@ -18,7 +19,8 @@ class ProbeImplBase : public Probe, public UltrasoundDevice {
setTxRxSequence(const std::vector<TxRxParameters> &seq, const ops::us4r::TGCCurve &tgcSamples, uint16 rxBufferSize,
uint16 rxBatchSize, std::optional<float> sri, bool triggerSync) = 0;

virtual void registerOutputBuffer(Us4ROutputBuffer *, const Us4RBuffer::Handle &, bool isTriggerSync) = 0;
virtual void registerOutputBuffer(Us4ROutputBuffer *, const Us4RBuffer::Handle &,
::arrus::ops::us4r::Scheme::WorkMode workMode) = 0;
};

}
Expand Down
9 changes: 5 additions & 4 deletions arrus/core/devices/us4r/Us4RImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace arrus::devices {

using ::arrus::ops::us4r::TxRxSequence;
using ::arrus::ops::us4r::Scheme;
using ::arrus::ops::us4r::Tx;
using ::arrus::ops::us4r::Rx;
using ::arrus::ops::us4r::Pulse;
Expand Down Expand Up @@ -95,8 +96,8 @@ Us4RImpl::upload(const ops::us4r::TxRxSequence &seq,
}

// Upload and register buffers.
bool isTriggerSync = workMode == ::arrus::ops::us4r::Scheme::WorkMode::HOST;
auto[rxBuffer, fcm] = uploadSequence(seq, rxBufferNElements, 1, isTriggerSync);
bool useTriggerSync = workMode == Scheme::WorkMode::HOST || workMode == Scheme::WorkMode::MANUAL;
auto[rxBuffer, fcm] = uploadSequence(seq, rxBufferNElements, 1, useTriggerSync);
ARRUS_REQUIRES_TRUE(!rxBuffer->empty(), "Us4R Rx buffer cannot be empty.");

// Calculate how much of the data each Us4OEM produces.
Expand All @@ -115,7 +116,7 @@ Us4RImpl::upload(const ops::us4r::TxRxSequence &seq,
}
// Create output buffer.
this->buffer = std::make_shared<Us4ROutputBuffer>(us4oemComponentSize, shape, dataType, hostBufferNElements);
getProbeImpl()->registerOutputBuffer(this->buffer.get(), rxBuffer, isTriggerSync);
getProbeImpl()->registerOutputBuffer(this->buffer.get(), rxBuffer, workMode);
return {this->buffer, std::move(fcm)};
}

Expand Down Expand Up @@ -184,7 +185,7 @@ Us4RImpl::uploadSequence(const ops::us4r::TxRxSequence &seq, uint16_t rxBufferSi
triggerSync);
}

void Us4RImpl::syncTrigger() {
void Us4RImpl::trigger() {
this->getDefaultComponent()->syncTrigger();
}

Expand Down
4 changes: 2 additions & 2 deletions arrus/core/devices/us4r/Us4RImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ class Us4RImpl : public Us4R {

void stop() override;

void trigger();

void setVoltage(Voltage voltage) override;

void disableHV() override;
Expand All @@ -127,8 +129,6 @@ class Us4RImpl : public Us4R {

void stopDevice();

void syncTrigger();

std::tuple<Us4RBuffer::Handle, FrameChannelMapping::Handle>
uploadSequence(const ops::us4r::TxRxSequence &seq, uint16_t rxBufferSize, uint16_t rxBatchSize, bool triggerSync);

Expand Down
12 changes: 7 additions & 5 deletions arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace arrus::devices {

using namespace ::arrus::ops::us4r;
using ::arrus::ops::us4r::Scheme;

ProbeAdapterImpl::ProbeAdapterImpl(DeviceId deviceId,
ProbeAdapterModelId modelId,
Expand Down Expand Up @@ -292,18 +293,18 @@ void ProbeAdapterImpl::syncTrigger() {
}

void ProbeAdapterImpl::registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4RBuffer::Handle &us4rBuffer,
bool isTriggerSync) {
::arrus::ops::us4r::Scheme::WorkMode workMode) {
Ordinal us4oemOrdinal = 0;
for (auto &us4oem: us4oems) {
auto us4oemBuffer = us4rBuffer->getUs4oemBuffer(us4oemOrdinal);
registerOutputBuffer(buffer, us4oemBuffer, us4oem,
isTriggerSync);
registerOutputBuffer(buffer, us4oemBuffer, us4oem, workMode);
++us4oemOrdinal;
}
}

void ProbeAdapterImpl::registerOutputBuffer(Us4ROutputBuffer *outputBuffer, const Us4OEMBuffer &us4oemBuffer,
Us4OEMImplBase::RawHandle us4oem, bool isTriggerSync) {
Us4OEMImplBase::RawHandle us4oem,
::arrus::ops::us4r::Scheme::WorkMode workMode) {
// Each transfer should have the same size.
std::unordered_set<size_t> sizes;
for (auto &element: us4oemBuffer.getElements()) {
Expand Down Expand Up @@ -398,7 +399,8 @@ void ProbeAdapterImpl::registerOutputBuffer(Us4ROutputBuffer *outputBuffer, cons

for (size_t i = 0; i < nRepeats; ++i) {
std::function<void()> releaseFunc;
if (!isTriggerSync) {
if (workMode == Scheme::WorkMode::ASYNC || workMode == Scheme::WorkMode::MANUAL) {
// The TX/RX is triggered by us4OEM or user.
releaseFunc = [this, nUs4OEM, startFiring, endFiring]() {
for (auto &us4oem: this->us4oems) {
us4oem->getIUs4oem()->MarkEntriesAsReadyForTransfer(startFiring, endFiring);
Expand Down
12 changes: 4 additions & 8 deletions arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ class ProbeAdapterImpl : public ProbeAdapterImplBase {

void syncTrigger() override;

void
registerOutputBuffer(Us4ROutputBuffer *buffer,
const Us4RBuffer::Handle &us4rBuffer,
bool isTriggerSync);
void registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4RBuffer::Handle &us4rBuffer,
::arrus::ops::us4r::Scheme::WorkMode workMode) override;

private:
Logger::Handle logger;
Expand All @@ -57,10 +55,8 @@ class ProbeAdapterImpl : public ProbeAdapterImplBase {
ChannelIdx numberOfChannels;
ChannelMapping channelMapping;

void registerOutputBuffer(Us4ROutputBuffer *outputBuffer,
const Us4OEMBuffer &us4oemBuffer,
Us4OEMImplBase::RawHandle us4oem,
bool isTriggerSync);
void registerOutputBuffer(Us4ROutputBuffer *outputBuffer, const Us4OEMBuffer &us4oemBuffer,
Us4OEMImplBase::RawHandle us4oem, ::arrus::ops::us4r::Scheme::WorkMode workMode);

Us4OEMImplBase::RawHandle getMasterUs4oem() const {
return this->us4oems[0];
Expand Down
6 changes: 3 additions & 3 deletions arrus/core/devices/us4r/probeadapter/ProbeAdapterImplBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "arrus/core/api/devices/us4r/ProbeAdapter.h"
#include "arrus/core/api/devices/us4r/FrameChannelMapping.h"
#include "arrus/core/api/ops/us4r/tgc.h"
#include "arrus/core/api/ops/us4r/Scheme.h"
#include "arrus/core/devices/TxRxParameters.h"
#include "arrus/core/devices/us4r/DataTransfer.h"
#include "arrus/core/devices/us4r/Us4ROutputBuffer.h"
Expand All @@ -26,9 +27,8 @@ class ProbeAdapterImplBase : public ProbeAdapter {
bool triggerSync) = 0;

virtual
void registerOutputBuffer(Us4ROutputBuffer *buffer,
const Us4RBuffer::Handle &transfers,
bool isTriggerSync) = 0;
void registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4RBuffer::Handle &transfers,
::arrus::ops::us4r::Scheme::WorkMode workMode) = 0;

virtual Ordinal getNumberOfUs4OEMs() = 0;

Expand Down
26 changes: 26 additions & 0 deletions arrus/core/session/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ SessionImpl::~SessionImpl() {
}

UploadResult SessionImpl::upload(const ops::us4r::Scheme &scheme) {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
if(state == State::STARTED) {
throw IllegalStateException("Stop the scheme first, before uploading new scheme");
}
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
auto &outputBufferSpec = scheme.getOutputBuffer();
auto[buffer, fcm] = us4r->upload(scheme.getTxRxSequence(), scheme.getRxBufferSize(),
Expand All @@ -114,18 +118,40 @@ UploadResult SessionImpl::upload(const ops::us4r::Scheme &scheme) {
std::unordered_map<std::string, std::shared_ptr<void>> metadataMap;
metadataMap.emplace("frameChannelMapping", std::move(fcm));
auto constMetadata = std::make_shared<UploadConstMetadata>(metadataMap);
currentScheme = scheme;
return UploadResult(buffer, constMetadata);
}

void SessionImpl::startScheme() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->start();
state = State::STARTED;
}

void SessionImpl::stopScheme() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->stop();
state = State::STOPPED;
}

void SessionImpl::run() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
if(!currentScheme.has_value()) {
throw IllegalStateException("Upload scheme before running.");
}
if(state == State::STOPPED) {
startScheme();
} else {
if(currentScheme.value().getWorkMode() == ops::us4r::Scheme::WorkMode::MANUAL) {
auto us4r = (::arrus::devices::Us4RImpl *)getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->trigger();
}
else {
throw IllegalStateException("Scheme already started.");
}
}
}

}
13 changes: 12 additions & 1 deletion arrus/core/session/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#define ARRUS_CORE_SESSION_SESSIONIMPL_H

#include <unordered_map>
#include <arrus/core/devices/us4r/Us4RFactory.h>
#include <mutex>

#include <arrus/core/devices/us4r/Us4RFactory.h>
#include "arrus/core/api/session/Session.h"
#include "arrus/core/common/hash.h"
#include "arrus/core/devices/DeviceId.h"
Expand All @@ -30,6 +31,8 @@ class SessionImpl : public Session {

void stopScheme() override;

void run() override;

SessionImpl(SessionImpl const &) = delete;

void operator=(SessionImpl const &) = delete;
Expand All @@ -39,6 +42,11 @@ class SessionImpl : public Session {
void operator=(SessionImpl const &&) = delete;

private:
enum class State {
STARTED,
STOPPED
};

using DeviceMap = std::unordered_map<
arrus::devices::DeviceId,
arrus::devices::Device::Handle,
Expand All @@ -49,6 +57,9 @@ class SessionImpl : public Session {

DeviceMap devices;
arrus::devices::Us4RFactory::Handle us4rFactory;
std::recursive_mutex stateMutex;
std::optional<ops::us4r::Scheme> currentScheme;
State state{State::STOPPED};
};


Expand Down

0 comments on commit 4a6441a

Please sign in to comment.