Documentation

sim-fft

sim-fft is an easy to use Fast Fourier Transform library primarily meant for embedded systems.

Features

The library offers the following features:

  • Easy to use
  • Suitable for no_std environments
  • fft: Fast Fourier Transform Algorithm
  • ifft: Inverse Fast Fourier Transform Algorithm
  • Peak Value
  • magnitude and frequency calculation
  • window function:
    • hamming
    • hann
    • blackman
    • kaiser

Examples

for STM32F103:

#![no_std]
#![no_main]

use cortex_m_rt::entry;
use defmt::info;
use defmt_rtt as _;
use panic_semihosting as _;

use sim_fft::{Complex, SimpleFft};

#[entry]
fn main() -> ! {
    //sample freq 1Mhz
    let freq = 1_000_000;
    //test freg 93KHZ
    let mut buf = [
        4091, 4089, 4091, 4093, 4092, 4091, 2, 1, 1, 1, 1, 1, 4092, 4091, 4091, 4092, 4093, 2, 2,
        1, 1, 1, 4090, 4091, 4092, 4093, 4093, 4092, 2, 1, 1, 2, 1, 4092, 4093, 4093, 4093, 4091,
        2, 1, 2, 1, 2, 2, 4093, 4093, 4091, 4092, 4093, 2, 2, 1, 2, 1, 1, 4093, 4092, 4092, 4091,
        4092, 2, 2, 1, 1, 2, 4092, 4092, 4091, 4092, 4092, 4091, 2, 1, 2, 1, 2, 4091, 4094, 4093,
        4091, 4093, 2, 2, 1, 1, 1, 1, 4092, 4091, 4093, 4093, 4092, 2, 1, 1, 2, 1, 2, 4092, 4092,
        4093, 4094, 4093, 2, 2, 1, 2, 1, 4092, 4091, 4092, 4092, 4091, 4092, 2, 2, 1, 1, 1, 4092,
        4092, 4089, 4090, 4093, 3, 2, 1, 1,
    ];
    cal_hz(&mut buf, freq as f64, freq as f64);
    //221KHZ
    let mut buf = [
        4089, 4089, 1, 0, 4089, 4091, 4092, 0, 0, 4092, 4091, 1, 0, 4089, 4090, 4092, 2, 0, 4092,
        4090, 1, 0, 4089, 4091, 4092, 1, 0, 4090, 4090, 1, 0, 4089, 4090, 4090, 1, 0, 4092, 4090,
        1, 1, 4089, 4090, 4092, 1, 1, 4092, 4092, 1, 0, 4045, 4090, 4092, 1, 0, 4091, 4090, 1, 0,
        0, 4090, 4092, 1, 0, 4091, 4091, 0, 0, 0, 4090, 4091, 1, 0, 4090, 4089, 1, 0, 0, 4090,
        4091, 1, 0, 4092, 4091, 1, 0, 0, 4090, 4092, 1, 0, 4092, 4091, 1, 1, 0, 4090, 4090, 1, 0,
        4093, 4091, 1, 0, 0, 4091, 4092, 1, 1, 4092, 4091, 0, 1, 0, 4090, 4092, 1, 0, 4092, 4090,
        1078, 0, 0, 4092, 4092, 1, 0, 4092, 4091,
    ];
    cal_hz(&mut buf, freq as f64, freq as f64);
    //250Khz
    let mut buf = [
        1, 1, 1, 4092, 4092, 1, 0, 4089, 4089, 1, 0, 4089, 4092, 1, 0, 4092, 4092, 1, 0, 4092,
        4089, 1, 0, 4091, 4092, 1, 0, 4092, 4092, 1, 0, 4090, 4091, 1, 0, 4089, 4091, 1, 1, 4092,
        4092, 1, 0, 4092, 4089, 1, 0, 4089, 4092, 1, 0, 4092, 4092, 1, 0, 4091, 4091, 0, 0, 4090,
        4092, 1, 0, 4092, 4092, 1, 0, 4092, 4091, 1, 1, 4089, 4092, 1, 1, 4092, 4090, 1, 0, 4092,
        4091, 1, 0, 4089, 4092, 1, 0, 4092, 4092, 1, 0, 4091, 4089, 1, 0, 4091, 4092, 1, 1, 4090,
        4089, 1, 0, 4092, 4091, 0, 0, 4089, 4092, 1, 1, 4092, 4092, 1, 0, 4092, 4089, 1, 0, 4089,
        4092, 1, 0, 4090, 4090, 1, 0, 4092,
    ];
    cal_hz(&mut buf, freq as f64, freq as f64);
    //125khz
    let mut buf = [
        1, 4089, 4089, 0, 0, 0, 0, 4091, 4089, 4092, 4092, 1, 0, 0, 0, 4092, 4092, 4089, 4092, 1,
        1, 0, 0, 4091, 4092, 4091, 4089, 1, 0, 1, 0, 4092, 4091, 4092, 4092, 1, 0, 0, 1, 4092,
        4091, 4091, 4092, 1, 0, 0, 0, 4089, 4092, 4092, 4091, 1, 1, 0, 0, 4091, 4089, 4092, 4090,
        1, 0, 0, 0, 4090, 4091, 4091, 4092, 1, 0, 0, 0, 4089, 4092, 4092, 4089, 1, 0, 0, 0, 4091,
        4089, 4090, 4089, 1, 0, 0, 0, 4092, 4092, 4089, 4092, 1, 1, 0, 0, 4091, 4092, 4092, 4089,
        1, 0, 1, 0, 4090, 4090, 4090, 4092, 1, 0, 0, 1, 4092, 4092, 4091, 4092, 1, 0, 0, 0, 4089,
        4092, 4092, 4091, 1, 1, 1, 0, 4091,
    ];
    cal_hz(&mut buf, freq as f64, freq as f64);
    panic!("exit");
    loop {}
}

const ADC_BUFFER_SIZE: usize = 128;

fn cal_hz(buf: &mut [u16], clk1: f64, clk2: f64) {
    //size=2^n
    let mut sin_table = [0.0; ADC_BUFFER_SIZE / 4 + 1];
    let mut data = [Complex::new(0.0, 0.0); ADC_BUFFER_SIZE];
    let mut fft = SimpleFft::new(&mut data, &mut sin_table, clk2 as f64);
    fft.init_sin_table();
    fft.load_data_u16(&buf);
    fft.apply_kaiser_window(5.);
    fft.fft();

    let (freq1, _) = fft.dominant_frequency();
    let (freq2, mag) = fft.dominant_freq(clk1);
    let freq = (freq1 + freq2) / 2000.;
    info!("freg:{}+{}= {} KHz, mag: {}", freq1, freq2, freq, mag);

    // // print top 10 freq
    // for i in 1..=10 {
    //     info!("f={}Hz, mag={}", fft.frequency(i), fft.magnitude(i));
    // }
}