#include "DDC1.h"

//Define the delay line lengths.
#define TDELAY 12 //Top delay line.
#define BDELAY 8  //Bottom delay line.

void hb(hls::stream<idata_t> *in, hls::stream<odata_t> *out)
{
    //Coefficient constants.
    static const Coeff coeff[] =
    {
        -0.00137901306152343750,  0.00764656066894531250, -0.02583885192871093800,
         0.06878852844238281300, -0.17095375061035156000,  0.62168693542480469000
    };

    //Delay lines.
    static idata_t shift_reg_real_t[TDELAY];
    static idata_t shift_reg_real_b[BDELAY];
    static idata_t shift_reg_imag_t[TDELAY];
    static idata_t shift_reg_imag_b[BDELAY];

    //Accumulators.
    Acc_real acc_real = 0;
    Acc_imag acc_imag = 0;

    //Get input data.
    shift_reg_real_t[0] = in->read();
    shift_reg_imag_t[0] = in->read();
    shift_reg_real_b[0] = in->read();
    shift_reg_imag_b[0] = in->read();

    //Multiply through.
    AccumLoop:
    for (int i = 0; i < TDELAY/2; i++)
    {
        acc_real += coeff[i]*(shift_reg_real_t[i] + shift_reg_real_t[TDELAY-1-i]);
        acc_imag += coeff[i]*(shift_reg_imag_t[i] + shift_reg_imag_t[TDELAY-1-i]);
    }

    //Shift all top values.
    MemUpdateTop:
    for (int i = TDELAY-1; i > 0; i--)
    {
        shift_reg_real_t[i] = shift_reg_real_t[i-1];
        shift_reg_imag_t[i] = shift_reg_imag_t[i-1];
    }

    //Shift all bottom values.
    MemUpdateBottom:
    for (int i = BDELAY-1; i > 0; i--)
    {
        shift_reg_real_b[i] = shift_reg_real_b[i-1];
        shift_reg_imag_b[i] = shift_reg_imag_b[i-1];
    }

    //Store output values.
    out->write_nb(acc_real + shift_reg_real_b[BDELAY-1]);
    out->write_nb(acc_imag + shift_reg_imag_b[BDELAY-1]);
}