XCORE SDK
XCORE Software Development Kit
Decimator.hpp
1 // Copyright 2022 XMOS LIMITED.
2 // This Software is subject to the terms of the XMOS Public Licence: Version 1.
3 
4 #pragma once
5 
6 #include <cstdint>
7 #include <string>
8 #include <cassert>
9 
10 #include "xs3_math.h"
11 #include "mic_array/etc/fir_1x16_bit.h"
12 
13 // This has caused problems previously, so just catch the problems here.
14 #if defined(MIC_COUNT) || defined(S2_DEC_FACTOR) || defined(S2_TAP_COUNT)
15 # error Application must not define the following as precompiler macros: MIC_COUNT, S2_DEC_FACTOR, S2_TAP_COUNT.
16 #endif
17 
18 
19 namespace mic_array {
20 
28 static inline
29 void shift_buffer(uint32_t* buff);
30 
31 
42 template <unsigned MIC_COUNT, unsigned S2_DEC_FACTOR, unsigned S2_TAP_COUNT>
44 {
45 
46  public:
50  static constexpr unsigned BLOCK_SIZE = MIC_COUNT * S2_DEC_FACTOR;
51 
55  static constexpr unsigned MicCount = MIC_COUNT;
56 
60  static const struct {
64  unsigned DecimationFactor = S2_DEC_FACTOR;
68  unsigned TapCount = S2_TAP_COUNT;
69  } Stage2;
70 
71  private:
72 
76  struct {
80  const uint32_t* filter_coef;
84  uint32_t pdm_history[MIC_COUNT][8]
85 #ifndef __DOXYGEN__ // doxygen breaks if it encounters this.
86  = {[0 ... (MIC_COUNT-1)] = { [0 ... 7] = 0x55555555 } }
87 #endif
88  ;
89  } stage1;
90 
94  struct {
102  int32_t filter_state[MIC_COUNT][S2_TAP_COUNT] = {{0}};
103  } stage2;
104 
105  public:
106 
107  constexpr TwoStageDecimator() noexcept { }
108 
134  void Init(
135  const uint32_t* s1_filter_coef,
136  const int32_t* s2_filter_coef,
137  const right_shift_t s2_filter_shr);
138 
165  void ProcessBlock(
166  int32_t sample_out[MIC_COUNT],
167  uint32_t pdm_block[BLOCK_SIZE]);
168  };
169 }
170 
172 // Template function implementations below. //
174 
175 
176 template <unsigned MIC_COUNT, unsigned S2_DEC_FACTOR, unsigned S2_TAP_COUNT>
178  const uint32_t* s1_filter_coef,
179  const int32_t* s2_filter_coef,
180  const right_shift_t s2_shr)
181 {
182  this->stage1.filter_coef = s1_filter_coef;
183 
184  for(int k = 0; k < MIC_COUNT; k++){
185  xs3_filter_fir_s32_init(&this->stage2.filters[k], &this->stage2.filter_state[k][0],
186  S2_TAP_COUNT, s2_filter_coef, s2_shr);
187  }
188 }
189 
190 
191 
192 template <unsigned MIC_COUNT, unsigned S2_DEC_FACTOR, unsigned S2_TAP_COUNT>
195  int32_t sample_out[MIC_COUNT],
196  uint32_t pdm_block[BLOCK_SIZE])
197 {
198  uint32_t (*pdm_data)[S2_DEC_FACTOR] = (uint32_t (*)[S2_DEC_FACTOR]) pdm_block;
199 
200  for(unsigned mic = 0; mic < MIC_COUNT; mic++){
201  uint32_t* hist = &this->stage1.pdm_history[mic][0];
202 
203  for(unsigned k = 0; k < S2_DEC_FACTOR; k++){
204  hist[0] = pdm_data[mic][k];
205  int32_t streamA_sample = fir_1x16_bit(hist, this->stage1.filter_coef);
206  shift_buffer(hist);
207 
208  if(k < (S2_DEC_FACTOR-1)){
209  xs3_filter_fir_s32_add_sample(&this->stage2.filters[mic], streamA_sample);
210  } else {
211  sample_out[mic] = xs3_filter_fir_s32(&this->stage2.filters[mic], streamA_sample);
212  }
213  }
214  }
215 }
216 
217 
218 static inline
219 void mic_array::shift_buffer(uint32_t* buff)
220 {
221  uint32_t* src = &buff[-1];
222  asm volatile("vldd %0[0]; vstd %1[0];" :: "r"(src), "r"(buff) : "memory" );
223 }
224 
225 
First and Second Stage Decimator.
Definition: Decimator.hpp:44
static constexpr unsigned MicCount
Definition: Decimator.hpp:55
int32_t filter_state[MIC_COUNT][S2_TAP_COUNT]
Definition: Decimator.hpp:102
static constexpr unsigned BLOCK_SIZE
Definition: Decimator.hpp:50
void Init(const uint32_t *s1_filter_coef, const int32_t *s2_filter_coef, const right_shift_t s2_filter_shr)
Initialize the decimator.
Definition: Decimator.hpp:177
xs3_filter_fir_s32_t filters[MIC_COUNT]
Definition: Decimator.hpp:98
uint32_t pdm_history[MIC_COUNT][8]
Definition: Decimator.hpp:88
static const struct mic_array::TwoStageDecimator::@15 Stage2
const uint32_t * filter_coef
Definition: Decimator.hpp:80
void ProcessBlock(int32_t sample_out[MIC_COUNT], uint32_t pdm_block[BLOCK_SIZE])
Process one block of PDM data.
Definition: Decimator.hpp:194
unsigned DecimationFactor
Definition: Decimator.hpp:64
unsigned TapCount
Definition: Decimator.hpp:68
int right_shift_t
A rightwards arithmetic bit-shift.
Definition: xs3_math_types.h:98
int32_t xs3_filter_fir_s32(xs3_filter_fir_s32_t *filter, const int32_t new_sample)
Definition: xs3_filter_fir_s32.c:15
void xs3_filter_fir_s32_init(xs3_filter_fir_s32_t *filter, int32_t *sample_buffer, const unsigned tap_count, const int32_t *coefficients, const right_shift_t shift)
Initialize a 32-bit FIR filter.
Definition: xs3_filters.c:43
void xs3_filter_fir_s32_add_sample(xs3_filter_fir_s32_t *filter, const int32_t new_sample)
Add a new input sample to a 32-bit FIR filter without processing an output sample.
Definition: xs3_filters.c:59
32-bit Discrete-Time Finite Impulse Response (FIR) Filter
Definition: xs3_filters.h:243