Today I would like to introduce you to two of my favorite open-source projects, Slint and FutureSDR, and show you how to plot data produced by FutureSDR in a Slint application.

Slint is a GUI framework written in Rust and has bindings to, e.g., Rust and C++, and it can be used on embedded devices. There is not much support for displays on STM32s (or others) in Rust at the moment, but at Systemscape we are working hard to change that. It has been very easy to get started with Slint and despite being a rather young project, there is already plenty of functionality available — and it's all properly documented.

FutureSDR is, as the name suggests, a new Software-defined Radio (SDR) runtime. If you're familiar with GNURadio, you can think of it as a nice and fast version GNURadio's Python interface. FutureSDR does not (yet) have a GUI that lets you connect and configure the blocks without coding, but I have not found that to be an issue at all. What I love most about FutureSDR is how it "just works"™, independent of the platform, and it works reliably and fast ("SDR go brrr!") thanks to Rust.

Considering that embedded Rust is not yet at a stage where we can "simply" control a display, the next closest platform in terms of restrictions regarding computation power and access to an operating system is the web. And using Rust it is easy to compile a program to WebAssembly (Wasm), as well. Although Rust's standard library is accessible in Wasm programs, not crates may work like on the desktop. For example, Tokio (an async runtime with lots of features) only has limited capabilities on the web and going multithreaded is also not yet possible. So the application is expected to be slower and have limited functionality compared to running on a full OS. This is quite similar to the situation on embedded, but with the additional comfort added by Rust's standard library.

Before we go into more details, you can try out the following demo application that generates data using FutureSDR and displays it on a Slint GUI. The Plot is created using plotters. Due to the SVG plot rendering consuming quite some resources, the plot is disabled on page load. You must enable it manually using the "Enable Plot" switch. To allow for some basic interaction with FutureSDR (controlling a real SDR from the GUI would be way cooler, of course!), you can adjust the amount of noise added to the sine wave before the FFT.

The code for this demo and code for streaming via WebSockets or replaying static data are found on Github.

Loading...

You may have noticed that changes to the noise level are not displayed immediately. This is due to buffering inside the processing chain of the flowgraph in FutureSDR. If the application seems laggy on your device or at least your CPU load goes higher than usual, this is not due to the FFT computation, but due to the SVG rendering inside Slint.

To see why that is and why we cannot simply render and display a bitmap from plotters (spoiler: we could), we should first understand how the example works. It consists of roughly three parts:

Why does the bitmap backend not work?

Well, it does! You can try it out for yourself by disabling the svg feature. You will quickly notice that the axes labels are gone. The issue here is that, although Slint itself will draw onto an HTML canvas, we cannot use the plotters canvas backend because Slint currently only accepts bitmap or SVG images. Since rendering text is somewhat involved, it is usually left to the browser or whoever displays the SVG. So we would need to leverage the browser to render text to pixels, then add those pixels to the plot, save the bitmap and give it to Slint to draw it on an HTML canvas again.

When comparing with the bitmap backend, you will probably notice that the SVG backend has better quality, less aliasing and looks "better" overall – but is causing much higher CPU load.

So what would be great to have in the future: a fast bitmap backend that can render text on the web (or on embedded devices). At least support for monospaced fonts like in embedded-graphics looks feasible with limited effort.