09/05/15
Hace un par de años compre una tarjeta de desarrollo de Texas Instruments basada en el DSP TMS320C5515 para utilizarla en lugar de la PC como controlador del SDR y realizar también todas las funciones de modulación y demodulación.
En los últimos meses he invertido tiempo en leer, aprender y hacer algunas experiencias con esta tarjeta obteniendo ya algunos buenos resultados.
La programación por el momento la estoy realizando en Lenguaje C pero no descarto utilizar assembler en algunas funciones del código.
06/06/15
Esta es la primera versión del demodulador para SSB utilizando el metodo de desplazamiento de fase. Probado 100% en LSB , resta hacerlo en USB.
El código es similar al que expuse en otras paginas de este sitio pero este caso y por tratarse de un DSP que opera con aritmética en punto fijo, el código
fue adaptado para números enteros.
#include <usbstk5515.h>
#include "aic3204.h"
#define TAPS 81
extern Int16 ICirBuf[TAPS],QCirBuf[TAPS];
extern Int16 Sine[4],Cosine[4];
extern int CBPtr;
extern Int32 IFil81[TAPS];
extern Int32 QFil81[TAPS];
extern long I, Q;
extern Uint16 SBFlg;
extern unsigned int i2;
void SSBDem(Int16 InputI,Int16 InputQ){
unsigned int i1;
long Output;
asm(" bset XF");
ICirBuf[CBPtr] = (InputI * Cosine[i2])-(InputQ * Sine[i2]); /* Quadrature Mixer */
QCirBuf[CBPtr] = (InputQ * Cosine[i2])+(InputI * Sine[i2]); /* Audio x Bfo (4kHz)*/
if (++i2 == 4) /* Inc LO index2 - Has it reached the last value ? */
i2=0; /* If so, point index2 to the array's begin */
I=0;
Q=0;
if (++CBPtr == TAPS) /* Inc CBPtr - Has CBPtr passed the buffer's end ? */
CBPtr=0; /* If so, put CBPtr back to the buffer's begin */
for (i1=0; i1<TAPS; i1++){ /* Convolution */
I+=IFil81[i1] * (long)ICirBuf[CBPtr];
Q+=QFil81[i1] * (long)QCirBuf[CBPtr];
if (++CBPtr == TAPS)
CBPtr=0;
}
if (SBFlg){ // USB
Output=(I>>15)-(Q>>15);
}
else{ // LSB
Output=(I>>15)+(Q>>15);
}
if (Output > 32767)
Output = 32767;
else if (Output < -32768)
Output = -32768;
aic3204_codec_write(Output, Output);
asm(" bclr XF");
}
Coeficientes Filtros Pasabanda
Los valores de los coeficientes están expresados en formato Q15.
// BP Filter 300-3000Hz @ 16kHz - 0° phase shift
const signed Int32 IFil81[TAPS]={0,0,1,1,0,2,10,15,8,-8,-7,19,44,20,-46,-80,-27,53,23,-150,-303,-244,-36,4,-316,-735,-762,-319,7,-403,-1316,-1692,-896,249,91,-1837,-3641,-2477,2445,8389,11059,
8389,2445,-2477,-3641,-1837,91,249,-896,-1692,-1316,-403,7,-319,-762,-735,-316,4,-36,-244,-303,-150,23,53,-27,-80,-46,20,44,19,-7,-8,8,15,10,2,0,1,1,0,0};
// BP Filter 300-3000Hz @ 16kHz - 90° phase shift
const signed Int32 QFil81[TAPS]={0,0,-1,-2,-1,2,0,-11,-24,-22,-5,-1,-37,-91,-100,-43,4,-55,-196,-256,-125,64,45,-229,-435,-223,281,498,94,-453,-262,821,1758,1396,85,-181,2231,6328,8670,6350,0,
-6350,-8670,-6328,-2231,181,-85,-1396,-1758,-821,262,453,-94,-498,-281,223,435,229,-45,-64,125,256,196,55,-4,43,100,91,37,1,5,22,24,11,0,-2,1,2,1,0,0};
Valores Oscilador local - 4kHz @ 16kHz sampling rate.
const signed Int32 Sine[4]={0,1,0,-1};
const signed Int32 Cosine[4]={1,0,-1,0};
24/05/15
Hoy complete parte del código para generar una la señal de audio en cuadratura a partir de dos filtros (FIR) pasabanda de 300 a 3000Hz.
La principal función de este código es filtrar la señal de entrada (proveniente del micrófono) , limitar su ancho de banda y generar dos señales iguales en términos de componentes de frecuencias pero desfasadas 90° entre si.
El codigo de la funcion FIR() es el siguiente.
#include <usbstk5515.h>
#include "aic3204.h"
#define TAPS 81
extern Int16 ICirBuf[TAPS];
extern int CBPtr;
extern Int32 IFil81[TAPS];
extern Int32 QFil81[TAPS];
extern long I, Q;
void FIR(Int16 Input){
unsigned int i1;
ICirBuf[CBPtr] = (Input);
I=0;
Q=0;
if (++CBPtr == TAPS) /* Inc CBPtr - Has CBPtr passed the buffer's end ? */
CBPtr=0; /* If so, put CBPtr back to the buffer's begin */
for (i1=0; i1<TAPS; i1++){ /* Convolution */
I+=IFil81[i1] * (long)ICirBuf[CBPtr];
Q+=QFil81[i1] * (long)ICirBuf[CBPtr];
if (++CBPtr == TAPS)
CBPtr=0;
}
aic3204_codec_write(I>>15, Q>>15);
}
Referencias