Real Time FIR Filter - Distinctive Excellence award winner :)

Dependencies:   mbed

main.c

Committer:
Gonzakpo
Date:
2011-08-13
Revision:
0:b3e50e98acac

File content as of revision 0:b3e50e98acac:

/*
==============================================================================================
 Name                        : QuiPad
 Contest Registration Number : NXP3854
 Description                 : Real time FIR filter controlled by a touchpad
==============================================================================================
*/

#include "mbed.h"
#include "cr_dsplib.h"
#include "filters.h"
#include "dma.h"
#include "adc_dac.h"
#include "timer.h"
#include "config.h"
#include "touchpad.h"
#include "leds_mbed.h"


#define init_ahb_ram0 0x2007c000
#define mid_ahb_ram0 0x2007DE00
#define init_ahb_ram1 0x20080000
#define mid_ahb_ram1 0x20081E00

/*Los buffers y listas de guardan en la memoria AHB SRAM*/
/*Esto es porque esta seccion de la memoria tiene menor tiempo de accesso*/
/*Los buffer del DAC tienen 3 muestras extra por un detalle del algoritmo de filtrado */
/*Esas tres muestras son descartadas luego al ser ignoradas por el DMA */
int dac_buff_ping[BLOCKSIZE+3] __attribute__ ((at(init_ahb_ram0))); /*Buffers de datos para el DAC*/
int dac_buff_pong[BLOCKSIZE+3] __attribute__ ((at(init_ahb_ram1)));
int adc_buff_ping[(COEFF_AMOUNT-1)+BLOCKSIZE] __attribute__ ((at(mid_ahb_ram0))); /*Buffers de datos para el ADC*/
int adc_buff_pong[(COEFF_AMOUNT-1)+BLOCKSIZE] __attribute__ ((at(mid_ahb_ram1)));
/* Los buffers estan distribuidos de tal forma que el filtrado de datos se realice solo en una
 * memoria SRAM a la vez y no estorbe la otra. De la misma forma, el DMA usa la otra memoria unicamente.
 * Asi logro que el DMA y el filtrado no compitan por la memoria y acelero el filtrado.
 */

int main(void)
{
    tS_blockfir32_Coeff filter_pad;

    int i;

    /* La declaro como static para que se almacene en RAM */
    static int filterRAM[256];

    /* Estructura para obtencion de coordenadas */
    touchpad_position current_position, prev_position, valid_position;

    valid_position.pos_x = 0;
    valid_position.pos_y = 0;

    /* Inicializacio DMA */

    static dmaLinkedListNode DACdmaList[2];    /*Lista del DMA del DAC*/
    static dmaLinkedListNode ADCdmaList[2];    /*Lista del DMA del ADC*/

    dmaLinkedListNode *pNodeDACping = &(DACdmaList[0]);
    dmaLinkedListNode *pNodeDACpong = &(DACdmaList[1]);
    dmaLinkedListNode *pNodeADCping = &(ADCdmaList[0]);
    dmaLinkedListNode *pNodeADCpong = &(ADCdmaList[1]);

    /* Configuro los nodos de las listas de los canales DMA */

    /* Nodos del DMA que copia de la memoria al DAC */
    pNodeDACping->sourceAddr = (unsigned int) dac_buff_ping; /*Direccion inicial de lectura del buffer DAC*/
    pNodeDACping->destAddr = (unsigned int) &(LPC_DAC->DACR); /*Direccion del DAC*/
    pNodeDACping->nextNode = (unsigned int) pNodeDACpong; /*Proximo nodo de la lista*/
    pNodeDACping->dmaControl =  (unsigned int)BLOCKSIZE  | /*Numero de transferencias en total (BLOCKSIZE)*/
                               ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
                               ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
                               ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
                               ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
                               ((unsigned int)0x0 << 24) | /*Reservado*/
                               ((unsigned int)0x1 << 26) | /*Incrementar source address luego de cada transferencia*/
                               ((unsigned int)0x0 << 27) | /*No incrementar el destination address luego de cada transferencia*/
                               ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 31);  /*Deshabilito interrupcion de "transferencia completa"*/

    pNodeDACpong->sourceAddr = (unsigned int) dac_buff_pong; /*Direccion inicial de lectura del buffer DAC*/
    pNodeDACpong->destAddr = (unsigned int) &(LPC_DAC->DACR); /*Direccion del DAC*/
    pNodeDACpong->nextNode = (unsigned int) pNodeDACping; /*Proximo nodo de la lista*/
    pNodeDACpong->dmaControl =  (unsigned int)BLOCKSIZE  | /*Numero de transferencias en total (BLOCKSIZE)*/
                               ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
                               ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
                               ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
                               ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
                               ((unsigned int)0x0 << 24) | /*Reservado*/
                               ((unsigned int)0x1 << 26) | /*Incrementar source address luego de cada transferencia*/
                               ((unsigned int)0x0 << 27) | /*No incrementar el destination address luego de cada transferencia*/
                               ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
                               ((unsigned int)0x0 << 31);  /*Deshabilito interrupcion de "transferencia completa"*/

    /* Nodos del DMA que copia del ADC a la memoria */
    pNodeADCping->sourceAddr = (unsigned int) &(LPC_ADC->ADDR0); /*Direccion de los datos de salida del ADC*/
    pNodeADCping->destAddr = (unsigned int) &(adc_buff_ping[(COEFF_AMOUNT-1)]) ; /*Direccion del buffer del ADC*/
    pNodeADCping->nextNode = (unsigned int) pNodeADCpong; /*Proximo nodo de la lista*/
    pNodeADCping->dmaControl =  (unsigned int)BLOCKSIZE  | /*Numero de transferencias en total (BLOCKSIZE)*/
                               ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
                                  ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
                                  ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
                                  ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
                                  ((unsigned int)0x0 << 24) | /*Reservado*/
                                  ((unsigned int)0x0 << 26) | /*No Incrementar source address luego de cada transferencia*/
                                  ((unsigned int)0x1 << 27) | /*Incrementar el destination address luego de cada transferencia*/
                                  ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x1 << 31);  /*Habilito interrupcion de "transferencia completa"*/

    pNodeADCpong->sourceAddr = (unsigned int) &(LPC_ADC->ADDR0); /*Direccion de los datos de salida del ADC*/
    pNodeADCpong->destAddr = (unsigned int) &(adc_buff_pong[(COEFF_AMOUNT-1)]) ; /*Direccion del buffer del ADC*/
    pNodeADCpong->nextNode = (unsigned int) pNodeADCping; /*Proximo nodo de la lista*/
    pNodeADCpong->dmaControl =  (unsigned int)BLOCKSIZE  | /*Numero de transferencias en total (BLOCKSIZE)*/
                                  ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
                                  ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
                                  ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
                                  ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
                                  ((unsigned int)0x0 << 24) | /*Reservado*/
                                  ((unsigned int)0x0 << 26) | /*No Incrementar source address luego de cada transferencia*/
                                  ((unsigned int)0x1 << 27) | /*Incrementar el destination address luego de cada transferencia*/
                                 ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
                                  ((unsigned int)0x1 << 31);  /*Habilito interrupcion de "transferencia completa"*/

    /* Inicializo perifericos */
    init_touchpad();
    initADC();
    initDAC();
    initDMAs(pNodeADCping , pNodeDACping);
    init_timer();

    /* Una vez inicializado el sistema, se tienen que atender las interrupciones generadas por el
     * DMA (cuando se llenan los buffer) y llamar a la funcion de filtrado FIR. */

     /* Loop infinito. */
    while(1)
    {
        if(BufferTransferCompleted == TRUE)
        {
            BufferTransferCompleted = FALSE;

            /* Obtengo posicion del touchpad */
            current_position = get_position();

            /* Aplico filtrado al valor de posicion para evitar ruido */
            /* Verifico que la misma posicion se haya registrado dos veces seguidas */
            /* En caso negativo, la descarto */
            if ((prev_position.pos_x == current_position.pos_x) && (prev_position.pos_y == current_position.pos_y))
            {
                valid_position.pos_x = current_position.pos_x;
                valid_position.pos_y = current_position.pos_y;
            }

            prev_position.pos_x = current_position.pos_x;
            prev_position.pos_y = current_position.pos_y;

            show_number_on_leds(valid_position.pos_y);

            /* Copio el filtro a utilizar a la RAM (mejora el tiempo de filtrado) */
            for(i = 0; i < 256; i++)
            {
                /* filterRAM[i] = filters[valid_position.pos_x][valid_position.pos_y][i]; */
                /* Por ahora, a modo de ejemplo, solo utilizo la coordenada Y */
                filterRAM[i] = filters[valid_position.pos_y][i];
            }

            filter_pad.NTaps = filter_length;
            filter_pad.pi_Coeff = filterRAM;

            if(BufferToProcess == PING)
            {
                /* Copio las ultimas (COEFF-1) muestras del buffer ping al buffer pong */
                for(i=0; i < COEFF_AMOUNT-1; i++)
                {
                    adc_buff_pong[i] = adc_buff_ping[BLOCKSIZE + i];
                }
                /* Proceso el buffer adc_buff_ping y guardo resultados en dac_buff_ping */
                vF_dspl_blockfir32(dac_buff_ping, adc_buff_ping, &filter_pad, (COEFF_AMOUNT-1)+BLOCKSIZE);
            }
            else
            {
                /* Copio las ultimas (COEFF-1) muestras del buffer pong al buffer ping */
                for(i=0; i < COEFF_AMOUNT-1; i++)
                {
                    adc_buff_ping[i] = adc_buff_pong[BLOCKSIZE + i];
                }
                /* Proceso el buffer adc_buff_pong y guardo resultados en dac_buff_pong */
                vF_dspl_blockfir32(dac_buff_pong, adc_buff_pong, &filter_pad, (COEFF_AMOUNT-1)+BLOCKSIZE);
            }
           }
    }

    return 1 ; /* Si se llego aqui, hay un problema! */
}