Giter Site home page Giter Site logo

futuresdr / futuresdr Goto Github PK

View Code? Open in Web Editor NEW
263.0 19.0 46.0 25.73 MB

An Async SDR Runtime for Heterogeneous Architectures

License: Apache License 2.0

JavaScript 0.02% Makefile 2.39% SCSS 0.01% HTML 0.11% Rust 91.39% Shell 1.69% CMake 0.22% C++ 1.83% Python 2.32% WGSL 0.03%
sdr dsp rust radio wireless research runtime stream-processing message-passing

futuresdr's Introduction

FutureSDR

An experimental asynchronous SDR runtime for heterogeneous architectures that is:

  • Extensible: custom buffers (supporting accelerators like GPUs and FPGAs) and custom schedulers (optimized for your application).

  • Asynchronous: solving long-standing issues around IO, blocking, and timers.

  • Portable: Linux, Windows, Mac, WASM, Android, and prime support for embedded platforms through a REST API and web-based GUIs.

  • Fast: SDR go brrr!

Crates.io Apache 2.0 licensed Build Status

Website | Guides | API Docs | Chat

Overview

FutureSDR supports Blocks with synchronous or asynchronous implementations for stream-based or message-based data processing. Blocks can be combined to a Flowgraph and launched on a Runtime that is driven by a Scheduler.

  • Single and multi-threaded schedulers, including examples for application-specific implementations.
  • Portable GPU acceleration using the Vulkan API (supports Linux, Windows, Android, ...).
  • User space DMA driver for Xilinx Zynq to interface FPGAs.

Development

Since FutureSDR is in an early state of development, it is likely that SDR applications will require changes to the runtime. We, therefore, do not recommend to add it as a dependency in a separate project but to clone the repository and implement the application as binary, example, or sub-crate.

Example

An example flowgraph that forwards 123 zeros into a sink:

use futuresdr::anyhow::Result;
use futuresdr::blocks::Head;
use futuresdr::blocks::NullSink;
use futuresdr::blocks::NullSource;
use futuresdr::macros::connect;
use futuresdr::runtime::Flowgraph;
use futuresdr::runtime::Runtime;

fn main() -> Result<()> {
    let mut fg = Flowgraph::new();

    let src = NullSource::<u8>::new();
    let head = Head::<u8>::new(123);
    let snk = NullSink::<u8>::new();

    connect!(fg, src > head > snk);

    Runtime::new().run(fg)?;

    Ok(())
}

Contributing

Contributions are very welcome. Please see the (work-in-progress) contributing guide for more information. If you develop larger features or work on major changes with the main intention to submit them upstream, it would be great, if you could announce them in advance.

Conduct

The FutureSDR project adheres to the Rust Code of Conduct. It describes the minimum behavior expected from all contributors.

License

This project is licensed under the Apache 2.0 license.

Using this license is in contrast to the large majority of Open Source SDR applications and frameworks, which are mostly AGLP, LGPL, or GPL. In a nutshell, this means that there is no money to be made from relicensing the project for commercial use, since this is already allowed by Apache 2.0. Furthermore, companies can use (parts of) the project and integrate (adapted) versions in commercial products without releasing the source or contributing back to the project.

The main motivation for this license is that

  • it better fits the Rust ecosystem
  • it eases adoption; one can use (parts of) the code with close to no strings attached
  • using Open Source and not contributing back (for the time being) seems better than not using Open Source at all

Contributions

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in FutureSDR, shall be licensed as Apache 2.0, without any additional terms or conditions.

futuresdr's People

Contributors

anderskaloer avatar arctic-alpaca avatar basicinside avatar bastibl avatar corvus-ch avatar etschneider avatar joushx avatar julidi avatar justacec avatar klangner avatar lkolbly avatar loic-fejoz avatar meinscheins avatar niklassadmin avatar nrot avatar phlorian avatar ratzrattillo avatar wcampbell0x2a avatar wspeirs avatar yuvadm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

futuresdr's Issues

Make SoapySource/Sink new() parameters optional

Using the dev parameter allows for flexibility in preconfiguring a Soapy device, but the freq,sample_rate, and gain parameters are always applied, which may override the desired device settings.

I propose making those inputs Option<>.

A PR will follow shortly.

There are some other architecture questions I have about the Soapy implementation (and block/arch in general), perhaps the discussion area (Q&A?) might be the right place for that?

For example, is Kernel::init() the mandated place for all device init, as opposed to doing it during creation of the block. It seems cleaner to me to init the device (and stream) in new() and just do the stream.activate() in Kernel.init(). That would alleviate the need to carry the initialization params in the sink/source struct, only to be used during flowgraph initialization.

Accessing data in VectorSink

I'm building simple GUI app for showing the spectrum. Just for learning purposes.
As a starting point I have Source -> FTT -> VectorSink

Now I need to access samples from VectorSink while the flowgraph is working. VectorSink kernel has function items(), but since I'm calling it from different thread I can't use this function directly. I think I should use message to get this data.

Currently VectorSink doesn't support this as an output. Would it make sens to add it to it? Something like

StreamIoBuilder::new()
  .add_input::<T>("in")
  .add_input("items", Self::items_handler)
  .build()

Where the message would be Pmt::VecF32.
The handler would copy internal buffer into a given vector.

Or maybe there is another way to get the output from FFT in realt time which I'm missing?

Unable to compile examples with soapysdr (Issue with libclang)

Version
Master

Platform

System Configuration

Darwin Justaces-MBP 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64
(MacOS 11.6)

Rust Configuration

❯ rustup show
Default host: x86_64-apple-darwin
rustup home:  /Users/justaceclutter/.rustup

installed toolchains
--------------------

stable-x86_64-apple-darwin
nightly-2019-07-19-x86_64-apple-darwin
nightly-2019-07-29-x86_64-apple-darwin
nightly-x86_64-apple-darwin (default)
1.52-x86_64-apple-darwin

installed targets for active toolchain
--------------------------------------

arm-unknown-linux-gnueabihf
armv7-unknown-linux-gnueabihf
thumbv7em-none-eabi
thumbv7em-none-eabihf
thumbv7m-none-eabi
wasm32-unknown-unknown
x86_64-apple-darwin

active toolchain
----------------

nightly-x86_64-apple-darwin (default)
rustc 1.57.0-nightly (11491938f 2021-09-29)

LLVM install info

❯ brew info llvm
llvm: stable 13.0.0 (bottled), HEAD [keg-only]
Next-gen compiler infrastructure
https://llvm.org/
/usr/local/Cellar/llvm/13.0.0_1 (10,841 files, 1.8GB)
  Poured from bottle on 2021-10-16 at 15:30:41
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/llvm.rb
License: Apache-2.0 with LLVM-exception
==> Dependencies
Build: cmake ✘, swig ✘
Required: [email protected] ✔
==> Options
--HEAD
	Install HEAD version
==> Caveats
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

llvm is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have llvm first in your PATH, run:
  echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> /Users/justaceclutter/.bash_profile

For compilers to find llvm you may need to set:
  export LDFLAGS="-L/usr/local/opt/llvm/lib"
  export CPPFLAGS="-I/usr/local/opt/llvm/include"

==> Analytics
install: 30,913 (30 days), 68,387 (90 days), 267,969 (365 days)
install-on-request: 22,031 (30 days), 47,539 (90 days), 201,152 (365 days)
build-error: 0 (30 days)

Environment Variables

LLVM_CONFIG_PATH=/usr/local/opt/llvm/bin/llvm-config
LIBCLANG_PATH=/usr/local/opt/llvm/lib/libclang.dylib

Description
I have been trying to compile FutureSDR with the "soapy" feature which pulls in clang-sys. I have installed LLVM via Homebrew and it is living at '/usr/local/opt/llvm'. The libclang.dynlib is under that dir in the lib directory and the 'llvm-config' command is under that directory in the bin dir. In addition, to get the examples to compile I have modified the Cargo.toml file to have the following default features:

default = ["soapy", "vulkan", "audio"]

I should also highlight that I have been able to cleanly build from git each of soapysdr, bindgen, and cpal without error. Seems that having each of them as reps in this repo simultaneously might be causing an issue. I also did see that cpal version 0.13.4 is pulling in bindgen version 0.56.0 while soapysdr is pulling in bindgen version 0.57.0. Not sure if that would cause any issue.

I have not tried to build those specific versions of bindgen individually, just the git master.

I tried this code:

RUST_BACKTRACE=full cargo build --examples

I expected to see this happen: [explanation]

[Clean build with no issues]

Instead, this happened: [explanation]

Build Error

❯ RUST_BACKTRACE=full cargo build --examples
   Compiling soapysdr-sys v0.7.2
   Compiling rodio v0.14.0
error: failed to run custom build command for `soapysdr-sys v0.7.2`

Caused by:
  process didn't exit successfully: `/Users/justaceclutter/Source/FutureSDR/target/debug/build/soapysdr-sys-763a0a3c5ea62682/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=SOAPYSDR_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=SOAPYSDR_STATIC
  cargo:rerun-if-env-changed=SOAPYSDR_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=SOAPYSDR_STATIC
  cargo:rerun-if-env-changed=SOAPYSDR_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rustc-link-search=native=/usr/local/Cellar/soapysdr/0.8.1/lib
  cargo:rustc-link-lib=SoapySDR
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=SOAPYSDR_STATIC
  cargo:rerun-if-env-changed=SOAPYSDR_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-apple-darwin
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_apple_darwin
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR

  --- stderr
  thread 'main' panicked at 'a `libclang` shared library is not loaded on this thread', /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-sys-1.2.0/src/lib.rs:1682:1
  stack backtrace:
     0:        0x10bd8a871 - std::backtrace_rs::backtrace::libunwind::trace::hbebac83a7f69c4c2
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
     1:        0x10bd8a871 - std::backtrace_rs::backtrace::trace_unsynchronized::h70204c1920f029d2
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
     2:        0x10bd8a871 - std::sys_common::backtrace::_print_fmt::he9f032d543410c72
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:67:5
     3:        0x10bd8a871 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h4e8c7f30caf14f6b
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:46:22
     4:        0x10bdaa0ab - core::fmt::write::h6f39ff4b18ec6aa7
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/fmt/mod.rs:1161:17
     5:        0x10bd867da - std::io::Write::write_fmt::h899eefaff8efe903
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/io/mod.rs:1668:15
     6:        0x10bd8c9b5 - std::sys_common::backtrace::_print::hd174081a00e4492d
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:49:5
     7:        0x10bd8c9b5 - std::sys_common::backtrace::print::h34ed55d4c4c57d09
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:36:9
     8:        0x10bd8c9b5 - std::panicking::default_hook::{{closure}}::h409faa78641a7645
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:210:50
     9:        0x10bd8c59f - std::panicking::default_hook::h7ee7aa30ab262721
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:227:9
    10:        0x10bd8d0a0 - std::panicking::rust_panic_with_hook::h5c4d3dad4cf39db7
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:624:17
    11:        0x10bd8cb3e - std::panicking::begin_panic_handler::{{closure}}::hbf5ff5e8c653ab15
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:521:13
    12:        0x10bd8ace7 - std::sys_common::backtrace::__rust_end_short_backtrace::h8ba5e37c718cb8e4
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:141:18
    13:        0x10bd8caaa - rust_begin_unwind
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:517:5
    14:        0x10bdb9eef - core::panicking::panic_fmt::h6c191e7f85e62838
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/panicking.rs:100:14
    15:        0x10bda86eb - core::panicking::panic_display::hec0e0339ecb4d7ac
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/panicking.rs:64:5
    16:        0x10bdb9dfc - core::option::expect_failed::hbff261a7d3cf636c
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/option.rs:1624:5
    17:        0x10bc92576 - core::option::Option<T>::expect::h230311a187a18542
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/option.rs:706:21
    18:        0x10bc7ff79 - clang_sys::clang_createIndex::hf8163e7de4770240
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/clang-sys-1.2.0/src/link.rs:157:25
    19:        0x10b9c0f0e - bindgen::clang::Index::new::h38e52c19637dc2b5
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.57.0/src/clang.rs:1532:20
    20:        0x10ba8d53a - bindgen::ir::context::BindgenContext::new::hd4732857e895e29c
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.57.0/src/ir/context.rs:516:21
    21:        0x10b99e338 - bindgen::Bindings::generate::hab6864fa3249b77e
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.57.0/src/lib.rs:2190:27
    22:        0x10b99bf8f - bindgen::Builder::generate::hd0bdc00bd5b95a37
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.57.0/src/lib.rs:1380:9
    23:        0x10b8d08ef - build_script_build::main::hf8f2c81678fffc65
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/soapysdr-sys-0.7.2/build.rs:32:20
    24:        0x10b8cfeae - core::ops::function::FnOnce::call_once::h6b4a5cfcb10bf215
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/ops/function.rs:227:5
    25:        0x10b8cfa71 - std::sys_common::backtrace::__rust_begin_short_backtrace::hc497ae0dfbce6332
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/sys_common/backtrace.rs:125:18
    26:        0x10b8cf924 - std::rt::lang_start::{{closure}}::he70b13a4c5aab169
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/rt.rs:146:18
    27:        0x10bd8a114 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h2bb4e56f9a9ac6d4
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/core/src/ops/function.rs:259:13
    28:        0x10bd8a114 - std::panicking::try::do_call::h9ea5cb80949e7410
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:403:40
    29:        0x10bd8a114 - std::panicking::try::h4b562ecd9d6aae1e
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:367:19
    30:        0x10bd8a114 - std::panic::catch_unwind::hb2383c409919c466
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panic.rs:133:14
    31:        0x10bd8a114 - std::rt::lang_start_internal::{{closure}}::hbab7bdef1dae4bda
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/rt.rs:128:48
    32:        0x10bd8a114 - std::panicking::try::do_call::h66dd746a0228a095
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:403:40
    33:        0x10bd8a114 - std::panicking::try::h9cadd6ac84f681cb
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panicking.rs:367:19
    34:        0x10bd8a114 - std::panic::catch_unwind::h5278b4a6bc69b4e6
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/panic.rs:133:14
    35:        0x10bd8a114 - std::rt::lang_start_internal::h8e9b61b890af96ee
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/rt.rs:128:20
    36:        0x10b8cf8fe - std::rt::lang_start::h463b8cec341bfbdf
                                 at /rustc/11491938f80988c7261a1179cf71a25c379c8783/library/std/src/rt.rs:145:17
    37:        0x10b8d0c46 - <unknown>
                                 at /Users/justaceclutter/.cargo/registry/src/github.com-1ecc6299db9ec823/soapysdr-sys-0.7.2/build.rs:41:2

The FIR filtering seems to not work with Complex32 signals

I have tried to implement a 2-FSK transmitter using the FutureSDK pieces (+ a VCO of my own), but whatever I try I cannot get a clean signal output.

futuresdr

Please check out the code here https://github.com/MarSik/debug-futuresdr-fsk-filtering/tree/no-filtering-issue

The debug outputs all show proper modulation at +/- 45 kHz, but the harmonics are still there. Comparing the output pre-filtering and post-filtering shows no difference.

The filter (140 kHz low pass with 50 kHz transition bw) I use:

let roofing_filter_taps = futuredsp::firdes::kaiser::lowpass::<f32>(140e3_f64 / SAMPLE_RATE, 50e3_f64 / SAMPLE_RATE, 0.01);
    let roofing_filter = FirBuilder::new::<Complex32, Complex32, f32, Vec<f32>>(roofing_filter_taps);

Sampling rate is 8 MHz.

I might be doing something wrong, but I can't figure out what that is.

The same approach (VCO + low pass filter) works just fine in GNURadio.

gnuradio

Add signal source block

It is often useful to have a source block that can generate basic functions, such as sinusoids, sawtooths, etc. While this can be done with the Source<A>, it is not particularly elegant and requires unsafe code due to potential race conditions:

static mut T: usize = 0;
let src = Source::<f32>::new(|| {
    let x = unsafe {
        T += 1;
        T
    };
    (2.0 * std::f32::consts::PI * (x as f32) * 0.1).sin()
});

A simple way to circumvent this issue would be to add a counter as argument the closure, so that it changes from f: impl FnMut() -> A + Send + 'static to f: impl Fn(usize) -> T + Send + 'static.

The implementation is straightforward, and I would be happy to create the block as well as some standard functions. The main question is whether Source<A> should be modified to include a counter, or should be implemented in a new SignalSource<A> block?

Example of using a networked SDR

Hi, I'm running a USRP n210, it's able to be discovered just fine by running SoapySDRUtil --probe="driver=uhd"

However I have been unsuccessful using Seify.

let src = SourceBuilder::new().args("soapy_driver=uhd")?.build()?;

I have tried a number of different args with no success as of yet, output just throws Error: Not Found

Any assistance would be much appreciated.

Thanks.

Produce More Output

I'm working on a FIR filter, and need the ability to produce more output than the length of the output slice. The pattern seems to be:

        let i = sio.input(0).slice::<f32>();
        let o = sio.output(0).slice::<f32>();

        let n = cmp::min(i.len(), o.len());

... do work ...

        sio.output(0).produce(n);

Then only work on n pieces of input/output. However, given interpolation for the FIR filter, it might produce more output than input. If I had say n*2 output, how can I make that work?

From my understanding of the code, there is no interface to do that.

Document required dependencies

On different operating systems different dependencies are required to make FutureSDR run smoothly with common SDR hardware.

Compiling the FutureSDR examples on Windows e.g. fails when compiling sopaysdr-sys 0.7.3:
pkg_config: Could not run "pkg-config" "--libs" "--cflags" "SoapySDR" "SoapySDR >= 0.6.0" Most likely, you need to install a pkg-config package for your OS.

or:

[INFO] [UHD] Win32; Microsoft Visual C++ version 14.2; Boost_107500; UHD_4.0.0.HEAD-0-g90ce6062 Found Rafael Micro R820T/2 tuner FutureSDR: ERROR - SoapySDR::Device::enumerate(sdrplay) sdrplay_api_Open() failed FutureSDR: INFO - Using format CF32.

The Readme.md should contain some information on the required dependencies e.g.:

Dependencies for Compiling on Microsoft Windows

The following dependencies are required to compile the FutureSDR examples on Windows:

Always select the "Add to PATH variable option in the installers", so the required libraries and binaries are found when compiling FutureSDR programs.
To avoid performance issues and warnings like FutureSDR: WARN - SoapyVOLKConverters: no VOLK config file found. Run volk_profile for best performance. please run: volk_profile on your commandline.

Dependencies for Compiling on Linux

...

Dependencies for Compiling on macOS

...

Note:

These dependencies might change over time and should constantly be updated. It would be best to keep the dependencies to a minimum and choose the most slim packages which fulfill the minimum requirements.

Let compiler infer types and ports in fg.connect()

Hey,

I am new to Rust, so some of the things I am saying may be wrong, or technically impossible. But looking at the example in your README I was a bit surprised to see

fg.connect_message(src, "out", snk, "in")?;

because it struck me as a bit "outdated" and error-prone. I would have expected more something like

fg.connect(src.out, snk.in)?;
  1. Not using strings as port-names, but instead struct fields, which allows us to catch more errors during compile time.
  2. This idea is a bit out there, but ports could be generics for their signal type, e.g. StreamPort<Complex<f32>>. This allows the compiler to even catch connection type errors and maybe even infer all connection types just from the output type of the first block?
  3. And because a field has a type (e.g. StreamPort vs MessagePort), we can infer what kind of connection we are building, so no need for connect_*() but one connect() for all port types.

Does that make sense, and would that work? As I said, I am new to Rust so my thinking may be wrong here...

FM Receiver Resampling Issue

I was trying to extend the FM receiver example. I added a function to the audio sink that allows querying the default sample rate of the device bastibl@8da5cea. For me, this returns 44.1kHz. Like in the current example, I wanted to resample in two steps with an intermediate rate of 5 * audio_rate. Using this in combination with my HackRF at a sample rate of 8MHz resulted in a rather long filter (~10k taps). With the default buffer size, this stalls the flowgraph, since only 4k samples fit in the buffer. Increasing the buffer size with a config.toml works. However, the audio is broken.

My WIP state is here https://github.com/bastibl/FutureSDR (the master branch). @AndersKaloer do you have any idea? I'm not sure if this is a problem with the resampler or my code.

Here's the diff with debug output: bastibl@6fcb45c

wgpu dependency broken

Our current dependency is:

wgpu = { git = "https://github.com/gfx-rs/wgpu.git", branch = "master", version = "0.12.0", optional = true }

However, wgpu recently pushed b87e50feaed8cf02f71da34e284c3c2147ef5666, which renames the adapter_downlevel_properties function to adapter_downlevel_capabilities. Depending on the latest master means that updating (or regenerating) .lock files will pull this in, which will break the build (this is breaking the CI in #37).

A couple options that I can think of:

  • Just fix our usage and leave the dependency how it is (the change doesn't seem to be functional),
  • Change the dependency to a specific git commit, or
  • Change it to depend on the v0.12 git branch, or
  • Depend only on the 0.12.0 version, which appears to have been released.

I'm not sure what the right fix is though.

Update wgpu depedency

Would it be possible to update dependency

wgpu = "0.19"
web-sys = "0.3.67"

I think pinning is not required now?

Currentlly it is not possible to compile this lib with other libraries which use newest version of web-sys (like iced)

Stream Tag Keys

Is it possible for stream tags to have keys?
In GNU Radio, tags have both keys and values, but I don't see this in FutureSDR.

AudioSink usability

After discussion with @bastibl in #110 and in fsdr-cli#6 I believe we should brainstorm a little bit on how to resolve the AudioSink topic.

Knowing that:

  • FutureSDR aims at being Fast: SDR go brrr!
  • leaky abstraction is to be avoided,
  • it is expected that one develop his own program for a dedicated hardware.
  • fsdr-cli is the exception of previous point (at the moment).
  • a flow-graph is usually fixed in its expected number of channels (mono or stereo or ...).
  • cpal crate cannot handle a StreamConfig that does not match exactly the hardware. In particular,
    • audio rate,
    • number of channels
  • rate adaptation could be done with RationalResampler
  • mono to stereo adaptation could be done with ApplyNM<1,2> (but read again your textbooks). Similarly for greater number of channels (bass channel is it?).
  • stereo to mono has no single answer and really depends on problem at hands, yet achievable with Combine.
  • complexity of last 3 adaptations points has impact on performance:
    • better reducing audio rate than increasing,
    • better increasing channel (just copy) than reducing channel.

The AudioSink API should aims at:

  • providing feedback to help the developer on how to best adapt his flow-graph for his own hardware.
  • ease automated decision on how to adapt the flow-graph.
  • not leaking cpal crate.

Proposal is to have a first function that, given a device name, an expected audio rate, and expected channels, return a list of potential adaptation to apply sorted by least complexity. Something along:

impl AudioSink {
  pub fn propose_config(
      device_name: Into<String>,
      expected_channels: u16,
      expected_audio_rate: u32,
  ) -> Vec<ConfigProposal > {
   ...
  }
}

The ConfigProposal shall contains information on the adaptation to be done, and even better could be a builder of Block.

pub struct ResamplerBuilder {
  expected_audio_rate: u32,
  actual_audio_rate: u32,
  interpolation: u32,
  decimation: u32,
}

pub struct ChannelizerBuilder {
  expected_channels: u16,
  actual_channels: u16
}

pub struct ConfigProposal {
  resampler: Option<ResamplerBuilder>,
  channelizer: Option<ChannelizerBuilder>,
}

impl ResamplerBuilder  {
  pub fn build(self) -> Block {
    ...
  }
}

impl ChannelizerBuilder {
  pub fn build(self) -> Block {
    ...
  }
}

Overall it should allow the developer to know what to do and an automated program to easily adapt its flow-graph.
Open for discussion. What do you think? What is missing?

macOS support? (making lttng optional)

Hello,

I'm new to FutureSdr and Rust, great project btw, and I'm stuck on macOS for some time, is it not too difficult to makes the lttng dependency optional as it's heavily linux dependent? Otherwise, what needs to be done to build and run on macOS?

Regards.

Two different crates trying to link different versions of the clang native library

When opening the FutureSDR repo with VS Code with the rust-analyzer extension installed, there are two persistent error pop-ups:

image

From looking at the logs, this appears to be the result of the rust-analyzer back-end running the command cargo check --workspace. Running the same command from the command line shows the problem:

PS C:\Users\jas\Develop\FutureSDR> cargo check --workspace
error: multiple packages link to native library `clang`, but a native library can be linked only once

package `clang-sys v0.21.2`
    ... which satisfies dependency `clang-sys = "^0.21.0"` (locked to 0.21.2) of package `bindgen v0.32.3`
    ... which satisfies dependency `bindgen = "^0.32.3"` (locked to 0.32.3) of package `lttng-ust-generate v0.1.1`
    ... which satisfies dependency `lttng-ust-generate = "^0.1.1"` (locked to 0.1.1) of package `futuresdr v0.0.19 (C:\Users\jas\Develop\FutureSDR)`
    ... which satisfies path dependency `futuresdr` (locked to 0.0.19) of package `androidfs v0.1.0 (C:\Users\jas\Develop\FutureSDR\examples\android)`
links to native library `clang`

package `clang-sys v1.3.3`
    ... which satisfies dependency `clang-sys = "^1"` (locked to 1.3.3) of package `bindgen v0.57.0`
    ... which satisfies dependency `bindgen = "^0.57.0"` (locked to 0.57.0) of package `soapysdr-sys v0.7.3`
    ... which satisfies dependency `soapysdr-sys = "^0.7.3"` (locked to 0.7.3) of package `soapysdr v0.3.2`
    ... which satisfies dependency `soapysdr = "^0.3.1"` (locked to 0.3.2) of package `futuresdr v0.0.19 (C:\Users\jas\Develop\FutureSDR)`
    ... which satisfies path dependency `futuresdr` (locked to 0.0.19) of package `androidfs v0.1.0 (C:\Users\jas\Develop\FutureSDR\examples\android)`
also links to native library `clang`

I see this on both Windows 10 and Ubuntu 22.04. It would be nice not to have those errors pop up every time you open FutureSDR with VS Code.

Instructions on how to start the frontend with FFT waterfall

When I run cargo run --example soapy --features="soapy" it starts okay, but when I visit http://127.0.0.1:1337/ I get 404: Not Found. Are there more steps needed to start the frontend with the FFT waterfall? Running make in frontend subdirectory succeeds.

FileSink repeated samples when writing to disk

So, I setup a graph which generates a frequency sweep (about the limit of my signal processing knowledge), throttles it, and then writes it to file:

fn main() -> Result<()> {
    let mut fg = Flowgraph::new();

    // Make a chirp source
    let mut freq = 0.0;
    let mut current_value = Complex::from_polar(1.0, 0.0);
    let src = fg.add_block(Source::<f32>::new(move || {
        freq += 0.00003;
        if freq > 3.14159265 / 2.0 {
            freq = 0.0;
        }
        current_value = current_value * Complex::from_polar(1.0, freq);
        current_value.re
    }));

    // Throttle that & send it to file
    let throttle = fg.add_block(Throttle::new(4, 100_000.0));
    let sink = fg.add_block(FileSink::new(4, "/tmp/tmp.f32"));

    fg.connect_stream(src, "out", throttle, "in")?;
    fg.connect_stream(throttle, "out", sink, "in")?;

    Runtime::new().run(fg)?;

    Ok(())
}

(I've pushed a branch which reproduces the problem here: https://github.com/lkolbly/FutureSDR/tree/lkolbly/clicks)

when I view the resulting file /tmp/tmp.f32 in inspectrum, I see this:
image
where I would expect a smooth tone sweep up to the top, starting again at the "bottom" (middle). To my untrained eye this looks like the FileSink block is repeatedly re-writing the last "few" samples, while it waits for the source + throttle to generate the next block of samples. (notably, I also have a somewhat more complicated flow graph involving FIR filters and such, which shows a similar behaviour but the glitches are further apart, maybe because the system is under more load?)

I considered the possibility that this was because of FileSink ignoring the item size, but I also wrote up this commit that should fix that, and I still saw this behaviour.

Because of the throttle block, it doesn't strike me as an issue with disk speed (additionally, my /tmp drive is on a SSD, so it should be very speedy)

It's also entirely possible that I'm just doing something dumb - but, is this known/unexpected behaviour?

Examples with wasm compilation target broken because of missing crate::async_io

Ran into this while trying to run examples:

  • cw
  • wgpu
  • spectrum
  • wasm

The error:

   Compiling futuresdr v0.0.18 (/home/jck/workspace/FutureSDR)                                                                                                                                                     
error[E0433]: failed to resolve: could not find `async_io` in the crate root                                                                                                                                       
  --> src/runtime/mocker.rs:72:16                                                                                                                                                                                  
   |                                                                                                                                                                                                               
72 |         crate::async_io::block_on(async move {                                                                                                                                                                
   |                ^^^^^^^^ could not find `async_io` in the crate root                                                                                                                                           
                                                                                                                                                                                                                   
error[E0425]: cannot find function `block_on` in this scope                                                                                                                                                        
   --> src/runtime/runtime.rs:119:9                                                                                                                                                                                
    |                                                                                                                                                                                                              
119 |         block_on(rx).expect("run_flowgraph did not signal startup completed");                                                                                                                               
    |         ^^^^^^^^ not found in this scope                                                                                                                                                                     
    |                                                                                                                                                                                                              
help: consider importing one of these items                                                                                                                                                                        
    |                                                                                                                                                                                                              
5   | use futures::executor::block_on;                                                                                                                                                                             
    |                                                                                                                                                                                                              
5   | use futures_lite::future::block_on;                                                                                                                                                                          
    |                                                                                                                                                                                                              
5   | use futures_lite::stream::block_on;                                                                                                                                                                          
    |                                                                                                                                                                                                              
                                                                                                                                                                                                                   
Some errors have detailed explanations: E0425, E0433.                                                                                                                                                              
For more information about an error, try `rustc --explain E0425`.                                                                                                                                                  
error: could not compile `futuresdr` due to 2 previous errors                                                                                                                                                      
Error: Compiling your crate to WebAssembly failed                                                                                                                                                                  
Caused by: failed to execute `cargo build`: exited with exit status: 101                                                                                                                                           
  full command: "cargo" "build" "--lib" "--target" "wasm32-unknown-unknown" "--features=wgpu"                                                                                                                      
make: *** [Makefile:4: wasm] Error 1                                                                                                                                                                               

I guess it's caused by conditional compilation of async_io re-export while code compiled to wasm still requires it (src/lib.rs):

// re-exports
#[cfg(not(target_arch = "wasm32"))]
pub extern crate async_io;

If you can think of easy enough fix I'd be glad to contribute.

Option to change soapy device properties at runtime

Hey,

Is it possible to change soapy device properties like the center frequency etc. at runtime? Or more general: Can the flowgraph be changed at runtime?

I would like to avoid stopping the flowgraph to create a new SoapySource object, which will cause a new device initialisation that takes a few seconds.
And if so, how could that be implemented in FutureSDR? I did not find a way to access the device after it is converted to a block.

From what I see in the soapy crate doc (https://kevinmehall.net/rustdoc/soapysdr/soapysdr/struct.Device.html#method.frequency) this might be possible, but I am anything but an expert on this.

What I would like to do at the end is an extension of the fm-receiver example:

let src = SoapySourceBuilder::new()
        .freq(93.7e6)
        .sample_rate(3.2e6)
        .gain(40.0)
        .build();

// Connect everything ...

// Execute 
Runtime::new().run(fg)?;
// as an asynchronous task/thread/whatever

// Make changes to the frequency to tune e.g. to a specific radio station on the go

Terminate `AudioSource` when the end of the file is reached

I try to write a flow graph reading an audio file, do some processing and writing the result to another file. Such a flow graph never exits, and the output is growing and growing. Testing with an AudioSink, I figured that, once the file ends, the output is a continuous hum.

I can mitigate this by using Head, but this requires knowing the length in advance.

Is this by intention? If so, what would be the correct way to approach this? If not, I suggest changing the current behavior and make AudioSink terminate once the end of the file is reached.

OpenTelemetry Integration

Problem

When designing a flowgraph, various blocks have to play together well in order to encode or decode a signal.

However, we are often blind as soon as the flowgraph is running and use ugly println debugging to know what is going on in a block.
So, while we can clearly look at the source and try to understand what they are doing, we do not have an insight on the concrete data/samples they operate on over time.

Gaining Observability

To tackle that lack of observability, projects often use tools like OpenTelemetry to record logs, traces and metrics.
The questions that telemetry might answer are e.g.:

  • Why is my AGC block not adjusting the signal strength appropriately?
  • Why is my ADSB-Decoder less sensitive than i would expect?

Telemetry could in these cases e.g. show, what the currently incoming power level of the IQ samples is, as well as the upper and lower threshold of the AGC, or its scaling factor. This gets even more interesting, when this data is visualized over time, because the behaviour of a block can be monitored, including how the AGC thresholds are adjusted over time or when e.g. edge cases are occuring.

Implememntation Ideas

An option to collect the telemetry data could be OpenTelemetry for Rust and the vendor agnostic OpenTelemetry-Collector.
Telemetry data can either be "pushed to" or "scraped by" a collector.
Afterwards, the telemetry data could be processed further with each persons favourite tooling in a pipeline like e.g. FutureSDR -> OpenTelemetry-Collector -> Prometheus -> Grafana.

The idea behind this issue is to discuss, if it would make sense to integrate a Telemetry Framework in the FutureSDR runtime.
Questions that have to be answered are:

  • How can we give block implementors an easy interface within a block to export required telemetry data?
  • Can we reuse the control port to automatically provide a /metrics route which can be scraped?
  • How can we implement telemetry with the least performance degradation possible (e.g. default to no telemetry at all, using feature flags)?
  • Does Telemetry affect the portability of FutureSDR?

Looking forward to some feedback! :)

Further Information:

OpenTelemetry Concepts
OpenTelemetry Metrics Spec
OpenTelemetry Exporter Example

Upgrade axum to 0.6.3

Axum 0.6 has a few nice features which make designing applications easier (e.g. new state handling).
Could you please upgrade axum to 0.6.3?

Do not return an error when flowgraph was terminated exteranlly.

There is currently no differentiation between termination because of a block error and external termination of the flowgraph through the flowgraph handle. In both cases the flowgraph task returns an Err("Flowgraph was terminated"). While this is fine when a block failed, we should probably try to shutdown gracefully in case of external termination. Maybe we should introduce Kill (in case of block error) and Shutdown (from external). In the latter case, the flowgraph task should succeed. See this example: https://github.com/samcarey/drop_block_test/blob/main/src/main.rs#L20

Checking type size is not enough

There is currently a type size check at runtime, preventing out of array access for input consumers. https://docs.rs/futuresdr/latest/src/futuresdr/runtime/topology.rs.html#199

This does not prevent undefined behaviour, for example it allows to connect f64 to Complex<f32> arguments:

use futuresdr::anyhow::Result;
use futuresdr::blocks::NullSink;
use futuresdr::runtime::Flowgraph;
use futuresdr::runtime::{Block, Runtime};
use futuresdr::blocks;
use futuresdr::blocks::Fft;

/// Create sine tone.
pub struct Oscillator64;

impl Oscillator64 {
    pub fn new(freq: f64, amp: f64, sample_rate: f64) -> Block {
        let mut arg = 0.0;
        let diff = 2.0 * std::f64::consts::PI * freq / sample_rate;
        blocks::Source::new(move || {
            let s = amp * f64::sin(arg);
            arg += diff;
            arg = arg.rem_euclid(std::f64::consts::PI * 2.0);
            s
        })
    }
}

fn main() -> Result<()> {
    let mut fg = Flowgraph::new();

    let src = Oscillator64::new(440.0, 0.3, 48000.0);
    let fft = Fft::new(512);
    let snk = NullSink::<f64>::new();

    // uh oh \o/
    let src = fg.add_block(src);
    let fft = fg.add_block(fft);
    let snk = fg.add_block(snk);

    fg.connect_stream(src, "out", fft, "in")?;
    fg.connect_stream(fft, "out", snk, "in")?;

    Runtime::new().run(fg)?;

    Ok(())
}

AudioSink add complex input or multiple taps

When using the AudioSink block with two channels, i would expect the block to have two input taps (e.g. one for the left and one for the right channel).
@loic-fejoz suggested two have either one tap per channel, or one tap accepting a Complex number as input.

Currently the AudioSink in blocks/audio/audio_sink.rs:40 creates the stream with a hardcoded size of 4 Bytes per sample:

StreamIoBuilder::new().add_input("in", 4).build(),

To play an audio file with only one channel (like the rick.mp3 example) on a windows PC, which in many cases only show an audio output device with two channels, hacks like this have to be done:

`
use cpal::traits::{DeviceTrait, HostTrait};
use futuresdr::anyhow::Result;
use futuresdr::blocks::ApplyIntoIter;
use futuresdr::blocks::audio::AudioSink;
use futuresdr::blocks::audio::FileSource;
use futuresdr::runtime::{Flowgraph, Runtime};

fn main() -> Result<()> {

let host = cpal::default_host();
let audio_device = host.default_output_device().expect("no output device available");
println!("Device name: {}", audio_device.name().unwrap());
let supported_configs_range = audio_device.supported_output_configs().expect("error while querying configs");
for format in supported_configs_range {
    println!("Sample Rate: Min: {:?}, Max: {:?}", format.min_sample_rate(), format.max_sample_rate());
    println!("Channels: {}", format.channels());
    println!("SampleFormat: {:?}", format.sample_format());
}

let filename = "rick.mp3";
let mut fg = Flowgraph::new();

let src = FileSource::new(filename);
let inner = src.as_async::<FileSource>().unwrap();

fn tuple(s: &f32) -> Vec<f32> {
    let mut vec = Vec::with_capacity(2);
    vec.push(*s); // L
    vec.push(*s); // R
    return vec;
}
let custom = ApplyIntoIter::<f32, Vec<f32>>::new(tuple);
let snk = AudioSink::new(inner.sample_rate(), 2); // inner.channels()

println!("File: {}, Sample Rate: {}, Channels: {}", filename, inner.sample_rate(), inner.channels());

let src = fg.add_block(src);
let custom = fg.add_block(custom);
let snk = fg.add_block(snk);

fg.connect_stream(src, "out", custom, "in")?;
fg.connect_stream(custom, "out", snk, "in")?;

let rt = Runtime::new();
rt.run(fg).unwrap();

Ok(())

}
`

Thanks to @loic-fejoz for providing the sample.

wasm example fails to build

Using the current main branch, the wasm example fails to build. This also happens when I try to compile a wasm project with FutureSDR as a dependency. I will try to figure out what's the issue and report back. Any hints on where to look are welcome!

error[E0433]: failed to resolve: could not find `UsbControlTransferParameters` in `web_sys`
   --> /home/user/Git/FutureSDR_main/src/blocks/wasm/hack_rf.rs:249:34
    |
249 |         let parameter = web_sys::UsbControlTransferParameters::new(
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not find `UsbControlTransferParameters` in `web_sys`

This indicates that web-sys is somehow not working, maybe a missing feature.

Soapy: multiple channel configuration

I've made a first attempt at:
https://github.com/etschneider/FutureSDR/tree/ets_new_soapy

[EDIT: I pushed up some major changes and am adjusting this comment to match. I hope no one was looking at the original code.]

If anyone interested, please review and comment. This isn't pull ready,I just want to see if this general approach is acceptable before spending more time on it.

I made a new blocks::soapy sub-module, since the code is more complex. I'm using the examples/soapy_multichan.rs as a test case. (Perhaps some #[ignore] tests in the soapy module would be better? Or both?) [EDIT: I've added some integration tests]

A few points:

  • The new 'cmd' port is used for all the new configuration methods, and supports the dict format of the GNU Radio Soapy block, among others.
  • The SoapyConfig type is meant to allow arbitrarily configurations of all channels/directions with a single message
  • There is also a new SoapyCommand enum, but it doesn't really add anything currently.
  • Since the configuration logic is the same for SoapySource and SoapySink, I've made a generic SoapyDevice<stream type> parent for them both. Trying to keep it DRY.
  • I tend to think that the old freq and sample_rate ports should be removed. This would be a breaking change, so???

Use enumeration to distinguish between samples and messages

FutureSDR is heavily inspired by Gnuradio; For example it distinguishes between messages and data in separate input/output operations StreamIO and MessageIO and duplicates blocks respectively (e.g. Copy vs MessageCopy, Sink vs. MessageSink etc.) Further tags have no type associated, restricting it to primitive types or rely on polymophism via type erasing.
This makes working with messages more awkward and implementing combinatiorics on them more difficult.

For me he problem feels very similar to error handling in Rust and has probably a similar, more concrete solution. We could for example bound the input type of a node to implement the conversion traits (e.g. From or TryFrom) and either have a global enumeration of all possible messages (+ samples) or inter node specific messages. If a downstream library defines their own blocks and messages, they have to implement conversion into futuresdr message type (I'm using messages here for samples as well as data).

I'm not familiar with Gnuradio and not informed about scheduling differences between messages and samples, if there are some the idea may not be feasible.

Allow custom routes to call handlers in blocks

With the introduction of flowgraph.set_custom_routes(router); we have the option to add custom routes to the axum server backing the FutureSDR control port.
While this is nice we are still having some limitations, as within these custom routes we cannot call the handlers of a block directly.
Example:
The default handler to set the RX frequency of a SoapySource Block to a out of range value might crash the flowgraph. Thus, users might want to introduce bounds checking. Bounds checking can be done in the handler of a custom route, but then how to call the original block handler to set the frequency?

The current workaround is to create a second axum server which can receive the handle to a flowgraph (let (task_handle, fg_handle) = block_on(runtime.start(fg)); and then giving the fg_handle to the custom route in the scond axum server. This is not very elegant.

Another workaround would be to do the bounds checking in a custom route and then create a new HTTP request to the handler function in the SoupySource Block. Not too elegant either.

We thus need a way to allow custom routes to efficiently call handler fucntions of a block in a flowgraph.
Also, we should considering that the axum server is not bound to a flowgraph, but rather to the runtime, meaning having not one axum server per flowgraph, but one per runtime instance.

ZeroMQ PubSink & SubSource

Why ZeroMQ?
ZeroMQ is by default in GNU Radio Companion.

ZMQSubSource & ZMQPubSink as blocks
I would like to have blocks to publish stream & receive stream from other systems.

Underlying ZMQ rust lib?
I have done an experiment with zmq library which is blocking one.
Should we consider using async-zmq (non blocking) or the more idiomatic libzmq (but unmaintained).

Additional context
Having those would enable tests where only part of a chain is migrated to FutureSDR. For instance, it could enable to split a chain between GNU Radio and FutureSDR until FutureSDR had all the mandatory blocks of the overall chain.

Runtime lifetime not tight to tasks

This deadlocks:

let (task, mut fg_handle) = block_on(Runtime::new().start(fg));

This works:

let rt = Runtime::new();
let (task, mut fg_handle) = block_on(rt.start(fg));

Originally posted by @etschneider in #80 (comment)

Note to self: I think the runtime and the task should get a lifetime and the task needs to outlive the runtime.

AudioSource & AudioSink

AudioSource & AudioSink
The AudioSource & AudioSink blocks are one of the basic blocks of a lot of tutorial.

underlying library?
cpal could be a candidate as the underlying library.
Being a newbie in Rust, I do not know much about the state of such audio crates.
NB: I have tried to provide such a block but I am stuck with some requirement from cpal of having 'static callbacks.

VCO and similar blocks

Voltage Controlled Oscillator (VCO) and other similar blocks are missing.
I believe we can come with a common implementation for various use-cases.
At least propose implementation for:

It should also be a base for Phase Shift Keying (PSK, eg BPSK, GMSK, QPSK) and other constellations handling.

Implementation experimentation started in my branch: https://github.com/loic-fejoz/FutureSDR/blob/feature/vco/src/blocks/signal_source/controlled_oscillator.rs

Raspberry Pi Compilation Error

Version
Master Branch

Platform

  • Raspbery Pi 2 B v1.1 2014
  • Raspberry Pi 400

Description

Compilation Error: expected u8 while getting i8

NB: PullRequest to come

choosing hackrf as device for examples?

Hi Everyone,
Do I need to choose or set hackrf as my device for the examples?
I get an error,
FutureSDR: ERROR - Source_0: Error during initialization. Terminating.
FutureSDR: ERROR - Source_0: Error in Block.run() Soapy (StreamError: RtAudio init error 'RtApiDs::probeDeviceOpen: error (Invalid parameter) creating input buffer (Default Device)!)
Richard

Example for SSB modulation

Recently, I played around with FutureSDR. That resulted in me implementing SSB modulation. Would it be interesting for this project to have this added as an example? If that is the case, I happily would provide a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.