Estoy utilizando una placa Microstick II con el PIC32MX250F128B incluido y me gustaría realizar el procesamiento de audio en tiempo real. Utilizo una entrada analógica para obtener el sonido de entrada y una salida PWM, en combinación con un filtro de paso bajo seguido de un amplificador, como mi salida de audio (conectada a los auriculares).
Lo que me gustaría hacer es realizar un procesamiento de señales más avanzado, como el filtrado, etc. El sitio web de Microchip dice que hay una DSP Library dedicada a eso. Puede encontrar el manual de lib aquí , pero no hay mucha Información en ella, solo algunos prototipos de funciones ...
Por primera vez, me gustaría realizar el filtrado de paso bajo y paso de banda. Hasta ahora, conseguí realizar fft usando el siguiente código:
// include header files
#include <plib.h>
#include <p32xxxx.h>
#include <dsplib_dsp.h>
#include <fftc.h>
// Config Bits
#pragma config FNOSC = FRCPLL // Internal Fast RC oscillator (8 MHz) w/ PLL
#pragma config FPLLIDIV = DIV_2 // Divide FRC before PLL (now 4 MHz)
#pragma config FPLLMUL = MUL_20 // PLL Multiply (now 80 MHz)
#pragma config FPLLODIV = DIV_2 // Divide After PLL (now 40 MHz)
#pragma config FWDTEN = OFF // Watchdog Timer Disabled
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (pins 4,5)
#pragma config JTAGEN = OFF // Disable JTAG
#pragma config FSOSCEN = OFF // Disable Secondary Oscillator
// Defines
#define fftc fft16c64 // from fftc.h, for N = 64
#define SYSCLK (40000000L)
#define SAMPLES 64
#define PWM_FREQ 48000 // Output PWM frequency
#define DUTY_CYCLE 1
int tab[SAMPLES];
int i = 0;
int analogRead(char analogPIN)
{
AD1CHS = analogPIN << 16; // AD1CHS<16:19> controls which analog pin goes to the ADC
AD1CON1bits.SAMP = 1; // Sampling
while(AD1CON1bits.SAMP); // wait until acquisition is done
while(!AD1CON1bits.DONE); // wait until conversion done
return ADC1BUF0;
}
void adcConfigureManual()
{
AD1CON1CLR = 0x8000; // disable ADC before configuration
AD1CON1 = 0x00E0; // internal counter ends sampling and starts conversion (manual sample)
AD1CON2 = 0; // AD1CON2<15:13> set voltage reference to pins AVSS/AVDD
// Found on the web (todo: check the datasheet)
AD1CON3 = 0x0f01; // TAD = 4*TPB, acquisition time = 15*TAD
}
int main( void)
{
SYSTEMConfigPerformance(SYSCLK);
// Set OC1 to pin 2 with peripheral pin select
RPA0Rbits.RPA0R = 0x0005;
// Configure standard PWM mode for output compare module 1
OC1CON = 0x0006;
for(i = 0; i<SAMPLES; i++)
tab[i] = 0;
// From datasheet:
// PR = [FPB / (PWM Frequency * TMR Prescale Value)] – 1
PR2 = (SYSCLK / PWM_FREQ) - 1;
// Initial duty cycle value
OC1RS = (PR2 + 1) * ((float)DUTY_CYCLE / 100);
T2CONSET = 0x8000; // Enable Timer2, prescaler 1:1
OC1CONSET = 0x8000; // Enable Output Compare Module 1
// Configure pins as analog inputs
ANSELBbits.ANSB3 = 1; // set RB3 (AN5) to analog
TRISBbits.TRISB3 = 1; // set RB3 as an input
TRISBbits.TRISB5 = 0; // set RB5 as an output (note RB5 is a digital only pin)
adcConfigureManual(); // Configure ADC
AD1CON1SET = 0x8000; // Enable ADC
int pos=0, dat = 0;
int log2N = 6; // log2(64) = 6
int N = 1 << log2N; // N = 2^6 = 64
int din[N];
int dout[N];
int dout2[N];
int scratch[N];
while(1)
{
//foo = analogRead 5); // note that we call pin AN5 (RB3) by it's analog number
dat = analogRead(5);
//dat += din[pos]*3/10;
//if(dat > 1023) dat -= 512;
din[pos] = dat;
mips_fft16(dout, din, fftc, scratch, 1);
mips_fft16(dout2, dout, fftc, scratch, 1);
if(++pos >= SAMPLES) pos = 0;
OC1RS = (PR2 + 1) * ( ((float)dout2[pos])/1023); // Write new duty cycle
}
return 0;
}
En primer lugar, me gustaría saber si lo que estoy haciendo es correcto. Quiero decir, no hay una función ifft, ¿el segundo fft realiza un ifft?
En segundo lugar, al hacer esto, puedo escuchar un sonido de alta frecuencia, que puede resultar de una latencia que retrasa el cambio del ciclo de trabajo de PWM OC1RS
.
Cómo puedo arreglar esto ? Vi que la gente usualmente utiliza Timer2 para cambiar el ciclo de trabajo, pero cada vez que lo intento, no obtengo nada en la salida (no hay sonido).
¿Cómo puedo implementar esto en mi caso?