Exemplo de sofware DSP para SDR

Por PY4ZBZ  02-04-2009

 

 

O fantástico utilitário BasicDSP de PA3FWM e PE1OIT permite fazer inúmeros testes de software de processamento digital DSP, sem precisar se preocupar com rotinas de acesso a placa de som. Basta escrever o código DSP desejado, usando as variáveis e funções disponíveis. 

Meu primeiro software SDR é de um demodulador SSB (USB e LSB) com AGC, para ser usado em conjunto com um hardware SDR como por exemplo o SDRZero. Os sinais I e Q produzidos pelo SDRZero são aplicados na entrada estereo da placa de som, sendo I no canal direito e Q no esquerdo. Comentarei, com ilustrações feitas com o próprio BasicDSP, o programa exemplo.

O BasicDSP contém um osciloscópio e um analisador de espectro, ambos de dois canais, com os quais podemos observar qualquer variável. Por exemplo, a figura seguinte é da tela do analisador de espectro, que mostra as variaveis inl = I , em amarelo, e out = áudio de saída, em azul, do meu programa. Podemos ver que no sinal I fornecido pelo SDRZero temos três sinais de SSB (um entre 9 e 11, outro entre 11 e 13 e outro entre 20 e 23 kHz, aproximadamente). Podemos ver também que o sinal de áudio demodulado tem espectro igual ao do sinal entre 11 e 13 kHz. Para ver qualquer variável basta entrar o seu nome nos retângulos amarelo e azul.

A figura seguinte mostra o diagrama em blocos das funções realizadas pelo programa RX_SSB_PY4ZBZ.dsp ao ser executado pelo BasicDSP :

 

O conteúdo do programa é reproduzido e comentado a seguir:

( Uma linha iniciada por # é um comentário, não processado...)

# Programa Demodulador SSB para o BasicDSP

# por PY4ZBZ

# Os sinais de entrada inr (I) e inl (Q) devem ser obtidos de um QSD,
# detetor por amostragem em quadratura, como por exemplo de um SDRZero.

# O demodulador assume que o SDR esteja sintonizado de tal
# forma a ter o sinal de entrada desejado centrado em 12 kHz

# O cursor 1 (slider 1) permite mudar de USB para LSB
# mudando a frequencia do oscilador local entre 10,5 (cursor em 0)
# e 13,5 kHz (cursor em 1), respectivamente


# Definição da taxa de amostragem da placa de som:
samplerate=48000

# Os coeficientes dos filtros digitais FIR foram calculados com:
#
http://mshook.googlepages.com/firkernel.htm

A resposta em freqüência dos filtros passa-faixa é a curva amarela seguinte. A curva azul é do filtro passa-baixo, usado mais adiante:



# Primeiro, os sinais I e Q passam cada um por um filtro passa-faixa,
# que determina a banda passante do demodulador, no caso, um
# FIR de ordem 120, banda de 10,5 a 13,5 kHz

# i e q são os sinais I e Q filtrados 

i = fir(inr,-0.0006004,-1e-7,0.0008371,0,-0.001024,1e-7,0.0011169,-2e-7,-0.0010371,3e-7,0.0006903,-5e-7,0,6e-7,-0.0010498,-6e-7,0.0023763,5e-7,-0.0037768,-2e-7,0.0049353,-2e-7,-0.0054638,8e-7,0.0049764,-0.0000015,-0.003185,0.0000021,0,-0.0000025,0.0043866,0.0000024,-0.0094575,-0.0000019,0.0143835,8e-7,-0.0181,9e-7,0.0194446,-0.000003,-0.0173364,0.0000052,0.0109716,-0.0000072,0,0.0000085,-0.0153503,-0.0000086,0.034228,0.000007,-0.0552081,-0.0000031,0.076436,-0.0000041,-0.0958489,0.0000165,0.1114422,-0.0000415,-0.1215419,0.0001476,0.1252745,0.0001476,-0.1215419,-0.0000415,0.1114422,0.0000165,-0.0958489,-0.0000041,0.076436,-0.0000031,-0.0552081,0.000007,0.034228,-0.0000086,-0.0153503,0.0000085,0,-0.0000072,0.0109716,0.0000052,-0.0173364,-0.000003,0.0194446,9e-7,-0.0181,8e-7,0.0143835,-0.0000019,-0.0094575,0.0000024,0.0043866,-0.0000025,0,0.0000021,-0.003185,-0.0000015,0.0049764,8e-7,-0.0054638,-2e-7,0.0049353,-2e-7,-0.0037768,5e-7,0.0023763,-6e-7,-0.0010498,6e-7,0,-5e-7,0.0006903,3e-7,-0.0010371,-2e-7,0.0011169,1e-7,-0.001024,0,0.0008371,-1e-7,-0.0006004)

q = fir(inl,-0.0006004,-1e-7,0.0008371,0,-0.001024,1e-7,0.0011169,-2e-7,-0.0010371,3e-7,0.0006903,-5e-7,0,6e-7,-0.0010498,-6e-7,0.0023763,5e-7,-0.0037768,-2e-7,0.0049353,-2e-7,-0.0054638,8e-7,0.0049764,-0.0000015,-0.003185,0.0000021,0,-0.0000025,0.0043866,0.0000024,-0.0094575,-0.0000019,0.0143835,8e-7,-0.0181,9e-7,0.0194446,-0.000003,-0.0173364,0.0000052,0.0109716,-0.0000072,0,0.0000085,-0.0153503,-0.0000086,0.034228,0.000007,-0.0552081,-0.0000031,0.076436,-0.0000041,-0.0958489,0.0000165,0.1114422,-0.0000415,-0.1215419,0.0001476,0.1252745,0.0001476,-0.1215419,-0.0000415,0.1114422,0.0000165,-0.0958489,-0.0000041,0.076436,-0.0000031,-0.0552081,0.000007,0.034228,-0.0000086,-0.0153503,0.0000085,0,-0.0000072,0.0109716,0.0000052,-0.0173364,-0.000003,0.0194446,9e-7,-0.0181,8e-7,0.0143835,-0.0000019,-0.0094575,0.0000024,0.0043866,-0.0000025,0,0.0000021,-0.003185,-0.0000015,0.0049764,8e-7,-0.0054638,-2e-7,0.0049353,-2e-7,-0.0037768,5e-7,0.0023763,-6e-7,-0.0010498,6e-7,0,-5e-7,0.0006903,3e-7,-0.0010371,-2e-7,0.0011169,1e-7,-0.001024,0,0.0008371,-1e-7,-0.0006004)

# O oscilador local OL, de 10,5 a 13,5 kHz, controlado pelo cursor 1
# é um gerador dente de serra, com f = samplerate * d
# simplesmente porque não há oscilador senoidal no BasicDSP !

d = 0.21875 + 0.0625*slider1
z = mod1(z + d);

# O sinal dente de serra z é transformado em dois sinais
# senoidais e em quadratura s e c, pelas funções sin1 e cos1.

s = sin1(z)
c = cos1(z)

# Os sinais de FI filtrados i e q são convertidos para áudio
# com os sinais do OL em quadratura, eliminando a freq. imagem,
# por meio de dois misturadores (produto), gerando ai e aq

ai = i * s

aq = q * c

# A soma (ou diferença) de ai com aq gera o áudio a :

a = ai + aq

# Trocando o sinal + por - mudamos a banda da entrada entre 
# freqüências positivas ou negativas. Equivale a trocar os sinais I e Q.
# esta soma (ou diferença) elimina a freqüência imagem gerada no QSD
# que no caso da soma está na banda em torno de -12 kHz.

Os sinais I e Q na saída do SDR são idênticos espectralmente (figura seguinte), pois o espectro é uma representação amplitude versus freqüência. Eles diferem na fase, e é justamente isso que permite rejeitar a freqüência imagem.



A figura seguinte mostra o espectro do sinal de áudio a demodulado, tendo como sinais I e Q de entrada ruído branco, Podemos ver o sinal de áudio desejado entre 0 e 3 kHz, e o termo soma indesejável entre 21 e 24 kHz, que será eliminado pelo filtro passa-baixo cuja resposta é a curva azul da figura anterior:

# Um filtro passa baixo FIR com ordem 50 e freq. de corte de 4 kHz
# elimina o termo soma da conversão anterior, e fornece na sua saída
# o sinal out de áudio. (esse filtro não é absolutamente necessário,
# pois o sinal indesejado fica entre 21 e 24 kHz, sendo inaudível.

A figura seguinte mostra o sinal i = I filtrado, em amarelo, e o oscilador local s , em azul, ajustado pelo cursor 1 de forma a estar em 10,5 kHz, permitido demodular USB:

Para demodular LSB, o oscilador local é ajustado para 13,5 kHz, com cursor 1 totalmente a direita:

Como o sinal fornecido pelo SDRZero é uma réplica do sinal de RF na sua entrada, este pode sofrer grandes variações de amplitude, donde a necessidade de um AGC, controle automático de ganho. Criei uma rotina bem simples:

# AGC 
# o sinal de áudio é retificado :

x = abs(a)

A figura seguinte do osciloscópio mostra o sinal de áudio a (amarelo) e o mesmo sinal retificado em onda completa x (azul):



# Um filtro passa-baixo extrai a componente continua
# gerando a tensão de controle vc de AGC:

dc = dc * 0.99 + 0.01 * x
vc = vc * 0.9995 + 0.0005 * dc;

# O ganho g é inversamente proporcional a tensão de AGC

g = 0.1 / (vc + 0.00001);

# o nível de áudio é corrigido pelo ganho de AGC:

# o cursor 2 permite mudar progressivamente entre 0 e 100% de AGC

ag = slider2 * g * a + (1 - slider2) * a

# Finalmente o sinal de audio pass pelo filtro passa-baixo:

out = fir(ag,0,-0.0002178,-0.0003928,-0.0004791,-0.0004439,-0.0002773,0,0.0003325,0.0006359,0.0008134,0.000782,0.0005016,0,-0.000619,-0.0011892,-0.0015212,-0.0014569,-0.0009286,0,0.0011253,0.0021396,0.0027069,0.0025639,0.0016161,0,-0.001917,-0.0036081,-0.0045213,-0.0042439,-0.0026527,0,0.0031003,0.0057984,0.0072253,0.0067494,0.0042019,0,-0.0048847,-0.0091243,-0.0113675,-0.0106289,-0.0066318,0,0.0077773,0.0146285,0.0183889,0.0173897,0.011004,0,-0.0134148,-0.0259061,-0.0336446,-0.033137,-0.0220746,0,0.0313787,0.068325,0.1056596,0.1376897,0.1592916,0.166915,0.1592916,0.1376897,0.1056596,0.068325,0.0313787,0,-0.0220746,-0.033137,-0.0336446,-0.0259061,-0.0134148,0,0.011004,0.0173897,0.0183889,0.0146285,0.0077773,0,-0.0066318,-0.0106289,-0.0113675,-0.0091243,-0.0048847,0,0.0042019,0.0067494,0.0072253,0.0057984,0.0031003,0,-0.0026527,-0.0042439,-0.0045213,-0.0036081,-0.001917,0,0.0016161,0.0025639,0.0027069,0.0021396,0.0011253,0,-0.0009286,-0.0014569,-0.0015212,-0.0011892,-0.000619,0,0.0005016,0.000782,0.0008134,0.0006359,0.0003325,0,-0.0002773,-0.0004439,-0.0004791,-0.0003928,-0.0002178,0);

O programa termina aqui, sendo as instruções seguintes apenas para ver melhor as variáveis ai e aq no osciloscópio.

Teste da rejeição de freqüência imagem, feito com os sinais Quadsine ajustados em +12 kHz para simular o sinal desejado (figura da esquerda abaixo) e em -12 kHz para simular a freqüência imagem existente nos sinais I e Q do SDRZero (figura da direita abaixo):

# para poder ver a fase dos sinais ai e aq no osciloscópio, em regime
# senoidal, aplicamos um filtro passa-baixo simples:

aif = aif + 0.1 * (ai - aif)
aqf = aqf + 0.1 * (aq - aqf)

# para poder ver as duas quando em fase, diminuímos um pouco aqf...

aqf = aqf *0.98

É fácil verificar que os sinais convertidos  ai e aq estão em fase para freqüências na banda desejada, e em oposição de fase para a freqüência imagem, donde o cancelamento desta ultima pela soma ai+aq.

 

Observação: o meu SDRZero, com oscilador local em 9 MHz, está ligado na FI de 9,012 MHz de um IC725. Posso portanto sintonizar de 0 a 30 MHz. Vejam aqui.

 

O programa exemplo está disponível aqui para download. Apesar da extensão .dsp, é um arquivo texto.

 

Vejam aqui como funciona um SDR.