#scpi #embedded-devices #async #no-alloc #protocols

no-std microscpi

A Rust library for creating SCPI interfaces

9 releases

new 0.3.2 Mar 3, 2025
0.3.1 Dec 29, 2024
0.3.0 Nov 26, 2024
0.2.0 Nov 12, 2024
0.1.0-alpha.3 Sep 29, 2024

#659 in Embedded development

Download history 28/week @ 2024-11-15 144/week @ 2024-11-22 17/week @ 2024-11-29 7/week @ 2024-12-06 1/week @ 2024-12-13 113/week @ 2024-12-27 14/week @ 2025-01-03 5/week @ 2025-01-10 85/week @ 2025-02-14 1/week @ 2025-02-21 111/week @ 2025-02-28

197 downloads per month

MIT license

105KB
2K SLoC

microSCPI

build Latest version Documentation Codecov License: MIT

A lightweight, zero-allocation async SCPI command interpreter for Rust, optimized for embedded systems.

📋 Overview

microSCPI provides a simple yet powerful interface for creating an asynchronous SCPI (Standard Commands for Programmable Instruments) command interpreter. It's specifically designed for embedded devices where resource constraints are a primary concern. The library enables developers to easily implement SCPI communication protocols with minimal overhead.

✨ Key Features

  • Zero Heap Allocations: Operates without dynamic memory allocation, perfect for memory-constrained embedded systems
  • Compile-Time Command Tree: Efficient command processing with command definitions resolved at compile time
  • Async Command Handling: Full support for asynchronous command handlers, enabling non-blocking operations
  • Type-Safe Responses: Return values are automatically formatted according to their type
  • Minimal Dependencies: Keeps your project's dependency tree lean and build times fast
  • Robust Error Handling: Comprehensive error reporting and recovery mechanisms

🚀 Getting Started

Installation

Add microSCPI to your project by including it in your Cargo.toml:

[dependencies]
microscpi = "0.3.2"

If you need async functionality, make sure to include an async runtime like tokio:

[dependencies]
tokio = { version = "1", features = ["full"] }

Basic Example

Here's a minimal example demonstrating how to use microSCPI to create an SCPI command interface:

use microscpi::{self as scpi, Interface, ErrorHandler};

pub struct ExampleInterface {
    value: u64
}

impl ErrorHandler for ExampleInterface {
    fn handle_error(&mut self, error: scpi::Error) {
        println!("Error: {error}");
    }
}

#[microscpi::interface]
impl ExampleInterface {
    #[scpi(cmd = "SYSTem:VALue?")]
    async fn system_value(&mut self) -> Result<u64, scpi::Error> {
        Ok(self.value)
    }
}

#[tokio::main]
pub async fn main() {
    let mut output = Vec::new();
    let mut interface = ExampleInterface { value: 42 };

    interface.run(b"SYSTEM:VAL?\n", &mut output).await;

    assert_eq!(output, b"42\n");
}

📖 Documentation

For comprehensive documentation, visit docs.rs/microscpi.

🔧 Project Structure

microSCPI is organized as a workspace with the following components:

  • microscpi: The core library implementation
  • microscpi-macros: Procedural macros for the #[microscpi::interface] and #[scpi] attributes

👥 Contributing

Contributions are welcome! Feel free to submit issues or pull requests on the GitHub repository.

📄 License

This project is licensed under the MIT License.

Dependencies

~0.6–1.2MB
~26K SLoC