Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
157 commits
Select commit Hold shift + click to select a range
0473401
pll: debug
jordens Nov 10, 2025
3adf3f4
clamp: add
jordens Nov 10, 2025
eb4a68f
clamp/overflowing sup: introduce Wrap
jordens Nov 10, 2025
aa231b1
clamp: optimize
jordens Nov 10, 2025
568edb8
clamp: optimize
jordens Nov 10, 2025
8c1afaa
unwrap: traits
jordens Nov 15, 2025
cfa6f5a
namespace org
jordens Nov 15, 2025
ce41c92
sos redo
jordens Nov 18, 2025
cda266c
filter repr: pub data
jordens Nov 18, 2025
17d6790
sos: Process
jordens Nov 18, 2025
86c6b86
sos: Stateful
jordens Nov 18, 2025
9ece5b6
atan2: style
jordens Nov 20, 2025
32a5b52
iir: Normal form, StatefulRef
jordens Nov 20, 2025
220c695
sos: Tree
jordens Nov 20, 2025
14d32b4
CHANGELOG: update
jordens Nov 20, 2025
a0e1813
sos: tree
jordens Nov 20, 2025
c957616
normal: mention chamberlain form
jordens Nov 26, 2025
0e44bb0
unwrap: tests
jordens Dec 1, 2025
0cffb64
wdf: init
jordens Dec 1, 2025
412f668
py: add python wrapper
jordens Dec 2, 2025
6fb927b
sos: python
jordens Dec 2, 2025
43fc622
py: cossin and atan2
jordens Dec 2, 2025
b9cb655
lints, test features
jordens Dec 2, 2025
dcbd3de
py: SosClamp, StateWide
jordens Dec 2, 2025
751e9b0
cargo: drop crate-type spec
jordens Dec 2, 2025
b680892
wdf: generic order
jordens Dec 2, 2025
ca5bd33
process: refactor, complementary, tuples, arrays, remove cascade
jordens Dec 3, 2025
1ee9a4c
process: generic over item
jordens Dec 4, 2025
78b8874
lowpass: port to Process
jordens Dec 5, 2025
dbbbc08
Butterfly: expand api
jordens Dec 9, 2025
4451943
Butterfly: add more api
jordens Dec 10, 2025
467a782
butterfly: no use for decimating highpass
jordens Dec 11, 2025
64083b9
Process: interpolate, bikeshedding, docs, checks
jordens Dec 11, 2025
0a65820
Process: elaborate Channels
jordens Dec 11, 2025
7836a7d
process: rename, refactor, introduce Chain
jordens Dec 11, 2025
d13889b
process: basic blocks
jordens Dec 11, 2025
d1c32a2
process: refactor
jordens Dec 12, 2025
f55fbdd
channels: transpose
jordens Dec 12, 2025
e0f828c
channels: remove
jordens Dec 12, 2025
69462de
process: refactor
jordens Dec 12, 2025
534dd20
process: flatten major
jordens Dec 12, 2025
e661fb4
process: port more
jordens Dec 13, 2025
87e1d0d
add back channels, refactor pair into fanout and sum
jordens Dec 13, 2025
67b7862
simplify buffer
jordens Dec 14, 2025
9ee7be9
process: allow array converting process
jordens Dec 15, 2025
8c12ec6
process: no inline, move interpolator, decimator
jordens Dec 15, 2025
b026b6c
process: type rename
jordens Dec 15, 2025
1d2efe7
process: factor entry from pair
jordens Dec 15, 2025
85d387e
process: move
jordens Dec 15, 2025
0118314
process: reorder, clean up
jordens Dec 17, 2025
e23b730
elaborate Q
jordens Dec 17, 2025
545e39b
q: strictify
jordens Dec 17, 2025
f119da3
process: transpose
jordens Dec 19, 2025
687d867
process: neg
jordens Dec 19, 2025
c2b3354
split dsp-process, dsp-fixedpoint [wip]
jordens Dec 19, 2025
b78c3d7
process: SplitProcess/Inplace
jordens Dec 19, 2025
9c43439
complex as R^2
jordens Dec 19, 2025
8b40981
lints
jordens Dec 19, 2025
95647b2
use q in sos
jordens Dec 19, 2025
8ba64b0
process:: transpose base
jordens Dec 20, 2025
b49d12c
process: refactor
jordens Dec 20, 2025
8b0f940
misc: renames, refactor, cleanup
jordens Dec 20, 2025
bc5635f
rm filter
jordens Dec 20, 2025
293b24b
process: small basic
jordens Dec 20, 2025
fab7d04
rpll: port to process
jordens Dec 20, 2025
0ac5247
hbf: start port
jordens Dec 20, 2025
84013c3
process: misc
jordens Dec 20, 2025
ffa32c0
process: port hbf
jordens Dec 22, 2025
ce906e3
hbf: change decimator gain to 2
jordens Dec 22, 2025
88c9976
hbf: prevent benchmark optimization
jordens Dec 22, 2025
7d90519
sos: add insns test
jordens Dec 22, 2025
3f27de3
changelog: tweaks
jordens Dec 22, 2025
4c09bfa
unwrap: refactor
jordens Dec 23, 2025
704509f
hbf: tweaks
jordens Dec 23, 2025
a151e4e
hbf: factor
jordens Dec 24, 2025
2cce586
sos: factor
jordens Dec 25, 2025
f539b4c
symfir: support anti-symmetric or hbf-style getters
jordens Dec 25, 2025
b0bf1f2
hbf: tweak symfir
jordens Dec 26, 2025
a1ccee3
fixedpoint: serde
jordens Dec 27, 2025
2612a67
tree wide: const assert
jordens Dec 27, 2025
1f984e3
sos: add insn comment, avoid overflow
jordens Dec 27, 2025
e6c0515
coefficients: port to sos
jordens Dec 27, 2025
6acb61d
iir: repr and misc tweaks
jordens Dec 27, 2025
45bc7c2
hbf: tweak
jordens Dec 29, 2025
05b0405
process: add major with buffer
jordens Dec 31, 2025
7e7fd17
hbf: use stack buffer
jordens Dec 31, 2025
d01a58f
process: add Chunk{,In,Out,InOut}, refactor
jordens Dec 31, 2025
eb9c1f4
hbf benchmarks: update
jordens Dec 31, 2025
8c28a3b
fixedpoint: fix Q32 f conversions
jordens Dec 31, 2025
99e0d3d
dsp-process: traits
jordens Jan 1, 2026
853ddba
hbf: demo and benchmark plumbing approach
jordens Jan 1, 2026
b778612
dsp-process: fix ChunkOut assert
jordens Jan 1, 2026
d4ef8e3
hbf: benchmark int cascade with plumbing
jordens Jan 1, 2026
37dd7c1
process: style
jordens Jan 2, 2026
92d0212
const new
jordens Jan 2, 2026
67d907a
hbf: use only declarative plumbing
jordens Jan 2, 2026
eec2d75
hbf: ractor states
jordens Jan 2, 2026
8975c6c
process: merge intermediate params
jordens Jan 2, 2026
32afd3e
process: discard unplit composition
jordens Jan 2, 2026
c941774
fixedpoint: ssh->shs
jordens Jan 2, 2026
6166ffe
fixedpoint: elaborate
jordens Jan 2, 2026
fbc0f9b
sos: simplify inplace
jordens Jan 2, 2026
e4dcbc0
process: stack buf creation for larger arrays
jordens Jan 2, 2026
9774812
fixedpoint: elaborate
jordens Jan 3, 2026
823798e
fixedpoint: doc, tests
jordens Jan 3, 2026
b4d1906
fixedpoint: impl temporary integer fmt traits
jordens Jan 5, 2026
8a171ee
hbf: implement odd/even symmetric/anti-symmetric firs
jordens Jan 5, 2026
b5820bb
hbf: refactor for evensymmetric
jordens Jan 5, 2026
3bb3a28
hbf: use common convolution
jordens Jan 5, 2026
066789a
hbf: add tap(s) to second stage to meet by-4 fom
jordens Jan 6, 2026
7bc0a1c
fixedpoint: Debug as inner
jordens Jan 6, 2026
a2d4c26
complex: impl some
jordens Jan 6, 2026
e0caa5b
lockin, lowpass: serde, default
jordens Jan 6, 2026
2f1e4bd
complex: bytemuck
jordens Jan 6, 2026
4a86196
complex: more impl
jordens Jan 7, 2026
c53c0fc
sos: fully port to fixedpoint, support float
jordens Jan 7, 2026
25e82c5
fixedpoint: consts
jordens Jan 7, 2026
9d55d87
fixedpoint: const for float
jordens Jan 7, 2026
7a9afd4
SosState -> DirectForm1 and DirectForm2Transposed
jordens Jan 7, 2026
1cf667b
fixedpoint: infinity const for fp
jordens Jan 7, 2026
5c2296b
pid: start port to sos
jordens Jan 7, 2026
5ff421d
pid, biquadrepr: port to sos
jordens Jan 8, 2026
b61a4f7
old biquad: remove
jordens Jan 8, 2026
f6f7a01
sos: rename to biquad
jordens Jan 8, 2026
e058cbe
README: update
jordens Jan 8, 2026
b1ccb73
fp: macros, sos: from
jordens Jan 8, 2026
f296f85
clamp: fix
jordens Jan 8, 2026
df0bd6b
clamp
jordens Jan 8, 2026
28afe4f
biquad: add docs, doctests
jordens Jan 8, 2026
e9b87b1
biquad: simplify from
jordens Jan 8, 2026
c1914f1
pid: simplify bounds and approach
jordens Jan 9, 2026
5f5d2d6
fixedpoint: don't duplicate traits
jordens Jan 9, 2026
7628e7c
biquad: use asprimitive
jordens Jan 9, 2026
00f55fd
biquad: fmt
jordens Jan 9, 2026
8ad402b
repr: use AsPrimitive
jordens Jan 9, 2026
7d06e63
repr: lint
jordens Jan 9, 2026
5a7e4fb
factor traits
jordens Jan 9, 2026
7cf4a79
dsp-process: docs
jordens Jan 9, 2026
62b77b2
pll: output
jordens Jan 9, 2026
ab3a243
accu: use Wrapping
jordens Jan 9, 2026
281d105
Const -> Clamp
jordens Jan 12, 2026
69bd645
reorg iir hierarchy
jordens Jan 12, 2026
eeac3cd
complex cleanup
jordens Jan 12, 2026
9143539
pll: port to wrapping/w32
jordens Jan 12, 2026
e772de5
pll: return accu
jordens Jan 12, 2026
c2b0d4c
accu: impl ops
jordens Jan 12, 2026
0804093
accu: more ops
jordens Jan 12, 2026
478d68f
Revert "accu: more ops"
jordens Jan 12, 2026
e797f67
accu: multiply by integer
jordens Jan 12, 2026
9f6cef1
accu, pll: use non-Q
jordens Jan 12, 2026
c36043b
cleanup q/w usage
jordens Jan 12, 2026
02a1c3b
fixedpoint: ord/eq
jordens Jan 12, 2026
556c492
rpll: port to wrapping
jordens Jan 12, 2026
ff0d0e2
rpll: style
jordens Jan 13, 2026
8a02280
ci: update
jordens Jan 13, 2026
48f236f
CHANGELOG: update
jordens Jan 13, 2026
fca580b
README: update
jordens Jan 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 18 additions & 51 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,68 +12,35 @@ jobs:
style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: cargo fmt --check
uses: actions-rs/cargo@v1
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
command: fmt
args: --all -- --check
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: cargo check
uses: actions-rs/cargo@v1
with:
command: check
args: --verbose
components: clippy, rustfmt
- run: cargo fmt --all --check
- run: cargo clippy --all-features

compile:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.toolchain == 'nightly' }}
strategy:
matrix:
toolchain: [stable, beta, nightly]
features: ['']
features: ["std"]
continue-on-error: ${{ matrix.toolchain == 'nightly' }}
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v1
- name: cargo build
uses: actions-rs/cargo@v1
with:
command: build
args: --release --features "${{ matrix.features }}"
- name: cargo test
uses: actions-rs/cargo@v1
with:
command: test
- name: cargo bench
uses: actions-rs/cargo@v1
with:
command: bench
- run: cargo check --features "${{ matrix.features }}"
- run: cargo test --features "${{ matrix.features }}"
- run: cargo bench --features "${{ matrix.features }}"
- run: cargo build --release --features "${{ matrix.features }}"

doc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/cargo@v1
with:
command: install
args: |
cargo-deadlinks
- name: cargo doc
uses: actions-rs/cargo@v1
with:
command: doc
args: --no-deps
- name: cargo deadlinks
uses: actions-rs/cargo@v1
with:
command: deadlinks
args: --ignore-fragments --check-intra-doc-links
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- run: cargo doc --no-deps
- run: cargo install cargo-deadlinks
- run: cargo deadlinks --ignore-fragments --check-intra-doc-links
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED](https://github.com/quartiq/idsp/compare/v0.19.0..HEAD) - DATE

### Changed

* All filters (`CIC`, `Cordic`, `Lockin`, `Unwrap`, `Lowpass`, `DSM`, `Svf` etc) port to `dsp-process`
* `iir`: `Biquad` family or reworked biquad/sos implementations
* `hbf`: Support all linear-phase FIR filters, redesign HBF cascades
* `PLL`, `RPLL`, `Accu`: use `core::num::Wrapping`

### Added

* `dsp-process`: new design and extracted as independent crate
* `dsp-fixedpoint`: new design and extracted as independent crate
* `iir`: `Normal` form implementation
* `iir`: `Wdf` Wave digital filter, two port adapter and tooling
* `ClampWrap`: single wrap phase monotonizer
* `idsp`: Python package for testing and evaluation
* Custom `Complex` type enforcing the `R²` structure and meshing with `dsp-fixedpoint`
* `iir`: Biquad with any combination of Simple/Clamp action on DF1, DF2T, DF1 Dither, DF1 Wide state
* `iir`: Biquad `a1` and `a2` flip sign

### Removed

* `MulScaled`

## [0.19.0](https://github.com/quartiq/idsp/compare/v0.18.0..v0.19.0) - 2025-10-22

### Changed
Expand Down
59 changes: 49 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
[package]
name = "idsp"
version = "0.19.0"
resolver = "2"
[workspace]
members = ["dsp-fixedpoint", "dsp-process", "."]
default-members = ["dsp-fixedpoint", "dsp-process", "."]

[workspace.package]
edition = "2024"
authors = ["Robert Jördens <rj@quartiq.de>"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/quartiq/idsp.git"

[workspace.dependencies]
dsp-process = { path = "dsp-process" }
dsp-fixedpoint = { path = "dsp-fixedpoint" }
num-traits = { version = "0.2.14", features = [
"libm",
], default-features = false }

[workspace.lints.rust]
unsafe_code = "forbid"
rust_2018_compatibility = { level = "deny", priority = -1 }
rust_2018_idioms = { level = "deny", priority = -1 }
missing_docs = "warn"

[package]
name = "idsp"
version = "0.19.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
description = "DSP algorithms for embedded, mostly integer math"
homepage = "https://github.com/quartiq/idsp"
repository = "https://github.com/quartiq/idsp.git"
documentation = "https://docs.rs/idsp"

[lints]
workspace = true

[dependencies]
serde = { version = "1.0", features = ["derive"], default-features = false }
num-complex = { version = "0.4.0", features = [
"serde",
], default-features = false }
num-traits = { version = "0.2.14", features = [
"libm",
], default-features = false }
num-traits.workspace = true
thiserror = { version = "2.0.9", default-features = false }
miniconf = "0.20.0"
strum = { version = "0.27.1", default-features = false, features = ["derive"] }
pyo3 = { version = "0.27.1", features = ["extension-module"], optional = true }
numpy = { version = "0.27", optional = true }
dsp-process.workspace = true
dsp-fixedpoint.workspace = true
bytemuck = { version = "1.24.0", features = ["derive"] }

[dev-dependencies]
quickcheck = "1.0.3"
Expand All @@ -33,6 +61,17 @@ log = "0.4"

[features]
std = []
py = ["dep:pyo3", "dep:numpy", "std"]

#[profile.release]
#opt-level = 3

[profile.dev]
debug = "line-tables-only"

[profile.dev.package."*"]
debug = false

[profile.release]
debug = 1
[profile.debugging]
inherits = "dev"
debug = true
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ Tools to handle, track, and unwrap phase signals or generate them.

## IIR/Biquad

[`iir::Biquad`] are fixed point (`i8`, `i16`, `i32`, `i64`) and floating point (`f32`, `f64`) biquad IIR filters.
[`iir::Biquad`] and [`iir::BiquadClamp`] are fixed point (`i8`, `i16`, `i32`, `i64`) and floating point (`f32`, `f64`) biquad IIR filters.
Robust and clean clipping and offset (anti-windup, no derivative kick, dynamically adjustable gains and gain limits) suitable for PID controller applications.
Three kinds of filter actions: Direct Form 1, Direct Form 2 Transposed, and Direct Form 1 with noise shaping supported.
Coefficient sharing for multiple channels.
Four kinds of filter action are supported for each Biquad: Direct Form 1, Direct Form 2 Transposed, Direct Form 1 with noise shaping,
and Direct Form 1 with wide output.
Coefficient sharing for multiple channels is implemented through [`dsp_process::SplitProcess`], [`dsp_process::Channels`].

### Comparison

Expand All @@ -48,21 +49,24 @@ TL;DR: `idsp` is slower but offers more features.
|---|---|---|---|
| Floating point `f32`/`f64` | ✅ | ❌ | ✅ |
| Fixed point `i32` | ❌ | ✅ | ✅ |
| Parametric fixed point `i32` | ❌ | ✅ | |
| Parametric fixed point `i32` | ❌ | ✅ | |
| Fixed point `i8`/`i16`/`i64`/`i128` | ❌ | ❌ | ✅ |
| DF2T | ✅ | ❌ | ✅ |
| Limiting/Clamping | ❌ | ✅ | ✅ |
| Fixed point accumulator guard bits | ❌ | ❌ | ✅ |
| Summing junction offset | ❌ | ❌ | ✅ |
| Fixed point noise shaping | ❌ | ❌ | ✅ |
| Wide output storage and feedback | ❌ | ❌ | ✅ |
| Configuration/state decoupling/multi-channel | ❌ | ❌ | ✅ |
| `f32` parameter audio filter builder | ✅ | ✅ | ✅ |
| `f64` parameter audio filter builder | ✅ | ❌ | ✅ |
| Additional filters (I/HO) | ❌ | ❌ | ✅ |
| `Q` fixed point parameter audio filter builder | ❌ | ❌ | ✅ |
| Additional filter shapes (I/HO) | ❌ | ❌ | ✅ |
| `f32` PI builder | ❌ | ✅ | ✅ |
| `f32/f64` PI²D² builder | ❌ | ❌ | ✅ |
| `Q` fixed point PI²D² builder | ❌ | ❌ | ✅ |
| PI²D² builder limits | ❌ | ❌ | ✅ |
| Support for fixed point `a1=-2` | ❌ | ❌ | ✅ |
| Support for fixed point `a1=-2` second order integrator | ❌ | ❌ | ✅ |

Three crates have been compared when processing 4x1M samples (4 channels) with a biquad lowpass.
Hardware was `thumbv7em-none-eabihf`, `cortex-m7`, code in ITCM, data in DTCM, caches enabled.
Expand All @@ -75,21 +79,23 @@ Hardware was `thumbv7em-none-eabihf`, `cortex-m7`, code in ITCM, data in DTCM, c
| `idsp::iir` | `i32`, limits, offset | 23.5 |
| `idsp::iir` | `i32`, limits, offset, noise shaping | 30.0 |

## State variable filter
## State variable, normal form, wave digital filter

[`svf`] is a simple IIR state variable filter simultaneously providing highpass, lowpass,
[`iir::svf`] is a simple IIR state variable filter simultaneously providing highpass, lowpass,
bandpass, and notch filtering of a signal.
[`iir::normal`] is a Normal Form IIR filter for narrowband applications.
[`iir::wdf`] has wave digital allpass filters that can be combined in a coupled [`dsp_process::Pair`].

## `Lowpass`, `Lockin`

[`Lowpass`], [`Lockin`] are fast, infinitely cascadable, first- and second-order lowpass and the corresponding integration into a lockin amplifier algorithm.

## FIR filters

[`hbf::HbfDec`], [`hbf::HbfInt`], [`hbf::HbfDecCascade`], [`hbf::HbfIntCascade`]:
[`hbf::HbfDec`], [`hbf::HbfInt`], [`hbf::HbfDec32`], [`hbf::HbfInt32`] etc:
Fast `f32` symmetric FIR filters, optimized half-band filters, half-band filter decimators and integators and cascades.
These are used in [`stabilizer-stream`](https://github.com/quartiq/stabilizer-stream) for online PSD calculation on log
frequency scale for arbitrarily large amounts of data.
These are used in [`stabilizer-stream`](https://github.com/quartiq/stabilizer-stream) for online PSD calculation for
arbitrarily low offset frequencies.

## Delta Sigma modulator/noise shaper

Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Static LUT generation
use std::env;
use std::f64::consts::PI;
use std::fs::File;
Expand Down
17 changes: 17 additions & 0 deletions dsp-fixedpoint/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "dsp-fixedpoint"
version = "0.1.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true

[features]
std = []

[dependencies]
num-traits.workspace = true
serde = { version = "1.0.228", default-features = false, features = ["derive"] }

[lints]
workspace = true
1 change: 1 addition & 0 deletions dsp-fixedpoint/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Fixed point primitives
Loading