793 lines
25 KiB
C
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;
|
|
}
|