ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
dsps_fird_init_s16.c
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include "dsps_fir.h"
8#include "malloc.h"
9#include <string.h>
10#include "dsp_tests.h"
11
12#define ROUNDING_VALUE 0x7fff
13
14esp_err_t dsps_fird_init_s16(fir_s16_t *fir, int16_t *coeffs, int16_t *delay, int16_t coeffs_len, int16_t decim, int16_t start_pos, int16_t shift)
15{
16 fir->coeffs = coeffs;
17 fir->delay = delay;
18 fir->coeffs_len = coeffs_len;
19 fir->pos = 0;
20 fir->decim = decim;
21 fir->d_pos = start_pos;
22 fir->shift = shift;
23 fir->rounding_val = (int16_t)(ROUNDING_VALUE);
24 fir->free_status = 0;
25
26 if (fir->coeffs_len < 2) { // number of coeffcients must be higer than 1
28 }
29
30 if ((fir->shift > 40) || (fir->shift < -40)) { // shift amount must be within a range from -40 to 40
32 }
33
34 if (fir->d_pos >= fir->decim) { // start position must be lower than decimation
36 }
37
38#if CONFIG_DSP_OPTIMIZED
39
40 // Rounding value buffer primary for a purpose of ee.ld.accx.ip, but used for both the esp32 and esp32s3
41 // dsps_fird_s16_aexx_free() must be called to free the memory after the FIR function is finished
42 int32_t *aexx_rounding_buff = (int32_t *)memalign(16, 2 * sizeof(int32_t));
43
44 long long rounding = (long long)(fir->rounding_val);
45
46 if (fir->shift >= 0) {
47 rounding = (rounding >> fir->shift);
48 } else {
49 rounding = (rounding << (-fir->shift));
50 }
51#if dsps_fird_s16_arp4_enabled
52 fir->pos = start_pos;
53
54 int16_t *new_delay_buff = (int16_t *)memalign(16, (coeffs_len + 8 * 2) * sizeof(int16_t));
55 for (int i = 0 ; i < (coeffs_len + 8 * 2) ; i++) {
56 new_delay_buff[i] = 0;
57 }
58 fir->delay = &new_delay_buff[8];
59 fir->free_status |= 0x0001;
60
61#endif // dsps_fird_s16_arp4_enabled
62
63
64 aexx_rounding_buff[0] = (int32_t)(rounding); // 32 lower bits (acclo) type reassignment to 32-bit
65 aexx_rounding_buff[1] = (int32_t)((rounding >> 32) & 0xFF); // 8 higher bits (acchi) shift by 32 and apply the mask
66 fir->rounding_buff = aexx_rounding_buff;
67 fir->free_status |= 0x0004;
68
69#if dsps_fird_s16_aes3_enabled
70
71 if (fir->delay == NULL) { // New delay buffer is allocated if the current delay line is NULL
72 int16_t *new_delay_buff = (int16_t *)memalign(16, coeffs_len * sizeof(int16_t));
73 fir->delay = new_delay_buff;
74 fir->free_status |= 0x0001;
75 } else {
76 if ((int)fir->delay & 0xf) { // Delay line array must be aligned
78 }
79 }
80
81 if ((int)fir->coeffs & 0xf) { // Coefficients array must be aligned
83 }
84
85 // If the number of coefficients is not divisible by 8, a new delay line a new coefficients arrays are allocated
86 // the newly allocated arrays are divisible by 8. Coefficients are copied from the original fir structure to
87 // the new coeffs array and the remaining space is filled with zeroes
88 // dsps_fird_s16_free_coeffs_delay must be called to free the memory after the FIR function is finished
89 if (fir->coeffs_len % 8) { // Number of coefficients must be devisible by 8
90 int16_t zero_coeffs = (8 - (fir->coeffs_len % 8));
91 int16_t new_coeffs_len = fir->coeffs_len + zero_coeffs;
92 int16_t *aes3_delay_buff = (int16_t *)memalign(16, new_coeffs_len * sizeof(int16_t));
93 int16_t *aes3_coeffs_buff = (int16_t *)memalign(16, new_coeffs_len * sizeof(int16_t));
94
95 for (int i = 0; i < fir->coeffs_len; i++) { // copy fir->coeffs to aes3_coeffs_buff
96 aes3_coeffs_buff[i] = fir->coeffs[i];
97 }
98
99 for (int i = fir->coeffs_len; i < new_coeffs_len; i++) { // add zeroes to the end
100 aes3_coeffs_buff[i] = 0;
101 }
102
103 fir->delay = aes3_delay_buff;
104 fir->coeffs = aes3_coeffs_buff;
105 fir->coeffs_len = new_coeffs_len;
106 fir->free_status |= 0x0002;
107 }
108
109#endif // dsps_fird_s16_aes3_enabled
110#endif // CONFIG_DSP_OPTIMIZED
111
112 for (int i = 0; i < fir->coeffs_len; i++) { // Initialize the delay line to zero
113 fir->delay[i] = 0;
114 }
115
116 return ESP_OK;
117}
118
120{
121
122 if (fir->free_status == 0) {
123 return ESP_OK;
124 }
125
126 if (fir->free_status & 0x0003) {
127
128 if (fir->free_status & 0x0002) {
129 free(fir->coeffs);
130 }
131#if dsps_fird_s16_arp4_enabled
132 fir->delay = &fir->delay[-8];
133#endif
134 free(fir->delay);
135 }
136
137 if (fir->free_status & 0x0004) {
138 free(fir->rounding_buff);
139 }
140 fir->free_status = 0;
141
142 return ESP_OK;
143}
144
145
146esp_err_t dsps_16_array_rev(int16_t *arr, int16_t len)
147{
148
149 int16_t temp;
150
151 for (int i = 0; i < (int)(len / 2); i++) {
152 temp = arr[i];
153 arr[i] = arr[len - 1 - i];
154 arr[len - 1 - i] = temp;
155 }
156 return ESP_OK;
157}
#define ESP_ERR_DSP_PARAM_OUTOFRANGE
#define ESP_ERR_DSP_INVALID_LENGTH
#define ESP_ERR_DSP_ARRAY_NOT_ALIGNED
#define memalign(align_, size_)
Definition dsp_tests.h:35
struct fir_s16_s fir_s16_t
Data struct of s16 fir filter.
esp_err_t dsps_fird_s16_aexx_free(fir_s16_t *fir)
support arrays freeing function
esp_err_t dsps_16_array_rev(int16_t *arr, int16_t len)
Array reversal.
#define ROUNDING_VALUE
esp_err_t dsps_fird_init_s16(fir_s16_t *fir, int16_t *coeffs, int16_t *delay, int16_t coeffs_len, int16_t decim, int16_t start_pos, int16_t shift)
initialize structure for 16 bit Decimation FIR filter Function initialize structure for 16 bit signed...
int esp_err_t
Definition esp_err.h:21
#define ESP_OK
Definition esp_err.h:23
int16_t shift
Definition dsps_fir.h:61
int16_t * coeffs
Definition dsps_fir.h:55
int32_t rounding_val
Definition dsps_fir.h:63
int16_t * delay
Definition dsps_fir.h:56
int16_t decim
Definition dsps_fir.h:59
int16_t pos
Definition dsps_fir.h:58
int32_t * rounding_buff
Definition dsps_fir.h:62
int16_t d_pos
Definition dsps_fir.h:60
int16_t coeffs_len
Definition dsps_fir.h:57
int16_t free_status
Definition dsps_fir.h:64
float delay[256]
Definition test_fir.c:15
float coeffs[256]
Definition test_fir.c:14