1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <common/bk_include.h>
16 #include "fft_hal.h"
17 #include "fft_driver.h"
18 #include "sys_driver.h"
19 #include "clock_driver.h"
20 #include <driver/fft_types.h>
21 #include <os/os.h>
22 #include <os/mem.h>
23 #include <driver/int.h>
24 #include <modules/pm.h>
25
26
27 #define FFT_RETURN_ON_NOT_INIT() do {\
28 if (!s_fft_driver_is_init) {\
29 return BK_ERR_AUD_NOT_INIT;\
30 }\
31 } while(0)
32
33 #define FFT_RETURN_ON_INVALID_ISR_ID(isr_id) do {\
34 if ((isr_id) >= SOC_FFT_ISR_NUM) {\
35 return BK_ERR_FFT_ISR_ID;\
36 }\
37 } while(0)
38
39
40 static bool s_fft_driver_is_init = false;
41 static fft_driver_t driver_fft;
42
43 static void fft_isr(void);
44 extern void delay(int num);//TODO fix me
45
fft_sat(uint16_t din)46 static __inline uint16_t fft_sat(uint16_t din)
47 {
48 if (din > 32767)
49 return 32767;
50 if (din < -32767)
51 return -32767;
52 else
53 return (din);
54 }
55
bk_fft_is_busy(void)56 bool bk_fft_is_busy(void)
57 {
58 return driver_fft.busy_flag;
59 }
60
bk_fft_enable(fft_input_t * fft_conf)61 bk_err_t bk_fft_enable(fft_input_t *fft_conf)
62 {
63 int i;
64
65 fft_hal_fft_config_reset(0);
66 fft_hal_fir_config_reset(0);
67
68 if (fft_conf->mode == FFT_WORK_MODE_FFT) {
69 fft_hal_fft_int_en(1);
70 fft_hal_fft_en(1);
71 } else {
72 fft_hal_ifft_en(1);
73 fft_hal_fft_int_en(1);
74 fft_hal_fft_en(1);
75 }
76
77 driver_fft.size = fft_conf->size;
78 driver_fft.busy_flag = true;
79
80 for (i = 0; i < fft_conf->size; i++) {
81 fft_hal_data_write(fft_conf->inbuf[i]);
82 }
83
84 fft_hal_start_trigger_set(1);
85 //fft_struct_dump();
86
87 return BK_OK;
88 }
89
bk_fft_fir_single_enable(fft_fir_input_t * fir_conf)90 bk_err_t bk_fft_fir_single_enable(fft_fir_input_t *fir_conf)
91 {
92 int i;
93 int32 temp_coef = 0;
94 int32 temp_data = 0;
95
96 if (fir_conf->fir_len > 256)
97 return BK_ERR_FFT_PARAM;
98
99 fft_hal_fft_config_reset(0);
100 fft_hal_fir_config_reset(0);
101
102 fft_hal_fir_length_set(fir_conf->fir_len);
103 fft_hal_fir_mode_set(fir_conf->mode);
104 fft_hal_fir_int_en(1);
105 fft_hal_fir_en(1);
106
107 driver_fft.size = fir_conf->fir_len;
108 driver_fft.busy_flag = true;
109 //os_printf("source data\r\n");
110
111 if (fir_conf->mode) {
112 for (i = 0; i < fir_conf->fir_len + 1; i++) {
113 temp_coef = (fir_conf->coef_c1[i] << 16) | fir_conf->coef_c0[i];
114 fft_hal_fir_coef_write(temp_coef);
115 temp_data = (fir_conf->input_d1[i] << 16) | fir_conf->input_d0[i];
116 fft_hal_data_write(temp_data);
117 //os_printf("coef:0x%08x, data:0x%08x\r\n", temp_coef, temp_data);
118 }
119 } else {
120 for (i = 0; i < fir_conf->fir_len + 1; i++) {
121 temp_coef = (int32)fir_conf->coef_c0[i];
122 fft_hal_fir_coef_write(temp_coef);
123 temp_data = (int32)fir_conf->input_d0[i];
124 fft_hal_data_write(temp_data);
125 //os_printf("coef:0x%08x, data:0x%08x\r\n", temp_coef, temp_data);
126 }
127 }
128
129 fft_hal_start_trigger_set(1);
130
131 return BK_OK;
132 }
133
bk_fft_driver_init(void)134 bk_err_t bk_fft_driver_init(void)
135 {
136 if (s_fft_driver_is_init)
137 return BK_OK;
138 //power on
139 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_AUDP_FFT, PM_POWER_MODULE_STATE_ON);
140 //sys_drv_aud_power_en(0); //temp used
141
142 //fft_disckg always on
143 sys_drv_fft_disckg_set(1);
144
145 os_memset(&driver_fft, 0, sizeof(driver_fft));
146 //max number of FFT data
147 driver_fft.i_out = os_malloc(256 * 2);
148 driver_fft.q_out = os_malloc(256 * 2);
149
150 //enable fft interrupt
151 sys_drv_cpu_fft_int_en(1);
152 //register fft isr
153 fft_int_config_t int_config_table = {INT_SRC_FFT, fft_isr};
154 bk_int_isr_register(int_config_table.int_src, int_config_table.isr, NULL);
155 s_fft_driver_is_init = true;
156
157 return BK_OK;
158 }
159
bk_fft_driver_deinit(void)160 bk_err_t bk_fft_driver_deinit(void)
161 {
162 //power down
163 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_AUDP_FFT, PM_POWER_MODULE_STATE_OFF);
164 //fft_disckg not always on
165 sys_drv_fft_disckg_set(0);
166 //disable fft interrupt
167 sys_drv_cpu_fft_int_en(0);
168
169 os_free(driver_fft.i_out);
170 os_free(driver_fft.q_out);
171 os_memset(&driver_fft, 0, sizeof(driver_fft));
172
173 fft_int_config_t int_config_table = {INT_SRC_FFT, fft_isr};
174 bk_int_isr_unregister(int_config_table.int_src);
175 s_fft_driver_is_init = false;
176
177 return BK_OK;
178 }
179
bk_fft_output_read(int16_t * i_output,int16_t * q_output,uint32_t size)180 bk_err_t bk_fft_output_read(int16_t *i_output, int16_t *q_output, uint32_t size)
181 {
182 os_memcpy(i_output, driver_fft.i_out, size);
183 os_memcpy(q_output, driver_fft.q_out, size);
184
185 return BK_OK;
186 }
187
fft_isr(void)188 void fft_isr(void)
189 {
190 int i;
191 uint32_t bit_ext;
192 int32 temp = 0;
193 int32 temp_out = 0;
194 int32 data = 0;
195 int16 temp_low = 0, temp_high = 0;
196 fft_status_t fft_status = {0};
197 fft_hal_status_get(&fft_status);
198 //fft_struct_dump();
199
200 if (fft_status.fft_done) {
201 bit_ext = (fft_status.bit_ext & 0x00001fff) >> 7;
202 os_printf("bit_ext:0x%x\r\n", bit_ext);
203
204 if (bit_ext & 0x20)
205 bit_ext = 64 - bit_ext;
206 else
207 bit_ext = 0;
208
209 for (i = 0; i < driver_fft.size; i++) {
210 temp = fft_hal_data_read();
211 temp_out = ((temp << 16) >> 16) << bit_ext;
212 temp_low = fft_sat(temp_out);
213 temp_out = (temp >> 16) << bit_ext;
214 temp_high = fft_sat(temp_out);
215 driver_fft.i_out[i] = temp_low;
216 driver_fft.q_out[i] = temp_high;
217 //os_printf("i:0x%04hx, q:0x%04hx\r\n", driver_fft.i_out[i], driver_fft.q_out[i]);
218 }
219
220 driver_fft.busy_flag = false;
221 fft_hal_fft_config_reset(0);
222 os_printf("\r\nexit isr \r\n");
223 }
224
225 if (fft_status.fir_done) {
226 for (i = 0; i < driver_fft.size; i++) {
227 data = fft_hal_data_read();
228 driver_fft.i_out[i] = (int16)(data & 0x0000ffff);
229 driver_fft.q_out[i] = (int16)((data & 0xffff0000) >> 16);
230 }
231 driver_fft.busy_flag = false;
232 fft_hal_fft_config_reset(0);
233 }
234 }
235
236