/* task_pq_fft_128.c */
#include "app.h"

/* 借用显存 */
extern uint16_t gLcdWaveformDispBuf[LCD_WIDTH]; /* 显示时域波形曲线. */
extern uint16_t gLcdFreqSpecDispBuf[LCD_WIDTH]; /* 显示频域频谱图. */
extern uint8_t  gLcdTextDispBuf[LCD_WIDTH/8u];  /* 显示字符区域 */

/* 借用FFT数据内存 */
extern q31_t     gPQFftQ31In[APP_PQ_FFT_SAMPLE_COUNT_MAX*2u];
extern q31_t     gPQFftQ31Out[APP_PQ_FFT_SAMPLE_COUNT_MAX*2u];
extern q31_t     gPQFftQ31InOut[APP_PQ_FFT_SAMPLE_COUNT_MAX*2u];
extern float32_t gPQFftF32In[APP_PQ_FFT_SAMPLE_COUNT_MAX*2u];
extern float32_t gPQFftF32Out[APP_PQ_FFT_SAMPLE_COUNT_MAX*2u];

extern volatile uint32_t  gPQProcCycles[APP_USER_TASK_COUNT];   /* PowerQuad timing cycles. */

void task_pq_fft_128(void)
{
    PRINTF("%s\r\n", __func__);

    arm_cfft_instance_q31 instance;
    uint32_t i;
    uint32_t calcTime;

    /* 创建混合信号. */
    for (i = 0; i < APP_PQ_FFT_SAMPLE_COUNT_128; i++)
    {
        /* 实部 */
        gPQFftF32In[i*2] = 1.5f /* 直流分量, 确保信号点值均在0以上 */
                         + 1.0f * arm_cos_f32( (       2.0f * PI / APP_PQ_FFT_PERIOD_BASE) * i  ) /* 低频交流信号 */
                         + 0.5f * arm_cos_f32( (4.0f * 2.0f * PI / APP_PQ_FFT_PERIOD_BASE) * i  ) /* 高频交流信号 */
                         ;
        gPQFftF32In[i*2] /= 3.0f; /* 格式化数据在(0, 1). 显示\计算都要求原始信号在这个范围内. */
        /* 虚部 */
        gPQFftF32In[i*2+1] = 0.0f;

    }

    /* 打印信号波形到显存 */
    memset(gLcdWaveformDispBuf, 0u, sizeof(gLcdWaveformDispBuf));
    for (i = 0u; (i < APP_PQ_FFT_SAMPLE_COUNT_128) && (i < LCD_WIDTH); i++)
    {
        gLcdWaveformDispBuf[i] = (uint16_t)(gPQFftF32In[i*2] * 128.0f);
    }

    /* Powerquad执行FFT的时候只能处理定点数 */
    arm_float_to_q31(gPQFftF32In, gPQFftQ31In, APP_PQ_FFT_SAMPLE_COUNT_128*2u);

    /* cfft函数使用原地存储.将原有信号备份,并且缩放计算信号 */
    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_128 * 2u; i++)
    {
        gPQFftQ31InOut[i] = gPQFftQ31In[i] >> 5u; /* powerquad的fft引擎只能处理27bit,暂时缩放一下,后面会还原 */
    }

    /* 开始计算并对关键操作计时 */
    instance.fftLen = APP_PQ_FFT_SAMPLE_COUNT_128;/* 指定FFT采样点个数(复数的个数) */
    TimerCount_Start();
    arm_cfft_q31(&instance, gPQFftQ31InOut, 0, 1); /* 开算 */
    TimerCount_Stop(calcTime);

    /* 还原之前缩放的信号 */
    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_128 * 2u; i++)
    {
        gPQFftQ31Out[i] = gPQFftQ31InOut[i] << 5u;
    }

    /* 转换不会溢出的浮点数 */
    arm_q31_to_float(gPQFftQ31Out, gPQFftF32Out, APP_PQ_FFT_SAMPLE_COUNT_128*2u);

    /* 对傅里叶系数取模,表示对应频点上的能量 */
    arm_cmplx_mag_f32( gPQFftF32Out, gPQFftF32In, APP_PQ_FFT_SAMPLE_COUNT_128);/* 临时借用一下gPQFftF32In的存储空间 */

    /* 打印频谱到显存 */
    memset(gLcdFreqSpecDispBuf, 0u, sizeof(gLcdFreqSpecDispBuf));
    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_128; i++)
    {
        gLcdFreqSpecDispBuf[i] = (int)(gPQFftF32In[i] * 128.0); /* 将(0,0.5)映射到(0, 128) */
    }

    /* 刷屏LCD */
    lcd_clear_screen(LCD_COLOR_WHITE);

    /* 打印时域波形 */
    lcd_print_waveform(gLcdWaveformDispBuf, APP_PQ_FFT_SAMPLE_COUNT_128, LCD_COLOR_BLUE);
    sprintf((char *)gLcdTextDispBuf, "Input:");
    lcd_print_waveform_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    /* 打印频域谱 */
    lcd_print_freqspec(gLcdFreqSpecDispBuf, APP_PQ_FFT_SAMPLE_COUNT_128, LCD_COLOR_RED);
    sprintf((char *)gLcdTextDispBuf, "Output:");
    lcd_print_freqspec_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    /* 打印结果数据 */
    sprintf((char *)gLcdTextDispBuf, "PowerQuad FFT %d points", APP_PQ_FFT_SAMPLE_COUNT_128);
    lcd_print_text(0, gLcdTextDispBuf, LCD_COLOR_BLUE);
#if APP_CFG_USING_TIMING_CYCLES
    sprintf((char *)gLcdTextDispBuf, "Time: %4d cycles.", calcTime);
#else
    sprintf((char *)gLcdTextDispBuf, "Time: %3d us @96MHz.", (calcTime + (APP_TIMER_CYCLE_PER_US-1)) / APP_TIMER_CYCLE_PER_US);
#endif /* APP_CFG_USING_TIMING_CYCLES */
    lcd_print_text(1, gLcdTextDispBuf, LCD_COLOR_RED);

    PRINTF("%s : %d cycles.\r\n", __func__, calcTime);

    /* Record the cycles into the table. */
    gPQProcCycles[APP_USER_TASK_FFT_128_IDX] = calcTime;

}

/* EOF. */

