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   */