cmsis_dsp/
lib.rs

1#![no_std]
2
3//!
4//! This library provides Rust-friendly interfaces to the CMSIS DSP library, which implements
5//! many mathematical and signal processing operations for ARM Cortex-M processors.
6//!
7//! Complete documentation for the underlying library can be found
8//! [here](https://arm-software.github.io/CMSIS_5/DSP/html/index.html).
9//!
10//! ## Configuring and using the bindings
11//!
12//! Different versions of the library will be linked depending on the type of processor the code will run on.
13//! You may need to enable some Cargo features depending on the target:
14//!
15//!  * Cortex-M7: Enable the feature `cortex-m7`. Also, if the processor has a double-precision floating point unit, enable
16//!    the `double-precision-fpu` feature.
17//!  * Cortex-M33 (target `thumbv8m.main-none-eabi` or `thumbv8m.main-none-eabihf`): If the processor supports DSP
18//!    instructions, enable the `dsp-instructions` feature.
19//!
20//! All other targets will be configured automatically based on the target passed to cargo. If you forget to enable a
21//! feature, everything should still work but it may be slower.
22//!
23//!
24
25extern crate cmsis_dsp_sys_pregenerated as cmsis_dsp_sys;
26
27pub mod basic;
28pub mod transform;
29pub mod complex;
30#[cfg(feature = "libm")]
31mod libm_c;
32#[cfg(all(feature = "micromath", not(feature = "libm")))]
33mod micromath_c;
34
35use core::convert::TryInto;
36use core::fmt::Debug;
37
38/// DSP library errors
39#[derive(Debug)]
40pub enum Error {
41    Argument,
42    Length,
43    SizeMismatch,
44    NanInf,
45    Singular,
46    TestFailure,
47    Unknown,
48}
49
50trait StatusCode {
51    /// Converts this status code into Ok(()) if this represents success, or an error value
52    /// if this represents an error
53    fn check_status(self) -> Result<()>;
54}
55
56impl StatusCode for cmsis_dsp_sys::arm_status::Type {
57    fn check_status(self) -> Result<()> {
58        use cmsis_dsp_sys::arm_status::*;
59        match self {
60            ARM_MATH_SUCCESS => Ok(()),
61            ARM_MATH_ARGUMENT_ERROR => Err(Error::Argument),
62            ARM_MATH_LENGTH_ERROR => Err(Error::Length),
63            ARM_MATH_NANINF => Err(Error::NanInf),
64            ARM_MATH_SINGULAR => Err(Error::Singular),
65            ARM_MATH_SIZE_MISMATCH => Err(Error::SizeMismatch),
66            ARM_MATH_TEST_FAILURE => Err(Error::TestFailure),
67            _ => Err(Error::Unknown),
68        }
69    }
70}
71
72/// Result type alias
73pub type Result<T> = ::core::result::Result<T, Error>;
74
75
76
77/// Checks that all elements of the provided lengths value/tuple are equal, and that the length
78/// value fits into the returned integer type. This function panics if any condition does not hold.
79fn check_length<L, N>(lengths: L) -> N
80    where
81        L: Lengths,
82        usize: TryInto<N>,
83        <usize as TryInto<N>>::Error: Debug,
84{
85    lengths.assert_lengths_equal();
86    lengths
87        .length()
88        .try_into()
89        .expect("Length too large for size type")
90}
91
92trait Lengths {
93    fn assert_lengths_equal(&self);
94    fn length(&self) -> usize;
95}
96
97impl Lengths for usize {
98    fn assert_lengths_equal(&self) {
99        // Only one element, nothing to do
100    }
101
102    fn length(&self) -> usize {
103        *self
104    }
105}
106
107impl Lengths for (usize, usize) {
108    fn assert_lengths_equal(&self) {
109        assert_eq!(self.0, self.1);
110    }
111
112    fn length(&self) -> usize {
113        self.0
114    }
115}
116
117impl Lengths for (usize, usize, usize) {
118    fn assert_lengths_equal(&self) {
119        assert!(self.0 == self.1 && self.1 == self.2);
120    }
121
122    fn length(&self) -> usize {
123        self.0
124    }
125}