Nödvändig bandbredd för FSK?
Re: Nödvändig bandbredd för FSK?
Tack. Jag har inte matlab, men tydligen gör fir() funktionen i Octaber samma sak, räknar ut värdena.
Re: Nödvändig bandbredd för FSK?
Jag tycker att mycket av mecket med mottagare är att synkronisera i tid och frekvens. Det kan ibland vara klurigare än själva demoduleringen.
Här kommer ett exempel som, trots sin längd, är ganska enkelt, och kan användas till flera saker, tror jag. Programmet räknar ut var centerfrekvensen ligger.
Centerfrekvensen tas fram genom att filtrera ut varje symbol, kvadrera dess amplitud för att få energin, och summera energin över alla symboler i din samplade fil. (I verkligheten kanske man tar de senaste N symbolerna eller liknande.) Om centerfrekvensen är F, summerar den energierna vid frekvenserna F-85Hz och F+85Hz. Dessutom summerar den energin vid frekvens F separat, som jämförelse. Här är en plot
Den svarta kurvan visar symbolenergin för en frekvens (den visar alltså var de två frekvenserna finns), medan den blå visar summan av två symboler offsetade 170Hz. För summan blir det alltså tre pucklar, en hög i mitten när man "kör med båda hjulen i hjulspåren", och två lägre på sidorna när man bara träffar den ena frekvensen och den andra är helt utanför. Jag får centerfrekvensen till 1385Hz.
Här kommer då programmet. Tyvärr är matlab inget bra språk på flera sätt. Matlabkod blir typiskt effektivare av att använda mycket matrisoperationer och lite for-loopar, typ, så för den som är van vid mera "vanliga" språk ser då väldigt svårbegripligt ut. Jag har gjort en mix här. En annan sak som är svår är subrutiner.
Först deklarerar vi lite konstanter som relaterar till standarden respektive din sampling, och så läser vi in filen. Notera att den också räknar ut antalet sampel per symbol, N, som i detta fallet blir 80. Vi skapar också en vektor "frange" som innehåller alla de frekvenser vi vill testa med. Från 800Hz till 2000Hz i steg om 10Hz. Öka steglängden till exempelvis 100 för snabbare exekvering.
Allokera tomma vektorer för resultaten
Och sedan loopen. Yttre loopen itererar frekvensen F. Vi testar en frekvens i taget. Inre loopen plockar ut N sampel i taget ur indatan i en variabel jag kallar "fifo". De tre exp(j...) är bandpassfilter som är konstanta för varje F. FIR-filterna är "fifo .* wx" som skapar en vektor "[fifo[0] * wx[0], fifo[1] * wx[1], ...]". Summan av detta är filtrets utsignal. Denna kvadreras, och ackumuleras till acc1 eller acc2, där acc1 är för F-85Hz och F+85Hz, och acc2 är för F.
Så som svar på en tidigare fråga är här exempel på hur man kan göra bandbassfilter. Filterna skall vara precis lika långa som symbolerna, dvs av längd N. Är de kortare tar man inte alla sampel i beaktande (suboptimalt), och är de längre får man intersymbolinterferens.
Notera att detta exempel inte har synkroniserat i tidsled. Vi vet inte ännu exakt när en symbol slutar och nästa börjar. För detta exempel funkar det ändå, men jag hoppas återkomma till det ämnet senare.
En annan grej är att dessa filter kan implementeras mycket effektivare om man ser det som ren mixning med en komplex svängning. Man behöver bara en komplex mulitplikation per insampel och filter, det blir också senare.
EDIT: Hade fel tecken i exponentialfunktionerna, resultaten blir desamma.
Här kommer ett exempel som, trots sin längd, är ganska enkelt, och kan användas till flera saker, tror jag. Programmet räknar ut var centerfrekvensen ligger.
Centerfrekvensen tas fram genom att filtrera ut varje symbol, kvadrera dess amplitud för att få energin, och summera energin över alla symboler i din samplade fil. (I verkligheten kanske man tar de senaste N symbolerna eller liknande.) Om centerfrekvensen är F, summerar den energierna vid frekvenserna F-85Hz och F+85Hz. Dessutom summerar den energin vid frekvens F separat, som jämförelse. Här är en plot
Den svarta kurvan visar symbolenergin för en frekvens (den visar alltså var de två frekvenserna finns), medan den blå visar summan av två symboler offsetade 170Hz. För summan blir det alltså tre pucklar, en hög i mitten när man "kör med båda hjulen i hjulspåren", och två lägre på sidorna när man bara träffar den ena frekvensen och den andra är helt utanför. Jag får centerfrekvensen till 1385Hz.
Här kommer då programmet. Tyvärr är matlab inget bra språk på flera sätt. Matlabkod blir typiskt effektivare av att använda mycket matrisoperationer och lite for-loopar, typ, så för den som är van vid mera "vanliga" språk ser då väldigt svårbegripligt ut. Jag har gjort en mix här. En annan sak som är svår är subrutiner.
Först deklarerar vi lite konstanter som relaterar till standarden respektive din sampling, och så läser vi in filen. Notera att den också räknar ut antalet sampel per symbol, N, som i detta fallet blir 80. Vi skapar också en vektor "frange" som innehåller alla de frekvenser vi vill testa med. Från 800Hz till 2000Hz i steg om 10Hz. Öka steglängden till exempelvis 100 för snabbare exekvering.
Kod: Markera allt
# NAVTEX parameters
Fdelta = 170; # BFSK frequency difference
Fsym = 100; # Symbol rate
# Receiver parameters
Fs = 8000; # sample frequency
N = Fs/Fsym; # Samples per symbol
# Read input signal. The prim (') transposes from row to line vector
r = audioread('rost.wav')';
# Run all frequencies in this range (low:stepsize:high)
frange = 800:10:2000;
Kod: Markera allt
# allocate output vectors
output1 = zeros(1, length(frange));
output2 = zeros(1, length(frange));
Kod: Markera allt
ix = 1;
for F = frange
# For each frequency F, define three bandpass filters with
# centers at (F-Fdelta/2), F, and (F+Fdelta/2).
wh = exp(j*2*pi*(F+Fdelta/2)/Fs*(0:N-1));
wl = exp(j*2*pi*(F-Fdelta/2)/Fs*(0:N-1));
wc = exp(j*2*pi*(F )/Fs*(0:N-1));
# Accumulate the energy of all "symbols" in the sampled vector
acc1 = 0;
acc2 = 0;
for n = 0:floor(length(r)/N)-2
fifo = r(1+n*N:(n+1)*N);
acc1 = acc1 + ...
abs(sum(fifo .* wl))^2 + ...
abs(sum(fifo .* wh))^2;
acc2 = acc2 + ...
abs(sum(fifo .* wc))^2;
end
output1(ix) = acc1;
output2(ix) = acc2;
ix = ix + 1;
end
Notera att detta exempel inte har synkroniserat i tidsled. Vi vet inte ännu exakt när en symbol slutar och nästa börjar. För detta exempel funkar det ändå, men jag hoppas återkomma till det ämnet senare.
En annan grej är att dessa filter kan implementeras mycket effektivare om man ser det som ren mixning med en komplex svängning. Man behöver bara en komplex mulitplikation per insampel och filter, det blir också senare.
EDIT: Hade fel tecken i exponentialfunktionerna, resultaten blir desamma.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Nödvändig bandbredd för FSK?
OK. Intressant. Jo i det allmäna fallet vill man säkert först hitta mittfrekvensen, sedan filtrera +/- 85 Hz om denna. Skall dock se om jag får en så stabil LO att jag helt kallt kan räkna med att min frekvens alltid är konstant.
Sedan har jag ju en annan begränsning: Tänkte göra detta i realtid och med en relativt strömsnål processor. Om jag antar att jag samplat med 4kHz så har jag sisådär 250us att spela med, tiden per sampel.
Motsvarar antalet "taps" "ordningen" på ett konventionellt filter?
Sedan har jag ju en annan begränsning: Tänkte göra detta i realtid och med en relativt strömsnål processor. Om jag antar att jag samplat med 4kHz så har jag sisådär 250us att spela med, tiden per sampel.
Nu får du förklara så jag förstår Om jag samplar 1kHz med 4kHz och datahastigheten är 100baud, vad är då symbollängden? Om vi har 100 baud, har vi 100 symboler/sek och symbollängden 1/100s eller 10ms? Skall då filtret vara 10ms/250us = 40? 40 "taps"??Filterna skall vara precis lika långa som symbolerna, dvs av längd N.
Motsvarar antalet "taps" "ordningen" på ett konventionellt filter?
Re: Nödvändig bandbredd för FSK?
Det finns ett filterverktyg från Microchip som direkt genererar kod för deras DSP-rutiner:
Tror knappast att C-koden hänger med så långt dock. Får väl kika på att göra vissa bitar i assembler.- dsPIC har en assemblerfunktion som heter MAC, Multiply and accumulate. Den gör följande:
Multiplicerar två 16-bits tal med teckenbit (17nde biten)
Adderar produkten till en 40-bitars ackumulator
Ökar eller minskar två pekare med valfritt värde
Allt detta i en instruktionscykel (100ns vid 40MHz klocka)
Är ganska kul att labba med. Jobbar med heltal så det är litet snabbare än Octave.Tror knappast att C-koden hänger med så långt dock. Får väl kika på att göra vissa bitar i assembler.- dsPIC har en assemblerfunktion som heter MAC, Multiply and accumulate. Den gör följande:
Multiplicerar två 16-bits tal med teckenbit (17nde biten)
Adderar produkten till en 40-bitars ackumulator
Ökar eller minskar två pekare med valfritt värde
Allt detta i en instruktionscykel (100ns vid 40MHz klocka)
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Nödvändig bandbredd för FSK?
Filtreringen i C-programmet till dsPIC sker väldigt lätt:
FIR(BLOCK_LENGTH, &FilterOut[0], &A_D_value[0], &Bandpassfilter_Coeffs);
BLOCK_LENGTH kan vara 1 om man vill filtrera ett "sampel" i taget, och då
trillar det ut ett ur filtret.
199-tap FIR vid fs=10kHz är inga problem alls finns gott om tid till annat.
Då är klockkristallen på 5MHz ( x 16 i PLL ger 80MHz som delas ner till 20MHz / 50ns som är cykeltiden)
FIR(BLOCK_LENGTH, &FilterOut[0], &A_D_value[0], &Bandpassfilter_Coeffs);
BLOCK_LENGTH kan vara 1 om man vill filtrera ett "sampel" i taget, och då
trillar det ut ett ur filtret.
199-tap FIR vid fs=10kHz är inga problem alls finns gott om tid till annat.
Då är klockkristallen på 5MHz ( x 16 i PLL ger 80MHz som delas ner till 20MHz / 50ns som är cykeltiden)
Re: Nödvändig bandbredd för FSK?
Det beror iofs på vilken dsPIC man väljer. Tänkte ta en litet mindre, men faktum är att då jag testar i simulatorn så får jag 96 cykler för anropet till FIR() nedan:
Slutar läsa assemblermanualen nu och läser docsen för DSP-biblioteken Misstänker att "CE001 Using dsPIC30F A/D Converters and the DSP library for Signal Filtering" kan inehålla en hel del matnyttigt
Edit:
M = Koefficienter, N = Samples
Kod: Markera allt
#include <p30f2011.h>
#include <dsp.h>
#define BLOCK_LENGTH 1;
// http://www.microchip.com/forums/m152177.aspx
float raw_coef[25] = {0.015591488063, 0.027520971951, 0.000000000000, -0.033636743495, -0.023387232095,
0.026728265251, 0.050455115243, 0.000000000000, -0.075682672864, -0.062365952253,
0.093548928379, 0.302730691456, 0.400000000000, 0.302730691456, 0.093548928379,
-0.062365952253, -0.075682672864, 0.000000000000, 0.050455115243, 0.026728265251,
-0.023387232095, -0.033636743495, 0.000000000000, 0.027520971951, 0.015591488063};
fractional delay1[25] __attribute__ ((space(ymemory), aligned (32)));
fractional coeffs1[25] __attribute__ ((space(xmemory), aligned (32)));
FIRStruct filter1;
int main(void) {
int i;
//convert float coefficients to fract
for(i=0;i<25;i++)
coeffs1[i]=Float2Fract(raw_coef[i]);
//init filter
FIRStructInit(&filter1,25,coeffs1,0xFF00,delay1);
FIRDelayInit(&filter1);
FIR(1, &FilterOut[0], &A_D_value[0], &filter1);
return 0;
}
Edit:
Kod: Markera allt
For dsPIC30F/33F:
Program words (24-bit instructions):
61
Cycles (including C-function call and return overheads):
61 + N*(4 + M) if coefficients are in data memory, or
68 + N*(9 + M) if coefficients in program memory.
Senast redigerad av AndersG 23 augusti 2017, 07:33:51, redigerad totalt 2 gånger.
Re: Nödvändig bandbredd för FSK?
Det rullar ju på bra det här, du är ju snart i hamn!
Ett annat sätt att se det är att det finns lika många tappar som nollor i "frekvensplanet".
Justera paramertrarna efter dina värden. Ut kommer reella filterkoefficienter. Exempel på hur överföringsfunktionerna ser ut:
(Och jag undrar om inte din centerfrekvens är 1385Hz )
Ursäkta om jag var lite slarvig där, N relaterade just då till variabeln N i programmet ovan. Du har räknat helt rätt, 40 tappar skall det vara i ditt exempel. Och 100 baud är 100 symboler/s vilket motsvarar en symboltid på 10ms.Nu får du förklara så jag förstår Om jag samplar 1kHz med 4kHz och datahastigheten är 100baud, vad är då symbollängden? Om vi har 100 baud, har vi 100 symboler/sek och symbollängden 1/100s eller 10ms? Skall då filtret vara 10ms/250us = 40? 40 "taps"??
Ja ungefär. Antalet tappar är hur mycket minne systemet har, vilket påminner om antalet tillstånd i en analog krets som är typiskt likamed antalet reaktiva element (kondingar och spolar).Motsvarar antalet "taps" "ordningen" på ett konventionellt filter?
Ett annat sätt att se det är att det finns lika många tappar som nollor i "frekvensplanet".
Här är ett par filter som du kan använda nästan rakt avKan du förklara hur jag enklast gör ett bandpassfilter för 1462 och ett för 1292Hz, dvs mittfrekvensen 1377 +/-85hz?
Kod: Markera allt
# NAVTEX parameters
Fdelta = 170; # BFSK frequency difference
Fsym = 100; # Symbol rate
F = 1385; # Center frequency
# Receiver parameters
Fs = 8000; # sample frequency
N = Fs/Fsym; # Samples per symbol
h_low = cos(2*pi*(F-Fdelta/2)/Fs*(0:N-1));
h_high = cos(2*pi*(F+Fdelta/2)/Fs*(0:N-1));
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Nödvändig bandbredd för FSK?
Det jag spelar in från HF3an kommer ju att bero på hur jag rattat BFOn. Jag avstämmer den till 517kHz så då borde jag få 1000Hz, men sedan skruvar man ju på BFOn (Clarify) så det låter braOch jag undrar om inte din centerfrekvens är 1385Hz
I den egna mottagaren borde jag ha en kristallstyrd LO på 517 eller 519 så där bör jag hamna rätt nära 1kHz.
Re: Nödvändig bandbredd för FSK?
@YD1150
När jag kikade i koden (FIR är skrivet i Assembler och använder dsPICens funktioner för multiply and accumulate samt modulo-adressering för ringbufferten så noterar jag att man definierar ett "delayminne" i filterstrukturen. Jag antar att det är det minnet som hanterar multiplikationen mot a, a-1, a-2 etc?
Skall koppla upp en dsPIC på labplatta och med en MCP4822 D/A som utgång så jag kan testa litet mera i realtid.
OK. Så det är i det fallet att man tex har ADn att plocka 16 samples och lägga i en buffert. Jag antar att det är effektivare än att ta ett sampel åt gången?BLOCK_LENGTH kan vara 1 om man vill filtrera ett "sampel" i taget, och då
trillar det ut ett ur filtret.
När jag kikade i koden (FIR är skrivet i Assembler och använder dsPICens funktioner för multiply and accumulate samt modulo-adressering för ringbufferten så noterar jag att man definierar ett "delayminne" i filterstrukturen. Jag antar att det är det minnet som hanterar multiplikationen mot a, a-1, a-2 etc?
Skall koppla upp en dsPIC på labplatta och med en MCP4822 D/A som utgång så jag kan testa litet mera i realtid.
Re: Nödvändig bandbredd för FSK?
Ja det ska gå bra och filtrera dem i en klump åt gången.
Sen gäller det att mata ut dem i rätt takt till D/A-omvandlaren, blir något buffert-aktigt där.
Jag använde ett sampel i taget för det vart enklast för det jag gjorde.
Jag använde MCP4821 och den fungerar bra ihop med dsPIC.
Sen gäller det att mata ut dem i rätt takt till D/A-omvandlaren, blir något buffert-aktigt där.
Jag använde ett sampel i taget för det vart enklast för det jag gjorde.
Jag använde MCP4821 och den fungerar bra ihop med dsPIC.
Re: Nödvändig bandbredd för FSK?
Snyyyyyyggggt!Justera paramertrarna efter dina värden. Ut kommer reella filterkoefficienter.
Edit:
Om jag skulle få önska en sak till är en omvandling från decimaltal till "fractional" (1.15)
Re: Nödvändig bandbredd för FSK?
OK. Det tar sig. Två filter med mittfrekvens 1300 och 1470 puttas ut på D/A-omvandlarens båda kanaler.
Återstår envelopp och logik, typ att hi != lo annars är signalen ogiltig.
Om jag skulle få filtervärdena direkt i fract-format skulle jag slippa lagra dem som flyttal och sedan flytta över dem.
Återstår envelopp och logik, typ att hi != lo annars är signalen ogiltig.
Om jag skulle få filtervärdena direkt i fract-format skulle jag slippa lagra dem som flyttal och sedan flytta över dem.
Kod: Markera allt
/*
* File: main.c
*
* Created on den 21 augusti 2017, 19:46
*/
//
// DSPTest for 28-pin dsPIC 30f2011
//
// 20170821
//
// DSPIC30F2011 Configuration Bit Settings
// 'C' source line config statements
// FOSC
#pragma config FOSFPR = XT_PLL8 // Oscillator (XT w/PLL 48)
#pragma config FCKSMEN = CSW_FSCM_OFF // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
// FWDT
#pragma config FWPSB = WDTPSB_16 // WDT Prescaler B (1:16)
#pragma config FWPSA = WDTPSA_512 // WDT Prescaler A (1:512)
#pragma config WDT = WDT_OFF // Watchdog Timer (Disabled)
// FBORPOR
#pragma config FPWRT = PWRT_64 // POR Timer Value (64ms)
#pragma config BODENV = BORV20 // Brown Out Voltage (Reserved)
#pragma config BOREN = PBOR_ON // PBOR Enable (Enabled)
#pragma config MCLRE = MCLR_EN // Master Clear Enable (Enabled)
// FGS
#pragma config GWRP = GWRP_OFF // General Code Segment Write Protect (Disabled)
#pragma config GCP = CODE_PROT_OFF // General Segment Code Protection (Disabled)
// FICD
#pragma config ICS = ICS_PGD // Comm Channel Select (Use PGC/EMUC and PGD/EMUD)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include "common.h"
#include <xc.h>
#include <p30f2011.h>
#include <dsp.h>
#include "spi_dspic30.h"
#include "ADC.h"
#define BLOCK_LENGTH 1
#define TAPS 80
// http://www.microchip.com/forums/m152177.aspx
__psv__ float __attribute__ ((space(psv))) raw_coef_lo[80] = {
1.0000e+000, 5.2250e-001, -4.5399e-001, -9.9692e-001, -5.8779e-001, 3.8268e-001, 9.8769e-001,
6.4945e-001, -3.0902e-001, -9.7237e-001, -7.0711e-001, 2.3345e-001, 9.5106e-001, 7.6041e-001,
-1.5643e-001, -9.2388e-001, -8.0902e-001, 7.8459e-002, 8.9101e-001, 8.5264e-001, -9.8036e-016,
-8.5264e-001, -8.9101e-001, -7.8459e-002, 8.0902e-001, 9.2388e-001, 1.5643e-001, -7.6041e-001,
-9.5106e-001, -2.3345e-001, 7.0711e-001, 9.7237e-001, 3.0902e-001, -6.4945e-001, -9.8769e-001,
-3.8268e-001, 5.8779e-001, 9.9692e-001, 4.5399e-001, -5.2250e-001, -1.0000e+000, -5.2250e-001,
4.5399e-001, 9.9692e-001, 5.8779e-001, -3.8268e-001, -9.8769e-001, -6.4945e-001, 3.0902e-001,
9.7237e-001, 7.0711e-001, -2.3345e-001, -9.5106e-001, -7.6041e-001, 1.5643e-001, 9.2388e-001,
8.0902e-001, -7.8459e-002, -8.9101e-001, -8.5264e-001, -4.1643e-015, 8.5264e-001, 8.9101e-001,
7.8459e-002, -8.0902e-001, -9.2388e-001, -1.5643e-001, 7.6041e-001, 9.5106e-001, 2.3345e-001,
-7.0711e-001, -9.7237e-001, -3.0902e-001, 6.4945e-001, 9.8769e-001, 3.8268e-001, -5.8779e-001
-9.9692e-001, -4.5399e-001, 5.2250e-001
};
__psv__ float __attribute__ ((space(psv))) raw_coef_hi[80] = {
1.000000, 0.404344, -0.673013, -0.948600, -0.094108, 0.872496, 0.799685, -0.225801,
-0.982287, -0.568562, 0.522499, 0.991100, 0.278991, -0.765483, -0.898028, 0.039260,
0.929776, 0.712639, -0.353475, -0.998489, -0.453990, 0.631353, 0.964557, 0.148672,
-0.844328, -0.831470, 0.171929, 0.970506, 0.612907, -0.474856, -0.996917, -0.331338,
0.728969, 0.920845, 0.015707, -0.908143, -0.750111, 0.301538, 0.993961, 0.502266,
-0.587785, -0.977600, -0.202787, 0.813608, 0.860742, -0.117537, -0.955793, -0.655400,
0.425779, 0.999722, 0.382683, -0.690251, -0.940881, -0.070627, 0.883766, 0.785317,
-0.248690, -0.986429, -0.549023, 0.542442, 0.987688, 0.256289, -0.780430, -0.887413,
0.062791, 0.938191, 0.695913, -0.375416, -0.999507, -0.432873, 0.649448, 0.958073,
0.125333, -0.856718, -0.818150, 0.195090, 0.975917, 0.594121, -0.495459, -0.994792
};
fractional inputSignal[NUMSAMP];
fractional outputSignal[NUMSAMP];
fractional outputSignal2[NUMSAMP];
fractional* oPtr;
fractional* iPtr;
unsigned int doFilterFlag;
fractional delay1[TAPS] __attribute__ ((space(ymemory), aligned (32)));
fractional coeffs1[TAPS] __attribute__ ((space(xmemory), aligned (32)));
fractional delay2[TAPS] __attribute__ ((space(ymemory), aligned (32)));
fractional coeffs2[TAPS] __attribute__ ((space(xmemory), aligned (32)));
FIRStruct filter1;
FIRStruct filter2;
int main(void) {
int i;
float x;
//
TRISDbits.TRISD0 = 0;
LATBbits.LATB0 = 1;
//
outputSignal[0] = 0;
spi_setup();
//convert float coefficients to fract
for(i=0;i<TAPS;i++)
{
x = raw_coef_hi[i];
coeffs1[i]=Float2Fract(x);
x = raw_coef_lo[i];
coeffs2[i]=Float2Fract(x);
}
//init filter
FIRStructInit(&filter1,TAPS,coeffs1,0xFF00,delay1);
FIRStructInit(&filter2,TAPS,coeffs2,0xFF00,delay2);
FIRDelayInit(&filter1);
FIRDelayInit(&filter2);
//
ADC_Init(); //Initialize the A/D converter, last!
while(1)
{
if (doFilterFlag)
{
//Filter a block of NUMSAMP samples using FIR
//
FIR(1, &outputSignal[0], &inputSignal[0], &filter1);
FIR(1, &outputSignal2[0], &inputSignal[0], &filter2);
spi_send((outputSignal[0]^0x8000)>>4);
spi_send2((outputSignal2[0]^0x8000)>>4); // Data it 10-bit, left adjusted
//
doFilterFlag = 0;
iPtr = &inputSignal[0];
}
}
return 0;
}
Re: Nödvändig bandbredd för FSK?
Några rader Matlab-kod levereras "as-is".
h_low och h_high är filterkoefficienterna typ 80st eller så, bara reella tal.
Funktionen 16int_to_hex var något jag tankade hem nån gång.
Nu ska det ha trillat ut en textfil i andra änden.
Som ser ut så här:
Bara att klippa och klistra in i MPLAB som jag använder till dsPIC.
Går så oerhört mycket snabbare än att manuellt översätta varenda tal.
Samt risken att skriva fel, som ger något filter med okänt passband.
h_low och h_high är filterkoefficienterna typ 80st eller så, bara reella tal.
Funktionen 16int_to_hex var något jag tankade hem nån gång.
Kod: Markera allt
Bits=16;
Navtex_16bit_Coeffs_lo = round(2*(((2^Bits)-1)*h_low)/sum(abs(h_low)));
Navtex_16bit_Coeffs_hi = round(2*(((2^Bits)-1)*h_low)/sum(abs(h_high)));
% Write to file
F_ID=fopen('Navtex_filter_coefficients.txt','w+');
fprintf(F_ID, '// ***** MPLAB Navtex filter coefficients for dsPIC *****\n\n');
fprintf(F_ID,'\n');
fprintf(F_ID,'// No of coefficients %i \n\n\n', length(Navtex_16bit_Coeffs_lo));
stopp=0;
fprintf(F_ID,'// Low tone coefficients\n');
for j=1:length(Navtex_16bit_Coeffs_lo)
if ( stopp==0 )
fprintf(F_ID, '.hword ');
end
if ( stopp==7 )
fprintf(F_ID, '0x');
fwrite(F_ID, int16_to_hex(Navtex_16bit_Coeffs_lo(j)) );
fprintf(F_ID, ' \n');
stopp=0;
else
fprintf(F_ID, '0x');
fwrite(F_ID, int16_to_hex(Navtex_16bit_Coeffs_lo(j)) );
if (j==length(Navtex_16bit_Coeffs_lo))
fprintf(F_ID, ' ');
else
fprintf(F_ID, ', ');
end
stopp=stopp+1;
end
end
fprintf(F_ID,'\n\n\n\n\n');
fprintf(F_ID,'// High tone coefficients\n');
for j=1:length(Navtex_16bit_Coeffs_hi)
if ( stopp==0 )
fprintf(F_ID, '.hword ');
end
if ( stopp==7 )
fprintf(F_ID, '0x');
fwrite(F_ID, int16_to_hex(Navtex_16bit_Coeffs_hi(j)) );
fprintf(F_ID, ' \n');
stopp=0;
else
fprintf(F_ID, '0x');
fwrite(F_ID, int16_to_hex(Navtex_16bit_Coeffs_hi(j)) );
if (j==length(Navtex_16bit_Coeffs_hi))
fprintf(F_ID, ' ');
else
fprintf(F_ID, ', ');
end
stopp=stopp+1;
end
end
fprintf(F_ID,'// End of file');
fprintf(F_ID,'\n');
fclose(F_ID);
Som ser ut så här:
Kod: Markera allt
// ***** MPLAB Navtex filter coefficients for dsPIC *****
// No of coefficients 80
// Low tone coefficients
.hword 0x09f5, 0x077f, 0x0153, 0xfa80, 0xf665, 0xf70a, 0xfc1e, 0x031d
.hword 0x0892, 0x09ca, 0x062a, 0xff7e, 0xf912, 0xf613, 0xf7fd, 0xfdde
.hword 0x04cc, 0x095b, 0x094a, 0x04a0, 0xfdad, 0xf7e0, 0xf618, 0xf936
.hword 0xffb0, 0x0651, 0x09d3, 0x0879, 0x02ee, 0xfbf0, 0xf6f5, 0xf673
.hword 0xfaaa, 0x0185, 0x07a0, 0x09f5, 0x075e, 0x0122, 0xfa56, 0xf658
.hword 0xf720, 0xfc4c, 0x034d, 0x08ab, 0x09c0, 0x0603, 0xff4c, 0xf8ee
.hword 0xf610, 0xf81b, 0xfe0f, 0x04f8, 0x096c, 0x0937, 0x0474, 0xfd7c
.hword 0xf7c3, 0xf61d, 0xf95b, 0xffe2, 0x0678, 0x09db, 0x085e, 0x02be
.hword 0xfbc2, 0xf6e0, 0xf681, 0xfad4, 0x01b6, 0x07bf, 0x09f3, 0x073c
.hword 0x00f0, 0xfa2e, 0xf64c, 0xf738, 0xfc7b, 0x037c, 0x08c4, 0x09b6
// High tone coefficients
.hword 0x0a09, 0x078e, 0x0156, 0xfa75, 0xf652, 0xf6f8, 0xfc16, 0x0323
.hword 0x08a3, 0x09dd, 0x0637, 0xff7d, 0xf904, 0xf600, 0xf7ed, 0xfdd9
.hword 0x04d6, 0x096e, 0x095c, 0x04a9, 0xfda8, 0xf7d0, 0xf604, 0xf929
.hword 0xffaf, 0x065e, 0x09e6, 0x0889, 0x02f3, 0xfbe8, 0xf6e3, 0xf660
.hword 0xfa9f, 0x0188, 0x07af, 0x0a09, 0x076c, 0x0124, 0xfa4b, 0xf645
.hword 0xf70f, 0xfc45, 0x0353, 0x08bd, 0x09d4, 0x060f, 0xff4b, 0xf8e0
.hword 0xf5fc, 0xf80c, 0xfe0b, 0x0502, 0x097f, 0x0949, 0x047c, 0xfd77
.hword 0xf7b3, 0xf60a, 0xf94e, 0xffe2, 0x0684, 0x09ee, 0x086e, 0x02c3
.hword 0xfbba, 0xf6ce, 0xf66e, 0xfaca, 0x01ba, 0x07cf, 0x0a07, 0x074a
.hword 0x00f2, 0xfa22, 0xf639, 0xf726, 0xfc74, 0x0383, 0x08d5, 0x09c9
// End of file
Bara att klippa och klistra in i MPLAB som jag använder till dsPIC.
Går så oerhört mycket snabbare än att manuellt översätta varenda tal.
Samt risken att skriva fel, som ger något filter med okänt passband.
Re: Nödvändig bandbredd för FSK?
AndersG skrev:OK. Det tar sig. Två filter med mittfrekvens 1300 och 1470 puttas ut på D/A-omvandlarens båda kanaler.
Återstår envelopp och logik, typ att hi != lo annars är signalen ogiltig.
Det är väl snarare att du skall jämför av värdet på hi och och lo och den som har mest värde (= mest signalenergi samlad) bestämmer om signalen skall gå mot plus (hi är högst) eller mot minus (lo är högst) - precis som en komparator - dvs. ingången med högst värde 'vinner' - är det plusingången högre än minusingången så driver det utgången hög, är det minus ingången högre än plusingången så drivs utgången mot låg.
på en analog komparator så är intervallet för Hi==Lo extremt litet i och med väldigt hög förstärkning så för det mesta så har det valt utgången hög eller låg även om spänningsskillnaden mellan ingångarna kan räknas i delar av µV (i verkligheten så brusar det friskt när det slår mellan ändlägena på utgången pga termiska bruset in på signalen och i själva komparatorn)
Försöker du 'digitalisera' det här innan beslut (komparatorn) så förlorar du mycket av vinsten som du gör med den här 'analoga' mottagningsmodellen.