flipperzero 0.15.0

Rust for Flipper Zero
Documentation
//! Example showcasing the use of a stream buffer on multiple threads.

#![no_main]
#![no_std]

// Required for panic handler
extern crate flipperzero_rt;

// Required for allocator
extern crate flipperzero_alloc;

extern crate alloc;

use core::{ffi::CStr, num::NonZeroUsize};

use flipperzero::{furi, println};
use flipperzero_rt::{entry, manifest};

use core::time::Duration as CoreDuration;
use furi::time::FuriDuration;

// Define the FAP Manifest for this application
manifest!(name = "Stream buffer example");

// Define the entry function
entry!(main);

// Entry point
fn main(_args: Option<&CStr>) -> i32 {
    // Create a stream buffer pair
    let size = NonZeroUsize::new(1024).unwrap();
    let trigger_level = 16;
    let stream_buffer = furi::stream_buffer::StreamBuffer::new(size, trigger_level);
    let (tx, rx) = stream_buffer.into_stream();

    let stream_buffer = tx.as_stream_buffer();

    // Stream buffer is empty
    assert_eq!(stream_buffer.spaces_available(), size.into());
    assert_eq!(stream_buffer.bytes_available(), 0);

    // Sending 4 bytes immediately
    assert_eq!(tx.send(&[1, 2, 3, 4]), 4);
    assert_eq!(stream_buffer.bytes_available(), 4);

    // Receive bytes
    let mut recv_buf = [0; 32];
    assert_eq!(rx.recv(&mut recv_buf), 4);
    assert_eq!(recv_buf[0..4], [1, 2, 3, 4]);

    // Move sender to another thread
    let tx_thread = furi::thread::spawn(move || {
        // Wait 2 seconds before we send some bytes
        furi::thread::sleep(CoreDuration::from_secs(2));
        assert_eq!(tx.send(&[5; 20]), 20);

        // Send some bytes in a loop to see how the receiver handles them
        for i in 4..20 {
            furi::thread::sleep(CoreDuration::from_millis(200));
            tx.send(&[i as u8; 3]);
        }

        0
    });

    // Move receiver to another thread
    let rx_thread = furi::thread::spawn(move || {
        let mut buf = [0; 32];

        // The sender waits 2 seconds, so we don't block and get no bytes
        assert_eq!(rx.recv(&mut buf), 0);

        // The sender sends 20 bytes after two seconds, that is more than the trigger, so we continue
        assert_eq!(rx.recv_blocking(&mut buf), 20);

        // Try to receive bytes as long as the sender is alive
        while rx.is_sender_alive() {
            let n = rx.recv_with_timeout(&mut buf, FuriDuration::from_secs(2));
            println!("got {} bytes: {:?}", n, buf[0..n]);
        }

        0
    });

    tx_thread.join();
    rx_thread.join();

    0
}