1#![cfg_attr(not(test), no_std)]
24
25mod decimator;
26mod differentiator;
27mod integrator;
28
29pub struct CicDecimationFilter<const M: usize, const N: usize> {
33 decimator: decimator::Decimator<M>,
34 integrators: [integrator::Integrator; N],
35 differentiators: [differentiator::Differentiator; N],
36}
37
38impl<const M: usize, const N: usize> CicDecimationFilter<M, N> {
39 pub const fn new() -> Self {
40 assert!(M > 0, "M (decimation factor) must be greater than 0. Without decimation, the CIC filter does not perform as an LPF.");
41 assert!(N > 0, "N (number of stages) must be greater than 0");
42
43 Self {
44 decimator: decimator::Decimator::new(),
45 integrators: [integrator::Integrator::new(); N],
46 differentiators: [differentiator::Differentiator::new(); N],
47 }
48 }
49
50 #[inline]
62 #[must_use]
63 pub fn process_sample(&mut self, input: &i32) -> Option<i32> {
64 let mut output = *input;
65 for integrator in self.integrators.iter_mut() {
66 output = integrator.integrate(output);
67 }
68
69 if let Some(output) = self.decimator.decimate(output) {
70 let mut v = output;
71 for differentiator in self.differentiators.iter_mut() {
72 v = differentiator.differentiate(v);
73 }
74 Some(v)
75 } else {
76 None
77 }
78 }
79
80 #[must_use]
85 pub const fn bit_growth(&self) -> u32 {
86 M.ilog2() * N as u32
87 }
88}
89
90impl<const M: usize, const N: usize> Default for CicDecimationFilter<M, N> {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn cic_decimation_test() {
102 let mut filter = CicDecimationFilter::<4, 2>::new();
103 let result = filter.process_sample(&0);
104 assert!(result.is_none());
105 let result = filter.process_sample(&1);
106 assert!(result.is_none());
107 let result = filter.process_sample(&2);
108 assert!(result.is_none());
109 let result = filter.process_sample(&3);
110 assert!(result.is_some());
111 assert_eq!(result.unwrap(), 10);
112
113 let result = filter.process_sample(&2);
114 assert!(result.is_none());
115 let result = filter.process_sample(&-1);
116 assert!(result.is_none());
117 let result = filter.process_sample(&-2);
118 assert!(result.is_none());
119 let result = filter.process_sample(&1);
120 assert!(result.is_some());
121 assert_eq!(result.unwrap(), 16);
122
123 let result = filter.process_sample(&2);
124 assert!(result.is_none());
125 let result = filter.process_sample(&-1);
126 assert!(result.is_none());
127 let result = filter.process_sample(&-2);
128 assert!(result.is_none());
129 let result = filter.process_sample(&1);
130 assert!(result.is_some());
131 assert_eq!(result.unwrap(), 0);
132
133 let result = filter.process_sample(&2);
134 assert!(result.is_none());
135 let result = filter.process_sample(&-1);
136 assert!(result.is_none());
137 let result = filter.process_sample(&-2);
138 assert!(result.is_none());
139 let result = filter.process_sample(&1);
140 assert!(result.is_some());
141 assert_eq!(result.unwrap(), 0);
142
143 let result = filter.process_sample(&0);
144 assert!(result.is_none());
145 let result = filter.process_sample(&1);
146 assert!(result.is_none());
147 let result = filter.process_sample(&2);
148 assert!(result.is_none());
149 let result = filter.process_sample(&3);
150 assert!(result.is_some());
151 assert_eq!(result.unwrap(), 8);
152
153 let result = filter.process_sample(&3);
154 assert!(result.is_none());
155 let result = filter.process_sample(&3);
156 assert!(result.is_none());
157 let result = filter.process_sample(&-2);
158 assert!(result.is_none());
159 let result = filter.process_sample(&1);
160 assert!(result.is_some());
161 assert_eq!(result.unwrap(), 32);
162 }
163
164 #[test]
165 fn overflow_test() {
166 let mut filter = CicDecimationFilter::<4, 2>::new();
167
168 for _ in 0..1000 {
169 let _ = filter.process_sample(&i32::MAX);
170 }
171 }
172
173 #[test]
178 fn output_range_test() {
179 let mut filter = CicDecimationFilter::<4, 2>::new();
180
181 for _ in 0..1000 {
182 let _result = filter.process_sample(&1);
183 }
184
185 for _ in 0..10 {
186 if let Some(output) = filter.process_sample(&1) {
187 println!("{}", output);
188 assert!(output == 16); }
190 }
191
192 for _ in 0..1000 {
193 let _result = filter.process_sample(&-1);
194 }
195
196 for _ in 0..10 {
197 if let Some(output) = filter.process_sample(&-1) {
198 println!("{}", output);
199 assert!(output == -16); }
201 }
202 }
203
204 #[test]
205 fn bit_growth_test() {
206 let filter = CicDecimationFilter::<64, 3>::new();
207 assert_eq!(filter.bit_growth(), 18);
208
209 let filter = CicDecimationFilter::<32, 5>::new();
210 assert_eq!(filter.bit_growth(), 25);
211
212 let filter = CicDecimationFilter::<8, 5>::new();
213 assert_eq!(filter.bit_growth(), 15);
214 }
215}