Real Time FIR Filter - Distinctive Excellence award winner :)

Dependencies:   mbed

Committer:
Gonzakpo
Date:
Sat Aug 13 17:35:52 2011 +0000
Revision:
0:b3e50e98acac

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Gonzakpo 0:b3e50e98acac 1 /*
Gonzakpo 0:b3e50e98acac 2 ==============================================================================================
Gonzakpo 0:b3e50e98acac 3 Name : QuiPad
Gonzakpo 0:b3e50e98acac 4 Contest Registration Number : NXP3854
Gonzakpo 0:b3e50e98acac 5 Description : Real time FIR filter controlled by a touchpad
Gonzakpo 0:b3e50e98acac 6 ==============================================================================================
Gonzakpo 0:b3e50e98acac 7 */
Gonzakpo 0:b3e50e98acac 8
Gonzakpo 0:b3e50e98acac 9 #include "mbed.h"
Gonzakpo 0:b3e50e98acac 10 #include "cr_dsplib.h"
Gonzakpo 0:b3e50e98acac 11 #include "filters.h"
Gonzakpo 0:b3e50e98acac 12 #include "dma.h"
Gonzakpo 0:b3e50e98acac 13 #include "adc_dac.h"
Gonzakpo 0:b3e50e98acac 14 #include "timer.h"
Gonzakpo 0:b3e50e98acac 15 #include "config.h"
Gonzakpo 0:b3e50e98acac 16 #include "touchpad.h"
Gonzakpo 0:b3e50e98acac 17 #include "leds_mbed.h"
Gonzakpo 0:b3e50e98acac 18
Gonzakpo 0:b3e50e98acac 19
Gonzakpo 0:b3e50e98acac 20 #define init_ahb_ram0 0x2007c000
Gonzakpo 0:b3e50e98acac 21 #define mid_ahb_ram0 0x2007DE00
Gonzakpo 0:b3e50e98acac 22 #define init_ahb_ram1 0x20080000
Gonzakpo 0:b3e50e98acac 23 #define mid_ahb_ram1 0x20081E00
Gonzakpo 0:b3e50e98acac 24
Gonzakpo 0:b3e50e98acac 25 /*Los buffers y listas de guardan en la memoria AHB SRAM*/
Gonzakpo 0:b3e50e98acac 26 /*Esto es porque esta seccion de la memoria tiene menor tiempo de accesso*/
Gonzakpo 0:b3e50e98acac 27 /*Los buffer del DAC tienen 3 muestras extra por un detalle del algoritmo de filtrado */
Gonzakpo 0:b3e50e98acac 28 /*Esas tres muestras son descartadas luego al ser ignoradas por el DMA */
Gonzakpo 0:b3e50e98acac 29 int dac_buff_ping[BLOCKSIZE+3] __attribute__ ((at(init_ahb_ram0))); /*Buffers de datos para el DAC*/
Gonzakpo 0:b3e50e98acac 30 int dac_buff_pong[BLOCKSIZE+3] __attribute__ ((at(init_ahb_ram1)));
Gonzakpo 0:b3e50e98acac 31 int adc_buff_ping[(COEFF_AMOUNT-1)+BLOCKSIZE] __attribute__ ((at(mid_ahb_ram0))); /*Buffers de datos para el ADC*/
Gonzakpo 0:b3e50e98acac 32 int adc_buff_pong[(COEFF_AMOUNT-1)+BLOCKSIZE] __attribute__ ((at(mid_ahb_ram1)));
Gonzakpo 0:b3e50e98acac 33 /* Los buffers estan distribuidos de tal forma que el filtrado de datos se realice solo en una
Gonzakpo 0:b3e50e98acac 34 * memoria SRAM a la vez y no estorbe la otra. De la misma forma, el DMA usa la otra memoria unicamente.
Gonzakpo 0:b3e50e98acac 35 * Asi logro que el DMA y el filtrado no compitan por la memoria y acelero el filtrado.
Gonzakpo 0:b3e50e98acac 36 */
Gonzakpo 0:b3e50e98acac 37
Gonzakpo 0:b3e50e98acac 38 int main(void)
Gonzakpo 0:b3e50e98acac 39 {
Gonzakpo 0:b3e50e98acac 40 tS_blockfir32_Coeff filter_pad;
Gonzakpo 0:b3e50e98acac 41
Gonzakpo 0:b3e50e98acac 42 int i;
Gonzakpo 0:b3e50e98acac 43
Gonzakpo 0:b3e50e98acac 44 /* La declaro como static para que se almacene en RAM */
Gonzakpo 0:b3e50e98acac 45 static int filterRAM[256];
Gonzakpo 0:b3e50e98acac 46
Gonzakpo 0:b3e50e98acac 47 /* Estructura para obtencion de coordenadas */
Gonzakpo 0:b3e50e98acac 48 touchpad_position current_position, prev_position, valid_position;
Gonzakpo 0:b3e50e98acac 49
Gonzakpo 0:b3e50e98acac 50 valid_position.pos_x = 0;
Gonzakpo 0:b3e50e98acac 51 valid_position.pos_y = 0;
Gonzakpo 0:b3e50e98acac 52
Gonzakpo 0:b3e50e98acac 53 /* Inicializacio DMA */
Gonzakpo 0:b3e50e98acac 54
Gonzakpo 0:b3e50e98acac 55 static dmaLinkedListNode DACdmaList[2]; /*Lista del DMA del DAC*/
Gonzakpo 0:b3e50e98acac 56 static dmaLinkedListNode ADCdmaList[2]; /*Lista del DMA del ADC*/
Gonzakpo 0:b3e50e98acac 57
Gonzakpo 0:b3e50e98acac 58 dmaLinkedListNode *pNodeDACping = &(DACdmaList[0]);
Gonzakpo 0:b3e50e98acac 59 dmaLinkedListNode *pNodeDACpong = &(DACdmaList[1]);
Gonzakpo 0:b3e50e98acac 60 dmaLinkedListNode *pNodeADCping = &(ADCdmaList[0]);
Gonzakpo 0:b3e50e98acac 61 dmaLinkedListNode *pNodeADCpong = &(ADCdmaList[1]);
Gonzakpo 0:b3e50e98acac 62
Gonzakpo 0:b3e50e98acac 63 /* Configuro los nodos de las listas de los canales DMA */
Gonzakpo 0:b3e50e98acac 64
Gonzakpo 0:b3e50e98acac 65 /* Nodos del DMA que copia de la memoria al DAC */
Gonzakpo 0:b3e50e98acac 66 pNodeDACping->sourceAddr = (unsigned int) dac_buff_ping; /*Direccion inicial de lectura del buffer DAC*/
Gonzakpo 0:b3e50e98acac 67 pNodeDACping->destAddr = (unsigned int) &(LPC_DAC->DACR); /*Direccion del DAC*/
Gonzakpo 0:b3e50e98acac 68 pNodeDACping->nextNode = (unsigned int) pNodeDACpong; /*Proximo nodo de la lista*/
Gonzakpo 0:b3e50e98acac 69 pNodeDACping->dmaControl = (unsigned int)BLOCKSIZE | /*Numero de transferencias en total (BLOCKSIZE)*/
Gonzakpo 0:b3e50e98acac 70 ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
Gonzakpo 0:b3e50e98acac 71 ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
Gonzakpo 0:b3e50e98acac 72 ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
Gonzakpo 0:b3e50e98acac 73 ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
Gonzakpo 0:b3e50e98acac 74 ((unsigned int)0x0 << 24) | /*Reservado*/
Gonzakpo 0:b3e50e98acac 75 ((unsigned int)0x1 << 26) | /*Incrementar source address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 76 ((unsigned int)0x0 << 27) | /*No incrementar el destination address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 77 ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 78 ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 79 ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 80 ((unsigned int)0x0 << 31); /*Deshabilito interrupcion de "transferencia completa"*/
Gonzakpo 0:b3e50e98acac 81
Gonzakpo 0:b3e50e98acac 82 pNodeDACpong->sourceAddr = (unsigned int) dac_buff_pong; /*Direccion inicial de lectura del buffer DAC*/
Gonzakpo 0:b3e50e98acac 83 pNodeDACpong->destAddr = (unsigned int) &(LPC_DAC->DACR); /*Direccion del DAC*/
Gonzakpo 0:b3e50e98acac 84 pNodeDACpong->nextNode = (unsigned int) pNodeDACping; /*Proximo nodo de la lista*/
Gonzakpo 0:b3e50e98acac 85 pNodeDACpong->dmaControl = (unsigned int)BLOCKSIZE | /*Numero de transferencias en total (BLOCKSIZE)*/
Gonzakpo 0:b3e50e98acac 86 ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
Gonzakpo 0:b3e50e98acac 87 ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
Gonzakpo 0:b3e50e98acac 88 ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
Gonzakpo 0:b3e50e98acac 89 ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
Gonzakpo 0:b3e50e98acac 90 ((unsigned int)0x0 << 24) | /*Reservado*/
Gonzakpo 0:b3e50e98acac 91 ((unsigned int)0x1 << 26) | /*Incrementar source address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 92 ((unsigned int)0x0 << 27) | /*No incrementar el destination address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 93 ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 94 ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 95 ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 96 ((unsigned int)0x0 << 31); /*Deshabilito interrupcion de "transferencia completa"*/
Gonzakpo 0:b3e50e98acac 97
Gonzakpo 0:b3e50e98acac 98 /* Nodos del DMA que copia del ADC a la memoria */
Gonzakpo 0:b3e50e98acac 99 pNodeADCping->sourceAddr = (unsigned int) &(LPC_ADC->ADDR0); /*Direccion de los datos de salida del ADC*/
Gonzakpo 0:b3e50e98acac 100 pNodeADCping->destAddr = (unsigned int) &(adc_buff_ping[(COEFF_AMOUNT-1)]) ; /*Direccion del buffer del ADC*/
Gonzakpo 0:b3e50e98acac 101 pNodeADCping->nextNode = (unsigned int) pNodeADCpong; /*Proximo nodo de la lista*/
Gonzakpo 0:b3e50e98acac 102 pNodeADCping->dmaControl = (unsigned int)BLOCKSIZE | /*Numero de transferencias en total (BLOCKSIZE)*/
Gonzakpo 0:b3e50e98acac 103 ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
Gonzakpo 0:b3e50e98acac 104 ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
Gonzakpo 0:b3e50e98acac 105 ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
Gonzakpo 0:b3e50e98acac 106 ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
Gonzakpo 0:b3e50e98acac 107 ((unsigned int)0x0 << 24) | /*Reservado*/
Gonzakpo 0:b3e50e98acac 108 ((unsigned int)0x0 << 26) | /*No Incrementar source address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 109 ((unsigned int)0x1 << 27) | /*Incrementar el destination address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 110 ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 111 ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 112 ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 113 ((unsigned int)0x1 << 31); /*Habilito interrupcion de "transferencia completa"*/
Gonzakpo 0:b3e50e98acac 114
Gonzakpo 0:b3e50e98acac 115 pNodeADCpong->sourceAddr = (unsigned int) &(LPC_ADC->ADDR0); /*Direccion de los datos de salida del ADC*/
Gonzakpo 0:b3e50e98acac 116 pNodeADCpong->destAddr = (unsigned int) &(adc_buff_pong[(COEFF_AMOUNT-1)]) ; /*Direccion del buffer del ADC*/
Gonzakpo 0:b3e50e98acac 117 pNodeADCpong->nextNode = (unsigned int) pNodeADCping; /*Proximo nodo de la lista*/
Gonzakpo 0:b3e50e98acac 118 pNodeADCpong->dmaControl = (unsigned int)BLOCKSIZE | /*Numero de transferencias en total (BLOCKSIZE)*/
Gonzakpo 0:b3e50e98acac 119 ((unsigned int)0x0 << 12) | /*Numero de transferencias por burst de origen (1)*/
Gonzakpo 0:b3e50e98acac 120 ((unsigned int)0x0 << 15) | /*Numero de transferencias por burst de destino (1)*/
Gonzakpo 0:b3e50e98acac 121 ((unsigned int)0x2 << 18) | /*Ancho de bus de origen de 32 bits */
Gonzakpo 0:b3e50e98acac 122 ((unsigned int)0x2 << 21) | /*Ancho de bus de destino de 32 bits */
Gonzakpo 0:b3e50e98acac 123 ((unsigned int)0x0 << 24) | /*Reservado*/
Gonzakpo 0:b3e50e98acac 124 ((unsigned int)0x0 << 26) | /*No Incrementar source address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 125 ((unsigned int)0x1 << 27) | /*Incrementar el destination address luego de cada transferencia*/
Gonzakpo 0:b3e50e98acac 126 ((unsigned int)0x0 << 28) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 127 ((unsigned int)0x0 << 29) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 128 ((unsigned int)0x0 << 30) | /*No usado en el LPC17xx*/
Gonzakpo 0:b3e50e98acac 129 ((unsigned int)0x1 << 31); /*Habilito interrupcion de "transferencia completa"*/
Gonzakpo 0:b3e50e98acac 130
Gonzakpo 0:b3e50e98acac 131 /* Inicializo perifericos */
Gonzakpo 0:b3e50e98acac 132 init_touchpad();
Gonzakpo 0:b3e50e98acac 133 initADC();
Gonzakpo 0:b3e50e98acac 134 initDAC();
Gonzakpo 0:b3e50e98acac 135 initDMAs(pNodeADCping , pNodeDACping);
Gonzakpo 0:b3e50e98acac 136 init_timer();
Gonzakpo 0:b3e50e98acac 137
Gonzakpo 0:b3e50e98acac 138 /* Una vez inicializado el sistema, se tienen que atender las interrupciones generadas por el
Gonzakpo 0:b3e50e98acac 139 * DMA (cuando se llenan los buffer) y llamar a la funcion de filtrado FIR. */
Gonzakpo 0:b3e50e98acac 140
Gonzakpo 0:b3e50e98acac 141 /* Loop infinito. */
Gonzakpo 0:b3e50e98acac 142 while(1)
Gonzakpo 0:b3e50e98acac 143 {
Gonzakpo 0:b3e50e98acac 144 if(BufferTransferCompleted == TRUE)
Gonzakpo 0:b3e50e98acac 145 {
Gonzakpo 0:b3e50e98acac 146 BufferTransferCompleted = FALSE;
Gonzakpo 0:b3e50e98acac 147
Gonzakpo 0:b3e50e98acac 148 /* Obtengo posicion del touchpad */
Gonzakpo 0:b3e50e98acac 149 current_position = get_position();
Gonzakpo 0:b3e50e98acac 150
Gonzakpo 0:b3e50e98acac 151 /* Aplico filtrado al valor de posicion para evitar ruido */
Gonzakpo 0:b3e50e98acac 152 /* Verifico que la misma posicion se haya registrado dos veces seguidas */
Gonzakpo 0:b3e50e98acac 153 /* En caso negativo, la descarto */
Gonzakpo 0:b3e50e98acac 154 if ((prev_position.pos_x == current_position.pos_x) && (prev_position.pos_y == current_position.pos_y))
Gonzakpo 0:b3e50e98acac 155 {
Gonzakpo 0:b3e50e98acac 156 valid_position.pos_x = current_position.pos_x;
Gonzakpo 0:b3e50e98acac 157 valid_position.pos_y = current_position.pos_y;
Gonzakpo 0:b3e50e98acac 158 }
Gonzakpo 0:b3e50e98acac 159
Gonzakpo 0:b3e50e98acac 160 prev_position.pos_x = current_position.pos_x;
Gonzakpo 0:b3e50e98acac 161 prev_position.pos_y = current_position.pos_y;
Gonzakpo 0:b3e50e98acac 162
Gonzakpo 0:b3e50e98acac 163 show_number_on_leds(valid_position.pos_y);
Gonzakpo 0:b3e50e98acac 164
Gonzakpo 0:b3e50e98acac 165 /* Copio el filtro a utilizar a la RAM (mejora el tiempo de filtrado) */
Gonzakpo 0:b3e50e98acac 166 for(i = 0; i < 256; i++)
Gonzakpo 0:b3e50e98acac 167 {
Gonzakpo 0:b3e50e98acac 168 /* filterRAM[i] = filters[valid_position.pos_x][valid_position.pos_y][i]; */
Gonzakpo 0:b3e50e98acac 169 /* Por ahora, a modo de ejemplo, solo utilizo la coordenada Y */
Gonzakpo 0:b3e50e98acac 170 filterRAM[i] = filters[valid_position.pos_y][i];
Gonzakpo 0:b3e50e98acac 171 }
Gonzakpo 0:b3e50e98acac 172
Gonzakpo 0:b3e50e98acac 173 filter_pad.NTaps = filter_length;
Gonzakpo 0:b3e50e98acac 174 filter_pad.pi_Coeff = filterRAM;
Gonzakpo 0:b3e50e98acac 175
Gonzakpo 0:b3e50e98acac 176 if(BufferToProcess == PING)
Gonzakpo 0:b3e50e98acac 177 {
Gonzakpo 0:b3e50e98acac 178 /* Copio las ultimas (COEFF-1) muestras del buffer ping al buffer pong */
Gonzakpo 0:b3e50e98acac 179 for(i=0; i < COEFF_AMOUNT-1; i++)
Gonzakpo 0:b3e50e98acac 180 {
Gonzakpo 0:b3e50e98acac 181 adc_buff_pong[i] = adc_buff_ping[BLOCKSIZE + i];
Gonzakpo 0:b3e50e98acac 182 }
Gonzakpo 0:b3e50e98acac 183 /* Proceso el buffer adc_buff_ping y guardo resultados en dac_buff_ping */
Gonzakpo 0:b3e50e98acac 184 vF_dspl_blockfir32(dac_buff_ping, adc_buff_ping, &filter_pad, (COEFF_AMOUNT-1)+BLOCKSIZE);
Gonzakpo 0:b3e50e98acac 185 }
Gonzakpo 0:b3e50e98acac 186 else
Gonzakpo 0:b3e50e98acac 187 {
Gonzakpo 0:b3e50e98acac 188 /* Copio las ultimas (COEFF-1) muestras del buffer pong al buffer ping */
Gonzakpo 0:b3e50e98acac 189 for(i=0; i < COEFF_AMOUNT-1; i++)
Gonzakpo 0:b3e50e98acac 190 {
Gonzakpo 0:b3e50e98acac 191 adc_buff_ping[i] = adc_buff_pong[BLOCKSIZE + i];
Gonzakpo 0:b3e50e98acac 192 }
Gonzakpo 0:b3e50e98acac 193 /* Proceso el buffer adc_buff_pong y guardo resultados en dac_buff_pong */
Gonzakpo 0:b3e50e98acac 194 vF_dspl_blockfir32(dac_buff_pong, adc_buff_pong, &filter_pad, (COEFF_AMOUNT-1)+BLOCKSIZE);
Gonzakpo 0:b3e50e98acac 195 }
Gonzakpo 0:b3e50e98acac 196 }
Gonzakpo 0:b3e50e98acac 197 }
Gonzakpo 0:b3e50e98acac 198
Gonzakpo 0:b3e50e98acac 199 return 1 ; /* Si se llego aqui, hay un problema! */
Gonzakpo 0:b3e50e98acac 200 }