From bd3477c5d0aa5570294d6338167b42d1af2470cd Mon Sep 17 00:00:00 2001 From: Piotr Jarosik Date: Wed, 3 Apr 2024 11:07:37 +0200 Subject: [PATCH] Uploaded PWI DDC C++ example. --- arrus/core/CMakeLists.txt | 6 - arrus/core/examples/AfeDDCExample.cpp | 370 ------------------ arrus/core/examples/AfeDDCExample_v2.cpp | 207 ---------- .../core/examples/AfeDDCExample_v2_FirGen.py | 36 -- arrus/core/examples/AfeDemodFIR.h | 11 - arrus/core/examples/CMakeLists.txt | 5 +- arrus/core/examples/PwiDdcExample.cpp | 117 ++++++ arrus/core/examples/fir.txt | 32 -- 8 files changed, 119 insertions(+), 665 deletions(-) delete mode 100644 arrus/core/examples/AfeDDCExample.cpp delete mode 100644 arrus/core/examples/AfeDDCExample_v2.cpp delete mode 100644 arrus/core/examples/AfeDDCExample_v2_FirGen.py delete mode 100644 arrus/core/examples/AfeDemodFIR.h create mode 100644 arrus/core/examples/PwiDdcExample.cpp delete mode 100644 arrus/core/examples/fir.txt diff --git a/arrus/core/CMakeLists.txt b/arrus/core/CMakeLists.txt index 0fd891f48..5f4cd5066 100644 --- a/arrus/core/CMakeLists.txt +++ b/arrus/core/CMakeLists.txt @@ -340,9 +340,3 @@ install( add_executable(pwi-example examples/PwiExample.cpp) target_link_libraries(pwi-example PRIVATE arrus-core) target_include_directories(pwi-example PRIVATE ${ARRUS_ROOT_DIR}) -# -#add_executable(demod-example examples/AfeDDCExample_v2.cpp) -#target_link_libraries(demod-example PRIVATE arrus-core Boost::Boost) -#target_include_directories(demod-example PRIVATE ${ARRUS_ROOT_DIR}) -#configure_file(examples/fir.txt fir.txt COPYONLY) -#configure_file(examples/AfeDDCExample_v2_FirGen.py AfeDDCExample_v2_FirGen.py COPYONLY) diff --git a/arrus/core/examples/AfeDDCExample.cpp b/arrus/core/examples/AfeDDCExample.cpp deleted file mode 100644 index db5ebf338..000000000 --- a/arrus/core/examples/AfeDDCExample.cpp +++ /dev/null @@ -1,370 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "arrus/core/api/arrus.h" - -#include "arrus/core/examples/AfeDemodFIR.h" - -enum Commands { - Write, - Read, - Start, - Exit, - DemodEn, - DemodDis, - DemodDef, - DemodDec, - DemodFreq, - DemodFsweepROI, - DemodFIR, - AfeReset, - Invalid -}; - -Commands ResolveInput(std::string inp) -{ - if (inp == "wr") return Write; - if (inp == "rd") return Read; - if (inp == "exit") return Exit; - if (inp == "trig") return Start; - if (inp == "afe-rst") return AfeReset; - if (inp == "demod-en") return DemodEn; - if (inp == "demod-dis") return DemodDis; - if (inp == "demod-def") return DemodDef; - if (inp == "demod-dec") return DemodDec; - if (inp == "demod-freq") return DemodFreq; - if (inp == "demod-fsweep") return DemodFsweepROI; - if (inp == "demod-fir") return DemodFIR; - - return Invalid; -} - -int main() noexcept { - char value = 0; - std::cout << "demod-example. press a key to continue... " << std::endl; - std::cin >> value; - - using namespace ::arrus::session; - using namespace ::arrus::devices; - using namespace ::arrus::ops::us4r; - using namespace ::arrus::framework; - try { - // TODO set path to us4r-lite configuration file - auto settings = ::arrus::io::readSessionSettings("C:/Users/user/us4r.prototxt"); - auto session = ::arrus::session::createSession(settings); - auto us4r = (::arrus::devices::Us4R *) session->getDevice("/Us4R:0"); - auto probe = us4r->getProbe(0); - - unsigned nElements = probe->getModel().getNumberOfElements().product(); - - ::arrus::BitMask rxAperture(nElements, true); - - Pulse pulse(8.125e6, 2, false); - // with the hardware decimation turned on proper rx data starts at sample 98. - ::std::pair<::arrus::uint32, arrus::uint32> sampleRange{ 98, 8192+98 }; - - std::vector txrxs; - - for (int i = 0; i < 1; ++i) { - // NOTE: the below vector should have size == probe number of elements. - // This probably will be modified in the future - // (delays only for active tx elements will be needed). - std::vector delays(nElements, 0.0f); - arrus::BitMask txAperture(nElements, true); - txrxs.emplace_back(Tx(txAperture, delays, pulse), - Rx(rxAperture, sampleRange), - 1000e-6f); - } - - TxRxSequence seq(txrxs, {}); - - DataBufferSpec outputBuffer{ DataBufferSpec::Type::FIFO, 4 }; - Scheme scheme(seq, 2, outputBuffer, Scheme::WorkMode::HOST); - - auto result = session->upload(scheme); - us4r->setVoltage(10); - - std::condition_variable cv; - std::condition_variable cv2; - using namespace std::chrono_literals; - - std::mutex mutex2; - std::unique_lock lock2(mutex2); - - OnNewDataCallback callback = [&, i = 0](const BufferElement::SharedHandle &ptr) mutable { - try { - std::cout << "Iteration: " << i << ", data: " << std::endl; - std::cout << "- memory ptr: " << std::hex - << ptr->getData().get() - << std::dec << std::endl; - std::cout << "- size: " << ptr->getSize() << std::endl; - std::cout << "- shape: (" << ptr->getData().getShape()[0] << // calkowita liczba probek - ", " << ptr->getData().getShape()[1] << // 32 - ")" << std::endl; - - std::ofstream file; - file.open("temp.bin", std::ios::binary | std::ios::out); - //short* dptr = ptr->getData().getInt16(); - file.write(reinterpret_cast(ptr->getData().getInt16()/*ptr->getData().get()*/), static_cast(ptr->getSize())); - file.close(); - - //std::string pycmd = "python ./plot.py"; - //system(pycmd.c_str()); - - // Stop the system after 10-th frame. - //ptr->release(); - - cv.notify_one(); - - cv2.wait(lock2); - - ptr->release(); - ++i; - } - catch (const std::exception &e) { - std::cout << "Exception: " << e.what() << std::endl; - cv.notify_all(); - } - catch (...) { - std::cout << "Unrecognized exception" << std::endl; - cv.notify_all(); - } - }; - - OnOverflowCallback overflowCallback = [&]() { - std::cout << "Data overflow occurred!" << std::endl; - cv.notify_one(); - }; - - // Register the callback for new data in the output buffer. - auto buffer = std::static_pointer_cast(result.getBuffer()); - buffer->registerOnNewDataCallback(callback); - buffer->registerOnOverflowCallback(overflowCallback); - - bool cont = true; - - std::mutex mutex; - std::unique_lock lock(mutex); - - //get number of oems? - int nOEMS = 0; - for (nOEMS = 0; nOEMS < 16; nOEMS++) - { - try { - us4r->getUs4OEM(nOEMS); - } - catch (const std::exception &e) { - break; - } - } - - std::cout << "press a key to startScheme... " << std::endl; - std::cin >> value; - - session->startScheme(); - cv.wait(lock); - - std::cout << std::endl << "Found " << nOEMS << " OEMs" << std::endl; - - //configure demodulator - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->enableAfeDemod(); - us4r->getUs4OEM(n)->setAfeDemodDefault(); - } - - //print menu - std::cout << std::endl << "--- Console options: ---" << std::endl; - std::cout << " trig - trigger new frame acquisition" << std::endl - << " wr - write AFE register" << std::endl - << " rd - read AFE register" << std::endl - << " demod-en - enable AFE demodulator" << std::endl - << " demod-dis - disable AFE demodulator" << std::endl - << " demod-def - writes AFE demodulator default config" << std::endl - << " demod-freq - sets AFE demodulator frequency" << std::endl - << " demod-fsweep - sets AFE demodulator frequency sweep ROI" << std::endl - << " demod-fir - writes AFE demodulator decimation filter coefficients" << std::endl - << " exit - exit app" << std::endl << std::endl; - - std::string inp; - - while (cont) { - //char value = 0; - std::cout << "CMD >>"; - std::cin >> inp; - switch (ResolveInput(inp)) { - case Write: - { - std::cout << "Register address (hex): " << std::endl; - std::cin >> inp; - int regAddr = std::stoi(inp, 0, 16); - std::cout << "Register value (hex): " << std::endl; - std::cin >> inp; - int regVal = std::stoi(inp, 0, 16); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfe(static_cast(regAddr), static_cast(regVal)); - } - //us4r->getUs4OEM(0)->setAfe(static_cast(regAddr), static_cast(regVal)); - break; - } - case DemodFIR: - { - //writes default 10MHz FIR for now, valid for M = 4 - //us4r->getUs4OEM(0)->writeAfeFIRCoeffs((int16_t*)&fir10M[0], 32); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->writeAfeFIRCoeffs((int16_t*)&fir10M[0], 32); - } - break; - } - case DemodEn: - { - //us4r->getUs4OEM(0)->enableAfeDemod(); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->enableAfeDemod(); - } - break; - } - case AfeReset: - { - //us4r->getUs4OEM(0)->resetAfe(); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->resetAfe(); - } - break; - } - case DemodDis: - { - //us4r->getUs4OEM(0)->disableAfeDemod(); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->disableAfeDemod(); - } - break; - } - case DemodDef: - { - //us4r->getUs4OEM(0)->setAfeDemodDefault(); - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodDefault(); - } - break; - } - case DemodDec: - { - std::cout << "Decimation factor integer part:" << std::endl; - std::cin >> inp; - int integer = std::stoi(inp, 0, 10); - - if (integer < 0 || integer > 0x3F) { - std::cout << "Invalid value" << std::endl; - break; - } - - std::cout << "Decimation factor fractional part (0 = 0, 1 = 0.25, 2 = 0.5, 3 = 0.75):" << std::endl; - std::cin >> inp; - int quarters = std::stoi(inp, 0, 10); - - if (quarters < 0 || quarters > 3) { - std::cout << "Invalid value" << std::endl; - break; - } - - if (quarters == 0) { - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodDecimationFactor(static_cast(integer)); - } - } - else { - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodDecimationFactor(static_cast(integer), static_cast(quarters)); - } - } - break; - } - case DemodFreq: - { - std::cout << "Demodulator frequency in MHz (start freuqency for sweep):" << std::endl; - std::cin >> inp; - double startFreq = std::stod(inp); - - std::cout << "Demodulator stop frequency in MHz (enter 0.0 to disable fsweep):" << std::endl; - std::cin >> inp; - double stopFreq = std::stod(inp); - - if (stopFreq == 0.0) { - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodFrequency(startFreq); - } - //get and output actual set frequency - startFreq = us4r->getUs4OEM(0)->getAfeDemodStartFrequency(); - std::cout << "Set demodulator frequency = " << startFreq << " MHz" << std::endl; - } - else { - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodFrequency(startFreq, stopFreq); - } - startFreq = us4r->getUs4OEM(0)->getAfeDemodStartFrequency(); - std::cout << "Set demodulator start frequency = " << startFreq << " MHz" << std::endl; - stopFreq = us4r->getUs4OEM(0)->getAfeDemodStopFrequency(); - std::cout << "Set demodulator stop frequency = " << stopFreq << " MHz" << std::endl; - } - break; - } - case DemodFsweepROI: - { - std::cout << "Frequency sweep start sample:" << std::endl; - std::cin >> inp; - int start = std::stoi(inp, 0, 10); - - if (start < 0 || start > 0xFFFF) { - std::cout << "Invalid value" << std::endl; - break; - } - - std::cout << "Frequency sweep stop sample:" << std::endl; - std::cin >> inp; - int stop = std::stoi(inp, 0, 10); - - if (stop < 0 || stop > 0xFFFF) { - std::cout << "Invalid value" << std::endl; - break; - } - - for (uint8_t n = 0; n < nOEMS; n++) { - us4r->getUs4OEM(n)->setAfeDemodFsweepROI(static_cast(start), static_cast(stop)); - } - break; - } - case Read: - { - std::cout << "Register address (hex): " << std::endl; - std::cin >> inp; - int regAddr = std::stoi(inp, 0, 16); - uint16_t regVal = us4r->getUs4OEM(0)->getAfe(static_cast(regAddr)); //read only AFE 0 on OEM 0 - std::cout << "Value = " << std::hex << static_cast(regVal) << std::endl; - break; - } - case Start: - cv2.notify_one(); - - break; - case Exit: - session->stopScheme(); - cv2.notify_all(); - cont = false; - break; - } - } - - // Wait for callback to signal that we hit 10-th iteration. - /// tutaj prawdodpobonie proste menu z poziomu konsoli - - } - catch (const std::exception &e) { - std::cerr << e.what() << std::endl; - return -1; - } - - return 0; -} diff --git a/arrus/core/examples/AfeDDCExample_v2.cpp b/arrus/core/examples/AfeDDCExample_v2.cpp deleted file mode 100644 index bc532a63c..000000000 --- a/arrus/core/examples/AfeDDCExample_v2.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "arrus/core/api/arrus.h" - -#include "arrus/core/examples/AfeDemodFIR.h" -#include - -namespace po = boost::program_options; - -int main(int ac, char *av[]) noexcept { - - char value = 0; - std::cout << "demod-example. press a key to continue... " << std::endl; - std::cin >> value; - - using namespace ::arrus::session; - using namespace ::arrus::devices; - using namespace ::arrus::ops::us4r; - using namespace ::arrus::framework; - try { - - po::options_description desc("Allowed options"); - desc.add_options() - ("help", "produce help message") - ("ddc-dec", po::value(), "Sets DDC decimation factor") - ("ddc-freq", po::value(), "Sets DDC frequency") - ("ddc-fir-load", po::value()->default_value("../fir.txt")->implicit_value("../fir.txt"), "Loads FIR coefficients from specified file") - ("ddc-fir-gen", po::value(), "Generates FIR coefficients with specified cutoff frequency") - ("fname", po::value()->default_value("rf.bin")->implicit_value("rf.bin"), "Filename for output data") - ; - - po::variables_map vm; - po::store(po::parse_command_line(ac, av, desc), vm); - po::notify(vm); - - if (vm.count("help")) - { - std::cout << desc << "\n"; - return 0; - } - - uint32_t sampleOffset; - double decFactor; - double ddcFreq; - double ddcFirCutoff = -255.0; - std::string fname, firFname; - - if (vm.count("ddc-dec")) - { - decFactor = vm["ddc-dec"].as(); - - if (decFactor < 2.0 || decFactor > 63.75) { - std::cout << "Invalid decimation factor (too low/high)" << std::endl; - return 0; - } - if ((decFactor - (long)decFactor) == 0.25) {} - else if ((decFactor - (long)decFactor) == 0.5) {} - else if ((decFactor - (long)decFactor) == 0.75) {} - else if ((decFactor - (long)decFactor) == 0.0) {} - else - { - std::cout << "Invalid decimation factor fraction - " << (decFactor - (long)decFactor) << std::endl; - return 0; - } - - sampleOffset = 34 + (uint32_t)(16 * decFactor); - } - if (vm.count("ddc-freq")) - { - ddcFreq = vm["ddc-freq"].as(); - } - if (vm.count("ddc-fir-gen")) - { - ddcFirCutoff = vm["ddc-fir-gen"].as(); - firFname = "fir_generated.txt"; - } - else if (vm.count("ddc-fir-load")) - { - firFname = vm["ddc-fir-load"].as(); - } - if (vm.count("fname")) - { - fname = vm["fname"].as(); - } - - - // TODO set path to us4r-lite configuration file - auto settings = ::arrus::io::readSessionSettings("C:/Users/user/us4r.prototxt"); - auto session = ::arrus::session::createSession(settings); - auto us4r = (::arrus::devices::Us4R *) session->getDevice("/Us4R:0"); - auto probe = us4r->getProbe(0); - - unsigned nElements = probe->getModel().getNumberOfElements().product(); - - ::arrus::BitMask rxAperture(nElements, true); - - Pulse pulse(8.125e6, 2, false); - // with the hardware decimation turned on proper rx data starts at sample 98. - ::std::pair<::arrus::uint32, arrus::uint32> sampleRange{ sampleOffset, (8192 + sampleOffset) }; - - std::vector txrxs; - - for (int i = 0; i < 1; ++i) { - // NOTE: the below vector should have size == probe number of elements. - // This probably will be modified in the future - // (delays only for active tx elements will be needed). - std::vector delays(nElements, 0.0f); - arrus::BitMask txAperture(nElements, true); - txrxs.emplace_back(Tx(txAperture, delays, pulse), - Rx(rxAperture, sampleRange), - 1000e-6f); - } - - TxRxSequence seq(txrxs, {}); - - DataBufferSpec outputBuffer{ DataBufferSpec::Type::FIFO, 4 }; - Scheme scheme(seq, 2, outputBuffer, Scheme::WorkMode::HOST); - - auto result = session->upload(scheme); - us4r->setVoltage(10); - //run fir generation script if requested - if (ddcFirCutoff > 0) - { - std::string pycmd = "python ../AfeDDCExample_v2_FirGen.py " + std::to_string(decFactor) + " " + std::to_string(ddcFirCutoff); - system(pycmd.c_str()); - } - - //read fir from file - int16_t fCoeffs[1024]; //arbitrary buffer size - uint16_t numCoeffs = 0; - - std::fstream firfile(firFname, std::ios_base::in); - while (firfile >> fCoeffs[numCoeffs]) - { - numCoeffs++; - } - - //configure demodulator - us4r->setAfeDemod(ddcFreq, decFactor, fCoeffs, numCoeffs); - - std::condition_variable cv; - using namespace std::chrono_literals; - - OnNewDataCallback callback = [&, i = 0](const BufferElement::SharedHandle &ptr) mutable { - try { - std::cout << "Iteration: " << i << ", data: " << std::endl; - std::cout << "- memory ptr: " << std::hex - << ptr->getData().get() - << std::dec << std::endl; - std::cout << "- size: " << ptr->getSize() << std::endl; - std::cout << "- shape: (" << ptr->getData().getShape()[0] << // calkowita liczba probek - ", " << ptr->getData().getShape()[1] << // 32 - ")" << std::endl; - - //dump data to file - std::ofstream file; - file.open(fname, std::ios::binary | std::ios::out); - file.write(reinterpret_cast(ptr->getData().getInt16()/*ptr->getData().get()*/), static_cast(ptr->getSize())); - file.close(); - - // Stop the system after receiving frame. - cv.notify_one(); - ptr->release(); - } - catch (const std::exception &e) { - std::cout << "Exception: " << e.what() << std::endl; - cv.notify_all(); - } - catch (...) { - std::cout << "Unrecognized exception" << std::endl; - cv.notify_all(); - } - }; - - OnOverflowCallback overflowCallback = [&]() { - std::cout << "Data overflow occurred!" << std::endl; - cv.notify_one(); - }; - - // Register the callback for new data in the output buffer. - auto buffer = std::static_pointer_cast(result.getBuffer()); - buffer->registerOnNewDataCallback(callback); - buffer->registerOnOverflowCallback(overflowCallback); - - std::cout << "press a key to startScheme... " << std::endl; - std::cin >> value; - - session->startScheme(); - - // Wait for callback to signal that we got frame. - std::mutex mutex; - std::unique_lock lock(mutex); - cv.wait(lock); - - session->stopScheme(); - } - catch (const std::exception &e) { - std::cerr << e.what() << std::endl; - return -1; - } - - return 0; -} diff --git a/arrus/core/examples/AfeDDCExample_v2_FirGen.py b/arrus/core/examples/AfeDDCExample_v2_FirGen.py deleted file mode 100644 index a2d920dd2..000000000 --- a/arrus/core/examples/AfeDDCExample_v2_FirGen.py +++ /dev/null @@ -1,36 +0,0 @@ -import numpy as np -import scipy as sp -import matplotlib.pyplot as plt -import sys - -from scipy import signal - -if len(sys.argv) < 3: - print('Usage: "DDCFirGen.py [decimation factor] [cutoff frequency]"') -else: - cutoff = float(sys.argv[2]) - M = float(sys.argv[1]) - - fs = 65 - - if M % 1 == 0.0: - n = 16 * M - elif M % 1 == 0.5: - n = 32 * M - elif M % 1 == 0.25: - n = 64 * M - elif M % 1 == 0.75: - n = 64 * M - - n = int(n) - - h = signal.firwin(n, cutoff / (fs / 2)) - Mh = max(h) - sf = 32624 / Mh - h2 = sf * h - h3 = h2[n//2:] - - out = open("fir_generated.txt", "w") - for i in range(0, n//2): - out.write(str(int(h3[i]))) - out.write('\n') diff --git a/arrus/core/examples/AfeDemodFIR.h b/arrus/core/examples/AfeDemodFIR.h deleted file mode 100644 index c7d50e6d1..000000000 --- a/arrus/core/examples/AfeDemodFIR.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ARRUS_CORE_EXAMPLES_AFEDEMODFIRS_H -#define ARRUS_CORE_EXAMPLES_AFEDEMODFIRS_H - -//FIR coefficients valid for 65 MHz clk - -const int16_t fir10M[32] = { 32700, 30949, 27632, 23096, 17802, 12264, 6981, 2383, - -1222, -3674, -4962, -5209, -4642, -3541, -2196, -866, - 252, 1040, 1461, 1545, 1368, 1031, 635, 263, - -32, -225, -320, -336, -300, -236, -160, -82 }; - -#endif //ARRUS_CORE_EXAMPLES_AFEDEMODFIRS_H \ No newline at end of file diff --git a/arrus/core/examples/CMakeLists.txt b/arrus/core/examples/CMakeLists.txt index 48f2f91f3..08c937d80 100644 --- a/arrus/core/examples/CMakeLists.txt +++ b/arrus/core/examples/CMakeLists.txt @@ -17,8 +17,7 @@ target_link_directories(pwi-example PRIVATE ${ARRUS_LIB_PATH}) target_link_libraries(pwi-example PRIVATE arrus-core) target_include_directories(pwi-example PRIVATE ${ARRUS_INCLUDE_PATH}) -add_executable(demod-example AfeDDCExample_v2.cpp) +add_executable(demod-example PwiDdcExample.cpp) target_link_directories(demod-example PRIVATE ${ARRUS_LIB_PATH}) -target_link_libraries(demod-example PRIVATE arrus-core PUBLIC Boost::Boost) - +target_link_libraries(demod-example PRIVATE arrus-core) target_include_directories(demod-example PRIVATE ${ARRUS_INCLUDE_PATH} ${Boost_INCLUDE_DIRS}) diff --git a/arrus/core/examples/PwiDdcExample.cpp b/arrus/core/examples/PwiDdcExample.cpp new file mode 100644 index 000000000..eb9a81148 --- /dev/null +++ b/arrus/core/examples/PwiDdcExample.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include + +#include "arrus/core/api/arrus.h" + +int main() noexcept { + using namespace ::arrus::session; + using namespace ::arrus::devices; + using namespace ::arrus::ops::us4r; + using namespace ::arrus::framework; + try { + arrus::useDefaultLoggerFactory()->setClogLevel(arrus::LogSeverity::INFO); + auto settings = ::arrus::io::readSessionSettings("us4r.prototxt"); + auto session = ::arrus::session::createSession(settings); + auto us4r = (::arrus::devices::Us4R*) session->getDevice("/Us4R:0"); + auto probe = us4r->getProbe(0); + + unsigned nElements = probe->getModel().getNumberOfElements().product(); + std::cout << "Probe with " << nElements << " elements." << std::endl; + + ::arrus::BitMask aperture(nElements, true); + float txFrequency = 6e6; // [MHz] + Pulse pulse(txFrequency, 2, false); + // NOTE: we specify here the NUMBER OF I/Q SAMPLES to acquire + // (i.e. the target sampling frequency = fs/decimation factor is assumed). + ::std::pair<::arrus::uint32, arrus::uint32> sampleRange{0, 512}; + + std::vector txrxs; + // 10 plane waves + for(int i = 0; i < 10; ++i) { + std::vector delays(nElements, 0.0f); + txrxs.emplace_back(Tx(aperture, delays, pulse), Rx(aperture, sampleRange), 200e-6f); + } + + TxRxSequence seq(txrxs, {}, 100e-3, 1); + DataBufferSpec outputBuffer{DataBufferSpec::Type::FIFO, 4}; + // Digital Down Conversion: + // FIR filter coefficients: + // - the FIR filter order should be equal decimationFactor*16 + // - only a upper half of the FIR filter coefficients should be provided. + // + float decimationFactor = 4.0f; + // NOTE: the below FIR coefficients were calculated using Python: + // filter_order = decimationFactor*16 + // coeffs = scipy.signal.firwin(filter_order, txFrequency, fs=65e6) + // coeffs = coeffs[filter_order//2:] + std::vector firCoefficients = {0.18234651659672152, 0.16172486625099816, 0.12487982587460944, 0.07944398046616387, 0.03430398844523893, -0.0026133185074908405, -0.026157255063119715, -0.034889180817011325, -0.030945327136370222, -0.018965928416555058, -0.004494915529298055, 0.007628287152588109, 0.014419713683593693, 0.015175743942293598, 0.011161684805841312, 0.00478318006743135, -0.001412573813589476, -0.005562384563359233, -0.006912138093338076, -0.005787361358840273, -0.0032172403273668768, -0.0004159330245921233, 0.0016683945062905931, 0.0025961471738894463, 0.0024366998597999934, 0.0015898600953486795, 0.0005435013516173024, -0.0003223898280114102, -0.0008232837583015619, -0.0009500466921633298, -0.000789093632050986, -0.00044401971096737745}; + float demodulationFrequency = txFrequency; + DigitalDownConversion ddc(demodulationFrequency, firCoefficients, decimationFactor); + + Scheme scheme(seq, 4, outputBuffer, Scheme::WorkMode::HOST, ddc); + + auto result = session->upload(scheme); + us4r->setDtgcAttenuation(24); + us4r->setVoltage(5); + + std::condition_variable cv; + using namespace std::chrono_literals; + + OnNewDataCallback callback = [&, i = 0](const BufferElement::SharedHandle &ptr) mutable { + try { + std::cout << "Iteration: " << i << ", data: " << std::endl; + std::cout << "- memory ptr: " << std::hex + << ptr->getData().get() + << std::dec << std::endl; + std::cout << "- size: " << ptr->getSize() << std::endl; + std::cout << "- shape (total number of samples, I/Q, RX channels): (" + << ptr->getData().getShape()[0] + << ", " << ptr->getData().getShape()[1] + << ", " << ptr->getData().getShape()[2] + << ")" << std::endl; + // Stop the system after 10-th frame. + if(i == 10) { + cv.notify_one(); + } + ptr->release(); + ++i; + } catch(const std::exception &e) { + std::cout << "Exception: " << e.what() << std::endl; + cv.notify_all(); + } catch (...) { + std::cout << "Unrecognized exception" << std::endl; + cv.notify_all(); + } + }; + + OnOverflowCallback overflowCallback = [&] () { + std::cout << "Data overflow occurred!" << std::endl; + cv.notify_one(); + }; + + // Register the callback for new data in the output buffer. + auto buffer = std::static_pointer_cast(result.getBuffer()); + buffer->registerOnNewDataCallback(callback); + buffer->registerOnOverflowCallback(overflowCallback); + + session->startScheme(); + + // Wait for callback to signal that we hit 10-th iteration. + std::mutex mutex; + std::unique_lock lock(mutex); + cv.wait(lock); + + // Stop the system. + session->stopScheme(); + + } catch(const std::exception &e) { + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} diff --git a/arrus/core/examples/fir.txt b/arrus/core/examples/fir.txt deleted file mode 100644 index f69a7e8a3..000000000 --- a/arrus/core/examples/fir.txt +++ /dev/null @@ -1,32 +0,0 @@ -32624 -29995 -25144 -18807 -11905 -5374 -0 --3707 --5576 --5762 --4676 --2868 --896 -777 -1863 -2269 -2075 -1476 -712 -0 --510 --758 --762 --594 --346 --102 -84 -191 -225 -205 -151 -80