/* Floating Point FIR Digital Filter Implementation */
/* EC581 Digital Signal Processing Laboratory       */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Mcbspdrv.h>
#include <Common.h>
#include <Intr.h>
#include <Board.h>
#include <Codec.h>
#include <Mcbsp.h>
#include <mathf.h>    

float	coeff[20],x[20];    /* coeff array holds FIR filter coeffs */
int	Norder;                 /* x array holds past input samples    */
void hookint(void);
interrupt void McBSPRcvISR(void);  

int main()
{   
   Mcbsp_dev dev;
    Mcbsp_config mcbspConfig;
    int sampleRate,Actual_Sampling_Rate;   
       
 /* Band-Stop Filter Coefficients Cut From MATLAB 
    B =

  Columns 1 through 7 

   -0.0038    0.0000    0.0218    0.0000   -0.0821    0.0000    0.1625

  Columns 8 through 14 

    0.0000    0.8031    0.0000    0.1625    0.0000   -0.0821    0.0000

  Columns 15 through 17 

    0.0218    0.0000   -0.0038    
  */     
       
      coeff[0] = -0.0038;      /* Here are the 17 coefficients corresponding  */
	coeff[1] =  0.0000 ;     /* to a 16th-order FIR Band Stop FIR filter    */
	coeff[2] =  0.0218;      /* FIR filter obtained using MATLAB FIR1       */
	coeff[3] =  0.0000;      /* Fs = 8 kHz, stop band between 1.6 kHz and   */
	coeff[4] = -0.0821;      /* 2.4 kHz.                                    */                               
	coeff[5] =  0.0000;
	coeff[6] =  0.1625;
	coeff[7] =  0.0000;
	coeff[8] =  0.8031;
	coeff[9] =  0.0000;
	coeff[10] = 0.1625;  
	coeff[11] = 0.0000;
	coeff[12] =-0.0821;
	coeff[13] = 0.0000;
	coeff[14] = 0.0218;
	coeff[15] = 0.0000;
	coeff[16] =-0.0038;  
	

    /******************************************************/
    /* Initialize EVM                                     */
    /******************************************************/  
    printf("Initializing EVM board\n");
    evm_init();     
    printf("Done initializing EVM\n");
    /******************************************************/
    /* Open MCBSP                                         */
    /******************************************************/
    mcbsp_drv_init();   /* initialize McBSP driver, allocates memory for 
                           the device handles */
    dev=mcbsp_open(0);  /* dev is the handle to control the McBSP */
    if(dev==NULL)
    {
        printf("Error Opening MCBSP 0\n");
        return(ERROR);
    }
    /******************************************************/
    /* Configure McBSP                                    */
    /******************************************************/
    memset(&mcbspConfig,0,sizeof(mcbspConfig));
    mcbspConfig.loopback            =FALSE;
    mcbspConfig.tx.update           =TRUE;
    mcbspConfig.tx.clock_mode       =CLK_MODE_EXT;
    mcbspConfig.tx.frame_length1    =0;
    mcbspConfig.tx.word_length1     =WORD_LENGTH_32;
    mcbspConfig.rx.update           =TRUE;
    mcbspConfig.rx.clock_mode       =CLK_MODE_EXT;
    mcbspConfig.rx.frame_length1    =0;
    mcbspConfig.rx.word_length1     =WORD_LENGTH_32;
    mcbsp_config(dev,&mcbspConfig); /* configuration adjustments */
    MCBSP_ENABLE(0,MCBSP_BOTH);         /* McBSP is activated */
    /******************************************************/
    /* Configure CODEC                                    */
    /******************************************************/
    codec_init();
    /* A/D 0.0dB (min) gain, turn OFF 20dB mic gain, sel(L/R)LINE input */
    /* Set codec for stereo mode of operation */
    codec_adc_control(LEFT,MIN_ADC_INPUT_GAIN,FALSE,LINE_SEL);
    codec_adc_control(RIGHT,MIN_ADC_INPUT_GAIN,FALSE,LINE_SEL);
    /* MUTE(L/R)LINE input to “DSP Bypass Path” by setting mute switch to TRUE */
    codec_line_in_control(LEFT,MIN_AUX_LINE_GAIN,TRUE);
    codec_line_in_control(RIGHT,MIN_AUX_LINE_GAIN,TRUE);
    /* D/A 0.0dB attenuation, do not mute DAC outputs */
    codec_dac_control(LEFT,0.0,FALSE);
    codec_dac_control(RIGHT,0.0,FALSE);  
    
    sampleRate=8000;
    Actual_Sampling_Rate = codec_change_sample_rate(sampleRate,TRUE);  
    /* set to the closest allowed rate */
    printf("The actual sampling rate is = %d\n",Actual_Sampling_Rate);
    hookint(); 
    codec_interrupt_enable();   
    /* codec generates interrupts when data are received in the DRR */   
    /******************************************************/
    /* Main Loop, wait for Interrupt                      */
    /******************************************************/    
    Norder = 16;
    while(1)
    {
    }
}

void hookint()
{
    /* an interrupt is assigned to DRR event of the serial port
       then, the interrupt will branch to ISP */
    intr_init();    /* initialize ISTP with the address of vec_table.  
                Placing the base address of the vector table in ISTP */
    intr_map(CPU_INT15,ISN_RINT0);  /* map CPU_INT15 to DRR interrupt */
    intr_hook(McBSPRcvISR,CPU_INT15);  /* connect ISR to the CPU_INT15 */
    INTR_ENABLE(15);
    INTR_GLOBAL_ENABLE();
    return;
}

interrupt void McBSPRcvISR(void)
{
    /* ISR for the DRR interrupt */
    /*
         This routine convolves the present and the Norder previous input 
         samples with the “Norder+1” FIR coefficients  h(0) through h(Norder):

                        y(n) = h(0)*x(n) + h(1)*x(n-1) + ... + h(Norder)*x(n-Norder)

    */
    int intsamp,i;
    float floatsamp,sum;    
    
    intsamp=MCBSP_READ(0);     /* read from CODEC’s data receive register (DRR) */  
    intsamp = (intsamp >>16);  /* Shift right channel data down to bottom 16 bits */
    if(intsamp & 0x8000) 
        intsamp = intsamp | 0xffff0000;      /* Sign extend right channel data */
    floatsamp = (float) intsamp;       /* Convert right channel to floating point */
    
    for(i=Norder; i >= 0;i--)             /* Update past input sample array, where
                                          x[0] holds present sample, x[1] holds 
                                          sample from 1 sample period ago, x[N]
                                          holds sample from N sampling periods ago*/
       {                                  /* This time-consuming loop could be    */
        x[i]=x[i-1];                      /* eliminated if circular buffering were*/
       }                                  /* to be employed.                      */
    x[0] = floatsamp;
    sum = 0;
    for(i=0;i<=Norder;i++)                 /* Perform FIR filtering (convolution) */
      {
         sum=sum+x[i]*coeff[i];
      }    
    
    
    intsamp = (int) sum;        /* Convert result back to integer form     */
    intsamp = intsamp << 16;    /* Shift result back into Right Channel position
                                   while zeroing the Left Channel position */
    MCBSP_WRITE(0,intsamp);     /* Send to CODEC (right channel only)      */
}
