• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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