1 /*
2 * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "bf0_hal.h"
8
9 /** @addtogroup BF0_HAL_Driver
10 * @{
11 */
12
13 /** @defgroup FFT FFT
14 * @brief FFT HAL module driver
15 * @{
16 */
17
18 #if defined(HAL_FFT_MODULE_ENABLED)||defined(_SIFLI_DOXYGEN_)
19
20 #ifdef hwp_fft2
21 #define IS_VALID_INSTANCE(inst) ((inst == hwp_fft1) || (inst == hwp_fft2))
22 #else
23 #define IS_VALID_INSTANCE(inst) (inst == hwp_fft1)
24 #endif
25
FFT_CalcDataSize(FFT_BitwidthTypeDef bitwidth,FFT_FFTLengthTypeDef fft_length,uint8_t rfft_flag,bool output)26 static uint32_t FFT_CalcDataSize(FFT_BitwidthTypeDef bitwidth, FFT_FFTLengthTypeDef fft_length,
27 uint8_t rfft_flag, bool output)
28 {
29 uint32_t size;
30
31 size = (1UL << bitwidth);
32 size *= (1UL << (fft_length + 4));
33 if (!rfft_flag || output)
34 {
35 size *= 2;
36 }
37
38 return size;
39 }
40
41 #ifdef SF32LB56X
DCT_CalcDataSize(FFT_BitwidthTypeDef bitwidth,FFT_DCTLengthTypeDef dct_length,uint8_t rdct_flag)42 static uint32_t DCT_CalcDataSize(FFT_BitwidthTypeDef bitwidth, FFT_DCTLengthTypeDef dct_length,
43 uint8_t rdct_flag)
44 {
45 uint32_t size;
46
47 size = (1UL << bitwidth);
48 size *= (1UL << (dct_length + 3));
49 if (!rdct_flag)
50 {
51 size *= 2;
52 }
53
54 return size;
55 }
56 #endif /* SF32LB56X */
57
FFT_Config(FFT_TypeDef * fft,FFT_ConfigTypeDef * config)58 static HAL_StatusTypeDef FFT_Config(FFT_TypeDef *fft, FFT_ConfigTypeDef *config)
59 {
60 uint32_t cr;
61 FFT_FFTLengthTypeDef max_fft_len;
62 uint32_t data_size;
63
64 if (!IS_VALID_INSTANCE(fft))
65 {
66 return HAL_ERROR;
67 }
68 if (hwp_fft1 == fft)
69 {
70 max_fft_len = FFT1_LEN_MAX;
71 }
72 #ifdef hwp_fft2
73 else if (hwp_fft2 == fft)
74 {
75 max_fft_len = FFT2_LEN_MAX;
76 }
77 #endif
78 else
79 {
80 return HAL_ERROR;
81 }
82
83 if (config->fft_length > max_fft_len)
84 {
85 return HAL_ERROR;
86 }
87
88 if (((uint32_t)config->input_data & 3) || ((uint32_t)config->output_data & 3))
89 {
90 return HAL_ERROR;
91 }
92
93 cr = MAKE_REG_VAL(config->bitwidth, FFT_CR_INPUT_BW_SEL_Msk, FFT_CR_INPUT_BW_SEL_Pos);
94 cr |= MAKE_REG_VAL(config->bitwidth, FFT_CR_OUTPUT_BW_SEL_Msk, FFT_CR_OUTPUT_BW_SEL_Pos);
95 cr |= MAKE_REG_VAL(config->fft_length, FFT_CR_FFT_LENGTH_Msk, FFT_CR_FFT_LENGTH_Pos);
96 cr |= MAKE_REG_VAL(config->ifft_flag, FFT_CR_IFFT_MODE_Msk, FFT_CR_IFFT_MODE_Pos);
97 cr |= MAKE_REG_VAL(config->rfft_flag, FFT_CR_RFFT_MODE_Msk, FFT_CR_RFFT_MODE_Pos);
98
99 #ifdef SF32LB56X
100 if (config->win_enabled)
101 {
102 cr |= MAKE_REG_VAL(config->win_bitwidth, FFT_CR_FFT_WIN_BW_SEL_Msk, FFT_CR_FFT_WIN_BW_SEL_Pos);
103 cr |= MAKE_REG_VAL(config->rwin_flag, FFT_CR_FFT_WIN_REAL_Msk, FFT_CR_FFT_WIN_REAL_Pos);
104 cr |= FFT_CR_FFT_WIN_EN;
105 fft->WAR = (uint32_t)config->win_data;
106 if (IS_DCACHED_RAM((uint32_t)config->win_data))
107 {
108 data_size = FFT_CalcDataSize(config->win_bitwidth, config->fft_length, config->rwin_flag, false);
109 mpu_dcache_clean(config->win_data, data_size);
110 }
111 }
112 #endif /* SF32LB56X */
113
114 fft->CR = cr;
115 fft->SAR = (uint32_t)config->input_data;
116 fft->DAR = (uint32_t)config->output_data;
117
118 if (IS_DCACHED_RAM((uint32_t)config->input_data))
119 {
120 data_size = FFT_CalcDataSize(config->bitwidth, config->fft_length, config->rfft_flag, false);
121 mpu_dcache_clean(config->input_data, data_size);
122 }
123
124 if (IS_DCACHED_RAM((uint32_t)config->output_data))
125 {
126 data_size = FFT_CalcDataSize(config->bitwidth, config->fft_length, config->rfft_flag, true);
127 mpu_dcache_invalidate(config->output_data, data_size);
128 }
129
130 return HAL_OK;
131 }
132
133 #ifdef SF32LB56X
DCT_Config(FFT_TypeDef * fft,DCT_ConfigTypeDef * config)134 static HAL_StatusTypeDef DCT_Config(FFT_TypeDef *fft, DCT_ConfigTypeDef *config)
135 {
136 uint32_t cr;
137 uint32_t data_size;
138
139 if (!IS_VALID_INSTANCE(fft))
140 {
141 return HAL_ERROR;
142 }
143
144 if (config->dct_length >= DCT_LEN_TYPE_NUM)
145 {
146 return HAL_ERROR;
147 }
148
149 if (!config->rdct_flag)
150 {
151 if (config->idct_flag || (DCT_TYPE_4 != config->dct_type))
152 {
153 return HAL_ERROR;
154 }
155 }
156
157 if (((uint32_t)config->input_data & 3) || ((uint32_t)config->output_data & 3))
158 {
159 return HAL_ERROR;
160 }
161
162 cr = MAKE_REG_VAL(config->bitwidth, FFT_CR_INPUT_BW_SEL_Msk, FFT_CR_INPUT_BW_SEL_Pos);
163 cr |= MAKE_REG_VAL(config->bitwidth, FFT_CR_OUTPUT_BW_SEL_Msk, FFT_CR_OUTPUT_BW_SEL_Pos);
164 cr |= MAKE_REG_VAL(config->dct_length, FFT_CR_FFT_LENGTH_Msk, FFT_CR_FFT_LENGTH_Pos);
165 cr |= MAKE_REG_VAL(config->idct_flag, FFT_CR_DCT_MODE_Msk, FFT_CR_DCT_MODE_Pos);
166 cr |= MAKE_REG_VAL(config->rdct_flag, FFT_CR_RFFT_MODE_Msk, FFT_CR_RFFT_MODE_Pos);
167 cr |= MAKE_REG_VAL(config->dct_type, FFT_CR_DCT_TYPE_Msk, FFT_CR_DCT_TYPE_Pos);
168 cr |= FFT_CR_FFT_DCT_MODE;
169
170 fft->CR = cr;
171 fft->SAR = (uint32_t)config->input_data;
172 fft->DAR = (uint32_t)config->output_data;
173
174 if (IS_DCACHED_RAM((uint32_t)config->input_data))
175 {
176 data_size = DCT_CalcDataSize(config->bitwidth, config->dct_length, config->rdct_flag);
177 mpu_dcache_clean(config->input_data, data_size);
178 }
179
180 if (IS_DCACHED_RAM((uint32_t)config->output_data))
181 {
182 data_size = DCT_CalcDataSize(config->bitwidth, config->dct_length, config->rdct_flag);
183 mpu_dcache_invalidate(config->output_data, data_size);
184 }
185
186 return HAL_OK;
187 }
188 #endif /* SF32LB56X */
189
190
HAL_FFT_IRQHandler(FFT_HandleTypeDef * fft)191 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_IRQHandler(FFT_HandleTypeDef *fft)
192 {
193 #ifdef SF32LB56X
194 uint8_t step;
195 #endif
196
197 if (!IS_VALID_INSTANCE(fft->Instance))
198 {
199 return HAL_ERROR;
200 }
201
202 fft->Instance->IRQ = FFT_IRQ_ICR | FFT_IRQ_IMR;
203
204 #ifdef SF32LB56X
205 if (HAL_FFT_STATE_CDCT_REAL == fft->State)
206 {
207 /* start img part calculation */
208 fft->State = HAL_FFT_STATE_BUSY;
209 step = GET_REG_VAL(fft->Instance->CR, FFT_CR_INPUT_BW_SEL_Msk, FFT_CR_INPUT_BW_SEL_Pos) + 1;
210 fft->Instance->SAR += step;
211 fft->Instance->DAR += step;
212 fft->Instance->IRQ &= ~FFT_IRQ_IMR;
213 fft->Instance->CR |= FFT_CR_START;
214 return HAL_OK;
215 }
216 #endif /* SF32LB56X */
217 fft->State = HAL_FFT_STATE_READY;
218
219 if (fft->CpltCallback)
220 {
221 fft->CpltCallback(fft);
222 }
223
224 return HAL_OK;
225 }
226
227
HAL_FFT_Init(FFT_HandleTypeDef * fft)228 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_Init(FFT_HandleTypeDef *fft)
229 {
230 if (HAL_FFT_STATE_RESET != fft->State)
231 {
232 return HAL_ERROR;
233 }
234 if (!IS_VALID_INSTANCE(fft->Instance))
235 {
236 return HAL_ERROR;
237 }
238
239 fft->State = HAL_FFT_STATE_READY;
240 return HAL_OK;
241 }
242
HAL_FFT_DeInit(FFT_HandleTypeDef * fft)243 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_DeInit(FFT_HandleTypeDef *fft)
244 {
245 if (HAL_FFT_STATE_READY != fft->State)
246 {
247 return HAL_ERROR;
248 }
249 fft->State = HAL_FFT_STATE_RESET;
250 return HAL_OK;
251 }
252
HAL_FFT_StartFFT(FFT_HandleTypeDef * fft,FFT_ConfigTypeDef * config)253 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_StartFFT(FFT_HandleTypeDef *fft, FFT_ConfigTypeDef *config)
254 {
255 HAL_StatusTypeDef status;
256
257 if (HAL_FFT_STATE_READY != fft->State)
258 {
259 return HAL_BUSY;
260 }
261
262 fft->State = HAL_FFT_STATE_BUSY;
263
264
265 status = FFT_Config(fft->Instance, config);
266
267 if (HAL_OK != status)
268 {
269 goto __EXIT;
270 }
271
272 fft->Instance->IRQ |= FFT_IRQ_IMR;
273 fft->Instance->CR |= FFT_CR_START;
274 while (0 == (fft->Instance->IRQ & FFT_IRQ_IRSR))
275 {
276 __NOP();
277 __NOP();
278 __NOP();
279 }
280 fft->Instance->IRQ = FFT_IRQ_ICR;
281
282 __EXIT:
283 fft->State = HAL_FFT_STATE_READY;
284
285 return status;
286 }
287
HAL_FFT_StartFFT_IT(FFT_HandleTypeDef * fft,FFT_ConfigTypeDef * config)288 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_StartFFT_IT(FFT_HandleTypeDef *fft, FFT_ConfigTypeDef *config)
289 {
290 HAL_StatusTypeDef status;
291
292 if (HAL_FFT_STATE_READY != fft->State)
293 {
294 return HAL_BUSY;
295 }
296
297 fft->State = HAL_FFT_STATE_BUSY;
298
299
300 status = FFT_Config(fft->Instance, config);
301
302 if (HAL_OK != status)
303 {
304 goto __EXIT;
305 }
306
307 fft->Instance->IRQ &= ~FFT_IRQ_IMR;
308 fft->Instance->CR |= FFT_CR_START;
309
310 __EXIT:
311
312 if (HAL_OK != status)
313 {
314 fft->State = HAL_FFT_STATE_READY;
315 }
316
317 return status;
318 }
319
320 #if defined(SF32LB56X) || defined(_SIFLI_DOXYGEN_)
HAL_FFT_StartDCT(FFT_HandleTypeDef * fft,DCT_ConfigTypeDef * config)321 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_StartDCT(FFT_HandleTypeDef *fft, DCT_ConfigTypeDef *config)
322 {
323 HAL_StatusTypeDef status;
324 int32_t loop_cnt;
325 uint32_t step;
326 uint32_t i;
327
328 if (HAL_FFT_STATE_READY != fft->State)
329 {
330 return HAL_BUSY;
331 }
332
333 fft->State = HAL_FFT_STATE_BUSY;
334
335 if (config->rdct_flag)
336 {
337 loop_cnt = 1;
338 step = 0;
339 }
340 else
341 {
342 loop_cnt = 2;
343 if (FFT_BW_8BIT == config->bitwidth)
344 {
345 step = 1;
346 }
347 else if (FFT_BW_16BIT == config->bitwidth)
348 {
349 step = 2;
350 }
351 else
352 {
353 step = 4;
354 }
355 }
356
357 for (i = 0; i < loop_cnt; i++)
358 {
359
360 status = DCT_Config(fft->Instance, config);
361
362 if (HAL_OK != status)
363 {
364 goto __EXIT;
365 }
366 fft->Instance->SAR += i * step;
367 fft->Instance->DAR += i * step;
368
369 fft->Instance->IRQ |= FFT_IRQ_IMR;
370 fft->Instance->CR |= FFT_CR_START;
371 while (0 == (fft->Instance->IRQ & FFT_IRQ_IRSR))
372 {
373 __NOP();
374 __NOP();
375 __NOP();
376 }
377 fft->Instance->IRQ = FFT_IRQ_ICR;
378 }
379
380 __EXIT:
381 fft->State = HAL_FFT_STATE_READY;
382 return status;
383 }
384
HAL_FFT_StartDCT_IT(FFT_HandleTypeDef * fft,DCT_ConfigTypeDef * config)385 __HAL_ROM_USED HAL_StatusTypeDef HAL_FFT_StartDCT_IT(FFT_HandleTypeDef *fft, DCT_ConfigTypeDef *config)
386 {
387 HAL_StatusTypeDef status;
388
389 if (HAL_FFT_STATE_READY != fft->State)
390 {
391 status = HAL_BUSY;
392 goto __EXIT;
393 }
394
395 fft->State = HAL_FFT_STATE_BUSY;
396
397
398 status = DCT_Config(fft->Instance, config);
399
400 if (HAL_OK != status)
401 {
402 goto __EXIT;
403 }
404
405 if (0 == config->rdct_flag)
406 {
407 fft->State = HAL_FFT_STATE_CDCT_REAL;
408 }
409
410 fft->Instance->IRQ &= ~FFT_IRQ_IMR;
411 fft->Instance->CR |= FFT_CR_START;
412
413 __EXIT:
414
415 if (HAL_OK != status)
416 {
417 fft->State = HAL_FFT_STATE_READY;
418 }
419
420 return status;
421 }
422
423 #endif /* SF32LB56X */
424
425
426 #endif /* HAL_FFT_MODULE_ENABLED */
427
428
429 /**
430 * @}
431 */
432
433 /**
434 * @}
435 */