
#include "app.h"

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

/* 借用FIR数据内存 */
extern float32_t gPQFirF32In[APP_PQ_FIR_SAMPLE_COUNT_240];
extern float32_t gPQFirF32Out[APP_PQ_FIR_SAMPLE_COUNT_240];

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

#define FIR_INPUT_LEN 240u
#define TEST_LENGTH_SAMPLES  320

/*将阶数由28改为32,NUM_TAPS=阶数+1*/
#define NUM_TAPS              32

#define DEMO_POWERQUAD POWERQUAD
#define EXAMPLE_PRIVATE_RAM ((void *)0xE0001000)

static float32_t firStateF32[FIR_INPUT_LEN + NUM_TAPS - 1];

/*低通滤波器系数，截止频率为6000Hz*/
float32_t firCoeffs32_lowpass[] = {
0.0000000000f, -0.0013361934f, -0.0026212054f, -0.0027337662f, 0.0000000000f, 0.0058338130f, 0.0116127053f, 0.0112869710f,
0.0000000000f, -0.0202965560f, -0.0380763812f, -0.0358973375f, 0.0000000000f, 0.0693732235f, 0.1539442321f, 0.2236157294f,
0.2505895307f, 0.2236157294f, 0.1539442321f, 0.0693732235f, 0.0000000000f, -0.0358973375f, -0.0380763812f, -0.0202965560f,
0.0000000000f, 0.0112869710f, 0.0116127053f, 0.0058338130f, 0.0000000000f, -0.0027337662f, -0.0026212054f, -0.0013361934f, 0.0000000000f,

};

/*高通滤波器系数，截止频率为6000Hz*/
float32_t firCoeffs32_highpass[]={
0.0000000000f, 0.0013338703f, 0.0026166481f, 0.0027290131f, 0.0000000000f, -0.0058236702f, -0.0115925151f, -0.0112673471f,
0.0000000000f, 0.0202612678f, 0.0380101804f, 0.0358349253f, 0.0000000000f, -0.0692526091f, -0.1536765800f, -0.2232269444f,
0.7504615446f, -0.2232269444f, -0.1536765800f, -0.0692526091f, 0.0000000000f, 0.0358349253f, 0.0380101804f, 0.0202612678f,
0.0000000000f, -0.0112673471f, -0.0115925151f, -0.0058236702f, 0.0000000000f, 0.0027290131f, 0.0026166481f, 0.0013338703f, 0.0000000000f,
};

/************************************************************************************************/


void task_pq_fir_lowpass(void)
{
    uint32_t i;
    uint32_t Fs=48000;

    arm_fir_instance_f32 S;
    float32_t  *inputF32, *outputF32;
    uint32_t calcTime;

    inputF32 = &gPQFirF32In[0];
    outputF32 = &gPQFirF32Out[0];

    /* Generate the wave. */
    for (i = 0; i < FIR_INPUT_LEN; i++)
    {
        gPQFirF32In[i]    =arm_sin_f32(2*PI*1000*i/Fs)+ 0.5*arm_sin_f32(2*PI*15000*i/Fs)+1.5;
        gPQFirF32In[i] /=3.0f;
    }

    /* 打印信号波形到显存 */
    memset(gLcdWaveformDispBuf, 0u, sizeof(gLcdWaveformDispBuf));

    for (i = 0u; (i < APP_PQ_FIR_SAMPLE_COUNT_240) && (i < LCD_WIDTH); i++)
    {
        gLcdWaveformDispBuf[i] = (uint16_t)(gPQFirF32In[i] * 128.0f);
    }

      /* Call FIR init function to initialize the instance structure. */
    arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32_lowpass[0], &firStateF32[0], FIR_INPUT_LEN);

    PQ_Init(POWERQUAD_NS);
    pq_config_t pqConfig;

    pqConfig.inputAFormat = kPQ_Float;
    pqConfig.inputAPrescale = 0;
    pqConfig.inputBFormat = kPQ_Float;
    pqConfig.inputBPrescale = 0;
    pqConfig.outputFormat = kPQ_Float;
    pqConfig.outputPrescale = 0;
    pqConfig.tmpFormat = kPQ_Float;
    pqConfig.tmpPrescale = 0;
    pqConfig.machineFormat = kPQ_Float;
    pqConfig.tmpBase = (uint32_t *)0xE0000000;

    PQ_SetConfig(POWERQUAD_NS, &pqConfig);
    /*将滤波器系数放到Private ram中以减小运算时间*/
    PQ_MatrixScale(POWERQUAD_NS, POWERQUAD_MAKE_MATRIX_LEN(16, NUM_TAPS / 16, 0), 1.0, firCoeffs32_lowpass,
                   EXAMPLE_PRIVATE_RAM);

    PQ_WaitDone(POWERQUAD);

    /* In the next calculation, data in private ram is used. */
    pqConfig.inputBFormat = kPQ_Float;
    pqConfig.outputFormat = kPQ_Float;
    PQ_SetConfig(POWERQUAD_NS, &pqConfig);

    /* 开始计算并对关键操作计时 */
    TimerCount_Start();

    PQ_FIR(POWERQUAD_NS, inputF32, APP_PQ_FIR_SAMPLE_COUNT_240, EXAMPLE_PRIVATE_RAM, NUM_TAPS, outputF32,PQ_FIR_FIR);
    PQ_WaitDone(POWERQUAD_NS);

    TimerCount_Stop(calcTime);


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

    /* 刷屏LCD */
    lcd_clear_screen(LCD_COLOR_WHITE);
    /* 打印新的内容 */
    lcd_print_waveform(gLcdWaveformDispBuf, APP_PQ_FIR_SAMPLE_COUNT_240, LCD_COLOR_BLUE);
    sprintf((char *)gLcdTextDispBuf, "Input:");
    lcd_print_waveform_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    lcd_print_waveform_fir(gLcdFreqSpecDispBuf, APP_PQ_FIR_SAMPLE_COUNT_240, LCD_COLOR_RED);
    sprintf((char *)gLcdTextDispBuf, "Output:");
    lcd_print_freqspec_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    /* 打印结果数据 */
    sprintf((char *)gLcdTextDispBuf, "PowerQuad FIR %d points", APP_PQ_FIR_SAMPLE_COUNT_240);
    lcd_print_text(0, gLcdTextDispBuf, LCD_COLOR_BLUE);
#if APP_CFG_USING_TIMING_CYCLES
    sprintf((char *)gLcdTextDispBuf, "Time: %4d cycles. lowpass", calcTime);
#else
    sprintf((char *)gLcdTextDispBuf, "Time: %3d us @96MHz. LowPass", (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);
    /* Record the cycles into the table. */
    gPQProcCycles[APP_USER_TASK_FIR_LPS_IDX] = calcTime;

}

void task_pq_fir_highpass(void)
{
    uint32_t i;
    uint32_t Fs=48000;

    arm_fir_instance_f32 S;
    float32_t  *inputF32, *outputF32;
    uint32_t calcTime;

    inputF32 = &gPQFirF32In[0];
    outputF32 = &gPQFirF32Out[0];

    /* Generate the wave. */
    for (i = 0; i < FIR_INPUT_LEN; i++)
    {
        gPQFirF32In[i]    =arm_sin_f32(2*PI*1000*i/Fs)+ 0.5*arm_sin_f32(2*PI*15000*i/Fs)+1.5;
        gPQFirF32In[i] /=3.0f;
    }

    /* 打印信号波形到显存 */
    memset(gLcdWaveformDispBuf, 0u, sizeof(gLcdWaveformDispBuf));

    for (i = 0u; (i < APP_PQ_FIR_SAMPLE_COUNT_240) && (i < LCD_WIDTH); i++)
    {
        gLcdWaveformDispBuf[i] = (uint16_t)(gPQFirF32In[i] * 128.0f);
    }

      /* Call FIR init function to initialize the instance structure. */
    arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32_highpass[0], &firStateF32[0], FIR_INPUT_LEN);

    PQ_Init(POWERQUAD_NS);
    pq_config_t pqConfig;

    pqConfig.inputAFormat = kPQ_Float;
    pqConfig.inputAPrescale = 0;
    pqConfig.inputBFormat = kPQ_Float;
    pqConfig.inputBPrescale = 0;
    pqConfig.outputFormat = kPQ_Float;
    pqConfig.outputPrescale = 0;
    pqConfig.tmpFormat = kPQ_Float;
    pqConfig.tmpPrescale = 0;
    pqConfig.machineFormat = kPQ_Float;
    pqConfig.tmpBase = (uint32_t *)0xE0000000;

    PQ_SetConfig(POWERQUAD_NS, &pqConfig);

    /*将滤波器系数放到Private ram中以减小运算时间*/
    PQ_MatrixScale(POWERQUAD_NS, POWERQUAD_MAKE_MATRIX_LEN(16, NUM_TAPS / 16, 0), 1.0, firCoeffs32_highpass,
                   EXAMPLE_PRIVATE_RAM);

    PQ_WaitDone(POWERQUAD);

    /* In the next calculation, data in private ram is used. */
    pqConfig.inputBFormat = kPQ_Float;
    pqConfig.outputFormat = kPQ_Float;
    PQ_SetConfig(POWERQUAD_NS, &pqConfig);


    /* 开始计算并对关键操作计时 */
    TimerCount_Start();
    PQ_FIR(POWERQUAD_NS, inputF32, APP_PQ_FIR_SAMPLE_COUNT_240, EXAMPLE_PRIVATE_RAM, NUM_TAPS, outputF32,PQ_FIR_FIR);
    PQ_WaitDone(POWERQUAD_NS);
    //arm_fir_f32(&S, inputF32, outputF32, FIR_INPUT_LEN);
    TimerCount_Stop(calcTime);

            /* 打印频谱到显存 */
    memset(gLcdFreqSpecDispBuf, 0u, sizeof(gLcdFreqSpecDispBuf));
    for (i = 0u; i < APP_PQ_FIR_SAMPLE_COUNT_240; i++)
    {
        /*之前的直流分量被高通滤波器滤掉，需要再增加一个直流分量以增加显示效果*/
        gLcdFreqSpecDispBuf[i] = (int)((gPQFirF32Out[i]+0.5) * 128.0); /* 将(0,0.5)映射到(0, 128) */
    }

    /* 刷屏LCD */
    lcd_clear_screen(LCD_COLOR_WHITE);
    /* 打印新的内容 */
    lcd_print_waveform(gLcdWaveformDispBuf, APP_PQ_FIR_SAMPLE_COUNT_240, LCD_COLOR_BLUE);
    sprintf((char *)gLcdTextDispBuf, "Input:");
    lcd_print_waveform_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    lcd_print_waveform_fir(gLcdFreqSpecDispBuf, APP_PQ_FIR_SAMPLE_COUNT_240, LCD_COLOR_RED);
    sprintf((char *)gLcdTextDispBuf, "Output:");
    lcd_print_freqspec_text(gLcdTextDispBuf, LCD_COLOR_BLACK);

    sprintf((char *)gLcdTextDispBuf, "PowerQuad FIR %d points", APP_PQ_FIR_SAMPLE_COUNT_240);
    lcd_print_text(0, gLcdTextDispBuf, LCD_COLOR_BLUE);
#if APP_CFG_USING_TIMING_CYCLES
    sprintf((char *)gLcdTextDispBuf, "Time: %4d cycles. highpass", calcTime);
#else
    sprintf((char *)gLcdTextDispBuf, "Time: %3d us @96MHz. highpass", (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);
    /* Record the cycles into the table. */
    gPQProcCycles[APP_USER_TASK_FIR_HPS_IDX] = calcTime;

}

/* EOF. */

