Files
kunlun/dtest/dtest3/kl3_fft_test/fft_test.c
2024-09-28 14:24:04 +08:00

793 lines
25 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "chip_reg_base.h"
#include "hw_reg_api.h"
#include "afft_hw.h"
#include "dbg_io.h"
#include "gp_timer.h"
#include "iot_irq.h"
#include "iot_clock.h"
#include "os_mem_api.h"
#include "iot_afft_api.h"
#include "iot_io_api.h"
#include "iot_errno_api.h"
#include "iot_utils_api.h"
#include "dtest_printf.h"
#include "fft_test_data_real.h"
#include "fft_test_data_complex.h"
#include "fft_test_data_float_real.h"
#include "fft_test_data_float_complex.h"
#define DTEST_FFT_CASE_REAL_FFT (1 << 0)
#define DTEST_FFT_CASE_REAL_IFFT (1 << 1)
#define DTEST_FFT_CASE_COMPLEX_FFT (1 << 2)
#define DTEST_FFT_CASE_COMPLEX_IFFT (1 << 3)
#define DTEST_FFT_CASE_FLOAT_REAL_FFT (1 << 4)
#define DTEST_FFT_CASE_FLOAT_REAL_IFFT (1 << 5)
#define DTEST_FFT_CASE_FLOAT_COMPLEX_FFT (1 << 6)
#define DTEST_FFT_CASE_FLOAT_COMPLEX_IFFT (1 << 7)
#define DTEST_FFT_CASE_COMPLETE_INTERRUPT (1 << 8)
#define DTEST_FFT_DATA_LEN_MAX 2048
#define DTEST_FFT_COMPARE_DEBUG 0
//#define iot_printf(fmt, ...)
typedef enum {
DTEST_FFT_MODE_REAL_FFT = 0,
DTEST_FFT_MODE_REAL_IFFT,
DTEST_FFT_MODE_COMPLEX_FFT,
DTEST_FFT_MODE_COMPLEX_IFFT,
DTEST_FFT_MODE_FLOAT_REAL_FFT,
DTEST_FFT_MODE_FLOAT_REAL_IFFT,
DTEST_FFT_MODE_FLOAT_COMPLEX_FFT,
DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT,
DTEST_FFT_MODE_MAX,
} DTEST_FFT_MODE_E;
typedef enum {
DTEST_FFT_SIZE_32 = 0,
DTEST_FFT_SIZE_64,
DTEST_FFT_SIZE_128,
DTEST_FFT_SIZE_256,
DTEST_FFT_SIZE_512,
DTEST_FFT_SIZE_1024,
DTEST_FFT_SIZE_2048,
DTEST_FFT_SIZE_MAX,
} DTEST_FFT_SIZE_E;
/* copy form dtest\ada_test\math.c */
static double dtest_fft_sqrt_double(double x)
{
double m = 0.0, n, y;
if (x < 0)
return -1;
if (x == 0)
return 0;
n = x / 2;
while(m != n) {
m = n;
n = (m + x / m) / 2;
}
y = m;
return (y + x / y) / 2;
}
static uint32_t dtest_fft_result_compare(uint32_t *cal,
uint32_t *expect, uint32_t size, DTEST_FFT_MODE_E mode)
{
int i, err_cnt = 0, index_max = 0;
if (mode < DTEST_FFT_MODE_FLOAT_REAL_FFT) {
int data_max = 0, data_temp;
int64_t data_square;
int data_cal, data_exp, data_delta, data_standard;
/* get max data */
for (i = 0; i < size; i++) {
data_temp = IOT_ABS((int)cal[i]);
if (data_temp >= data_max) {
#if DTEST_FFT_COMPARE_DEBUG
iot_printf("find bigger int data:%d, index:%d\n", data_temp, i);
#endif
index_max = i;
data_max = data_temp;
}
}
index_max = (index_max % 2) ? (index_max - 1) : index_max;
/* calculate sqrt root */
data_temp = IOT_ABS((int)cal[index_max]);
iot_printf("get max data index:%d, real part:%d, ", index_max, (int)data_temp);
data_square = (int64_t)data_temp * (int64_t)data_temp;
data_temp = IOT_ABS((int)cal[index_max + 1]);
iot_printf("imaginary part:%d\n\t", (int)data_temp);
data_square += (int64_t)data_temp * (int64_t)data_temp;
data_temp = iot_math_sqrt(data_square);
data_standard = data_temp * 5 / 10000;
iot_printf("square:(0x%x%08x) sqrt:%d, standard:%d\n",(int)(data_square >> 32),
(int)(data_square & 0xffffffff), data_temp, data_standard);
for (i = 0; i < size; i++) {
data_cal = (int)cal[i];
data_exp = (int)expect[i];
data_delta = (data_cal > data_exp) ? (data_cal - data_exp) : (data_exp - data_cal);
#if DTEST_FFT_COMPARE_DEBUG
iot_printf("data dump, i:%d, \tcal:%d, \texpect:%d, \tdelta:%d\n",
i, data_cal, data_exp, data_delta);
#endif
if (data_delta > data_standard) {
err_cnt++;
}
}
} else {
float data_max = 0.0, data_temp;
double data_square;
float data_cal, data_exp, data_delta, data_standard;
float *p_cal = (float *)cal, *p_expect = (float *)expect;
/* get max data */
for (i = 0; i < size; i++) {
data_temp = IOT_ABS(p_cal[i]);
if (data_temp >= data_max) {
#if DTEST_FFT_COMPARE_DEBUG
iot_printf("find bigger float data:%f, index:%d\n", data_temp, i);
#endif
index_max = i;
data_max = data_temp;
}
}
index_max = (index_max % 2) ? (index_max - 1) : index_max;
/* calculate sqrt root */
data_temp = IOT_ABS(p_cal[index_max]);
iot_printf("get max data index:%d, real part:%f, ", index_max, data_temp);
data_square = data_temp * data_temp;
data_temp = IOT_ABS(p_cal[index_max + 1]);
iot_printf("imaginary part:%f\n\t", data_temp);
data_square += data_temp * data_temp;
data_temp = (float)dtest_fft_sqrt_double(data_square);
data_standard = data_temp * 5 / 10000;
iot_printf("square:%lf sqrt:%f, standard:%f\n", data_square, data_temp, data_standard);
for (i = 0; i < size; i++) {
data_cal = p_cal[i];
data_exp = p_expect[i];
data_delta = (data_cal > data_exp) ? (data_cal - data_exp) : (data_exp - data_cal);
#if DTEST_FFT_COMPARE_DEBUG
iot_printf("data dump, i:%d, \tcal:%f, \texpect:%f, \tdelta:%f\n",
i, data_cal, data_exp, data_delta);
#endif
if (data_delta > data_standard) {
err_cnt++;
}
}
}
iot_printf("compare data complete - %d/%d\n", err_cnt, size);
if(err_cnt) {
return ERR_FAIL;
} else {
return ERR_OK;
}
}
#if 0
static uint32_t time_s, time_e, time_d;
static uint32_t result[DTEST_FFT_DATA_LEN_MAX] = {0};
static uint32_t dtest_fft_real_fft_64_test()
{
dcase_start("real fft 64\n");
os_mem_set(result, 0x00, sizeof(result));
time_s = gp_timer_get_current_val(0);
iot_afft_real_fft(result, (uint32_t*)dtest_fft_data_input_real_64, 64, AFFT_FMT_KL3_32BIT, AFFT_REAL_64, 1, 0, 0);
time_e = gp_timer_get_current_val(0);
time_d = (time_e > time_s) ? (time_e - time_s) : (0xffffffff - time_s + time_e);
dprintf("real fft calculate complete, time %d us\n", time_d);
if (dtest_fft_result_compare(result, (uint32_t *)dtest_fft_data_output_real_64, 64) != ERR_OK) {
dcase_failed();
return ERR_FAIL;
} else {
dcase_success();
return ERR_OK;
}
}
#endif
static uint32_t dtest_fft_test_com(DTEST_FFT_MODE_E mode, DTEST_FFT_SIZE_E size)
{
uint32_t t_s_1, t_e_1, t_d_1, t_s_2, t_e_2, t_d_2, compare_result;
uint32_t result[DTEST_FFT_DATA_LEN_MAX] = {0};
uint8_t fft_bit_cfg = AFFT_FMT_KL3_32BIT;
char ay_name[DTEST_FFT_MODE_MAX][32] = {"real fft", "real ifft", "complex fft", "complex ifft",
"float real fft", "float real ifft", "float complex fft", "float complex ifft"};
uint32_t ay_size[DTEST_FFT_SIZE_MAX] = {32, 64, 128, 256, 512, 1024, 2048};
/* The order of enumeration values in the adapter driver */
uint8_t ay_cfg_mode[4][DTEST_FFT_SIZE_MAX] = {
{0, AFFT_REAL_64, AFFT_REAL_128, AFFT_REAL_256, AFFT_REAL_512, AFFT_REAL_1024, AFFT_REAL_2048},
{AFFT_COMPLEX_32, AFFT_COMPLEX_64, AFFT_COMPLEX_128, AFFT_COMPLEX_256, AFFT_COMPLEX_512, AFFT_COMPLEX_1024, 0},
{0, AFFT_REAL_64, AFFT_REAL_128, AFFT_REAL_256, AFFT_REAL_512, AFFT_REAL_1024, AFFT_REAL_2048},
{AFFT_COMPLEX_32, AFFT_COMPLEX_64, AFFT_COMPLEX_128, AFFT_COMPLEX_256, AFFT_COMPLEX_512, AFFT_COMPLEX_1024, 0},
};
/* size0: 256r 128c,
* size1: 512r 256c,
* size2:1024r 512c,
* size3: 2048r 1024c,
* size4: 64r 32c,
* size5: 128r 64c */
uint32_t *ay_inbuf_ptr[DTEST_FFT_MODE_MAX][DTEST_FFT_SIZE_MAX] = {
/* real fft\ifft data */
{NULL, fft_size4_r_in, fft_size5_r_in, fft_size0_r_in, fft_size1_r_in, fft_size2_r_in, fft_size3_r_in},
{NULL, ifft_size4_r_in, ifft_size5_r_in, ifft_size0_r_in, ifft_size1_r_in, ifft_size2_r_in, ifft_size3_r_in},
/* complex fft\ifft data */
{fft_size4_c_in, fft_size5_c_in, fft_size0_c_in, fft_size1_c_in, fft_size2_c_in, fft_size3_c_in, NULL},
{ifft_size4_c_in, ifft_size5_c_in, ifft_size0_c_in, ifft_size1_c_in, ifft_size2_c_in, ifft_size3_c_in, NULL},
/* float real fft\ifft data */
{NULL, (uint32_t*)f_fft_size4_r_in, (uint32_t*)f_fft_size5_r_in, (uint32_t*)f_fft_size0_r_in,
(uint32_t*)f_fft_size1_r_in, (uint32_t*)f_fft_size2_r_in, (uint32_t*)f_fft_size3_r_in},
{NULL, (uint32_t*)f_ifft_size4_r_in, (uint32_t*)f_ifft_size5_r_in, (uint32_t*)f_ifft_size0_r_in,
(uint32_t*)f_ifft_size1_r_in, (uint32_t*)f_ifft_size2_r_in, (uint32_t*)f_ifft_size3_r_in},
/* float complex fft\ifft data */
{(uint32_t*)f_fft_size4_c_in, (uint32_t*)f_fft_size5_c_in, (uint32_t*)f_fft_size0_c_in,
(uint32_t*)f_fft_size1_c_in, (uint32_t*)f_fft_size2_c_in, (uint32_t*)f_fft_size3_c_in, NULL},
{(uint32_t*)f_ifft_size4_c_in, (uint32_t*)f_ifft_size5_c_in, (uint32_t*)f_ifft_size0_c_in,
(uint32_t*)f_ifft_size1_c_in, (uint32_t*)f_ifft_size2_c_in, (uint32_t*)f_ifft_size3_c_in, NULL},
};
uint32_t *ay_outbuf_ptr[DTEST_FFT_MODE_MAX][DTEST_FFT_SIZE_MAX] = {
/* real fft\ifft data */
{NULL, fft_size4_r_out, fft_size5_r_out, fft_size0_r_out, fft_size1_r_out, fft_size2_r_out, fft_size3_r_out},
{NULL, ifft_size4_r_out, ifft_size5_r_out, ifft_size0_r_out, ifft_size1_r_out, ifft_size2_r_out, ifft_size3_r_out},
/* complex fft\ifft data */
{fft_size4_c_out, fft_size5_c_out, fft_size0_c_out, fft_size1_c_out, fft_size2_c_out, fft_size3_c_out, NULL},
{ifft_size4_c_out, ifft_size5_c_out, ifft_size0_c_out, ifft_size1_c_out, ifft_size2_c_out, ifft_size3_c_out, NULL},
/* float real fft\ifft data */
{NULL, (uint32_t*)f_fft_size4_r_out, (uint32_t*)f_fft_size5_r_out, (uint32_t*)f_fft_size0_r_out,
(uint32_t*)f_fft_size1_r_out, (uint32_t*)f_fft_size2_r_out, (uint32_t*)f_fft_size3_r_out},
{NULL, (uint32_t*)f_ifft_size4_r_out, (uint32_t*)f_ifft_size5_r_out, (uint32_t*)f_ifft_size0_r_out,
(uint32_t*)f_ifft_size1_r_out, (uint32_t*)f_ifft_size2_r_out, (uint32_t*)f_ifft_size3_r_out},
/* complex fft\ifft data */
{(uint32_t*)f_fft_size4_c_out, (uint32_t*)f_fft_size5_c_out, (uint32_t*)f_fft_size0_c_out,
(uint32_t*)f_fft_size1_c_out, (uint32_t*)f_fft_size2_c_out, (uint32_t*)f_fft_size3_c_out, NULL},
{(uint32_t*)f_ifft_size4_c_out, (uint32_t*)f_ifft_size5_c_out, (uint32_t*)f_ifft_size0_c_out,
(uint32_t*)f_ifft_size1_c_out, (uint32_t*)f_ifft_size2_c_out, (uint32_t*)f_ifft_size3_c_out, NULL},
};
(void)ay_name;
(void)t_d_1;
(void)t_d_2;
if (mode >= DTEST_FFT_MODE_MAX || size >= DTEST_FFT_SIZE_MAX) {
dprintf("parameter error, mode:%d, size:%d\n", mode, size);
return ERR_FAIL;
}
dprintf("%s, size:%d\n", ay_name[mode], ay_size[size]);
if (mode >= DTEST_FFT_MODE_FLOAT_REAL_FFT) {
fft_bit_cfg = AFFT_FMT_KL3_FLOAT_32BIT;
}
t_s_1 = gp_timer_get_current_val(0);
os_mem_set(result, 0x00, sizeof(result));
t_s_2 = gp_timer_get_current_val(0);
switch (mode) {
case DTEST_FFT_MODE_REAL_FFT:
case DTEST_FFT_MODE_FLOAT_REAL_FFT:
iot_afft_real_fft(result, ay_inbuf_ptr[mode][size], ay_size[size],
fft_bit_cfg, ay_cfg_mode[mode / 2][size], 1, 0, 0);
break;
case DTEST_FFT_MODE_REAL_IFFT:
case DTEST_FFT_MODE_FLOAT_REAL_IFFT:
iot_afft_real_ifft(result, ay_inbuf_ptr[mode][size], ay_size[size],
fft_bit_cfg, ay_cfg_mode[mode / 2][size], 1, 0, 0);
break;
case DTEST_FFT_MODE_COMPLEX_FFT:
case DTEST_FFT_MODE_FLOAT_COMPLEX_FFT:
iot_afft_complex_fft(result, ay_inbuf_ptr[mode][size], ay_size[size],
fft_bit_cfg, ay_cfg_mode[mode / 2][size], 1, 0, 0);
break;
case DTEST_FFT_MODE_COMPLEX_IFFT:
case DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT:
iot_afft_complex_ifft(result, ay_inbuf_ptr[mode][size], ay_size[size],
fft_bit_cfg, ay_cfg_mode[mode / 2][size], 1, 0, 0);
break;
default:
IOT_ASSERT(0);
break;
}
t_e_2 = gp_timer_get_current_val(0);
compare_result = dtest_fft_result_compare(result, ay_outbuf_ptr[mode][size], ay_size[size], mode);
t_e_1 = gp_timer_get_current_val(0);
t_d_1 = (t_e_1 > t_s_1) ? (t_e_1 - t_s_1) : (0xffffffff - t_s_1 + t_e_1);
t_d_2 = (t_e_2 > t_s_2) ? (t_e_2 - t_s_2) : (0xffffffff - t_s_2 + t_e_2);
dprintf("real fft calculate complete, time fft:%dus, total:%dus\n", t_d_2, t_d_1);
if (compare_result != ERR_OK) {
return ERR_FAIL;
} else {
return ERR_OK;
}
}
static uint32_t dtest_fft_real_fft_test()
{
dcase_start("real fft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_FFT, DTEST_FFT_SIZE_2048) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_real_ifft_test()
{
dcase_start("real ifft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_REAL_IFFT, DTEST_FFT_SIZE_2048) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_complex_fft_test()
{
dcase_start("complex fft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_32) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_FFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_complex_ifft_test()
{
dcase_start("complex ifft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_32) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_COMPLEX_IFFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_float_real_fft_test()
{
dcase_start("float real fft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_FFT, DTEST_FFT_SIZE_2048) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_float_real_ifft_test()
{
dcase_start("float real ifft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_REAL_IFFT, DTEST_FFT_SIZE_2048) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_float_complex_fft_test()
{
dcase_start("float complex fft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_32) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_FFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint32_t dtest_fft_float_complex_ifft_test()
{
dcase_start("float complex ifft\n");
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_32) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_64) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_128) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_256) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_512) != ERR_OK) {
goto fail;
}
if (dtest_fft_test_com(DTEST_FFT_MODE_FLOAT_COMPLEX_IFFT, DTEST_FFT_SIZE_1024) != ERR_OK) {
goto fail;
}
dcase_success();
return ERR_OK;
fail:
dcase_failed();
return ERR_FAIL;
}
static uint8_t g_fft_interrupt_trig = 0;
static iot_irq_t g_fft_irq;
static uint32_t g_result[DTEST_FFT_DATA_LEN_MAX] = {0};
uint32_t dtest_fft_interrupt_handle(uint32_t vector, iot_addrword_t data)
{
dprintf("init trig, data:0x%08x, result:%p\n", data, g_result);
if (vector != HAL_VECTOR_FFT) {
dprintf("interrupt vector error(%d- %d)\n", vector, HAL_VECTOR_FFT);
IOT_ASSERT(0);
}
if (data != (iot_addrword_t)g_result) {
dprintf("interrupt param error\n");
IOT_ASSERT(0);
}
uint32_t state = afft_interrupt_state_get();
uint32_t done = afft_get_done_bit();
(void)state;
(void)done;
dprintf("after fft cal, interrupt state:%d, done:%d\n", state, done);
if (state != 1 || done != 1) {
dprintf("fft status error\n");
IOT_ASSERT(0);
}
afft_interrupt_state_clear();
afft_clr_done_bit();
if (dtest_fft_result_compare(g_result, fft_size4_r_out, 64,
DTEST_FFT_MODE_REAL_FFT) == ERR_OK) {
g_fft_interrupt_trig = 1;
}
return 0;
}
static uint32_t dtest_fft_interrupt_test()
{
uint32_t t_s, t_e, t_d;
dcase_start("fft interrupt\n");
/* reset fft module */
/* clear interrupt state, and enable interrupt function */
afft_interrupt_enable(1);
uint32_t state = afft_interrupt_state_get();
uint32_t done = afft_get_done_bit();
(void)state;
(void)done;
dprintf("before fft cal, interrupt state:%d, done:%d\n", state, done);
afft_interrupt_state_clear();
afft_clr_done_bit();
/* enable fft core interrupt */
g_fft_irq = iot_interrupt_create(HAL_VECTOR_FFT, HAL_INTR_PRI_5,
(iot_addrword_t)g_result, dtest_fft_interrupt_handle);
iot_interrupt_attach(g_fft_irq);
iot_interrupt_unmask(g_fft_irq);
/* fft cal */
afft_cfg(AFFT_OP_FFT, AFFT_FMT_KL3_32BIT, AFFT_DATA_REAL, AFFT_REAL_64, 1, 0, 0);
afft_data_trans(fft_size4_r_in, 64, AFFT_BUF_INPUT, g_result);
afft_start();
/* wait interrupt */
t_s = gp_timer_get_current_val(0);
dprintf("wait fft complete interrupt, start time:%d\n", t_s);
while (!g_fft_interrupt_trig) {
t_e = gp_timer_get_current_val(0);
t_d = (t_e > t_s) ? (t_e - t_s) : (0xffffffff - t_s + t_e);
if (t_d > 10000000) { //1s
dprintf("fft interrupt timeout, use time:%d\n", t_d);
dcase_failed();
return ERR_FAIL;
}
}
t_e = gp_timer_get_current_val(0);
t_d = (t_e > t_s) ? (t_e - t_s) : (0xffffffff - t_s + t_e);
dprintf("fft interupt compare complete, use time:%d\n", t_d);
dcase_success();
return ERR_OK;
}
static void dtest_fft_main()
{
uint32_t case_group = 0, failed_cnt = 0;
(void)case_group;
dbg_uart_init();
dconfig();
dstart();
dversion();
if (dtest_get_case_group(&case_group) < 0) {
case_group = 0xffffffff;
}
dprintf("get case group:0x%08X\n", case_group);
gp_timer_init();
gp_timer_set(0, 0xffffffff, 0);
gp_timer_start(0);
iot_afft_init();
if (case_group & DTEST_FFT_CASE_REAL_FFT) {
if (dtest_fft_real_fft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_REAL_IFFT) {
if (dtest_fft_real_ifft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_COMPLEX_FFT) {
if (dtest_fft_complex_fft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_COMPLEX_IFFT) {
if (dtest_fft_complex_ifft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_FLOAT_REAL_FFT) {
if (dtest_fft_float_real_fft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_FLOAT_REAL_IFFT) {
if (dtest_fft_float_real_ifft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_FLOAT_COMPLEX_FFT) {
if (dtest_fft_float_complex_fft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_FLOAT_COMPLEX_IFFT) {
if (dtest_fft_float_complex_ifft_test() != ERR_OK) {
failed_cnt++;
}
}
if (case_group & DTEST_FFT_CASE_COMPLETE_INTERRUPT) {
if (dtest_fft_interrupt_test() != ERR_OK) {
failed_cnt++;
}
}
if (failed_cnt) {
dprintf("fft dtest failed\n");
} else {
dprintf("fft dtest succeed\n");
}
dend();
return;
}
int main(void)
{
dtest_fft_main();
return 0;
}