Gonzalo Brusco
/
QuiPAD
Real Time FIR Filter - Distinctive Excellence award winner :)
Diff: main.c
- Revision:
- 0:b3e50e98acac
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.c Sat Aug 13 17:35:52 2011 +0000 @@ -0,0 +1,200 @@ +/* +============================================================================================== + 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! */ +}