Gonzalo Brusco
/
QuiPAD
Real Time FIR Filter - Distinctive Excellence award winner :)
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! */ }