Re: Nödvändig bandbredd för FSK?
Postat: 21 augusti 2017, 16:34:37
Tack. Jag har inte matlab, men tydligen gör fir() funktionen i Octaber samma sak, räknar ut värdena.
Svenskt forum för elektroniksnack.
https://elektronikforumet.com/forum/
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
Nu får du förklara så jag förstårFilterna skall vara precis lika långa som symbolerna, dvs av längd N.
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;
}
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.
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årOm 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?
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));
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
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.
Snyyyyyyggggt!Justera paramertrarna efter dina värden. Ut kommer reella filterkoefficienter.
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;
}
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);
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
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.