servo_pio/
lib.rs

1//! # servo-pio
2//!
3//! This crate allows controlling up to 30 servos on rp2040-based boards. It
4//! requires one PIO state machine and 2 dma channels for every servo cluster
5//! created.
6
7#![no_std]
8#![deny(unsafe_op_in_unsafe_fn)]
9
10use core::mem::MaybeUninit;
11
12pub mod calibration;
13pub mod pwm_cluster;
14pub mod servo_cluster;
15pub mod servo_state;
16
17fn initialize_array<T, const LEN: usize>(initializer: impl Fn() -> T) -> [T; LEN] {
18    let mut arr: [MaybeUninit<T>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
19    for item in &mut arr {
20        item.write(initializer());
21    }
22
23    // Safety: All entries initialized above.
24    unsafe {
25        (*(&MaybeUninit::<[MaybeUninit<T>; LEN]>::new(arr) as *const _
26            as *const MaybeUninit<[T; LEN]>))
27            .assume_init_read()
28    }
29}
30
31fn initialize_array_by_index<T, const LEN: usize>(initializer: impl Fn(usize) -> T) -> [T; LEN] {
32    let mut arr: [MaybeUninit<T>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
33    for (i, item) in arr.iter_mut().enumerate() {
34        item.write(initializer(i));
35    }
36
37    // Safety: All entries initialized above.
38    unsafe {
39        (*(&MaybeUninit::<[MaybeUninit<T>; LEN]>::new(arr) as *const _
40            as *const MaybeUninit<[T; LEN]>))
41            .assume_init_read()
42    }
43}
44
45fn initialize_array_from<T, U, const LEN: usize>(
46    other: [T; LEN],
47    initializer: impl Fn(T) -> U,
48) -> [U; LEN] {
49    let mut arr: [MaybeUninit<U>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
50    for (item, mapped) in arr.iter_mut().zip(other.into_iter()) {
51        item.write(initializer(mapped));
52    }
53
54    // Safety: All entries initialized above. arr and other have the same length.
55    unsafe {
56        (*(&MaybeUninit::<[MaybeUninit<U>; LEN]>::new(arr) as *const _
57            as *const MaybeUninit<[U; LEN]>))
58            .assume_init_read()
59    }
60}
61
62fn initialize_arrays_from<T, U, V, const LEN: usize>(
63    other: [T; LEN],
64    initializer: impl Fn(T) -> (U, V),
65) -> ([U; LEN], [V; LEN]) {
66    let mut arr1: [MaybeUninit<U>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
67    let mut arr2: [MaybeUninit<V>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
68    for ((item1, item2), mapped) in arr1.iter_mut().zip(arr2.iter_mut()).zip(other.into_iter()) {
69        let (v, w) = initializer(mapped);
70        item1.write(v);
71        item2.write(w);
72    }
73
74    // Safety: All entries initialized above. arr and other have the same length.
75    unsafe {
76        (
77            (*(&MaybeUninit::<[MaybeUninit<U>; LEN]>::new(arr1) as *const _
78                as *const MaybeUninit<[U; LEN]>))
79                .assume_init_read(),
80            (*(&MaybeUninit::<[MaybeUninit<V>; LEN]>::new(arr2) as *const _
81                as *const MaybeUninit<[V; LEN]>))
82                .assume_init_read(),
83        )
84    }
85}