kopia lustrzana https://github.com/ag1le/morse-wip
Multichannel CW decoder implemented for FLDIGI.
rodzic
41ed8623a5
commit
8578ee44ce
25
README
25
README
|
@ -88,7 +88,30 @@ MORSE - PROJECT IDEAS
|
||||||
http://orgmode.org/worg/org-contrib/babel/examples/data-collection-analysis.html
|
http://orgmode.org/worg/org-contrib/babel/examples/data-collection-analysis.html
|
||||||
|
|
||||||
|
|
||||||
|
3. CW Skimmer type functionality
|
||||||
|
Automatically detect CW signals in the baseband
|
||||||
|
|
||||||
|
- initialize
|
||||||
|
do
|
||||||
|
- get input buffer (512 samples * 1/Fs) (Fs=4000 Hz)
|
||||||
|
- calculate FFT
|
||||||
|
- find peaks in power spectrum Ps
|
||||||
|
- Fpeak = peak_detect(Ps,delta)
|
||||||
|
- integrate Fpeak over N timeslots (64 .. 128 ms ? )
|
||||||
|
|
||||||
|
- calculate noise floor level
|
||||||
|
- noisemax => frequency bins from 1 to first detected peak
|
||||||
|
- fbin => freq bin size
|
||||||
|
- Pxx => power spectrum
|
||||||
|
=> Nrms = sqrt(sum(Pxx(1:noisemax)*fbin)) / sqrt(f(noisemax));
|
||||||
|
- update delta & threshold
|
||||||
|
- calculate SNR of found Fpeak
|
||||||
|
- integrate Srms = sqrt(sum(Fpeak +/- 10 Hz)*fbin))
|
||||||
|
- SNR = Srms / Nrms
|
||||||
|
if (SNR > threshold )
|
||||||
|
Run decoder instance on detected signal frequency
|
||||||
|
while (timer >
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
int bfv; // 0
|
int bfv; // 0
|
||||||
double frequency; // 600
|
double frequency; // 600
|
||||||
double sample_duration; // 5
|
double sample_duration; // 5
|
||||||
double sample_rate; // 0
|
double sample_rate; // 4000
|
||||||
double delta; // 10.0
|
double delta; // 10.0
|
||||||
double amplify; // 0.0
|
double amplify; // 0.0
|
||||||
int fft; // 0
|
int fft; // 0
|
||||||
|
@ -275,6 +275,21 @@ void apply_window (double * data, int datalen)
|
||||||
return ;
|
return ;
|
||||||
} /* apply_window */
|
} /* apply_window */
|
||||||
|
|
||||||
|
double calc_SNR(double *data, int len, double fbin)
|
||||||
|
{
|
||||||
|
double CG,NG;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i< len; i++) {
|
||||||
|
CG += data[i];
|
||||||
|
NG += data[i]*data[i];
|
||||||
|
}
|
||||||
|
CG = CG/N;
|
||||||
|
NG = NG/N;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void interp_spec (float * mag, int maglen, const double *spec, int speclen)
|
void interp_spec (float * mag, int maglen, const double *spec, int speclen)
|
||||||
{
|
{
|
||||||
int k, lastspec = 0 ;
|
int k, lastspec = 0 ;
|
||||||
|
@ -360,9 +375,76 @@ void process_data(double x)
|
||||||
int rx_FFTprocess(const double *buf, int len)
|
int rx_FFTprocess(const double *buf, int len)
|
||||||
{
|
{
|
||||||
complex z, *zp;
|
complex z, *zp;
|
||||||
int n,i;
|
int n,i,speclen,Hz;
|
||||||
static int smpl_ctr = 0;
|
static int smpl_ctr = 0;
|
||||||
static double FFTvalue,FFTphase =0.0;
|
static double FFTvalue,FFTphase =0.0;
|
||||||
|
fftw_plan plan;
|
||||||
|
double single_max,noise_sum,sig_sum,Nrms,Srms,fbin;
|
||||||
|
double time_domain[1024];
|
||||||
|
double freq_domain[1024];
|
||||||
|
double single_mag_spec[1024];
|
||||||
|
struct PEAKS p;
|
||||||
|
|
||||||
|
p.delta = params.delta;
|
||||||
|
speclen = 512;
|
||||||
|
|
||||||
|
for (i=0; i< len; i++)
|
||||||
|
time_domain[i] = buf[i];
|
||||||
|
|
||||||
|
|
||||||
|
plan = fftw_plan_r2r_1d (2*speclen, time_domain, freq_domain, FFTW_R2HC, FFTW_MEASURE | FFTW_PRESERVE_INPUT) ;
|
||||||
|
if (plan == NULL)
|
||||||
|
{ printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ;
|
||||||
|
exit (1) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
// calculate FFT
|
||||||
|
apply_window (time_domain, 2*speclen) ;
|
||||||
|
fftw_execute (plan) ;
|
||||||
|
single_max = calc_magnitude (freq_domain, 2*speclen, single_mag_spec) ;
|
||||||
|
|
||||||
|
// find peaks in power spectrum Ps
|
||||||
|
// - Fpeak = peak_detect(Ps,delta)
|
||||||
|
// - integrate Fpeak over N timeslots (64 .. 128 ms ? )
|
||||||
|
|
||||||
|
peak_detect(single_mag_spec, 2*speclen, &p);
|
||||||
|
|
||||||
|
// print found freq peaks - only once
|
||||||
|
if (1 ) {
|
||||||
|
for (i=0; i <p.mxcount; i++) {
|
||||||
|
Hz = (p.mxpos[i]*(4000/2))/(speclen);
|
||||||
|
printf("peak[%d]:%f\tHz:%d\tmaxcount:%d\n",p.mxpos[i],p.mx[i],Hz,p.mxcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params.frequency = Hz;
|
||||||
|
/*
|
||||||
|
- calculate noise floor level
|
||||||
|
- noisemax => frequency bins from 1 to first detected peak
|
||||||
|
- fbin => freq bin size
|
||||||
|
- Pxx => power spectrum 512
|
||||||
|
=> Nrms = sqrt(sum(Pxx(1:noisemax)*fbin)) / sqrt(f(noisemax));
|
||||||
|
- update delta & threshold
|
||||||
|
*/
|
||||||
|
fbin = 4000./1024;
|
||||||
|
noise_sum = 0.;
|
||||||
|
for (i = 10; i<p.mxpos[0]-10; i++) {
|
||||||
|
noise_sum += single_mag_spec[i];
|
||||||
|
}
|
||||||
|
printf("\n noise_sum:%f bins:%d",noise_sum,p.mxpos[0]-10);
|
||||||
|
Nrms = sqrt(noise_sum* fbin)/sqrt(Hz);
|
||||||
|
|
||||||
|
sig_sum = 0.;
|
||||||
|
for (i = p.mxpos[0]-5; i< p.mxpos[0]+5; i++) {
|
||||||
|
sig_sum += single_mag_spec[i];
|
||||||
|
}
|
||||||
|
Srms = sqrt (sig_sum*fbin);
|
||||||
|
printf("\n SNR = %5.2f S:%f ss:%f N:%f Hz:%d", Srms/Nrms, Srms, sig_sum,Nrms,Hz);
|
||||||
|
|
||||||
|
/* - calculate SNR of found Fpeak
|
||||||
|
- integrate Srms = sqrt(sum(Fpeak +/- 10 Hz)*fbin))
|
||||||
|
- SNR = Srms / Nrms
|
||||||
|
*/
|
||||||
|
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
// convert CW signal to baseband
|
// convert CW signal to baseband
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct TREE { // Tree structure to decode dit/dah sequence to corresponding char
|
||||||
{55,00,"Z"}, // --..
|
{55,00,"Z"}, // --..
|
||||||
{57,00,"Q"}, // --.-
|
{57,00,"Q"}, // --.-
|
||||||
{54,00,"Ö"}, // ---. Ö
|
{54,00,"Ö"}, // ---. Ö
|
||||||
{56,57,"Š"}, // ---- Š
|
{56,57,"*----*"}, // ---- Š
|
||||||
{00,00,"5"}, // .....
|
{00,00,"5"}, // .....
|
||||||
{00,00,"4"}, // ....-
|
{00,00,"4"}, // ....-
|
||||||
{00,60,"*...-.*"}, // ...-.
|
{00,60,"*...-.*"}, // ...-.
|
||||||
|
@ -68,36 +68,39 @@ struct TREE { // Tree structure to decode dit/dah sequence to corresponding char
|
||||||
{00,00,"2"}, // ..---
|
{00,00,"2"}, // ..---
|
||||||
{00,00,"*.-...*"}, // .-...
|
{00,00,"*.-...*"}, // .-...
|
||||||
{00,00,"e"}, // .-..-
|
{00,00,"e"}, // .-..-
|
||||||
{00,63,"+"}, // .-.-.
|
{00,63,"<AR>"}, // .-.-.
|
||||||
{00,00,"*.-.--*"}, // .-.--
|
{00,00,"*"}, // .-.--
|
||||||
{00,00,"*.--..*"}, // .--..
|
{00,00,"*.--..*"}, // .--..
|
||||||
{59,00,"a"}, // .--.-
|
{59,00,"a"}, // .--.-
|
||||||
{00,00,"*.---.*"}, // .---.
|
{00,00,"*.---.*"}, // .---.
|
||||||
{00,00,"1"}, // .----
|
{00,00,"1"}, // .----
|
||||||
{00,00,"6"}, // -....
|
{00,00,"6"}, // -....
|
||||||
{61,00,"="}, // -...-
|
{61,00,"<BT>"}, // -...-
|
||||||
{00,00,"/"}, // -..-.
|
{00,00,"/"}, // -..-.
|
||||||
{00,00,"*-..--*"}, // -..--
|
{00,00,"*-..--*"}, // -..--
|
||||||
{00,00,"*-.-..*"}, // -.-..
|
{00,00,"*-.-..*"}, // -.-..
|
||||||
{00,00,"^H"}, // -.-.-
|
{00,00,"^H"}, // -.-.-
|
||||||
{00,00,"~N"}, // -.--.
|
{00,00,"<KN>"}, // -.--.
|
||||||
{00,00,"8"}, // ---..
|
{00,00,"8"}, // ---..
|
||||||
{00,00,"7"}, // --...
|
{00,00,"7"}, // --...
|
||||||
{00,00,"9"}, // ----.
|
{00,00,"9"}, // ----.
|
||||||
{00,00,"0"}, // -----
|
{00,00,"0"}, // -----
|
||||||
{00,00,"?"}, // ..--..
|
{00,00,"?"}, // ..--..
|
||||||
{00,00,"@"}, // .--.-.
|
{00,00,"@"}, // .--.-.
|
||||||
{00,00,"SK"}, // ...-.-
|
{00,00,"<SK>"}, // ...-.-
|
||||||
{00,62,"*-...-.*"}, // -...-.
|
{00,62,"*-...-.*"}, // -...-.
|
||||||
{00,00,"BK"}, // -...-.-
|
{00,00,"<BK>"}, // -...-.-
|
||||||
{00,00,"."} // .-.-.-
|
{00,00,"."}, // .-.-.-
|
||||||
|
{00,65,"*--..-*"}, // --..-
|
||||||
|
{00,00,","}, // --..--
|
||||||
|
{00,00,"'"} // .----.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//***********************************************************************************
|
//***********************************************************************************
|
||||||
// (c) 2013 AG1LE Mauri Niininen
|
// (c) 2013,2014 AG1LE Mauri Niininen
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
int morse::transl_(int *ltr)
|
int morse::transl_(int *ltr)
|
||||||
|
|
Plik binarny nie jest wyświetlany.
Ładowanie…
Reference in New Issue