1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22
23
24 #include "globdef.h"
25 #include "uidef.h"
26 #include "sigdef.h"
27 #include "screendef.h"
28 #include "fft1def.h"
29 #include "options.h"
30 #include "llsqdef.h"
31 #include "fft3def.h"
32
33 #define MIN_DASHNO 8
34 #define CW_CORRELATE_GOODLEN 25
35 #define MIN_CORRELATE_SEP 70
36 #define MAX_CORRSUM 10
37 #define OVFL_PROTECT 0.00000000000000001
38 #define MORSE_CLOCK_COH_TIME 16
39
40
41 #define ZZ 0.000001
42 // name data length
43 // CW_DASH |---_| 4
44 // CW_DOT |-_| 2
45 // CW_SPACE |__| 2
46 // CW_WORDSEP |____| 4
47
48 void check_cw(int num,int type);
49 void first_morse_decode(void);
50 void continued_morse_decode(void);
51 void show_cw(char *caller);
52
53 // *********************************************************
54 // *********************************************************
55 // These defines allow a lot of information to be written to dmp
56 // define DUMPFILE 1 in main.c to use this.
57 #if DUMPFILE == TRUE
58 #define PR00 0
59 #define PR01 0
60 #define PR02 1
61 #define PR03 0
62 #define PR04 0
63 #define PR05 0
64 #define PR06 0
65 #define PR07 0
66 #define PR08 0
67 #define PR09 0
68 #define PR10 0
69 #else
70 #define PR00 0
71 #define PR01 0
72 #define PR02 0
73 #define PR03 0
74 #define PR04 0
75 #define PR05 0
76 #define PR06 0
77 #define PR07 0
78 #define PR08 0
79 #define PR09 0
80 #define PR10 0
81 #endif
82
83
84 #define PRT00 if(PR00 != 0)DEB
85 #define PRT01 if(PR01 != 0)DEB
86 #define PRT02 if(PR02 != 0)DEB
87 #define PRT03 if(PR03 != 0)DEB
88 #define PRT04 if(PR04 != 0)DEB
89 #define PRT05 if(PR05 != 0)DEB
90 #define PRT06 if(PR06 != 0)DEB
91 #define PRT07 if(PR07 != 0)DEB
92 #define PRT08 if(PR08 != 0)DEB
93 #define PRT09 if(PR09 != 0)DEB
94 #define PRT10 if(PR10 != 0)DEB
95 // *********************************************************
96 // *********************************************************
97
98 // float[2] baseb_out=data to send to loudspeaker
99 // float[2] baseb=complex amplitude of first level coherent data.
100 // float[2] baseb_raw=complex amplitude of baseband signal. Raw data, pol. adapted.
101 // float[2] baseb_raw_orthog=complex amplitude of pol. orthog signal. Raw data.
102 // float[2] baseb_carrier=phase of carrier. Complex data, cosines and sines.
103 // float[1] baseb_carrier_ampl=amplitude of carrier
104 // float[1] baseb_totpwr=total power of baseb_raw
105 // float[2] baseb_envelope=complex amplitude from fitted dots and dashes.
106 // float[1] baseb_upthreshold=forward peak detector for power
107 // float[1] baseb_threshold=combined forward and backward peak detector at -6dB
108 // float[2] baseb_fit=fitted dots and dashes.
109 // float[2] baseb_tmp=array for intermediate data in complex format
110 // float[2] baseb_sho1=array for showing intermediate data in complex format
111 // float[2] baseb_sho2=array for showing intermediate data in complex format
112 // float[1] baseb_agc_level=used only when AGC is enabled.
113 // short int[1] baseb_ramp=indicator for time of power above/below threshold.
114 // short_int[1] baseb_clock=CW code clock
115 // float[2] baseb_tmp=for debug during development
116
117 // baseb_pa The starting point of the latest mix2.size/2 points.
118 // baseb_pb The point up to which thresholds exist.
119 // baseb_pc The point up to which cw speed statistics and ramp is collected.
120 // baseb_pd A key up region close before baseb_pc
121 // baseb_pe The point up to which we have run first detect.
122 // baseb_pf
123 // baseb_px The oldest point that contains valid data.
124
125 int best_corr_ia;
126 int best_corr_ib;
127 float best_corr_ampl;
128 int corr_len;
129 int no_of_corr;
130 int msig_ptr;
131 float msig_signal;
132 float msig_noise;
133
134 #define MAX_GUESS_DATA 100
135 typedef struct {
136 float pos;
137 float re;
138 float im;
139 float noise;
140 int wei;
141 } GUESS_DATA;
142
143 GUESS_DATA msig[MAX_GUESS_DATA];
144
145 typedef struct {
146 int pos;
147 int sep;
148 float fpos;
149 float val;
150 } CORR_INFO;
151
152 CORR_INFO corr[MAX_CORRSUM];
153 CORR_INFO tmpcorr;
154
show_msig(int ic)155 void show_msig(int ic)
156 {
157 int k;
158 for(k=0; k<ic; k++)
159 {
160 fprintf( dmp,"\nmsig[%d] [%.1f]=%f, (%f,%f) W=%d",k,msig[k].pos,
161 msig[k].pos/cwbit_pts,ZZ*msig[k].re,ZZ*msig[k].im,msig[k].wei);
162 }
163 }
164
165
fit_msig(void)166 void fit_msig(void)
167 {
168 int i, k, m;
169 float t1, r1, re, im, midpoint;
170 // The structure msig[0] to msig[msig_ptr-1] contains complex amplitudes
171 // that are hopefully reasonably well synchronized to the Morse symbol clock.
172 // msig[].wei is > 0 for those points that the current guess assumes
173 // the key is pressed. Fit a slowly varying complex amplitude to
174 // all points with wei > 0.
175
176 // The time interval contained in msig is typically 30 ticks of the
177 // morse symbol clock.
178 // Over a short time like this, the complex amplitude of the
179 // carrier can not change very much so we should only fit a
180 // small number of parameters to describe it.
181 t1=msig[msig_ptr-1].pos-msig[0].pos;
182 if(t1<0)t1+=baseband_size;
183 t1/=2;
184 midpoint=msig[0].pos+t1;
185 if(midpoint >= baseband_size)midpoint+=baseband_size;
186 t1=sqrt(t1);
187 llsq_neq=0;
188 for(i=0; i<msig_ptr; i++)
189 {
190 if(msig[i].wei > 0)llsq_neq++;
191 }
192 llsq_errors=fftn_tmp;
193 llsq_derivatives=&llsq_errors[2*llsq_neq];
194 k=0;
195 for(i=0; i<msig_ptr; i++)
196 {
197 if(msig[i].wei > 0)
198 {
199 llsq_errors[2*k ]=msig[i].re*msig[i].wei;
200 llsq_errors[2*k+1]=msig[i].im*msig[i].wei;
201 llsq_derivatives[k]=t1*msig[i].wei;
202 r1=msig[i].pos-midpoint;
203 if(r1<-(baseband_size>>1))r1+=baseband_size;
204 llsq_derivatives[llsq_neq+k]=r1*msig[i].wei;
205 llsq_derivatives[2*llsq_neq+k]=r1*r1*msig[i].wei;
206 llsq_derivatives[3*llsq_neq+k]=r1*r1*r1*msig[i].wei/t1;
207 k++;
208 }
209 }
210 llsq_npar=4;
211 if(llsq2() != 0)
212 {
213 lirerr(9361050);
214 return;
215 }
216 // compute signal and noise
217
218 msig_noise=0;
219 msig_signal=0;
220 k=0;
221 m=0;
222 for(i=0; i<msig_ptr; i++)
223 {
224 if(msig[i].wei > 0)
225 {
226 llsq_errors[2*k ]=msig[i].re*msig[i].wei;
227 llsq_errors[2*k+1]=msig[i].im*msig[i].wei;
228 llsq_derivatives[k]=t1*msig[i].wei;
229 r1=msig[i].pos-midpoint;
230 if(r1<-(baseband_size>>1))r1+=baseband_size;
231 re=t1*llsq_steps[0]+r1*llsq_steps[2]+r1*r1*llsq_steps[4]+r1*r1*r1*llsq_steps[6]/t1;
232 im=t1*llsq_steps[1]+r1*llsq_steps[3]+r1*r1*llsq_steps[5]+r1*r1*r1*llsq_steps[7]/t1;
233 msig_signal+=msig[i].wei*(re*re+im*im);
234 re-=msig[i].re;
235 im-=msig[i].im;
236 // Dashes integrate 3 times longer so their noise is sqrt(3) smaller.
237 // Take that into account.
238 // A region with noise only would give Ndots=n1*n1+n2*n2+n3*n3 when
239 // evaluated as a dot (assume n1=n2=n3 on the average) so the
240 // noise contribution from a false dash would be Ndots=3*n*n.
241 // When evaluated as a dash, Ndash=3*n4*n4, because we have three parts
242 // with the same complex amplitude n4. n4 is n/sqrt(3) on the average
243 // because of the longer integration time so when evaluating as a
244 // dash we would get 3 times less noise when there is no signal.
245 // Therefore, multiply the contribution to msig_noise by 9 for a dash.
246 re*=msig[i].wei;
247 im*=msig[i].wei;
248 msig_noise+=msig[i].wei*(re*re+im*im);
249 m+=msig[i].wei;
250 k++;
251 }
252 else
253 {
254 if(msig[i].wei == 0)msig_noise+=msig[i].noise;
255 }
256 }
257 msig_signal=sqrt(msig_signal/m);
258 msig_noise=sqrt(msig_noise/msig_ptr);
259 }
260
261
store_msig(int k)262 void store_msig(int k)
263 {
264 int j;
265 switch (cw[k].type)
266 {
267 case CW_DOT:
268 // CW_DOT |-_| 2
269 // ^
270 msig[msig_ptr].pos=cw[k].midpoint;
271 msig[msig_ptr].wei=1;
272 msig[msig_ptr].re=cw[k].raw_re;
273 msig[msig_ptr].im=cw[k].raw_im;
274 msig_ptr++;
275 cg_wave_midpoint=cw[k].midpoint+cwbit_pts;
276 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
277 msig[msig_ptr].pos=cg_wave_midpoint;
278 wb_investigate_region(cg_wave_midpoint, 1);
279 msig[msig_ptr].re=reg_dot_re[0];
280 msig[msig_ptr].im=reg_dot_im[0];
281 msig[msig_ptr].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
282 msig[msig_ptr].wei=0;
283 msig_ptr++;
284 break;
285
286 case CW_SPACE:
287 // CW_SPACE |__| 2
288 // ^
289 cg_wave_midpoint=cw[k].midpoint;
290 msig[msig_ptr].pos=cg_wave_midpoint;
291 wb_investigate_region(cg_wave_midpoint, 1);
292 msig[msig_ptr].re=reg_dot_re[0];
293 msig[msig_ptr].im=reg_dot_im[0];
294 msig[msig_ptr].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
295 msig[msig_ptr].wei=0;
296 msig_ptr++;
297 cg_wave_midpoint+=cwbit_pts;
298 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
299 msig[msig_ptr].pos=cg_wave_midpoint;
300 wb_investigate_region(cg_wave_midpoint, 1);
301 msig[msig_ptr].re=reg_dot_re[0];
302 msig[msig_ptr].im=reg_dot_im[0];
303 msig[msig_ptr].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
304 msig[msig_ptr].wei=0;
305 msig_ptr++;
306 break;
307
308 case CW_DASH:
309 // CW_DASH |---_| 4
310 // ^
311 msig[msig_ptr].pos=cw[k].midpoint-cwbit_pts;
312 msig[msig_ptr].wei=0;
313 msig[msig_ptr].re=0;
314 msig[msig_ptr].im=0;
315 msig[msig_ptr].noise=0;
316 msig_ptr++;
317 msig[msig_ptr].pos=cw[k].midpoint;
318 msig[msig_ptr].wei=3;
319 msig[msig_ptr].re=cw[k].raw_re;
320 msig[msig_ptr].im=cw[k].raw_im;
321 msig_ptr++;
322 msig[msig_ptr].pos=cw[k].midpoint+cwbit_pts;
323 cg_wave_midpoint=msig[msig_ptr].pos;
324 msig[msig_ptr].wei=0;
325 msig[msig_ptr].re=0;
326 msig[msig_ptr].im=0;
327 msig[msig_ptr].noise=0;
328 msig_ptr++;
329 cg_wave_midpoint+=cwbit_pts;
330 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
331 msig[msig_ptr].pos=cg_wave_midpoint;
332 wb_investigate_region(cg_wave_midpoint, 1);
333 msig[msig_ptr].re=reg_dot_re[0];
334 msig[msig_ptr].im=reg_dot_im[0];
335 msig[msig_ptr].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
336 msig[msig_ptr].wei=0;
337 msig_ptr++;
338 break;
339
340 case CW_WORDSEP:
341 // CW_WORDSEP |____| 4
342 // ^
343 cg_wave_midpoint=cw[k].midpoint;
344 wb_investigate_region(cg_wave_midpoint, 3);
345 cg_wave_midpoint-=cwbit_pts;
346 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
347 for(j=0; j<3; j++)
348 {
349 msig[msig_ptr].pos=cg_wave_midpoint;
350 msig[msig_ptr].re=reg_dot_re[j];
351 msig[msig_ptr].im=reg_dot_im[j];
352 msig[msig_ptr].noise=reg_dot_re[j]*reg_dot_re[j]+reg_dot_im[j]*reg_dot_im[j];
353 msig[msig_ptr].wei=0;
354 msig_ptr++;
355 cg_wave_midpoint+=cwbit_pts;
356 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
357 }
358 msig[msig_ptr].pos=cg_wave_midpoint;
359 wb_investigate_region(cg_wave_midpoint, 1);
360 msig[msig_ptr].re=reg_dot_re[0];
361 msig[msig_ptr].im=reg_dot_im[0];
362 msig[msig_ptr].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
363 msig[msig_ptr].wei=0;
364 msig_ptr++;
365 break;
366
367 default:
368 lirerr(874529);
369 break;
370 }
371 }
372
fill_known_high_msig(void)373 void fill_known_high_msig(void)
374 {
375 int k, dist;
376 // ptr points to a decoded Morse part in the CW array.
377 // Step downwards through decoded parts until the first
378 // undecoded is encountered or until the total distance is
379 // 10 parts.
380 show_cw("----- fill high guesses -----");
381 dist=0;
382 k=cw_ptr+1;
383 if(cw[k].unkn == 0)lirerr(8835263);
384 store_msig(k);
385 k++;
386 while(k<no_of_cwdat && cw[k].unkn == 0 && dist < 10)
387 {
388 dist+=cw[k].len;
389 store_msig(k);
390 k++;
391 }
392 }
393
fill_known_low_msig(void)394 void fill_known_low_msig(void)
395 {
396 int k, dist;
397 // ptr points to a decoded Morse part in the CW array.
398 // Step downwards through decoded parts until the first
399 // undecoded is encountered or until the total distance is
400 // 10 parts.
401 dist=0;
402 k=cw_ptr;
403 while(k>0 && cw[k].unkn == 0 && dist < 10)
404 {
405 dist+=cw[k].len;
406 k--;
407 }
408 // fill known info into msig.
409 while(k<cw_ptr || cw[k].unkn == 0)
410 {
411 store_msig(k);
412 k++;
413 }
414 }
415
check_hguess3(int val,int bits,int charval_dwn_rev,int charbits_dwn)416 char check_hguess3(int val, int bits, int charval_dwn_rev, int charbits_dwn)
417 {
418 int i, m, charbits, charval;
419 charbits=bits+charbits_dwn+2;
420 if(charbits > 6)return FALSE;
421 charval=val<<2;
422 m=charval_dwn_rev;
423 for(i=0; i<charbits_dwn; i++)
424 {
425 charval<<=1;
426 charval+=m&1;
427 m>>=1;
428 }
429 if(morsascii[charbits-1][charval] == 242 ||
430 morsascii[charbits-1][charval] == 243)return FALSE;
431 return TRUE;
432 }
433
check_hguess4(int val,int bits,int charval_dwn_rev,int charbits_dwn)434 char check_hguess4(int val, int bits, int charval_dwn_rev, int charbits_dwn)
435 {
436 int i, m, charbits, charval;
437 charbits=bits+charbits_dwn+1;
438 if(charbits > 6)return FALSE;
439 charval=val<<1;
440 charval++;
441 m=charval_dwn_rev;
442 for(i=0; i<charbits_dwn; i++)
443 {
444 charval<<=1;
445 charval+=m&1;
446 m>>=1;
447 }
448 if(morsascii[charbits-1][charval] == 242 ||
449 morsascii[charbits-1][charval] == 243)return FALSE;
450 return TRUE;
451 }
452
check_hguess3a(int val,int bits,int charval_dwn_rev,int charbits_dwn)453 char check_hguess3a(int val, int bits, int charval_dwn_rev, int charbits_dwn)
454 {
455 int i, m, charbits, charval;
456 charbits=bits+charbits_dwn+1;
457 if(charbits > 6)return FALSE;
458 charval=val<<1;
459 m=charval_dwn_rev;
460 for(i=0; i<charbits_dwn; i++)
461 {
462 charval<<=1;
463 charval+=m&1;
464 m>>=1;
465 }
466 if(morsascii[charbits-1][charval] == 242 ||
467 morsascii[charbits-1][charval] == 243)return FALSE;
468 return TRUE;
469 }
470
check_hguess4a(int val,int bits,int charval_dwn_rev,int charbits_dwn)471 char check_hguess4a(int val, int bits, int charval_dwn_rev, int charbits_dwn)
472 {
473 int i, m, charbits, charval;
474 charbits=bits+charbits_dwn;
475 if(charbits > 6)return FALSE;
476 charval=val;
477 m=charval_dwn_rev;
478 for(i=0; i<charbits_dwn; i++)
479 {
480 charval<<=1;
481 charval+=m&1;
482 m>>=1;
483 }
484 if(morsascii[charbits-1][charval] == 242 ||
485 morsascii[charbits-1][charval] == 243)return FALSE;
486 return TRUE;
487 }
488
part_guesses(void)489 int part_guesses(void)
490 {
491 // Look for long undecoded regions where a decision might be certain
492 // enough based on an extrapolation from the surrounding decoded
493 // regions.
494
495 return 0;
496 }
497
character_guesses(void)498 int character_guesses(void)
499 {
500 char lguess_flag[7],hguess_flag[5],guess_flag[7][5];
501 int charval_up, charbits_up;
502 int charval_dwn, charval_dwn_rev, charbits_dwn;
503 int added_parts;
504 int i, j, k, m, ia, ib, ic, gap, iptr;
505 int nlg, nhg, mlg, mhg;
506 int val, bits;
507 float r1, t1;
508 float dash_re[3], dash_im[3];
509 float dot_re[20], dot_im[20],dot_pwr[20];
510 // We have dashes and hopefully some dots and separators.
511 // Look for a space or a word separator and try to decode upwards.
512 show_cw(" char guesses");
513 cw_ptr=0;
514 added_parts=0;
515 region_guesses:;
516 show_cw(" char guesses");
517 while(cw_ptr < no_of_cwdat &&
518 cw[cw_ptr].type != CW_WORDSEP &&
519 cw[cw_ptr].type != CW_SPACE)cw_ptr++;
520 fprintf( dmp,"\nCHARGUESS cw_ptr=%d",cw_ptr);
521 if(cw_ptr < no_of_cwdat)
522 {
523 // We have a separator here!
524 // Check for an undecoded region above it.
525 iptr=cw_ptr+1;
526 while(iptr < no_of_cwdat && cw[iptr].unkn == 0)
527 {
528 if( cw[iptr].type == CW_WORDSEP || cw[iptr].type == CW_SPACE)cw_ptr=iptr;
529 iptr++;
530 }
531 fprintf( dmp,"\ncw_ptr %d iptr %d",cw_ptr,iptr);
532 if(iptr < no_of_cwdat-1)
533 {
534 charval_up=0;
535 charbits_up=0;
536 k=cw_ptr;
537 k++;
538 while(k < iptr)
539 {
540 charbits_up++;
541 charval_up<<=1;
542 if(cw[k].type==CW_DASH)charval_up++;
543 k++;
544 }
545 gap=cw[iptr].unkn;
546 fprintf( dmp,"\ngap=%d iptr %d",gap,iptr);
547 fprintf( dmp,"\nbits %d val %d %c", charbits_up,charval_up,
548 morsascii[charbits_up-1][charval_up]);
549 if(charbits_up > 6 ||
550 morsascii[charbits_up-1][charval_up] == 243 ||
551 gap >= 16 ||
552 gap <= 4 ||
553 cw[iptr].type == CW_WORDSEP ||
554 cw[iptr].type == CW_SPACE)
555 {
556 cw_ptr=iptr;
557 fprintf( dmp,"\nERROR below");
558 // This is an error. Do nothing for now.
559 goto region_guesses;
560 }
561 // We here have a sequence like this:
562 // known-_??????????????_-known
563 // gap is the length of the undecoded region and it has to be
564 // an even number.
565 msig_ptr=0;
566 // This is a small gap. Use the information from decoded dots and
567 // dashes from both sides of the region.
568 cw_ptr=iptr-1;
569 fill_known_low_msig();
570 ia=msig_ptr;
571 msig_ptr+=gap;
572 ib=msig_ptr;
573 fill_known_high_msig();
574 ic=msig_ptr;
575 cg_wave_midpoint=msig[ib].pos-cwbit_pts;
576 ib--;
577 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
578 wb_investigate_region(cg_wave_midpoint, 1);
579 msig[ib].pos=cg_wave_midpoint;
580 msig[ib].re=reg_dot_re[0];
581 msig[ib].im=reg_dot_im[0];
582 msig[ib].noise=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
583 msig[ib].wei=0;
584 // We will fill in different guesses in the region ia to ib.
585 // First we fill in what is known above the undecoded region.
586 // note that we do not trust the symbol clock speed very much -
587 // we only use it 4 positions into the unknown region from
588 // either side. The operator could use hand keying and
589 // the length of dots, dashes and separators could be
590 // deviating from the nominal values.
591 t1=msig[ia-1].pos;
592 for(k=ia; k<ib; k++)
593 {
594 t1+=cwbit_pts;
595 if(t1>=baseband_size)t1-=baseband_size;
596 msig[k].pos=t1;
597 msig[k].re=0;
598 msig[k].im=k;
599 msig[k].wei=-1;
600 }
601 ib--;
602 t1=cg_wave_midpoint;
603 k=1+(ia+ib)/2;
604 t1-=(ib-k+2)*cwbit_pts;
605 if(t1<0)t1+=baseband_size;
606 while(k<=ib)
607 {
608 t1+=cwbit_pts;
609 if(t1>=baseband_size)t1-=baseband_size;
610 msig[k].pos=t1;
611 k++;
612 }
613 // The Morse code goes in units of 2 or 4.
614 // The region has key-down at both ends so we know that the first
615 // pand the last points in the gap region must be key-up.
616 // Here are all possible guesses for the beginning:
617 // ****-_____?????_-**** lguess 0
618 // ****-___-_?????_-**** lguess 1
619 // ****-_-___?????_-**** lguess 2
620 // ****-_-_-_?????_-**** lguess 3
621 // ****-_---_?????_-**** lguess 4
622 // ****-___--?????_-**** lguess 5
623 // ****-_-_--?????_-**** lguess 6
624 // ia^
625 // 0123
626 //
627 // Here are all possible guesses for the end:
628 // ****-_?????____-**** hguess 0
629 // ****-_?????-___-**** hguess 1
630 // ****-_?????__-_-**** hguess 2
631 // ****-_?????-_-_-**** hguess 3
632 // ****-_?????---_-**** hguess 4
633 // ib^
634 // 210
635 //
636 // In all we have 35 guesses, but many of them are likely
637 // to be impossible since the decoded data would not fit
638 // the Morse alphabet.
639 for(nlg=0; nlg<7; nlg++)lguess_flag[nlg]=TRUE;
640 for(nhg=0; nhg<5; nhg++)hguess_flag[nhg]=TRUE;
641 // Fill in acceptable guesses in lguess_flag.
642 if(charbits_up == 6)
643 {
644 // This is the maximum length for a Morse character.
645 // Skip if not legal, force key-up otherwise.
646 if(morsascii[charbits_up-1][charval_up] == 243)
647 {
648 fprintf( dmp,"\nERROR above");
649 goto skip_guesses;
650 }
651 lguess_flag[2]=FALSE;
652 lguess_flag[3]=FALSE;
653 lguess_flag[4]=FALSE;
654 lguess_flag[6]=FALSE;
655 }
656 else
657 {
658 if(charbits_up == 5)
659 {
660 // Skip guesses that would add more than one part.
661 lguess_flag[3]=FALSE;
662 lguess_flag[6]=FALSE;
663 // In case the character is not legal, but adding one part
664 // could make it legal, skip guesses that do not add one part.
665 if(morsascii[charbits_up-1][charval_up] == 242)
666 {
667 lguess_flag[0]=FALSE;
668 lguess_flag[1]=FALSE;
669 lguess_flag[5]=FALSE;
670 }
671 // Check whether adding a dot would give a legal character.
672 if(morsascii[charbits_up][charval_up<<1] == 243)
673 {
674 lguess_flag[2]=FALSE;
675 }
676 // Check whether adding a dash would give a legal character.
677 if(morsascii[charbits_up][(charval_up<<1)+1] == 243)
678 {
679 lguess_flag[4]=FALSE;
680 }
681 }
682 else
683 {
684 if(charbits_up == 4)
685 {
686 if(morsascii[charbits_up][charval_up<<1] == 243)
687 {
688 lguess_flag[2]=FALSE;
689 }
690 if(morsascii[charbits_up+1][charval_up<<2] == 243)
691 {
692 lguess_flag[3]=FALSE;
693 }
694 if(morsascii[charbits_up][(charval_up<<1)+1] == 243)
695 {
696 lguess_flag[4]=FALSE;
697 }
698 if(morsascii[charbits_up+1][(charval_up<<2)+1] == 243)
699 {
700 lguess_flag[6]=FALSE;
701 }
702 }
703 }
704 }
705 // Look for a separator upwards.
706 k=iptr+1;
707 while( k < no_of_cwdat &&
708 cw[k].unkn==0 &&
709 cw[k].type != CW_WORDSEP &&
710 cw[k].type != CW_SPACE)k++;
711 if( k == no_of_cwdat || cw[k].unkn != 0)goto skip_guesses;
712 // There is a known separator above the current region.
713 // Decode it downwards.
714 charbits_dwn=0;
715 charval_dwn_rev=0;
716 while(k > iptr)
717 {
718 charval_dwn_rev<<=1;
719 k--;
720 if(cw[k].type==CW_DASH)charval_dwn_rev++;
721 charbits_dwn++;
722 }
723 if(charbits_dwn > 6)goto skip_guesses;
724 k=0;
725 m=charval_dwn_rev;
726 for(i=0; i<charbits_dwn; i++)
727 {
728 k<<=1;
729 k+=m&1;
730 m>>=1;
731 }
732 charval_dwn=k;
733 if(charbits_dwn==6)
734 {
735 if(morsascii[charbits_dwn-1][charval_dwn] == 243)
736 {
737 goto skip_guesses;
738 }
739 hguess_flag[2]=FALSE;
740 hguess_flag[3]=FALSE;
741 hguess_flag[4]=FALSE;
742 }
743 else
744 {
745 if(charbits_dwn==5)
746 {
747 hguess_flag[3]=FALSE;
748 if(morsascii[charbits_dwn-1][charval_dwn] == 243)
749 {
750 hguess_flag[0]=FALSE;
751 hguess_flag[1]=FALSE;
752 }
753 if(morsascii[charbits_dwn][charval_dwn] == 243)
754 {
755 hguess_flag[2]=FALSE;
756 }
757 if(morsascii[charbits_dwn][charval_dwn+32] == 243)
758 {
759 hguess_flag[4]=FALSE;
760 }
761 }
762 else
763 {
764 if(charbits_dwn==4)
765 {
766 if(morsascii[charbits_dwn+1][charval_dwn] == 243)
767 {
768 hguess_flag[3]=FALSE;
769 }
770 }
771 }
772 }
773 for(nlg=0;nlg<7;nlg++)
774 {
775 for(nhg=0;nhg<5;nhg++)
776 {
777 guess_flag[nlg][nhg]=lguess_flag[nlg]&hguess_flag[nhg];
778 }
779 }
780 if(gap == 8)
781 {
782 // The regions touch each other.
783 // We can not combine lguesses 5 and 6 with hguesses 0,2 or 4
784 for(i=5; i<=6; i++)
785 {
786 for(j=0; j<=4; j+=2)
787 {
788 guess_flag[i][j]=FALSE;
789 }
790 }
791 // When we combine lguesses and hguesses that both contain no
792 // space or word separator, the entire region has to be a valid
793 // Morse code.
794 // We have to check l=3,4,6 combined with h=3,4
795 // **************************************************
796 // lguess=3
797 val=charval_up<<2;
798 bits=charbits_up+2;
799 guess_flag[3][3]=check_hguess3(val, bits, charval_dwn_rev, charbits_dwn);
800 guess_flag[3][4]=check_hguess4(val, bits, charval_dwn_rev, charbits_dwn);
801 // lguess=4
802 val=(charval_up<<1)+1;
803 bits=charbits_up+1;
804 guess_flag[4][3]=check_hguess3(val, bits, charval_dwn_rev, charbits_dwn);
805 guess_flag[4][4]=check_hguess4(val, bits, charval_dwn_rev, charbits_dwn);
806 // lguess=6
807 val=(charval_up<<2)+1;
808 bits=charbits_up+2;
809 guess_flag[6][3]=check_hguess3a(val, bits, charval_dwn_rev, charbits_dwn);
810 }
811 else
812 {
813 if(gap == 6)
814 {
815 // Two positions overlap. Make all combinations that have
816 // different patterns in the overlapping region illegal.
817 guess_flag[0][1]=FALSE;
818 guess_flag[0][3]=FALSE;
819 guess_flag[0][4]=FALSE;
820 guess_flag[1][0]=FALSE;
821 guess_flag[1][2]=FALSE;
822 guess_flag[1][4]=FALSE;
823 guess_flag[2][1]=FALSE;
824 guess_flag[2][3]=FALSE;
825 guess_flag[2][4]=FALSE;
826 guess_flag[3][0]=FALSE;
827 guess_flag[3][2]=FALSE;
828 guess_flag[3][4]=FALSE;
829 guess_flag[4][0]=FALSE;
830 guess_flag[4][2]=FALSE;
831 guess_flag[4][4]=FALSE;
832 guess_flag[5][0]=FALSE;
833 guess_flag[5][1]=FALSE;
834 guess_flag[5][2]=FALSE;
835 guess_flag[5][3]=FALSE;
836 guess_flag[6][0]=FALSE;
837 guess_flag[6][1]=FALSE;
838 guess_flag[6][2]=FALSE;
839 guess_flag[6][3]=FALSE;
840 // When we combine lguesses and hguesses without any space
841 // or word separator, the entire region has to be a valid
842 // Morse code.
843 // We have to check lguess=3,4,6 when combined with hguess=2,3,4
844 // **************************************************
845 // lguess=3: only hguess=3 is possible.
846 val=charval_up<<1;
847 bits=charbits_up+1;
848 guess_flag[3][3]=check_hguess3(val, bits, charval_dwn_rev, charbits_dwn);
849 // lguess=4: only hguess=3 is possible.
850 val=(charval_up<<1)+1;
851 bits=charbits_up+1;
852 guess_flag[4][3]=check_hguess3a(val, bits, charval_dwn_rev, charbits_dwn);
853 // lguess=6: only hguess=4 is possible.
854 val=(charval_up<<2)+1;
855 bits=charbits_up+2;
856 guess_flag[6][4]=check_hguess4a(val, bits, charval_dwn_rev, charbits_dwn);
857 }
858 }
859
860 fprintf( dmp,"\nib-ia %d, gap %d",ib-ia,gap);
861 fprintf( dmp,"\nia %d ib %d",ia,ib);
862 for(k=1; k<msig_ptr; k++)
863 fprintf( dmp,"\n%d %f (%f,%f) %d %f",k,msig[k].pos,ZZ*msig[k].re,ZZ*msig[k].im,msig[k].wei,msig[k].pos-msig[k-1].pos);
864 for(k=0; k<7; k++)fprintf( dmp,"\nlguess_flag[%d] %d",k,lguess_flag[k]);
865 for(k=0; k<5; k++)fprintf( dmp,"\nhguess_flag[%d] %d",k,hguess_flag[k]);
866 fprintf( dmp,"\n");
867 for(i=0; i<7; i++)
868 {
869 fprintf( dmp,"\n");
870 for(j=0; j<5; j++)fprintf( dmp,"[%d][%d] %d ",i,j,guess_flag[i][j]);
871 }
872 fprintf( dmp,"\n");
873 show_msig(ic);
874
875
876
877 // *****************************************************************
878 // Prepare to set up msig for all allowed guesses.
879 // Dashes may be placed at ia+1 and at ib-2.
880 cg_wave_midpoint=msig[ia+1].pos;
881 wb_investigate_region(cg_wave_midpoint, -5);
882 dash_re[0]=reg_dash_re;
883 dash_im[0]=reg_dash_im;
884 cg_wave_midpoint=msig[ia+3].pos;
885 wb_investigate_region(cg_wave_midpoint, -5);
886 dash_re[1]=reg_dash_re;
887 dash_im[1]=reg_dash_im;
888
889
890 cg_wave_midpoint=msig[ib-2].pos;
891 wb_investigate_region(cg_wave_midpoint, -5);
892 dash_re[2]=reg_dash_re;
893 dash_im[2]=reg_dash_im;
894 for(k=ia; k<ib; k++)
895 {
896 cg_wave_midpoint=msig[k].pos;
897 wb_investigate_region(cg_wave_midpoint, 1);
898 dot_re[k-ia]=reg_dot_re[0];
899 dot_im[k-ia]=reg_dot_im[0];
900 dot_pwr[k-ia]=reg_dot_re[0]*reg_dot_re[0]+reg_dot_im[0]*reg_dot_im[0];
901 }
902 // Fill in all allowed guesses in msig one by one.
903 // Fit a smooth function to the carrier at those points where there
904 // is a key down according to the current guess.
905 // Compute the associated RMS error (noise) and average carrier
906 // amplitude (signal.) Remember S and N for each valid guess.
907 r1=0;
908 mlg=-1;
909 mhg=-1;
910 for(nlg=0; nlg<7; nlg++)
911 {
912 if(lguess_flag[nlg] == TRUE)
913 {
914 for(k=0; k<4; k++)
915 {
916 msig[ia+k].wei=0;
917 msig[ia+k].re=dot_re[k];
918 msig[ia+k].im=dot_im[k];
919 msig[ia+k].noise=dot_pwr[k];
920 }
921 switch (nlg)
922 {
923 case 0:
924 // ****-_____?????_-**** lguess 0
925 // ia^
926 // 0123
927 break;
928
929 case 1:
930 // ****-___-_?????_-**** lguess 1
931 // ia^
932 // 0123
933 msig[ia+2].wei=1;
934 break;
935
936 case 2:
937 // ****-_-___?????_-**** lguess 2
938 // ia^
939 // 0123
940 msig[ia].wei=1;
941 break;
942
943 case 3:
944 // ****-_-_-_?????_-**** lguess 3
945 // ia^
946 // 0123
947 msig[ia].wei=1;
948 msig[ia+2].wei=1;
949 break;
950
951 case 4:
952 // ****-_---_?????_-**** lguess 4
953 // ia^
954 // 0123
955 msig[ia ].wei=0;
956 msig[ia ].re=0;
957 msig[ia ].im=0;
958 msig[ia ].noise=0;
959 msig[ia+1].wei=3;
960 msig[ia+1].re=dash_re[0];
961 msig[ia+1].im=dash_im[0];
962 msig[ia+1].noise=dash_re[0]*dash_re[0]+dash_im[0]*dash_im[0];
963 msig[ia+2].wei=0;
964 msig[ia+2].re=0;
965 msig[ia+2].im=0;
966 msig[ia+2].noise=0;
967 break;
968
969 case 5:
970 // ****-___--?????_-**** lguess 5
971 // ia^
972 // 0123
973 msig[ia+2].wei=1;
974 msig[ia+3].wei=1;
975 break;
976
977 case 6:
978 // ****-_-_--?????_-**** lguess 6
979 // ia^
980 // 0123
981 msig[ia ].wei=1;
982 msig[ia+2].wei=1;
983 msig[ia+3].wei=1;
984 break;
985 }
986 for(nhg=0; nhg<5; nhg++)
987 {
988 if(guess_flag[nlg][nhg]==TRUE)
989 {
990 for(k=ib-ia-3; k<ib-ia; k++)
991 {
992 msig[ia+k].wei=0;
993 msig[ia+k].re=dot_re[k];
994 msig[ia+k].im=dot_im[k];
995 msig[ia+k].noise=dot_pwr[k];
996 }
997 switch (nhg)
998 {
999 case 0:
1000 // ****-_?????____-**** hguess 0
1001 // ib^
1002 // 210
1003 break;
1004
1005 case 1:
1006 // ****-_?????-___-**** hguess 1
1007 // ib^
1008 // 210
1009 msig[ib-2].wei=1;
1010 break;
1011
1012 case 2:
1013 // ****-_?????__-_-**** hguess 2
1014 // ib^
1015 // 210
1016 msig[ib].wei=1;
1017 break;
1018
1019 case 3:
1020 // ****-_?????-_-_-**** hguess 3
1021 // ib^
1022 // 210
1023 msig[ib].wei=1;
1024 msig[ib-2].wei=1;
1025 break;
1026
1027 case 4:
1028 // ****-_?????---_-**** hguess 4
1029 // ib^
1030 // 210
1031 msig[ib-2].wei=0;
1032 msig[ib-2].re=0;
1033 msig[ib-2].im=0;
1034 msig[ib-2].noise=0;
1035 msig[ib-1].wei=3;
1036 msig[ib-1].re=dash_re[2];
1037 msig[ib-1].im=dash_im[2];
1038 msig[ib-1].noise=dash_re[2]*dash_re[2]+dash_im[2]*dash_im[2];
1039 msig[ib].wei=0;
1040 msig[ib].re=0;
1041 msig[ib].im=0;
1042 msig[ib].noise=0;
1043 break;
1044 }
1045
1046 fit_msig();
1047 t1=msig_signal/msig_noise;
1048 if(t1 > r1)
1049 {
1050 r1=t1;
1051 mhg=nhg;
1052 mlg=nlg;
1053 }
1054 }
1055 }
1056 }
1057 }
1058 // Implement the best guess.
1059 if(mlg < 0)goto skip_guesses;
1060 cw_ptr=iptr;
1061
1062 fprintf( dmp,"\n\n!!!!!!!!!!!! mlg %d mhg %d !!!!!!!!!!!!!",mlg,mhg);
1063 fprintf( dmp,"\nia %d ib %d",ia,ib);
1064 // ****-_____?????_-**** lguess 0
1065 // ****-___-_?????_-**** lguess 1
1066 // ****-_-___?????_-**** lguess 2
1067 // ****-_-_-_?????_-**** lguess 3
1068 // ****-_---_?????_-**** lguess 4
1069 // ****-___--?????_-**** lguess 5
1070 // ****-_-_--?????_-**** lguess 6
1071 // ia^
1072 // 0123
1073 //
1074 // Here are all possible guesses for the end:
1075 // ****-_?????____-**** hguess 0
1076 // ****-_?????-___-**** hguess 1
1077 // ****-_?????__-_-**** hguess 2
1078 // ****-_?????-_-_-**** hguess 3
1079 // ****-_?????---_-**** hguess 4
1080 // ib^
1081 // 210
1082
1083 switch (mlg)
1084 {
1085 case 0:
1086 // ****-_____?????_-**** lguess 0
1087 // ia^
1088 // 0123
1089 cg_wave_raw_re=0;
1090 cg_wave_raw_im=0;
1091 cg_wave_midpoint=msig[ia+1].pos;
1092 insert_item(CW_WORDSEP);
1093 cw_ptr++;
1094 break;
1095
1096 case 1:
1097 // ****-___-_?????_-**** lguess 1
1098 // ia^
1099 // 0123
1100 cg_wave_raw_re=0;
1101 cg_wave_raw_im=0;
1102 cg_wave_midpoint=msig[ia].pos;
1103 insert_item(CW_SPACE);
1104 cw_ptr++;
1105 cg_wave_raw_re=dot_re[2];
1106 cg_wave_raw_im=dot_im[2];
1107 cg_wave_midpoint=msig[ia+2].pos;
1108 insert_item(CW_DOT);
1109 cw_ptr++;
1110 break;
1111
1112 case 2:
1113 // ****-_-___?????_-**** lguess 2
1114 // ia^
1115 // 0123
1116 cg_wave_raw_re=dot_re[0];
1117 cg_wave_raw_im=dot_im[0];
1118 cg_wave_midpoint=msig[ia].pos;
1119 insert_item(CW_DOT);
1120 cw_ptr++;
1121 cg_wave_raw_re=0;
1122 cg_wave_raw_im=0;
1123 cg_wave_midpoint=msig[ia+2].pos;
1124 insert_item(CW_SPACE);
1125 cw_ptr++;
1126 break;
1127
1128 case 3:
1129 // ****-_-_-_?????_-**** lguess 3
1130 // ia^
1131 // 0123
1132 cg_wave_raw_re=dot_re[0];
1133 cg_wave_raw_im=dot_im[0];
1134 cg_wave_midpoint=msig[ia].pos;
1135 insert_item(CW_DOT);
1136 cw_ptr++;
1137 cg_wave_raw_re=dot_re[2];
1138 cg_wave_raw_im=dot_im[2];
1139 cg_wave_midpoint=msig[ia+2].pos;
1140 insert_item(CW_DOT);
1141 cw_ptr++;
1142 break;
1143
1144 case 4:
1145 // ****-_---_?????_-**** lguess 4
1146 // ia^
1147 // 0123
1148 cg_wave_raw_re=dash_re[0];
1149 cg_wave_raw_im=dash_im[0];
1150 cg_wave_midpoint=msig[ia+1].pos;
1151 insert_item(CW_DASH);
1152 cw_ptr++;
1153 break;
1154
1155 case 5:
1156 // ****-___--?????_-**** lguess 5
1157 // ia^
1158 // 0123
1159 cg_wave_raw_re=0;
1160 cg_wave_raw_im=0;
1161 cg_wave_midpoint=msig[ia].pos;
1162 insert_item(CW_SPACE);
1163 cw_ptr++;
1164 if(gap==8)goto gap8_add_dash;
1165 break;
1166
1167 case 6:
1168 // ****-_-_--?????_-**** lguess 6
1169 // ia^
1170 // 0123
1171 cg_wave_raw_re=dot_re[0];
1172 cg_wave_raw_im=dot_im[0];
1173 cg_wave_midpoint=msig[ia].pos;
1174 insert_item(CW_DOT);
1175 cw_ptr++;
1176 if(gap==8)
1177 {
1178 gap8_add_dash:;
1179 cg_wave_raw_re=dash_re[1];
1180 cg_wave_raw_im=dash_im[1];
1181 cg_wave_midpoint=msig[ia+3].pos;
1182 insert_item(CW_DOT);
1183 cw_ptr++;
1184 }
1185 break;
1186
1187 default:
1188 lirerr(634293);
1189 return 0;
1190 }
1191 switch (mhg)
1192 {
1193 case 0:
1194 // ****-_?????____-**** hguess 0
1195 // ib^
1196 // 210
1197 cg_wave_raw_re=0;
1198 cg_wave_raw_im=0;
1199 if(gap==8)
1200 {
1201 cg_wave_midpoint=msig[ib-1].pos;
1202 insert_item(CW_WORDSEP);
1203 }
1204 else
1205 {
1206 cg_wave_midpoint=msig[ib].pos;
1207 insert_item(CW_SPACE);
1208 }
1209 cw_ptr++;
1210 break;
1211
1212 case 1:
1213 // ****-_?????-___-**** hguess 1
1214 // ib^
1215 // 210
1216 if(gap==8)
1217 {
1218 cg_wave_raw_re=dot_re[ib-ia-2];
1219 cg_wave_raw_im=dot_im[ib-ia-2];
1220 cg_wave_midpoint=msig[ib-2].pos;
1221 insert_item(CW_DOT);
1222 cw_ptr++;
1223 }
1224 cg_wave_raw_re=0;
1225 cg_wave_raw_im=0;
1226 cg_wave_midpoint=msig[ib].pos;
1227 insert_item(CW_SPACE);
1228 cw_ptr++;
1229 break;
1230
1231
1232 case 2:
1233 // ****-_?????__-_-**** hguess 2
1234 // ib^
1235 // 210
1236 if(gap==8)
1237 {
1238 cg_wave_raw_re=0;
1239 cg_wave_raw_im=0;
1240 cg_wave_midpoint=msig[ib-2].pos;
1241 insert_item(CW_SPACE);
1242 cw_ptr++;
1243 }
1244 cg_wave_raw_re=dot_re[ib-ia];
1245 cg_wave_raw_im=dot_im[ib-ia];
1246 cg_wave_midpoint=msig[ib].pos;
1247 insert_item(CW_DOT);
1248 cw_ptr++;
1249 break;
1250
1251 case 3:
1252 // ****-_?????-_-_-**** hguess 3
1253 // ib^
1254 // 210
1255 if(gap==8)
1256 {
1257 cg_wave_raw_re=dot_re[ib-ia-2];
1258 cg_wave_raw_im=dot_im[ib-ia-2];
1259 cg_wave_midpoint=msig[ib-2].pos;
1260 insert_item(CW_DOT);
1261 cw_ptr++;
1262 }
1263 cg_wave_raw_re=dot_re[ib-ia];
1264 cg_wave_raw_im=dot_im[ib-ia];
1265 cg_wave_midpoint=msig[ib].pos;
1266 insert_item(CW_DOT);
1267 cw_ptr++;
1268 break;
1269
1270 case 4:
1271 // ****-_?????---_-**** hguess 4
1272 // ib^
1273 // 210
1274 cg_wave_raw_re=dash_re[2];
1275 cg_wave_raw_im=dash_im[2];
1276 cg_wave_midpoint=msig[ib-1].pos;
1277 insert_item(CW_DASH);
1278 cw_ptr++;
1279 break;
1280
1281 default:
1282 lirerr(634294);
1283 return 0;
1284 }
1285 added_parts+=cw_ptr-iptr;
1286 iptr=cw_ptr;
1287 skip_guesses:;
1288 cw_ptr=iptr;
1289 goto region_guesses;
1290 }
1291 }
1292
1293 cw_detect_flag=CWDETECT_DEBUG_STOP;
1294 show_cw(" char guesses finished ");
1295 return added_parts;
1296 }
1297
1298
1299
1300
1301
make_baseb_sho1(void)1302 void make_baseb_sho1(void)
1303 {
1304 int i,k;
1305 k=2*baseband_size;
1306 for(i=0; i<k; i++)baseb_sho1[i]=baseb_tmp[i]*0.5;
1307 }
1308
make_baseb_sho2(void)1309 void make_baseb_sho2(void)
1310 {
1311 int i,k;
1312 k=2*baseband_size;
1313 for(i=0; i<k; i++)baseb_sho2[i]=baseb_fit[i]*0.5;
1314 }
1315
correlated_detect(void)1316 void correlated_detect(void)
1317 {
1318 int pa;
1319 int ia, ka;
1320 char s[80];
1321 // Check the detected dots and dashes against the average waveform.
1322 ka=corr[0].pos;
1323 pa=-1;
1324 for(cw_ptr=0; cw_ptr<no_of_cwdat; cw_ptr++)
1325 {
1326 ia=((int)(cw[cw_ptr].midpoint+0.5)-ka+baseband_size)&baseband_mask;
1327 if(ia > baseband_sizhalf)goto outside;
1328 ia=(ia-corr_len+baseband_size)&baseband_mask;
1329 if(ia < baseband_sizhalf)goto outside;
1330 if(pa < 0)pa=cw_ptr;
1331 switch (cw[cw_ptr].type)
1332 {
1333 case CW_DASH:
1334 sprintf(s,"dash ");
1335 break;
1336
1337 case CW_DOT:
1338 sprintf(s,"dot ");
1339 break;
1340
1341 case CW_SPACE:
1342 sprintf(s,"space ");
1343 break;
1344
1345 case CW_WORDSEP:
1346 sprintf(s,"wordsep");
1347 break;
1348
1349 default:
1350 sprintf(s,"{%3d} %c",cw[cw_ptr].type,cw[cw_ptr].type);
1351 break;
1352 }
1353 DEB"\n%s %5d [%8.3f]%8.3f %2d %3d (%f %f)",
1354 s,cw_ptr,cw[cw_ptr].midpoint,cw[cw_ptr].sep,cw[cw_ptr].len,cw[cw_ptr].unkn,
1355 ZZ*cw[cw_ptr].coh_re,ZZ*cw[cw_ptr].coh_im);
1356 outside:;
1357 }
1358 }
1359
find_best_region(void)1360 int find_best_region(void)
1361 {
1362 int i, j, k, m;
1363 int ia, ib;
1364 float t1,da;
1365 // Locate the best region by use of the amplitudes stored in cw[].tmp
1366 j=0;
1367 t1=0;
1368 for(i=0; i<no_of_cwdat; i++)
1369 {
1370 if(cw[i].tmp > t1)
1371 {
1372 j=i;
1373 t1=cw[i].tmp;
1374 }
1375 }
1376 if(best_corr_ampl==0)
1377 {
1378 best_corr_ampl=t1;
1379 }
1380 else
1381 {
1382 if(t1 < 0.33*best_corr_ampl)
1383 {
1384 PRT10"\n----------- exit -------------");
1385 return FALSE;
1386 }
1387 }
1388 // Decide what length to use for correlation.
1389 ia=j;
1390 ib=j;
1391 k=no_of_cwdat-1;
1392 t1*=.25;
1393 m=0;
1394 get_corrlen:;
1395 da=cw[ib].midpoint-cw[ia].midpoint;
1396 if(da < 0)da+=baseband_size;
1397 if(da < MIN_CORRELATE_SEP*cwbit_pts)
1398 {
1399 if(ia > 0)
1400 {
1401 if(ib < k)
1402 {
1403 if(cw[ia-1].tmp > cw[ib+1].tmp)
1404 {
1405 goto iadec;
1406 }
1407 else
1408 {
1409 goto ibinc;
1410 }
1411 }
1412 else
1413 {
1414 goto iadec;
1415 }
1416 }
1417 else
1418 {
1419 if(ib < k)
1420 {
1421 goto ibinc;
1422 }
1423 }
1424 iadec:;
1425 if(cw[ia-1].tmp > t1)
1426 {
1427 ia--;
1428 m=-1;
1429 goto get_corrlen;
1430 }
1431 goto corrlen_x;
1432 ibinc:;
1433 if(cw[ib+1].tmp > t1)
1434 {
1435 m=1;
1436 ib++;
1437 goto get_corrlen;
1438 }
1439 }
1440 corrlen_x:;
1441 best_corr_ia=((int)(cw[ia].midpoint-3*cwbit_pts)+baseband_size)&baseband_mask;
1442 best_corr_ib=((int)(cw[ib].midpoint+3*cwbit_pts))&baseband_mask;
1443 i=(best_corr_ib-best_corr_ia+baseband_size)&baseband_mask;
1444 i-=MIN_CORRELATE_SEP*cwbit_pts;
1445 if(i > 0)
1446 {
1447 if(m>0)
1448 {
1449 ib--;
1450 best_corr_ib=(best_corr_ib-i+baseband_size)&baseband_mask;
1451 }
1452 else
1453 {
1454 ia++;
1455 best_corr_ia=(best_corr_ia+i)&baseband_mask;
1456 }
1457 }
1458 corr_len=(best_corr_ib-best_corr_ia+baseband_size)&baseband_mask;
1459 // best_corr_ia and best_corr_ib are pointers in the baseband.
1460 // Clear cw[].tmp for points within the region ia to ib so we
1461 // will not try to correlate the same region again.
1462 ib++;
1463 while(ia != ib)
1464 {
1465 cw[ia].tmp=0;
1466 ia++;
1467 }
1468 return TRUE;
1469 }
1470
compute_region_quality(void)1471 void compute_region_quality(void)
1472 {
1473 int i, ia, ib;
1474 float amp, da, db, t1, trilen;
1475 //
1476 // Good regions contain several dashes and or dots within a time
1477 // frame corresponding to a morse character.
1478 // Store a triangle of width +/- CW_CORRELATE_GOODLEN norse code units
1479 // around each part.
1480 // Make the height A or 3*A for dots and dashes respectively
1481 // where A is the signal amplitude.
1482 // Good regions are characterised by sucessful detection of the
1483 // carrier so we use cw[].coh_re for the amplitude A.
1484 trilen=CW_CORRELATE_GOODLEN*cwbit_pts;
1485 for(i=0; i<no_of_cwdat; i++)
1486 {
1487 cw[i].tmp=0;
1488 }
1489 for(i=0; i<no_of_cwdat; i++)
1490 {
1491 if(cw[i].type==CW_DOT)
1492 {
1493 amp=1;
1494 }
1495 else
1496 {
1497 if(cw[i].type==CW_DASH)
1498 {
1499 amp=3;
1500 }
1501 else
1502 {
1503 goto keyup;
1504 }
1505 }
1506 amp*=cw[i].coh_re;
1507 cw[i].tmp+=amp;
1508 amp/=trilen;
1509 ia=i-1;
1510 ib=i+1;
1511 da=0.5*cw[i].len;
1512 db=da;
1513 while(ia >=0 && da<trilen)
1514 {
1515 da+=0.5*(cw[ia+1].len+cw[ia].len)+cw[ia+1].unkn;
1516 t1=trilen-da;
1517 if(t1>0)
1518 {
1519 cw[ia].tmp+=t1*amp;
1520 }
1521 ia--;
1522 }
1523 while(ib < no_of_cwdat && db<trilen)
1524 {
1525 db+=0.5*(cw[ib].len+cw[ib-1].len)+cw[ib].unkn;
1526 t1=trilen-db;
1527 if(t1>0)
1528 {
1529 cw[ib].tmp+=t1*amp;
1530 }
1531 ib++;
1532 }
1533 keyup:;
1534 }
1535 }
1536
find_good_regions(void)1537 void find_good_regions(void)
1538 {
1539 int i, j, k, m, ia, ib, ja, jb, corr_step, clrlen;
1540 int first_corr, last_corr;
1541 float t1, t2, maxval;
1542 double dt2;
1543 // Our data does not change very rapidly. The shortest signal
1544 // duration of interest is cwbit_pts/2, the approximate time for
1545 // the separation between the 3 dB points of a Morse code dot.
1546 // Search for correlations using a step size of cwbit_pts/2;
1547 corr_step=0.5*(cwbit_pts+1);
1548 ja=baseb_px/corr_step;
1549 baseb_tmp[ja]=0;
1550 ia=ja*corr_step;
1551 corr[1].val=0;
1552 corr[1].pos=-1;
1553 getcorr_ia:;
1554 ia+=corr_step;
1555 ja++;
1556 if(ia > baseband_mask)
1557 {
1558 ia=0;
1559 ja=0;
1560 }
1561 k=(best_corr_ia-ia-corr_len+baseband_size)&baseband_mask;
1562 if(k<baseband_neg)
1563 {
1564 dt2=0;
1565 j=best_corr_ia;
1566 k=ia;
1567 while(j != best_corr_ib)
1568 {
1569 dt2+=baseb[2*j]*baseb[2*k];
1570 j=(j+1)&baseband_mask;
1571 k=(k+1)&baseband_mask;
1572 }
1573 t2=dt2*OVFL_PROTECT;
1574 if(corr[1].val < t2)
1575 {
1576 corr[1].pos=ja;
1577 corr[1].val=t2;
1578 }
1579 baseb_tmp[ja]=t2;
1580 goto getcorr_ia;
1581 }
1582 jb=best_corr_ib/corr_step;
1583 m=baseband_mask/corr_step;
1584 while(ja != jb)
1585 {
1586 baseb_tmp[ja]=0;
1587 ja++;
1588 if(ja > m)
1589 {
1590 ja=0;
1591 }
1592 }
1593 ib=jb*corr_step;
1594 getcorr_ib:;
1595 k=(baseb_pc-ib-corr_len+baseband_size)&baseband_mask;
1596 if(k<baseband_sizhalf)
1597 {
1598 dt2=0;
1599 j=best_corr_ia;
1600 k=ib;
1601 while(j != best_corr_ib)
1602 {
1603 dt2+=baseb[2*j]*baseb[2*k];
1604 j=(j+1)&baseband_mask;
1605 k=(k+1)&baseband_mask;
1606 }
1607 t2=dt2*OVFL_PROTECT;
1608 if(corr[1].val < t2)
1609 {
1610 corr[1].pos=jb;
1611 corr[1].val=t2;
1612 }
1613 baseb_tmp[jb]=t2;
1614 ib+=corr_step;
1615 jb++;
1616 if(ib > baseband_mask)
1617 {
1618 ib=0;
1619 jb=0;
1620 }
1621 goto getcorr_ib;
1622 }
1623 baseb_tmp[jb]=0;
1624 // If all the data is zero, return here.
1625 if(corr[1].pos ==-1)return;
1626 // Make sure that the very first point does not create a maximum
1627 // from either end.
1628 jb=jb-1;
1629 if(jb<0)jb=m;
1630 k=jb-1;
1631 if(k<0)k=m;
1632 while(baseb_tmp[k] !=0 && baseb_tmp[k] <= baseb_tmp[jb])
1633 {
1634 baseb_tmp[jb]=0;
1635 jb=k;
1636 k--;
1637 if(k<0)k=m;
1638 }
1639 last_corr=jb;
1640 ja=baseb_px/corr_step;
1641 ja++;
1642 if(ja>0)ja=0;
1643 k=ja+1;
1644 if(k>m)k=0;
1645 while(baseb_tmp[k] !=0 && baseb_tmp[k] <= baseb_tmp[ja])
1646 {
1647 baseb_tmp[ja]=0;
1648 ja=k;
1649 k++;
1650 if(k>m)k=0;
1651 }
1652 first_corr=ja;
1653 clrlen=1+corr_len/(4*corr_step);
1654 // Clear baseb_tmp in the surroundings of the current maximum.
1655 // Then search for the largest value in baseb_tmp.
1656 // This way corr[].pos and corr_val[] will contain correlation
1657 // maxima in descending order by corr_val.
1658 no_of_corr=1;
1659 while( no_of_corr < MAX_CORRSUM-1 && corr[no_of_corr].pos != -1)
1660 {
1661 // First just clear 2*clrlen points.
1662 i=corr[no_of_corr].pos-clrlen;
1663 if(i<0)i=m;
1664 k=corr[no_of_corr].pos+clrlen;
1665 if(k>m)k=0;
1666 j=i;
1667 while(i != k)
1668 {
1669 baseb_tmp[i]=0;
1670 i++;
1671 if(i>m)i=0;
1672 }
1673 // Clear points upwards to avoid that the first point becomes a maximum.
1674 i=k+1;
1675 if(i>m)i=0;
1676 while(baseb_tmp[i] !=0 && baseb_tmp[i] <= baseb_tmp[k])
1677 {
1678 baseb_tmp[k]=0;
1679 k=i;
1680 i++;
1681 if(i>m)i=0;
1682 }
1683 j--;
1684 if(j<0)j=m;
1685 k=j-1;
1686 if(k<0)k=m;
1687 while(baseb_tmp[k] !=0 && baseb_tmp[k] <= baseb_tmp[j])
1688 {
1689 baseb_tmp[j]=0;
1690 j=k;
1691 k--;
1692 if(k<0)k=m;
1693 }
1694 no_of_corr++;
1695 corr[no_of_corr].val=0;
1696 corr[no_of_corr].pos=-1;
1697 ia=first_corr;
1698 while(ia != last_corr)
1699 {
1700 if(baseb_tmp[ia] > corr[no_of_corr].val)
1701 {
1702 corr[no_of_corr].val=baseb_tmp[ia];
1703 corr[no_of_corr].pos=ia;
1704 }
1705 ia++;
1706 if(ia>m)ia=0;
1707 }
1708 if(corr[no_of_corr].val < 0.5*corr[1].val)corr[no_of_corr].pos=-1;
1709 }
1710 while(no_of_corr<MAX_CORRSUM-1)
1711 {
1712 no_of_corr++;
1713 corr[no_of_corr].pos=-1;
1714 corr[no_of_corr].val=0;
1715 }
1716 if(PR10 != 0)
1717 {
1718 for(i=1; i<MAX_CORRSUM; i++)
1719 {
1720 DEB"\nNo:%d pos:%d val %f",i,corr[i].pos*corr_step,corr[i].val);
1721 }
1722 }
1723 // Now we know points where correlation has maxima,
1724 // but we know the points within corr_step points only.
1725 // Make a finer search so we get the optimum within a single point
1726 // and include the complex part this time.
1727 // Accumulate the summed baseband function in baseb_tmp.
1728 i=best_corr_ia;
1729 while(i != best_corr_ib)
1730 {
1731 baseb_tmp[2*i ]=baseb[2*i ];
1732 baseb_tmp[2*i+1]=baseb[2*i+1];
1733 i=(i+1)&baseband_mask;
1734 }
1735 // Make the best region itself region 0
1736 corr[0].pos=(best_corr_ia+(corr_step>>1))/corr_step;
1737 no_of_corr=0;
1738 corr[0].sep=0;
1739 maxval=0;
1740 accumulate_corr:;
1741 ia=((corr[no_of_corr].pos-1)*corr_step+baseband_mask)&baseband_mask;
1742 ib=((corr[no_of_corr].pos+1)*corr_step+2)&baseband_mask;
1743 corr[no_of_corr].val=0;
1744 while(ia!=ib)
1745 {
1746 dt2=0;
1747 i=best_corr_ia;
1748 k=ia;
1749 // Correlate to the summed function in baseb_tmp
1750 while(i != best_corr_ib)
1751 {
1752 dt2+=baseb_tmp[2*i]*baseb[2*k]+baseb_tmp[2*i+1]*baseb[2*k+1];
1753 i=(i+1)&baseband_mask;
1754 k=(k+1)&baseband_mask;
1755 }
1756 t2=dt2*OVFL_PROTECT;
1757 if(corr[no_of_corr].val < t2)
1758 {
1759 corr[no_of_corr].pos=ia;
1760 corr[no_of_corr].val=t2;
1761 }
1762 ia=(ia+1)&baseband_mask;
1763 }
1764 if(no_of_corr==0)
1765 {
1766 PRT10"\nCorr no:%d pos:%d val %f maxval %f",
1767 no_of_corr,corr[no_of_corr].pos,corr[no_of_corr].val,maxval);
1768 goto noadd;
1769 }
1770 if(no_of_corr==1)
1771 {
1772 PRT10"\nCorr no:%d pos:%d val %f maxval %f",
1773 no_of_corr,corr[no_of_corr].pos,corr[no_of_corr].val,maxval);
1774 corr[1].sep=(corr[1].pos-best_corr_ia+baseband_size)&baseband_mask;
1775 if(corr[1].sep>(baseband_size>>1))corr[1].sep=
1776 (baseband_size-corr[1].sep)&baseband_mask;
1777
1778 PRT10" sep%d",corr[1].sep);
1779 }
1780
1781 // Check if this point has an integer relation to previously esteblished
1782 // repeat separations.
1783 if(no_of_corr > 1)
1784 {
1785 corr[no_of_corr].val*=corr[0].val/maxval;
1786 PRT10"\nCorr no:%d pos:%d val %f maxval %f",
1787 no_of_corr,corr[no_of_corr].pos,corr[no_of_corr].val,maxval);
1788 corr[no_of_corr].sep=(corr[no_of_corr].pos-best_corr_ia
1789 +baseband_size)&baseband_mask;
1790 if(corr[no_of_corr].sep>(baseband_size>>1))corr[no_of_corr].sep=
1791 (baseband_size-corr[no_of_corr].sep)&baseband_mask;
1792 PRT10" sep%d", corr[no_of_corr].sep);
1793
1794 t1=(float)(corr[no_of_corr].sep)/corr[1].sep;
1795 PRT10"\nt1=%f",t1);
1796 if(corr[no_of_corr].val < 0.4*corr[0].val)
1797 {
1798 PRT10" skip for small corr_value.");
1799 goto skip_corr;
1800 }
1801 if(!(fabs(t1-1.0) < 0.015 ||
1802 fabs(t1-2.0) < 0.02 ||
1803 fabs(t1-3.0) < 0.03 ||
1804 fabs(t1-0.5) < 0.01 ||
1805 fabs(t1-1.5) < 0.015 ||
1806 fabs(t1-0.33333333) < 0.01 ||
1807 fabs(t1-0.66666666) < 0.015 ||
1808 fabs(t1-1.33333333) < 0.015 ||
1809 fabs(t1-1.66666666) < 0.015))
1810 {
1811 PRT10" skip for non-integer ratio.");
1812 skip_corr:;
1813 i=no_of_corr+1;
1814 while(i<MAX_CORRSUM)
1815 {
1816 corr[i-1].pos=corr[i].pos;
1817 corr[i-1].val=corr[i].val;
1818 i++;
1819 }
1820 corr[MAX_CORRSUM-1].pos=-1;
1821 corr[MAX_CORRSUM-1].val=0;
1822 goto next_corr;
1823 }
1824 }
1825 i=best_corr_ia;
1826 k=corr[no_of_corr].pos;
1827 while(i!=best_corr_ib)
1828 {
1829 baseb_tmp[2*i ]+=baseb[2*k ];
1830 baseb_tmp[2*i+1]+=baseb[2*k+1];
1831 i=(i+1)&baseband_mask;
1832 k=(k+1)&baseband_mask;
1833 }
1834 noadd:;
1835 maxval+=corr[no_of_corr].val;
1836 no_of_corr++;
1837 next_corr:;
1838 if( corr[no_of_corr].pos != -1 && no_of_corr<MAX_CORRSUM) goto accumulate_corr;
1839 PRT10"\nNO_OF_CORR %d",no_of_corr);
1840 }
1841
1842
1843
1844 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1845 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1846 // !!
1847 // !! WORK AREA
1848 // !!
1849 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1850 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1851
1852
1853
correlate_undecoded_baseband(void)1854 void correlate_undecoded_baseband(void)
1855 {
1856 int region, region_flag;
1857 int i,j,k,ia,ib,ja,jb;
1858 int ka,kb,k1,k2,k3;
1859 int mix2_mask, sizhalf, carrfilter_pts;
1860 //float amp,t1,t2,t3,r1,r2;
1861 float amp,t1,t2,t3,r2;
1862 double dt1, dt2, dt3;
1863 sizhalf=mix2.size>>1;
1864 mix2_mask=mix2.size-1;
1865 // The standard procedure for detect has failed but there is
1866 // probably a signal present because we have decoded many dots
1867 // and dashes although not well enough to identify a single character.
1868 // First find a few particularly good regions, then compute
1869 // the auto-correlation function to see if the pattern repeats.
1870 compute_region_quality();
1871 best_corr_ampl=0;
1872 DEB"\n----------- start correlate undecoded -------------");
1873 goto zzb;
1874 retry_correlation:;
1875 DEB"\n---------- retry correlate undecoded -------------");
1876 zzb:;
1877 if(find_best_region() == FALSE)return;
1878 find_good_regions();
1879 if(no_of_corr==0)goto retry_correlation;
1880 // The average waveform we now have in baseb_tmp would be correct
1881 // and it would have S/N better by a factor of no_of_corr compared to an
1882 // individual waveform if AND ONLY IF the phase of the carrier
1883 // were correct and the signal level were constant.
1884 //
1885 // Real signals typically suffer from multipath propagation and
1886 // as a result there is fading, QSB. When the amplitude goes
1887 // through a minimum, the phase may twist rapidly and the
1888 // carrier phase is very uncertain at such times. Whether a
1889 // 180 degree phase shift goes over 90 or 270 degrees may depend
1890 // on the noise only and the very weak signal close to the
1891 // minimum might come out from our coherent detection procedure
1892 // with the wrong phase. Actually with a random phase.
1893 //
1894 // Coherent averaging improves S/N for reasonably good signals,
1895 // good enough to give good S/N for the carrier, but the price
1896 // to pay is that poor signals average out to nothing.
1897 //
1898 // Here we have some good coherently averaged signals in baseb_tmp.
1899 // We will use them to improve the carrier phase.
1900 //
1901 // Compute the optimum position with decimals for each sequence
1902 // from the correlation with the summed curve. Store in corr_val[]
1903 j=0;
1904 while(j<no_of_corr)
1905 {
1906 ia=corr[j].pos;
1907 dt1=0;
1908 dt2=0;
1909 dt3=0;
1910 i=best_corr_ia;
1911 k1=(ia+baseband_mask)&baseband_mask;
1912 k2=ia;
1913 k3=(ia+1)&baseband_mask;
1914 while(i != best_corr_ib)
1915 {
1916 dt1+=baseb_tmp[2*i]*baseb[2*k1]+baseb_tmp[2*i+1]*baseb[2*k1+1];
1917 dt2+=baseb_tmp[2*i]*baseb[2*k2]+baseb_tmp[2*i+1]*baseb[2*k2+1];
1918 dt3+=baseb_tmp[2*i]*baseb[2*k3]+baseb_tmp[2*i+1]*baseb[2*k3+1];
1919 k1=k2;
1920 k2=k3;
1921 i=(i+1)&baseband_mask;
1922 k3=(k3+1)&baseband_mask;
1923 }
1924 t1=dt1*OVFL_PROTECT;
1925 t2=dt2*OVFL_PROTECT;
1926 t3=dt3*OVFL_PROTECT;
1927 if(t1 > t2 && t3 > t1)
1928 {
1929 // If the middle point is a local minimum, something is very wrong.
1930 // Then skip this waveform.
1931 skipit:;
1932 i=j;
1933 while(i < no_of_corr-1)
1934 {
1935 corr[i].pos=corr[i+1].pos;
1936 i++;
1937 }
1938 no_of_corr--;
1939 goto shiftfind_x;
1940 }
1941 if(t1 > t2)
1942 {
1943 t3=t2;
1944 t2=t1;
1945 ia=corr[j].pos;
1946 ia=(ia+baseband_mask)&baseband_mask;
1947 corr[j].pos=ia;
1948 dt1=0;
1949 i=best_corr_ia;
1950 k1=(ia+baseband_mask)&baseband_mask;
1951 while(i != best_corr_ib)
1952 {
1953 dt1+=baseb_tmp[2*i]*baseb[2*k1]+baseb_tmp[2*i+1]*baseb[2*k1+1];
1954 i=(i+1)&baseband_mask;
1955 k1=(k1+1)&baseband_mask;
1956 }
1957 t1=dt1*OVFL_PROTECT;
1958 if(t1>t2)goto skipit;
1959 }
1960 if(t3 > t2)
1961 {
1962 t1=t2;
1963 t2=t3;
1964 ia=corr[j].pos;
1965 ia=(ia+1)&baseband_mask;
1966 corr[j].pos=ia;
1967 dt3=0;
1968 i=best_corr_ia;
1969 k3=(ia+1)&baseband_mask;
1970 while(i != best_corr_ib)
1971 {
1972 dt3+=baseb_tmp[2*i]*baseb[2*k3]+baseb_tmp[2*i+1]*baseb[2*k3+1];
1973 i=(i+1)&baseband_mask;
1974 k3=(k3+1)&baseband_mask;
1975 }
1976 t3=dt3*OVFL_PROTECT;
1977 if(t3>t2)goto skipit;
1978 }
1979 parabolic_fit(&,&corr[j].fpos,t1*t1,t2*t2,t3*t3);
1980 corr[j].fpos+=ia;
1981 j++;
1982 shiftfind_x:;
1983 }
1984 if(no_of_corr < 2)goto retry_correlation;
1985 // Shift our pos references for corr[0].pos to become equal to best_corr_ia.
1986 // Then increase the separation between corr[].fpos and corr[].pos
1987 // by a factor no_of_corr/(no_of_corr-1) to compensate to some extent
1988 // for the fact that correlation contains a component of the
1989 // signal to itself.
1990 t1=corr[0].fpos-best_corr_ia;
1991 t3=(float)(no_of_corr)/(no_of_corr-1);
1992 for(i=0; i<no_of_corr; i++)
1993 {
1994 t2=corr[i].fpos-t1;
1995 if(t2 < 0)t2+=baseband_size;
1996 if(t2 > baseband_size)t2-=baseband_size;
1997 t2=corr[i].pos-t2;
1998 t2*=t3;
1999 corr[i].fpos=corr[i].pos-t2;
2000 if(corr[i].fpos < 0)corr[i].fpos+=baseband_size;
2001 if(corr[i].fpos > baseband_size)corr[i].fpos-=baseband_size;
2002 corr[i].pos=((int)(corr[i].fpos+0.5))&baseband_mask;
2003 corr[i].sep=(corr[i].pos-baseb_px+baseband_size)&baseband_mask;
2004 }
2005 // Reorder the regions from ascending order of .val (quality)
2006 // to .sep (now time = distance to baseb_px)
2007 for(i=0; i<no_of_corr-1; i++)
2008 {
2009 for(j=i; j<no_of_corr; j++)
2010 {
2011 if(corr[i].sep > corr[j].sep)
2012 {
2013 tmpcorr=corr[i];
2014 corr[i]=corr[j];
2015 corr[j]=tmpcorr;
2016 }
2017 }
2018 }
2019 // Make corr[].sep the distance between consecutive regions.
2020 corr[0].sep=0;
2021 for(i=1; i<no_of_corr; i++)
2022 {
2023 corr[i].sep=corr[i].fpos-corr[i-1].fpos+0.5;
2024 }
2025 // Find out what the real repeat separation might be.
2026 k=baseband_size;
2027 for(i=1; i<no_of_corr; i++)
2028 {
2029 if(k > corr[i].sep)
2030 {
2031 k=corr[i].sep;
2032 }
2033 }
2034 // k is now the smallest repeat separation.
2035 // Divide k by 2 or 3 (or 6) in case it is required to make
2036 // the longer separations multiples of k.
2037 i=0;
2038 while(i<no_of_corr)
2039 {
2040 t1=(float)(corr[i].sep)/k;
2041 if(fabs(t1-1.5) < 0.05||
2042 fabs(t1-2.5) < 0.05)
2043 {
2044 k/=2;
2045 i=no_of_corr;
2046 }
2047 else
2048 {
2049 i++;
2050 }
2051 }
2052 i=0;
2053 while(i<no_of_corr)
2054 {
2055 t1=(float)(corr[i].sep)/k;
2056 if(fabs(t1-1.3333333333) < 0.05 ||
2057 fabs(t1-1.6666666666) < 0.05 ||
2058 fabs(t1-2.3333333333) < 0.05 )
2059 {
2060 k=(k+1)/3;
2061 i=no_of_corr;
2062 }
2063 else
2064 {
2065 i++;
2066 }
2067 }
2068 // Change k from being the repeat interval to become the max
2069 // number of points by which we may increase corr_len at both sides, but
2070 // do not allow corr_len to increase by more than a factor of three.
2071 k=(k-corr_len)/2;
2072 if(k>corr_len)k=corr_len;
2073 // Shift the start pointers by k downwards.
2074 // make sure we do not go below baseb_px.
2075 ia=0;
2076 for(i=0; i<no_of_corr; i++)
2077 {
2078 corr[i].fpos-=k;
2079 if(corr[i].fpos < 0)corr[i].fpos+=baseband_size;
2080 j=corr[i].fpos-baseb_px+baseband_mask;
2081 j&=baseband_mask;
2082 if(j > baseband_sizhalf)
2083 {
2084 j=baseband_size-j;
2085 if(j>ia)ia=j;
2086 }
2087 }
2088 for(i=0; i<no_of_corr; i++)
2089 {
2090 corr[i].fpos+=ia;
2091 if(corr[i].fpos >= baseband_size)corr[i].fpos-=baseband_size;
2092 corr[i].pos=corr[i].fpos+0.5;
2093 corr[i].pos&=baseband_mask;
2094 }
2095 k=corr_len+2*k-ia;
2096 // Make sure the last point is not above baseb_pc
2097 ib=0;
2098 for(i=0; i<no_of_corr; i++)
2099 {
2100 j=corr[i].fpos+k+1;
2101 j=(baseb_pc-j+baseband_size)&baseband_mask;
2102 if(j > baseband_sizhalf)
2103 {
2104 j=baseband_size-j;
2105 if(j>ib)ib=j;
2106 }
2107 }
2108 corr_len=k-ib;
2109 for(i=0; i<no_of_corr; i++)
2110 {
2111 corr[i].pos=((int)(corr[i].fpos+0.5))&baseband_mask;
2112 }
2113
2114 // !!!!!!!!!!!!!!!!!!!!! for debug purposes !!!!!!!!!!!!!!!
2115 // ö
2116 for(i=0;i<baseband_size/2;i+=2)
2117 {
2118 baseb_tmp[4*i ]=-1/(ZZ*ZZ);
2119 baseb_tmp[4*i+1]=1/(ZZ*ZZ);
2120 baseb_tmp[4*i+2]=1;
2121 baseb_tmp[4*i+3]=1;
2122 baseb_tmp[4*i+4]=0;
2123 baseb_tmp[4*i+5]=0;
2124 baseb_tmp[4*i+6]=0;
2125 baseb_tmp[4*i+7]=0;
2126 baseb_fit[4*i ]=-1/(ZZ*ZZ);
2127 baseb_fit[4*i+1]=1/(ZZ*ZZ);
2128 baseb_fit[4*i+2]=1;
2129 baseb_fit[4*i+3]=1;
2130 baseb_fit[4*i+4]=0;
2131 baseb_fit[4*i+5]=0;
2132 baseb_fit[4*i+6]=0;
2133 baseb_fit[4*i+7]=0;
2134 }
2135
2136 // Use the detect information from all regions to select the time
2137 // intervals when the key is likely to have been pressed. Use the
2138 // same pattern for all regions.
2139 // store the gated raw data in baseb_fit.
2140 for(region=0; region<no_of_corr; region++)
2141 {
2142 ia=corr[region].pos;
2143 ib=(ia+corr_len)&baseband_mask;
2144 while(ia!=ib)
2145 {
2146 baseb_fit[2*ia ]=0;
2147 baseb_fit[2*ia+1]=0;
2148 ia=(ia+1)&baseband_mask;
2149 }
2150 }
2151 region=0;
2152 ia=corr[region].pos;
2153 for(i=0; i<no_of_cwdat; i++)
2154 {
2155 if( cw[i].type == CW_DASH || cw[i].type == CW_DOT)
2156 {
2157 gate_part:;
2158 k=((int)(cw[i].midpoint)-ia+baseband_size)&baseband_mask;
2159 if(k<baseband_neg)
2160 {
2161 if(k>corr_len)
2162 {
2163 region++;
2164 if(region > no_of_corr)goto gate_x;
2165 ia=corr[region].pos;
2166 goto gate_part;
2167 }
2168 for(j=0; j<no_of_corr; j++)
2169 {
2170 if( cw[i].type == CW_DASH)
2171 {
2172 t1=1.5;
2173 }
2174 else
2175 {
2176 t1=0.5;
2177 }
2178 ja=cw[i].midpoint-t1*cwbit_pts;
2179 jb=cw[i].midpoint+t1*cwbit_pts;
2180 ja=(ja+corr[j].pos-corr[region].pos+baseband_size)&baseband_mask;
2181 jb=(jb+corr[j].pos-corr[region].pos+baseband_size)&baseband_mask;
2182 while(ja != jb)
2183 {
2184 baseb_fit[2*ja ]=baseb_wb_raw[2*ja ];
2185 baseb_fit[2*ja+1]=baseb_wb_raw[2*ja+1];
2186 ja=(ja+1)&baseband_mask;
2187 }
2188 }
2189 }
2190 }
2191 }
2192 gate_x:;
2193 // We use a mix2.size fft to filter out the carrier in the
2194 // frequency domain with a filter of the same width as used
2195 // before when extracting the carrier.
2196 // In case the carrier clearly is narrower we use a narrower filter.
2197 // We will use a sine squared window with 50 % overlap for the transforms.
2198 carrfilter_pts=1+(bg_flatpoints+2*bg_curvpoints)/bg.coh_factor;
2199 k3=carrfilter_pts/2+1;
2200 for(region=0; region<no_of_corr; region++)
2201 {
2202 ka=corr[region].pos;
2203 kb=(ka+corr_len)&baseband_mask;
2204 for(i=0; i<2*sizhalf; i++)mix2_tmp[i]=0;
2205 ia=ka;
2206 ka=(ka-sizhalf+baseband_size)&baseband_mask;
2207 for(i=sizhalf; i<(int)mix2.size; i++)
2208 {
2209 mix2_tmp[2*i ]=baseb_fit[2*ia ]*cw_carrier_window[i];
2210 mix2_tmp[2*i+1]=baseb_fit[2*ia+1]*cw_carrier_window[i];
2211 ia=(ia+1)&baseband_mask;
2212 }
2213 region_flag=1;
2214 new_carrier:;
2215 fftforward(mix2.size, mix2.n, mix2_tmp,
2216 mix2.table, mix2.permute, yieldflag_ndsp_mix2);
2217 // Compute the power spectrum and locate the carrier.
2218 // The carrier has to be close to frequency=0 so we search a limited
2219 // range only (4 times the carrier filter).
2220 t1=0;
2221 t2=4;
2222 if(t2>0.5*bg.coh_factor)t2=0.5*bg.coh_factor;
2223 i=1+t2*carrfilter_pts;
2224 k=mix2.size-i-1;
2225 k2=i+1;
2226 k1=k;
2227 ia=2*k3-1;
2228 ib=(k2-k1-ia+mix2.size)&mix2_mask;
2229 while(i>=0)
2230 {
2231 t2=mix2_tmp[2*i ]*mix2_tmp[2*i ]+
2232 mix2_tmp[2*i+1]*mix2_tmp[2*i+1];
2233 mix2_pwr[i]=t2;
2234 if(t2 > t1)
2235 {
2236 j=i;
2237 t1=t2;
2238 }
2239 t2=mix2_tmp[2*k ]*mix2_tmp[2*k ]+
2240 mix2_tmp[2*k+1]*mix2_tmp[2*k+1];
2241 mix2_pwr[k]=t2;
2242 if(t2 > t1)
2243 {
2244 j=k;
2245 t1=t2;
2246 }
2247 i--;
2248 k++;
2249 }
2250 i=j;
2251 if(i>sizhalf)i-=mix2.size;
2252 if(abs(i) > k3)goto fail;
2253 i=k1;
2254 // r1=0;
2255 r2=0;
2256 while(i!=k2)
2257 {
2258 k=(i-j+mix2.size)&mix2_mask;
2259 if(k>sizhalf)k=mix2.size-k;
2260 if(k<k3)
2261 {
2262 // r1+=mix2_pwr[i];
2263 }
2264 else
2265 {
2266 r2+=mix2_pwr[i];
2267 }
2268 i=(i+1)&mix2_mask;
2269 }
2270 // r1/=ia;
2271 r2/=ib;
2272 ia=(j-k3+mix2.size)&mix2_mask;
2273 ib=(j+k3)&mix2_mask;
2274 if( (r2 != 0 && t1/r2 < 4) || t1 == 0)
2275 {
2276 fail:;
2277 t1=0;
2278 ia=0;
2279 ib=0;
2280 mix2_tmp[0]=0.1;
2281 mix2_tmp[1]=0;
2282 }
2283 else
2284 {
2285 // Our passband is from ia to ib. It is centered on the maximum power bin.
2286 // Try to shift the passband up or down to see if we can get more signal.
2287 for(i=k3; i>0; i--)
2288 {
2289 t2=0;
2290 k1=(ia+mix2_mask)&mix2_mask;
2291 k2=ib;
2292 j=i;
2293 while(j!=0)
2294 {
2295 t2+=mix2_pwr[k1]-mix2_pwr[k2];
2296 k1=(k1+mix2_mask)&mix2_mask;
2297 k2=(k2+mix2_mask)&mix2_mask;
2298 j--;
2299 }
2300 t3=0;
2301 k1=ia;
2302 k2=(ib+1)&mix2_mask;
2303 j=i;
2304 while(j!=0)
2305 {
2306 t3+=mix2_pwr[k2]-mix2_pwr[k1];
2307 k1=(k1+1)&mix2_mask;
2308 k2=(k2+1)&mix2_mask;
2309 j--;
2310 }
2311 if(t2 > t3)
2312 {
2313 if(t2 > 0)
2314 {
2315 ia=(ia-i+mix2.size)&mix2_mask;
2316 ib=(ib-i+mix2.size)&mix2_mask;
2317 }
2318 }
2319 else
2320 {
2321 if(t3 > 0)
2322 {
2323 ia=(ia+i)&mix2_mask;
2324 ib=(ib+i)&mix2_mask;
2325 }
2326 }
2327 }
2328 // Now that we have the optimum position for the passband,
2329 // see if there is a good reason to increase the bandwidth slightly.
2330 // The noise floor is r2 and the max signal is t1.
2331 // Look at both sides for a signal that is 9 dB or more above the noise.
2332 // The signal must also be less than 15 dB below the main signal.
2333 t3=r2*4;
2334 if(t3 < t1/32)t3=t1/32;
2335 for(i=1; i<k3; i++)
2336 {
2337 k1=(ia-i+mix2.size)&mix2_mask;
2338 k2=(ib+i)&mix2_mask;
2339 if(mix2_pwr[k1]>t3)
2340 {
2341 ia=k1;
2342 }
2343 if(mix2_pwr[k2]>t3)
2344 {
2345 ib=k2;
2346 }
2347 }
2348 // Now, use a 3 dB lower threshold and see if we can make the
2349 // filter narrower.
2350 t3/=2;
2351 while(mix2_pwr[ia] < t3)ia=(ia+1)&mix2_mask;
2352 while(mix2_pwr[ib] < t3)ib=(ib+mix2_mask)&mix2_mask;
2353 }
2354 // Now that we decided to use the frequencies from ia to ib, clear all
2355 // other frequencies in our buffer.
2356 ib=(ib+1)&mix2_mask;
2357 while(ib != ia)
2358 {
2359 mix2_tmp[2*ib ]=0;
2360 mix2_tmp[2*ib+1]=0;
2361 ib=(ib+1)&mix2_mask;
2362 }
2363 // Go back to the time domain to get the carrier.
2364 fftback(mix2.size, mix2.n, mix2_tmp, mix2.table, mix2.permute, yieldflag_ndsp_mix2);
2365 if(region_flag < 3)
2366 {
2367 ia=(ka+sizhalf)&baseband_mask;
2368 for(i=sizhalf; i<(int)mix2.size; i++)
2369 {
2370 baseb_tmp[2*ia ]=mix2_tmp[2*i ];
2371 baseb_tmp[2*ia+1]=mix2_tmp[2*i+1];
2372 ia=(ia+1)&baseband_mask;
2373 }
2374 }
2375 else
2376 {
2377 if(region_flag == 3)
2378 {
2379 ia=(ka+sizhalf)&baseband_mask;
2380 i=sizhalf;
2381 while(i<(int)mix2.size && ia != kb)
2382 {
2383 baseb_tmp[2*ia ]=mix2_tmp[2*i ];
2384 baseb_tmp[2*ia+1]=mix2_tmp[2*i+1];
2385 ia=(ia+1)&baseband_mask;
2386 i++;
2387 }
2388 }
2389 }
2390
2391 if(region_flag == 2 || region_flag == 3)
2392 {
2393 ia=ka;
2394 for(i=0; i<sizhalf; i++)
2395 {
2396 baseb_tmp[2*ia ]+=mix2_tmp[2*i ];
2397 baseb_tmp[2*ia+1]+=mix2_tmp[2*i+1];
2398 ia=(ia+1)&baseband_mask;
2399 }
2400 }
2401 else
2402 {
2403 if(region_flag == 4)
2404 {
2405 ia=ka;
2406 i=0;
2407 while(i<sizhalf && ia != kb)
2408 {
2409 baseb_tmp[2*ia ]+=mix2_tmp[2*i ];
2410 baseb_tmp[2*ia+1]+=mix2_tmp[2*i+1];
2411 ia=(ia+1)&baseband_mask;
2412 i++;
2413 }
2414 }
2415 }
2416 // Prepare for a new section of the current region.
2417 ka=(ka+sizhalf)&baseband_mask;
2418 if( ((kb-ka-(int)mix2.size+baseband_size)&baseband_mask)< baseband_sizhalf)
2419 {
2420 region_flag=2;
2421 }
2422 else
2423 {
2424 region_flag++;
2425 }
2426 if( ((kb-ka+baseband_size)&baseband_mask)< baseband_sizhalf)
2427 {
2428 ia=ka;
2429 i=0;
2430 while(i<(int)mix2.size && ia != kb)
2431 {
2432 mix2_tmp[2*i ]=baseb_fit[2*ia ]*cw_carrier_window[i];
2433 mix2_tmp[2*i+1]=baseb_fit[2*ia+1]*cw_carrier_window[i];
2434 ia=(ia+1)&baseband_mask;
2435 i++;
2436 }
2437 while(i<(int)mix2.size)
2438 {
2439 mix2_tmp[2*i ]=0;
2440 mix2_tmp[2*i+1]=0;
2441 ia=(ia+1)&baseband_mask;
2442 i++;
2443 }
2444 goto new_carrier;
2445 }
2446 }
2447 goto debug_x;
2448
2449 // Use the positons with decimals to form the summed baseband
2450 // function over a larger time interval, the new corr_len.
2451
2452
2453 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2454 ia=corr[0].pos;
2455 ib=(ia+corr_len)&baseband_mask;
2456 while(ia!=ib)
2457 {
2458 baseb_tmp[2*ia ]=0;
2459 baseb_tmp[2*ia+1]=0;
2460 ia=(ia+1)&baseband_mask;
2461 }
2462 for(i=0; i<no_of_corr; i++)
2463 {
2464 ia=corr[0].pos;
2465 ka=corr[i].pos;
2466 kb=(ka+1)&baseband_mask;
2467 t1=corr[i].fpos-ka;
2468 t2=1-t1;
2469 while(ia!=ib)
2470 {
2471 baseb_tmp[2*ia ]+=t2*baseb[2*ka ]+t1*baseb[2*kb ];
2472 baseb_tmp[2*ia+1]+=t2*baseb[2*ka+1]+t1*baseb[2*kb+1];
2473 ia=(ia+1)&baseband_mask;
2474 ka=kb;
2475 kb=(kb+1)&baseband_mask;
2476 }
2477 }
2478
2479
2480
2481 goto debug_x; //ö
2482
2483
2484
2485
2486
2487 debug_x:;
2488 make_baseb_sho1();
2489 make_baseb_sho2();
2490 if(no_of_corr > 2)
2491 {
2492 cw_detect_flag=CWDETECT_DEBUG_STOP;//öö
2493 XZ("STOP!!");
2494 }
2495 return;//öööööööööööööööööööööööööööööööööööööööööööööööööööö
2496
2497
2498
2499
2500 // Use the carrier now present in baseb_tmp[] to compute a new
2501 // and hopefully more accurate coherently detected signal in baseb_fit[]
2502 // Accumulate the average waveform in baseb_envelope[].
2503
2504 // !!!!!!!!!!!!!!!!!!!!! for debug purposes !!!!!!!!!!!!!!!
2505 // ö ö ö
2506 for(i=0;i<baseband_size/2;i+=2)
2507 {
2508 baseb_envelope[4*i ]=-1/(ZZ*ZZ);
2509 baseb_envelope[4*i+1]=1/(ZZ*ZZ);
2510 baseb_envelope[4*i+2]=1;
2511 baseb_envelope[4*i+3]=1;
2512 baseb_envelope[4*i+4]=0;
2513 baseb_envelope[4*i+5]=0;
2514 baseb_envelope[4*i+6]=0;
2515 baseb_envelope[4*i+7]=0;
2516 }
2517 // """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2518
2519 ia=corr[0].pos;
2520 ib=(ia+corr_len)&baseband_mask;
2521 while(ia != ib)
2522 {
2523 baseb_envelope[2*ia ]=0;
2524 baseb_envelope[2*ia+1]=0;
2525 ia=(ia+1)&baseband_mask;
2526 }
2527 for(region=0; region<no_of_corr; region++)
2528 {
2529 ia=corr[0].pos;
2530 ka=corr[region].pos;
2531
2532 DEB"\nfinal:[%d] %d",region,ka);
2533
2534 kb=(ka+corr_len)&baseband_mask;
2535 while(ka != kb)
2536 {
2537 t1=sqrt(baseb_tmp[2*ka ]*baseb_tmp[2*ka ]+
2538 baseb_tmp[2*ka+1]*baseb_tmp[2*ka+1]);
2539 if(t1!=0)
2540 {
2541 t2=baseb_tmp[2*ka ]/t1;
2542 t3=baseb_tmp[2*ka+1]/t1;
2543 baseb_fit[2*ka ]=t2*baseb_raw[2*ka ]+t3*baseb_raw[2*ka+1];
2544 baseb_fit[2*ka+1]=t2*baseb_raw[2*ka+1]-t3*baseb_raw[2*ka ];
2545 }
2546 else
2547 {
2548 baseb_fit[2*ka ]=0;
2549 baseb_fit[2*ka+1]=0;
2550 }
2551 baseb_envelope[2*ia ]+=0.3*baseb_fit[2*ka ];
2552 baseb_envelope[2*ia+1]+=0.3*baseb_fit[2*ka+1];
2553 ka=(ka+1)&baseband_mask;
2554 ia=(ia+1)&baseband_mask;
2555 }
2556 }
2557 correlated_detect();
2558
2559
2560 show_cw("correlate end");
2561
2562
2563
2564
2565
2566
2567 return;
2568 goto retry_correlation;
2569 // set cw_detect_flag >40 if sucessful
2570 }
2571
show_cw(char * caller)2572 void show_cw(char *caller)
2573 {
2574 int i;
2575 char s[80];
2576 DEB"\n**** show_cw: (%s) *****",caller);
2577 DEB"\n N [mid] sep l unk tmp coh raw");
2578 for(i=0; i<no_of_cwdat; i++)
2579 {
2580 switch (cw[i].type)
2581 {
2582 case CW_DASH:
2583 sprintf(s,"dash ");
2584 break;
2585
2586 case CW_DOT:
2587 sprintf(s,"dot ");
2588 break;
2589
2590 case CW_SPACE:
2591 sprintf(s,"space ");
2592 break;
2593
2594 case CW_WORDSEP:
2595 sprintf(s,"wordsep");
2596 break;
2597
2598 default:
2599 sprintf(s,"{%3d} %c",cw[i].type,cw[i].type);
2600 break;
2601 }
2602 DEB"\n%s %5d [%8.2f]%8.2f %2d %3d %.4f (%7.1f,%7.1f) (%7.1f,%7.1f) ",
2603 s,i,cw[i].midpoint,cw[i].sep,cw[i].len,cw[i].unkn,
2604 0.00001*ZZ*cw[i].tmp, ZZ*cw[i].coh_re,ZZ*cw[i].coh_im,
2605 ZZ*cw[i].raw_re,ZZ*cw[i].raw_im);
2606 }
2607 DEB"\n");
2608 }
2609
insert_item(int type)2610 void insert_item(int type)
2611 {
2612 int i, ja, jb, k, m;
2613 float t1,t2,r1,r2;
2614 check_cw(4001,1);
2615 if(kill_all_flag)return;
2616 r2=0;
2617 if(cw_ptr==0)
2618 {
2619 ja=0;
2620 r1=cg_wave_midpoint-baseb_px;
2621 }
2622 else
2623 {
2624 ja=cw[cw_ptr-1].len;
2625 r1=cg_wave_midpoint-cw[cw_ptr-1].midpoint;
2626 }
2627 if(r1 < 0)r1+=baseband_size;
2628 i=no_of_cwdat;
2629 while(i > cw_ptr)
2630 {
2631 cw[i]=cw[i-1];
2632 i--;
2633 }
2634 if(cw_ptr != no_of_cwdat)
2635 {
2636 r2=cw[cw_ptr].midpoint-cg_wave_midpoint;
2637 if(r2 < 0)r2+=baseband_size;
2638 cw[cw_ptr+1].sep=r2;
2639 jb=(cw[cw_ptr+1].len+cw[cw_ptr].len)/2;
2640 r2/=cwbit_pts;
2641 r2-=jb;
2642 if(r2 < 0)r2=0;
2643 k=(int)(r2)&0xfffffffe;
2644 if(r2-k > 1)k+=2;
2645 cw[cw_ptr+1].unkn=k;
2646 }
2647 cw[cw_ptr].midpoint=cg_wave_midpoint;
2648 cw[cw_ptr].type=type;
2649 cw[cw_ptr].coh_re=cg_wave_coh_re;
2650 cw[cw_ptr].coh_im=cg_wave_coh_im;
2651 if(cg_wave_raw_re == 0 && cg_wave_raw_im == 0)
2652 {
2653 m=cg_wave_midpoint+0.5;
2654 t1=baseb_carrier[2*m ];
2655 t2=baseb_carrier[2*m+1];
2656 cg_wave_raw_re=cg_wave_coh_re*t1+cg_wave_coh_im*t2;
2657 cg_wave_raw_im=cg_wave_coh_im*t1-cg_wave_coh_re*t2;
2658 }
2659 cw[cw_ptr].raw_re=cg_wave_raw_re;
2660 cw[cw_ptr].raw_im=cg_wave_raw_im;
2661 cw[cw_ptr].len=cw_item_len[255-type];
2662 ja=(ja+cw[cw_ptr].len)/2;
2663 cw[cw_ptr].sep=r1;
2664 r1/=cwbit_pts;
2665 r1-=ja;
2666 k=(int)(r1)&0xfffffffe;
2667 if(r1-k > 1)k+=2;
2668 cw[cw_ptr].unkn=k;
2669 DEB"\ninsert[%f] type %s len %d sep[i] %.0f sep[i+1] %.0f",
2670 cg_wave_midpoint,cw_item_text[255-type],cw_item_len[255-type],r1,r2);
2671 no_of_cwdat++;
2672 if(no_of_cwdat > max_cwdat)lirerr(1189);
2673 check_cw(40011,1);
2674 }
2675
2676
second_detect(void)2677 void second_detect(void)
2678 {
2679 int k;
2680 float r1;
2681 // *****************************************************
2682 // *****************************************************
2683 // ***** Fit key up or key down patterns to short *****
2684 // ***** regions that are surrounded by dashes *****
2685 // *****************************************************
2686 // *****************************************************
2687 // Look for the following cases:
2688 // -_-_ 2
2689 // ---_- 3
2690 // -_--- 3
2691 // -___- 4
2692 // ---___- 5
2693 // -___--- 5
2694 // -_____- 7
2695 //
2696 // Code Sep
2697 // ---_--- 4
2698 // ---_-_--- 6
2699 // ---___--- 6
2700 // ---_-_-_--- 8
2701 // ---_---_--- 8
2702 // ---___-_--- 8
2703 // ---_-___--- 8
2704 // ---_____--- 8
2705 // ---_---_?_--- 10
2706 // ---_?_---_--- 10
2707 // ---_---_????.... default
2708 // ....????_---_--- default
2709
2710 // Look for the following cases:
2711 // Code Unkn
2712 // |__| 2
2713 // |-_| 2
2714 // |____| 4
2715 // |-___| 4
2716 // |__-_| 4
2717 // |-_-_| 4
2718 // |---_| 4
2719 // |______| 6
2720 // |-_____| 6
2721 // |__-___| 6
2722 //show_cw("second_detect enter");
2723
2724
2725 PRT02"\nsecond_detect: CWBIT PTS %f x",cwbit_pts);
2726 // Store the most probable signal in each case.
2727 // name data length
2728 // CW_DASH |---_| 4
2729 // CW_DOT |-_| 2
2730 // CW_SPACE |__| 2
2731 // CW_WORDSEP |____| 4
2732 // The item starts (length/2 + 0.5) below cw[].midpoint because
2733 // midpoint is the center of a key down period while the item
2734 // midpoint is 0.5 above that because one space is always
2735 // included in an item.
2736 PRT02"\n0 PRT02(2)> [%7.1f] ", cw[0].midpoint);
2737 cw_ptr=1;
2738
2739 while(cw_ptr < no_of_cwdat &&
2740 cw[cw_ptr].type==CW_DASH &&
2741 cw[cw_ptr-1].type==CW_DASH)
2742 {
2743 r1=cw[cw_ptr].sep/cwbit_pts;
2744 if( (cw[cw_ptr].type==CW_DASH && cw[cw_ptr-1].type==CW_DASH)||
2745 (cw[cw_ptr].type==CW_DOT && cw[cw_ptr-1].type==CW_DOT) )
2746 {
2747 k=(int)(r1)&0xfffffffe;
2748 if(r1-k > 1)k+=2;
2749 }
2750 else
2751 {
2752 if( (cw[cw_ptr].type==CW_DASH && cw[cw_ptr-1].type==CW_DOT)||
2753 (cw[cw_ptr].type==CW_DOT && cw[cw_ptr-1].type==CW_DASH) )
2754 {
2755 k=(int)(r1+1)&0xfffffffe;
2756 if(r1+1-k > 1)k+=2;
2757 k--;
2758
2759
2760
2761 goto skip; // !!!!! REMOVE !!!!!
2762
2763
2764 }
2765 else
2766 {
2767 goto skip;
2768 }
2769 }
2770 PRT02"\n%d PRT02(2)>k=%3d [%7.1f][%7.1f]",cw_ptr,k,cw[cw_ptr-1].midpoint,
2771 cw[cw_ptr].midpoint);
2772 switch (k)
2773 {
2774 case 2:
2775 case 4:
2776 // We have two close spaced dashes.
2777 // There can be nothing in between.
2778 break;
2779
2780 case 6:
2781 // ---_-_--- 6
2782 // ---___--- 6
2783 if(kill_all_flag)return;
2784 break;
2785
2786 case 8:
2787 // ---_-_-_--- 8 ity=4
2788 // ---_---_--- 8 ity=1
2789 // ---___-_--- 8 ity=3
2790 // ---_-___--- 8 ity=2
2791 // ---_____--- 8 ity=5
2792 /*
2793 cg_wave_midpoint=dashpos1+t2*dashpos1_err;
2794 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
2795 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
2796 ia=cg_wave_midpoint;
2797 cg_wave_coh_re=t3*dash1_re+t2*baseb_envelope[2*ia ];
2798 cg_wave_coh_im=t3*dash1_im+t2*baseb_envelope[2*ia+1];
2799 PRT04"\nstore_dash %f",cg_wave_midpoint);
2800 insert_item(CW_DASH);
2801 if(kill_all_flag)return;
2802 cw_ptr++;
2803
2804 break;
2805
2806 case 2:
2807 // Store dot1 and space
2808 // ---_-___--- 8 ity=2
2809 // ---___-_--- 8 ity=3
2810 // ---_____--- 8 ity=5
2811 // ---_-_-_--- 8 ity=4
2812 t3=0;
2813 if(dot_fit1 > DOT_DETECT_LIMIT && fabs(dotpos1_err) < 0.25*cwbit_pts)
2814 {
2815 if(dot1_chk < 0.25)
2816 {
2817 t3=0.75;
2818 }
2819 else
2820 {
2821 t3=0.5;
2822 }
2823 }
2824 t2=1-t3;
2825 cg_wave_midpoint=dotpos1+t2*dotpos1_err;
2826 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
2827 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
2828 ia=cg_wave_midpoint;
2829 cg_wave_coh_re=t3*dot1_re+t2*baseb_envelope[2*ia ];
2830 cg_wave_coh_im=t3*dot1_im+t2*baseb_envelope[2*ia+1];
2831 PRT04"\nstore dot %f",cg_wave_midpoint);
2832 insert_item(CW_DOT);
2833 if(kill_all_flag)return;
2834 cw_ptr++;
2835 cg_wave_midpoint=dotpos2_nom;
2836 PRT04"\nstore_space %f",cg_wave_midpoint);
2837 insert_item(CW_SPACE);
2838 if(kill_all_flag)return;
2839 cw_ptr++;
2840 break;
2841
2842 case 3:
2843 // Store space and dot2
2844 // ---___-_--- 8 ity=3
2845 cg_wave_midpoint=dotpos1_nom;
2846 PRT04"\nstore_space %f",cg_wave_midpoint);
2847 insert_item(CW_SPACE);
2848 if(kill_all_flag)return;
2849 cw_ptr++;
2850 t3=0;
2851 if(dot_fit2 > DOT_DETECT_LIMIT && fabs(dotpos2_err) < 0.25*cwbit_pts)
2852 {
2853 if(dot2_chk < 0.25)
2854 {
2855 t3=0.75;
2856 }
2857 else
2858 {
2859 t3=0.5;
2860 }
2861 }
2862 t2=1-t3;
2863 cg_wave_midpoint=dotpos2+t2*dotpos2_err;
2864 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
2865 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
2866 ia=cg_wave_midpoint;
2867 cg_wave_coh_re=t3*dot2_re+t2*baseb_envelope[2*ia ];
2868 cg_wave_coh_im=t3*dot2_im+t2*baseb_envelope[2*ia+1];
2869 PRT04"\nstore dot %f",cg_wave_midpoint);
2870 insert_item(CW_DOT);
2871 if(kill_all_flag)return;
2872 cw_ptr++;
2873 break;
2874
2875 case 4:
2876 // Store dot1 and dot2
2877 // ---_-_-_--- 8 ity=4
2878 t3=0;
2879 if(dot_fit1 > DOT_DETECT_LIMIT && fabs(dotpos1_err) < 0.25*cwbit_pts)
2880 {
2881 if(dot1_chk < 0.25)
2882 {
2883 t3=0.75;
2884 }
2885 else
2886 {
2887 t3=0.5;
2888 }
2889 }
2890 t2=1-t3;
2891 cg_wave_midpoint=dotpos1+t2*dotpos1_err;
2892 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
2893 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
2894 ia=cg_wave_midpoint;
2895 cg_wave_coh_re=t3*dot1_re+t2*baseb_envelope[2*ia ];
2896 cg_wave_coh_im=t3*dot1_im+t2*baseb_envelope[2*ia+1];
2897 PRT04"\nstore dot %f",cg_wave_midpoint);
2898 insert_item(CW_DOT);
2899 if(kill_all_flag)return;
2900 cw_ptr++;
2901 t3=0;
2902 if(dot_fit2 > DOT_DETECT_LIMIT && fabs(dotpos2_err) < 0.25*cwbit_pts)
2903 {
2904 if(dot2_chk < 0.25)
2905 {
2906 t3=0.75;
2907 }
2908 else
2909 {
2910 t3=0.5;
2911 }
2912 }
2913 t2=1-t3;
2914 cg_wave_midpoint=dotpos2+t2*dotpos2_err;
2915 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
2916 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
2917 ia=cg_wave_midpoint;
2918 cg_wave_coh_re=t3*dot2_re+t2*baseb_envelope[2*ia ];
2919 cg_wave_coh_im=t3*dot2_im+t2*baseb_envelope[2*ia+1];
2920 PRT04"\nstore dot %f",cg_wave_midpoint);
2921 insert_item(CW_DOT);
2922 if(kill_all_flag)return;
2923 cw_ptr++;
2924 break;
2925
2926 case 5:
2927 // Store word separator
2928 // ---_____--- 8 ity=5
2929 cg_wave_midpoint=dashpos1_nom;
2930 PRT04"\nstore word sep %f",cg_wave_midpoint);
2931 insert_item(CW_WORDSEP);
2932 if(kill_all_flag)return;
2933 cw_ptr++;
2934 break;
2935 }
2936 */
2937 break;
2938
2939 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2940 // ööAug 2004
2941 //
2942 default:
2943 /*
2944 if(k==10)
2945 {
2946 set_region_envelope();
2947 }
2948 else
2949 {
2950 set_long_region_envelope();
2951 }
2952 // See if a dash will fit in the first position.
2953 dashpos1_nom=cw[cw_ptr-1].midpoint+4*cwbit_pts;
2954 if(dashpos1_nom >= baseband_size)dashpos1_nom-=baseband_size;
2955 dash1_chk=check_dash(dashpos1_nom);
2956 cg_wave_start=dashpos1_nom-(dash_pts>>1)+baseband_size;
2957 cg_wave_start&=baseband_mask;
2958 fit_dash();
2959 dash1_re=cg_wave_coh_re;
2960 dash1_im=cg_wave_coh_im;
2961 dashpos1=cg_wave_midpoint;
2962 dashpos1_err=dashpos1_nom-cg_wave_midpoint;
2963 if(dashpos1_err < -sizhalf)dashpos1_err+=baseband_size;
2964 dash_fit1=cg_wave_fit;
2965 PRT05"\n{def.l(2)}CHK DASH %f fit= %f (%f) [%f]",
2966 dash1_chk,dash_fit1,dashpos1_nom,cg_wave_midpoint);
2967 // See if a dot will fit in the first position
2968 dotpos1_nom=dashpos1_nom-cwbit_pts;
2969 if(dotpos1_nom < 0)dotpos1_nom+=baseband_size;
2970 dot1_chk=check_dot(dotpos1_nom);
2971 cg_wave_start=dotpos1_nom-(dot_pts>>1)+baseband_size;
2972 cg_wave_start&=baseband_mask;
2973 fit_dot();
2974 dot1_re=cg_wave_coh_re;
2975 dot1_im=cg_wave_coh_im;
2976 dotpos1=cg_wave_midpoint;
2977 dotpos1_err=dotpos1_nom-cg_wave_midpoint;
2978 if(dotpos1_err < -sizhalf)dotpos1_err+=baseband_size;
2979 dot_fit1=cg_wave_fit;
2980 PRT05"\n{def.l(2)}CHK DOT1 %f fit=%f (%f) [%f]",
2981 dot1_chk,dot_fit1,dotpos1_nom,cg_wave_midpoint);
2982 ity=0;
2983 if( (dash_fit1 > DASH_DETECT_LIMIT &&
2984 fabs(dashpos1_err) < 0.7*cwbit_pts &&
2985 dash1_chk > 0) ||
2986 (dash_fit1 > DASH_MISFIT_LIMIT &&
2987 fabs(dashpos1_err) < 0.5*cwbit_pts &&
2988 dash1_chk > 0.5) )
2989 {
2990 // A dash fits reasonably well in the lower position.
2991 ity=1;
2992 // Check how well dots would fit at the beginning or end of the dash position.
2993 if(fabs(dotpos1_err) < 0.7 * cwbit_pts &&
2994 dash_fit1 < dot_fit1+0.05 &&
2995 dot1_chk > 0)
2996 {
2997 PRT05"\ndot1.l good(2). Skip dash for now.");
2998 ity=0;
2999 if( dot_fit1 > DOT_DETECT_LIMIT ||
3000 (dot_fit1 > DOT_MISFIT_LIMIT &&
3001 fabs(dotpos1_err) < 0.5*cwbit_pts &&
3002 dash_fit1 < dot_fit1 &&
3003 dot1_chk > 0.5) )
3004 {
3005 goto store_dot1;
3006 }
3007 }
3008 else
3009 {
3010 dotpos2_nom=dashpos1_nom+cwbit_pts;
3011 if(dotpos2_nom >= baseband_size)dotpos2_nom-=baseband_size;
3012 dot2_chk=check_dot(dotpos2_nom);
3013 cg_wave_start=dotpos2_nom-(dot_pts>>1)+baseband_size;
3014 cg_wave_start&=baseband_mask;
3015 fit_dot();
3016 dotpos2=cg_wave_midpoint;
3017 dotpos2_err=dotpos2_nom-cg_wave_midpoint;
3018 if(dotpos2_err < -sizhalf)dotpos2_err+=baseband_size;
3019 dot_fit2=cg_wave_fit;
3020 PRT05"\n{def.l}CHK DOT2 %f fit=%f (%f) [%f]",
3021 dot2_chk,cg_wave_fit,dotpos2_nom,cg_wave_midpoint);
3022 if(fabs(dotpos2_err) < 0.5 * cwbit_pts &&
3023 dash_fit1 < dot_fit2+0.05 &&
3024 dot2_chk > 0.25)
3025 {
3026 PRT05"\ndot2.h good, skip dash for now.");
3027 ity=0;
3028 }
3029 }
3030 }
3031 else
3032 {
3033 // A dash did not fit in the first position.
3034 // See if a dot does.
3035 if( (dot_fit1 > DOT_DETECT_LIMIT &&
3036 fabs(dotpos1_err) < 0.7*cwbit_pts &&
3037 dot1_chk > 0) ||
3038 (dot_fit1 > DOT_MISFIT_LIMIT &&
3039 fabs(dotpos1_err) < 0.5*cwbit_pts &&
3040 dot1_chk > 0.5) )
3041 {
3042 PRT05"\ndash1 bad, dot1 good.");
3043 store_dot1:;
3044 cg_wave_midpoint=dotpos1+0.5*dotpos1_err;
3045 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3046 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3047 ia=cg_wave_midpoint;
3048 cg_wave_coh_re=0.5*dot1_re+0.5*baseb_envelope[2*ia ];
3049 cg_wave_coh_im=0.5*dot1_im+0.5*baseb_envelope[2*ia+1];
3050 PRT05"\nstore dot1.l %f",cg_wave_midpoint);
3051 insert_item(CW_DOT);
3052 if(kill_all_flag)return;
3053 cw_ptr++;
3054 }
3055 }
3056 // See if a dash will fit in the upper position.
3057 dashpos2_nom=cw[cw_ptr].midpoint-4*cwbit_pts;
3058 if(dashpos2_nom < 0)dashpos2_nom+=baseband_size;
3059 dash2_chk=check_dash(dashpos2_nom);
3060 cg_wave_start=dashpos2_nom-(dash_pts>>1)+baseband_size;
3061 cg_wave_start&=baseband_mask;
3062 fit_dash();
3063 dash2_re=cg_wave_coh_re;
3064 dash2_im=cg_wave_coh_im;
3065 dashpos2=cg_wave_midpoint;
3066 dashpos2_err=dashpos2_nom-cg_wave_midpoint;
3067 if(dashpos2_err < -sizhalf)dashpos2_err+=baseband_size;
3068 dash_fit2=cg_wave_fit;
3069 PRT05"\n{def.h(2)}CHK DASH %f fit= %f (%f) [%f]",
3070 dash2_chk,dash_fit2,dashpos2_nom,cg_wave_midpoint);
3071 dotpos4_nom=dashpos2_nom+cwbit_pts;
3072 if(dotpos4_nom >= baseband_size)dotpos4_nom-=baseband_size;
3073 dot4_chk=check_dot(dotpos4_nom);
3074 cg_wave_start=dotpos4_nom-(dot_pts>>1)+baseband_size;
3075 cg_wave_start&=baseband_mask;
3076 fit_dot();
3077 dot4_re=cg_wave_coh_re;
3078 dot4_im=cg_wave_coh_im;
3079 dotpos4=cg_wave_midpoint;
3080 dotpos4_err=dotpos4_nom-cg_wave_midpoint;
3081 if(dotpos4_err < -sizhalf)dotpos4_err+=baseband_size;
3082 dot_fit4=cg_wave_fit;
3083 PRT05"\n{def.h(2)}CHK DOT4 %f fit=%f (%f) [%f]",
3084 dot4_chk,dot_fit4,dotpos4_nom,cg_wave_midpoint);
3085
3086 if( (dash_fit2 > DASH_DETECT_LIMIT &&
3087 fabs(dashpos2_err) < 0.7*cwbit_pts &&
3088 dash2_chk > 0) ||
3089 (dash_fit2 > DASH_MISFIT_LIMIT &&
3090 fabs(dashpos2_err) < 0.5*cwbit_pts &&
3091 dash2_chk > 0.5) )
3092 {
3093 // A dash fits reasonably well in the upper position.
3094 ity|=2;
3095 // Check how well dots would fit at the beginning or end of the dash position.
3096 if( fabs(dotpos4_err) < 0.7 * cwbit_pts &&
3097 dash_fit2 < dot_fit4+0.05 &&
3098 dot4_chk > 0)
3099 {
3100 PRT05"\ndot4.h good(2), skip dash for now.");
3101 ity&=1;
3102 if( dot_fit4 > DOT_DETECT_LIMIT ||
3103 (dot_fit4 > DOT_MISFIT_LIMIT &&
3104 fabs(dotpos4_err) < 0.5*cwbit_pts &&
3105 dash_fit2 < dot_fit4 &&
3106 dot4_chk > 0.5) )
3107 {
3108 goto store_dot4;
3109 }
3110 }
3111 else
3112 {
3113 dotpos3_nom=dashpos2_nom-cwbit_pts;
3114 if(dotpos3_nom < 0)dotpos3_nom+=baseband_size;
3115 dot3_chk=check_dot(dotpos3_nom);
3116 cg_wave_start=dotpos3_nom-(dot_pts>>1)+baseband_size;
3117 cg_wave_start&=baseband_mask;
3118 fit_dot();
3119 dotpos3=cg_wave_midpoint;
3120 dotpos3_err=dotpos3_nom-cg_wave_midpoint;
3121 if(dotpos3_err < -sizhalf)dotpos3_err+=baseband_size;
3122 dot_fit3=cg_wave_fit;
3123 PRT05"\n{def.h}CHK DOT3 %f fit=%f (%f) [%f]",
3124 dot3_chk,cg_wave_fit,dotpos3_nom,cg_wave_midpoint);
3125 if(fabs(dotpos3_err) < 0.5 * cwbit_pts &&
3126 dash_fit2 < dot_fit3+0.05 &&
3127 dot3_chk > 0.25)
3128 {
3129 PRT05"\ndot3.h good, skip dash for now.");
3130 ity&=1;
3131 }
3132 }
3133 if( (ity & 3) == 3 && k < 12)
3134 {
3135 // We can not have one dash at each side in a short region.
3136 // choose the best one.
3137 if( fabs(dash_fit1-dash_fit2) > 0.05)
3138 {
3139 if(dash_fit1 > dash_fit2)
3140 {
3141 ity=1;
3142 }
3143 else
3144 {
3145 ity=2;
3146 }
3147 }
3148 else
3149 {
3150 t1=2*dash_fit1-dot_fit1-dot_fit2-2*dash_fit2+dot_fit3+dot_fit4;
3151 if(fabs(t1) < 0.05)
3152 {
3153 ity=0;
3154 }
3155 else
3156 {
3157 if(t1>0)ity=1; else ity=2;
3158 }
3159 }
3160 }
3161 }
3162 else
3163 {
3164 // A dash did not fit in the upper position.
3165 // See if a dot does.
3166 if( (dot_fit4 > DOT_DETECT_LIMIT &&
3167 fabs(dotpos4_err) < 0.7*cwbit_pts &&
3168 dot4_chk > 0) ||
3169 (dot_fit4 > DOT_MISFIT_LIMIT &&
3170 fabs(dotpos4_err) < 0.5*cwbit_pts &&
3171 dot4_chk > 0.5) )
3172 {
3173 PRT05"\ndash2 bad, dot4 good.");
3174 store_dot4:;
3175 ity|=4;
3176 }
3177 }
3178 if( (ity & 3) == 3 && k < 12)
3179 {
3180 // We can not have one dash at each side in a short region.
3181 // choose the best one.
3182 if( fabs(dash_fit1-dash_fit2) > 0.05)
3183 {
3184 if(dash_fit1 > dash_fit2)
3185 {
3186 ity=1;
3187 }
3188 else
3189 {
3190 ity=2;
3191 }
3192 }
3193 else
3194 {
3195 t1=2*dash_fit1-dot_fit1-dot_fit2-2*dash_fit2+dot_fit3+dot_fit4;
3196 if(fabs(t1) < 0.05)
3197 {
3198 ity=0;
3199 }
3200 else
3201 {
3202 if(t1>0)ity=1; else ity=2;
3203 }
3204 }
3205 }
3206 if( (ity&1) != 0)
3207 {
3208 cg_wave_midpoint=dashpos1+0.5*dashpos1_err;
3209 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3210 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3211 ia=cg_wave_midpoint;
3212 cg_wave_coh_re=0.5*dash1_re+0.5*baseb_envelope[2*ia ];
3213 cg_wave_coh_im=0.5*dash1_im+0.5*baseb_envelope[2*ia+1];
3214 PRT05"\nstore_dash.l %f",cg_wave_midpoint);
3215 insert_item(CW_DASH);
3216 if(kill_all_flag)return;
3217 cw_ptr++;
3218 }
3219 if( (ity&2) != 0)
3220 {
3221 cg_wave_midpoint=dashpos2+0.5*dashpos2_err;
3222 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3223 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3224 ia=cg_wave_midpoint;
3225 cg_wave_coh_re=0.5*dash2_re+0.5*baseb_envelope[2*ia ];
3226 cg_wave_coh_im=0.5*dash2_im+0.5*baseb_envelope[2*ia+1];
3227 PRT05"\nstore_dash.h %f",cg_wave_midpoint);
3228 insert_item(CW_DASH);
3229 if(kill_all_flag)return;
3230 cw_ptr++;
3231 }
3232 if( (ity&4) != 0)
3233 {
3234 cg_wave_midpoint=dotpos4+0.5*dotpos4_err;
3235 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3236 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3237 ia=cg_wave_midpoint;
3238 cg_wave_coh_re=0.5*dot4_re+0.5*baseb_envelope[2*ia ];
3239 cg_wave_coh_im=0.5*dot4_im+0.5*baseb_envelope[2*ia+1];
3240 PRT05"\nstore dot4.h(2) %f",cg_wave_midpoint);
3241 insert_item(CW_DOT);
3242 if(kill_all_flag)return;
3243 cw_ptr++;
3244 }
3245 */
3246 break;
3247 }
3248 skip:;
3249 cw_ptr++;
3250 }
3251 //show_cw("second_detect exit");
3252 }
3253
3254
get_old_dashes(void)3255 void get_old_dashes(void)
3256 {
3257 int i;
3258 int ia, ib;
3259 // Speed and wave forms are known.
3260 // Look for new dashes, in the range cw[0].midpoint
3261 // to baseb_px.
3262 ia=baseb_px;
3263 while(baseb_ramp[ia] < 0)ia=(ia+1)&baseband_mask;
3264 while(baseb_ramp[ia] > 0)ia=(ia+1)&baseband_mask;
3265 while(baseb_ramp[ia] < 0)ia=(ia+1)&baseband_mask;
3266 ia=(ia+baseband_mask)&baseband_mask;
3267 ib=cw[0].midpoint;
3268 ib=(ib-abs(baseb_ramp[ib])+baseband_size)&baseband_mask;
3269 if(baseb_ramp[ib] > 0)ib=(ib-baseb_ramp[ib]+baseband_size)&baseband_mask;
3270 if(no_of_cwdat < 1)lirerr(876231);
3271 i=((int)(cw[no_of_cwdat-1].midpoint)-ib+baseband_size)&baseband_mask;
3272 if( i+((ib-ia+baseband_size)&baseband_mask) > baseband_neg)return;
3273 find_good_dashes(ia, ib, 14);
3274 check_cw(30035,1);
3275 }
3276
get_recent_dashes(void)3277 void get_recent_dashes(void)
3278 {
3279 int ia;
3280 // Speed and wave forms are known.
3281 // Look for new dashes, in the range cw[no_of_cwdat-1].midpoint
3282 // to baseb_pc.
3283 ia=cw[no_of_cwdat-1].midpoint;
3284 while(baseb_ramp[ia] > 0)ia=(ia+1)&baseband_mask;
3285 while(baseb_ramp[ia] < 0)ia=(ia+1)&baseband_mask;
3286 ia=(ia+baseband_mask)&baseband_mask;
3287 // ia now points to the last point of the first negative ramp
3288 // after the most recent cw[].midpoint.
3289 if( ((baseb_pc-ia+baseband_size)&baseband_mask) > baseband_neg)return;
3290 find_good_dashes(ia, baseb_pc, 14);
3291 check_cw(30030,1);
3292 }
3293
3294
3295
first_detect(int first_item)3296 void first_detect(int first_item)
3297 {
3298 mailbox[0]=first_item;
3299 cw_detect_flag=CWDETECT_DEBUG_STOP;
3300 return;
3301 lirerr(888922);
3302 /*
3303
3304 int sizhalf;
3305 int k, ia;
3306 int ity, item;
3307 float dotpos1_nom, dotpos2_nom, dotpos3_nom, dotpos4_nom;
3308 float dashpos1_nom, dashpos2_nom;
3309 float dot1_chk, dot2_chk, dot3_chk, dot4_chk, dash1_chk, dash2_chk;
3310 float dashpos1, dashpos2, dotpos1, dotpos2, dotpos3, dotpos4;
3311 float dashpos1_err, dashpos2_err;
3312 float dotpos1_err, dotpos2_err, dotpos3_err, dotpos4_err;
3313 float dash_fit1, dash_fit2, dot_fit1, dot_fit2, dot_fit3, dot_fit4;
3314 float r1, t1, t2, t3;
3315 float dash1_re, dash1_im, dash2_re, dash2_im;
3316 float dot1_re, dot1_im, dot2_re, dot2_im;
3317 // **************************************************************
3318 // **************************************************************
3319 // **** This routine is called to initiate a recently ****
3320 // *** collected data area for which dashes have been ****
3321 // **** fitted but for which nothing else has yet been done. ****
3322 // **************************************************************
3323 // **************************************************************
3324 sizhalf=baseband_size>>1;
3325 // Initiate with stupid values. This avoids compiler complaints.
3326 dot1_chk=-BIG;
3327 dotpos1=BIG;
3328 dotpos1_err=BIG;
3329 dot1_re=BIG;
3330 dot1_im=BIG;
3331 dot_fit1=-BIG;
3332 dot2_chk=-BIG;
3333 dotpos2=BIG;
3334 dotpos2_err=BIG;
3335 dot2_re=BIG;
3336 dot2_im=BIG;
3337 dot_fit2=-BIG;
3338 dotpos1_nom=BIG;
3339 dotpos2_nom=BIG;
3340 dash_fit2=-BIG;
3341 dot_fit4=-BIG;
3342 // *****************************************************
3343 // *****************************************************
3344 // ***** Fit key up or key down patterns to short *****
3345 // ***** regions that are surrounded by dashes *****
3346 // *****************************************************
3347 // *****************************************************
3348 // Look for the following cases:
3349 // Code Sep
3350 // ---_--- 4
3351 // ---_-_--- 6
3352 // ---___--- 6
3353 // ---_-_-_--- 8
3354 // ---_---_--- 8
3355 // ---___-_--- 8
3356 // ---_-___--- 8
3357 // ---_____--- 8
3358 // ---_---_?_--- 10
3359 // ---_?_---_--- 10
3360 // ---_---_????.... default
3361 // ....????_---_--- default
3362 #if PR02 == 1
3363 show_cw("first_detect enter");
3364 PRT02"\nfirst_detect: CWBIT PTS %f",cwbit_pts);
3365 #endif
3366 // Store the most probable signal in each case.
3367 // name data length
3368 // CW_DASH |---_| 4
3369 // CW_DOT |-_| 2
3370 // CW_SPACE |__| 2
3371 // CW_WORDSEP |____| 4
3372 // The item starts (length/2 + 0.5) below cw[].midpoint because
3373 // midpoint is the center of a key down period while the item
3374 // midpoint is 0.5 above that because one space is always
3375 // included in an item.
3376 cw_ptr=first_item;
3377 while(cw_ptr < no_of_cwdat)
3378 {
3379 r1=cw[cw_ptr].sep/cwbit_pts;
3380 k=(int)(r1)&0xfffffffe;
3381 if(r1-k > 1)k+=2;
3382 PRT02"\n%d PRT02(1)> k=%d %f [%f][%f]",cw_ptr,k,
3383 r1,cw[cw_ptr-1].midpoint,cw[cw_ptr].midpoint);
3384 check_cw(467501,1);
3385 if(kill_all_flag)return;
3386
3387 switch (k)
3388 {
3389 case 2:
3390 case 4:
3391 // We have two close spaced dashes.
3392 // There can be nothing in between.
3393 break;
3394
3395 case 6:
3396 // ---_-_--- 6
3397 // ---___--- 6
3398 // Base the decision on the probability that there is a dot
3399 // right between the two dashes.
3400 set_region_envelope();
3401 dotpos1_nom=cw[cw_ptr].midpoint-0.5*cw[cw_ptr].sep;
3402 if(dotpos1_nom < 0)dotpos1_nom+=baseband_size;
3403 dot1_chk=check_dot(dotpos1_nom);
3404 PRT03"\n{6}CHK DOT %f (%f)",dot1_chk,dotpos1_nom);
3405 // If dot1_chk in negative, the fit is better for a space than for a dot.
3406 // Be careful and check if a dot would fit even for dot1_chk a little below zero.
3407 if(dot1_chk > -0.25)
3408 {
3409 cg_wave_start=dotpos1_nom-(dot_pts>>1)+baseband_size;
3410 cg_wave_start&=baseband_mask;
3411 fit_dot();
3412 PRT03" [%f]", cg_wave_midpoint);
3413 dotpos1_err=dotpos1_nom-cg_wave_midpoint;
3414 if(dotpos1_err < -sizhalf)dotpos1_err+=baseband_size;
3415 PRT03" poserr %f fit %f",dotpos1_err/cwbit_pts,cg_wave_fit);
3416 t3=-1;
3417 // Use t3 as an indicator.
3418 // t3 < 0 => store space.
3419 // t3 > 0 => store dot using t3 as the weight on fit_dot data.
3420 if(cg_wave_fit > DOT_DETECT_LIMIT && fabs(dotpos1_err) < 0.25*cwbit_pts)
3421 {
3422 if(dot1_chk < 0.25)
3423 {
3424 t3=0.75;
3425 }
3426 else
3427 {
3428 t3=0.5;
3429 }
3430 }
3431 if(cg_wave_fit > DOT_MISFIT_LIMIT &&
3432 fabs(dotpos1_err) < 0.5*cwbit_pts && dot1_chk > 0.5)t3=0.5;
3433 if(t3 >= 0)
3434 {
3435 t2=1-t3;
3436 cg_wave_midpoint+=t2*dotpos1_err;
3437 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3438 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3439 ia=cg_wave_midpoint;
3440 cg_wave_coh_re=t3*cg_wave_coh_re+t2*baseb_envelope[2*ia ];
3441 cg_wave_coh_im=t3*cg_wave_coh_im+t2*baseb_envelope[2*ia+1];
3442 clear_region();
3443 PRT03"\nstore dot %f",cg_wave_midpoint);
3444 item=CW_DOT;
3445 }
3446 else
3447 {
3448 if( dot1_chk > 0)
3449 {
3450 item=0;
3451 }
3452 else
3453 {
3454 cg_wave_midpoint=dotpos1_nom;
3455 clear_region();
3456 PRT03"\nstore space %f",cg_wave_midpoint);
3457 item=CW_SPACE;
3458 }
3459 }
3460 }
3461 else
3462 {
3463 cg_wave_midpoint=dotpos1_nom;
3464 clear_region();
3465 PRT03"\nstore space %f",cg_wave_midpoint);
3466 item=CW_SPACE;
3467 }
3468 if(item!=0)insert_item(item);
3469 if(kill_all_flag)return;
3470 break;
3471
3472 case 8:
3473 // ---_-_-_--- 8 ity=4
3474 // ---_---_--- 8 ity=1
3475 // ---___-_--- 8 ity=3
3476 // ---_-___--- 8 ity=2
3477 // ---_____--- 8 ity=5
3478 set_region_envelope();
3479 ity=0;
3480 // See if a dash will fit well.
3481 dashpos1_nom=cw[cw_ptr].midpoint-0.5*cw[cw_ptr].sep;
3482 if(dashpos1_nom < 0)dashpos1_nom+=baseband_size;
3483 dash1_chk=check_dash(dashpos1_nom);
3484 cg_wave_start=dashpos1_nom-(dash_pts>>1)+baseband_size;
3485 cg_wave_start&=baseband_mask;
3486 fit_dash();
3487 dash1_re=cg_wave_coh_re;
3488 dash1_im=cg_wave_coh_im;
3489 dashpos1=cg_wave_midpoint;
3490 dashpos1_err=dashpos1_nom-cg_wave_midpoint;
3491 if(dashpos1_err < -sizhalf)dashpos1_err+=baseband_size;
3492 dash_fit1=cg_wave_fit;
3493 if( dash_fit1 > DASH_DETECT_LIMIT &&
3494 dash1_chk > 0.5 && fabs(dashpos1_err) < 0.5*cwbit_pts)
3495 {
3496 ity=1;
3497 PRT04"\n{8}GOOD DASH %f fit= %f (%f) [%f]",
3498 dash1_chk,cg_wave_fit,dashpos1_nom,cg_wave_midpoint);
3499 goto store8;
3500 }
3501 PRT04"\n{8}CHK DASH %f fit= %f (%f) [%f]",
3502 dash1_chk,cg_wave_fit,dashpos1_nom,cg_wave_midpoint);
3503 dotpos1_nom=cw[cw_ptr].midpoint-0.625*cw[cw_ptr].sep;
3504 if(dotpos1_nom < 0)dotpos1_nom+=baseband_size;
3505 dot1_chk=check_dot(dotpos1_nom);
3506 dotpos2_nom=cw[cw_ptr].midpoint-0.375*cw[cw_ptr].sep;
3507 if(dotpos2_nom < 0)dotpos2_nom+=baseband_size;
3508 dot2_chk=check_dot(dotpos2_nom);
3509 if(dash1_chk < -0.25 && dot1_chk < -0.25 && dot2_chk < -0.25)
3510 {
3511 PRT04"\nALL chk NEG (< -0.25)");
3512 ity=5;
3513 goto store8;
3514 }
3515 cg_wave_start=dotpos1_nom-(dot_pts>>1)+baseband_size;
3516 cg_wave_start&=baseband_mask;
3517 fit_dot();
3518 dot1_re=cg_wave_coh_re;
3519 dot1_im=cg_wave_coh_im;
3520 dotpos1=cg_wave_midpoint;
3521 dotpos1_err=dotpos1_nom-cg_wave_midpoint;
3522 if(dotpos1_err < -sizhalf)dotpos1_err+=baseband_size;
3523 dot_fit1=cg_wave_fit;
3524 PRT04"\n{8}CHK DOT1 %f fit=%f (%f) [%f]",
3525 dot1_chk,cg_wave_fit,dotpos1_nom,cg_wave_midpoint);
3526 cg_wave_start=dotpos2_nom-(dot_pts>>1)+baseband_size;
3527 cg_wave_start&=baseband_mask;
3528 fit_dot();
3529 dot2_re=cg_wave_coh_re;
3530 dot2_im=cg_wave_coh_im;
3531 dotpos2=cg_wave_midpoint;
3532 dotpos2_err=dotpos2_nom-cg_wave_midpoint;
3533 if(dotpos2_err < -sizhalf)dotpos2_err+=baseband_size;
3534 dot_fit2=cg_wave_fit;
3535 PRT04"\n{8}CHK DOT2 %f fit=%f (%f) [%f]",
3536 dot2_chk,cg_wave_fit,dotpos2_nom,cg_wave_midpoint);
3537 if( dash_fit1 < DASH_MISFIT_LIMIT ||
3538 ( (dash1_chk < -0.25 && fabs(dashpos1_err) < 0.5*cwbit_pts) ||
3539 ( dash1_chk < 0.25 && fabs(dashpos1_err) < cwbit_pts ) ) )
3540 {
3541 // The fit to a dash is very poor.
3542 // Set ity to 5 (word separator), then check whether dot or space will fit.
3543 ity=5;
3544 PRT04"\nset ity=5");
3545 PRT04"\ndot1 fit %f chk %f poserr %f ",dot_fit1,dot1_chk,dotpos1_err);
3546 if( dot_fit1 > DOT_MISFIT_LIMIT &&
3547 dot1_chk > 0.25 && fabs(dotpos1_err) < 0.5*cwbit_pts )
3548 {
3549 ity=2;
3550 PRT04"\nset ity=2");
3551 }
3552 PRT04"\ndot2 fit %f chk %f poserr %f ",dot_fit2,dot2_chk,dotpos2_err);
3553 if( dot_fit2 > DOT_MISFIT_LIMIT &&
3554 dot2_chk > 0.25 && fabs(dotpos2_err) < 0.5*cwbit_pts )
3555 {
3556 if(ity == 2)
3557 {
3558 ity=4;
3559 PRT04"\nset ity=4");
3560 }
3561 else
3562 {
3563 ity=3;
3564 PRT04"\nset ity=3");
3565 }
3566 }
3567 goto store8;
3568 }
3569 PRT04"\nUnclear");
3570 // The situation is unclear. Nothing fits well...........
3571 if(dash1_chk < 0 && dot1_chk < 0 && dot2_chk < 0)
3572 {
3573 ity=5;
3574 PRT04"\nset ity=5 (all neg)");
3575 goto store8;
3576 }
3577 t1=dot1_chk*dot2_chk;
3578 if( fabs(t1) > dash1_chk*fabs(dash1_chk) )
3579 {
3580 // The fit to a dash is worse than dots and/or spaces.
3581 PRT04"\nset ity=5 (dash worse than dots)");
3582 ity=5;
3583 if( dot_fit1 > DOT_MISFIT_LIMIT &&
3584 dot1_chk > 0 && fabs(dotpos1_err) < 0.7*cwbit_pts )
3585 {
3586 ity=2;
3587 PRT04"\nset ity=2");
3588 }
3589 if( dot_fit2 > DOT_MISFIT_LIMIT &&
3590 dot2_chk > 0 && fabs(dotpos2_err) < 0.7*cwbit_pts )
3591 {
3592 if(ity == 2)
3593 {
3594 ity=4;
3595 PRT04"\nset ity=4");
3596 }
3597 else
3598 {
3599 ity=3;
3600 PRT04"\nset ity=3");
3601 }
3602 }
3603 goto store8;
3604 }
3605 if( dash_fit1 > DASH_MISFIT_LIMIT &&
3606 (dash1_chk > 0 || fabs(dashpos1_err) < cwbit_pts ) )
3607 {
3608 ity=1;
3609 PRT04"\nset ity=1");
3610 }
3611 store8:;
3612 clear_region();
3613 PRT04"\nity=%d",ity);
3614 switch (ity)
3615 {
3616 case 1:
3617 // Store a dash
3618 // ---_---_--- 8 ity=1
3619 t3=0;
3620 if(dash_fit1 > DASH_DETECT_LIMIT && fabs(dashpos1_err) < 0.25*cwbit_pts)
3621 {
3622 if(dash1_chk < 0.25)
3623 {
3624 t3=0.75;
3625 }
3626 else
3627 {
3628 t3=0.5;
3629 }
3630 }
3631 t2=1-t3;
3632 cg_wave_midpoint=dashpos1+t2*dashpos1_err;
3633 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3634 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3635 ia=cg_wave_midpoint;
3636 cg_wave_coh_re=t3*dash1_re+t2*baseb_envelope[2*ia ];
3637 cg_wave_coh_im=t3*dash1_im+t2*baseb_envelope[2*ia+1];
3638 PRT04"\nstore_dash %f",cg_wave_midpoint);
3639 insert_item(CW_DASH);
3640 if(kill_all_flag)return;
3641 cw_ptr++;
3642 break;
3643
3644 case 2:
3645 // Store dot1 and space
3646 // ---_-___--- 8 ity=2
3647 // ---___-_--- 8 ity=3
3648 // ---_____--- 8 ity=5
3649 // ---_-_-_--- 8 ity=4
3650 t3=0;
3651 if(dot_fit1 > DOT_DETECT_LIMIT && fabs(dotpos1_err) < 0.25*cwbit_pts)
3652 {
3653 if(dot1_chk < 0.25)
3654 {
3655 t3=0.75;
3656 }
3657 else
3658 {
3659 t3=0.5;
3660 }
3661 }
3662 t2=1-t3;
3663 cg_wave_midpoint=dotpos1+t2*dotpos1_err;
3664 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3665 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3666 ia=cg_wave_midpoint;
3667 cg_wave_coh_re=t3*dot1_re+t2*baseb_envelope[2*ia ];
3668 cg_wave_coh_im=t3*dot1_im+t2*baseb_envelope[2*ia+1];
3669 PRT04"\nstore dot %f",cg_wave_midpoint);
3670 insert_item(CW_DOT);
3671 if(kill_all_flag)return;
3672 cw_ptr++;
3673 cg_wave_midpoint=dotpos2_nom;
3674 PRT04"\nstore_space %f",cg_wave_midpoint);
3675 insert_item(CW_SPACE);
3676 if(kill_all_flag)return;
3677 cw_ptr++;
3678 break;
3679
3680 case 3:
3681 // Store space and dot2
3682 // ---___-_--- 8 ity=3
3683 cg_wave_midpoint=dotpos1_nom;
3684 PRT04"\nstore_space %f",cg_wave_midpoint);
3685 insert_item(CW_SPACE);
3686 if(kill_all_flag)return;
3687 cw_ptr++;
3688 t3=0;
3689 if(dot_fit2 > DOT_DETECT_LIMIT && fabs(dotpos2_err) < 0.25*cwbit_pts)
3690 {
3691 if(dot2_chk < 0.25)
3692 {
3693 t3=0.75;
3694 }
3695 else
3696 {
3697 t3=0.5;
3698 }
3699 }
3700 t2=1-t3;
3701 cg_wave_midpoint=dotpos2+t2*dotpos2_err;
3702 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3703 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3704 ia=cg_wave_midpoint;
3705 cg_wave_coh_re=t3*dot2_re+t2*baseb_envelope[2*ia ];
3706 cg_wave_coh_im=t3*dot2_im+t2*baseb_envelope[2*ia+1];
3707 PRT04"\nstore dot %f",cg_wave_midpoint);
3708 insert_item(CW_DOT);
3709 if(kill_all_flag)return;
3710 cw_ptr++;
3711 break;
3712
3713 case 4:
3714 // Store dot1 and dot2
3715 // ---_-_-_--- 8 ity=4
3716 t3=0;
3717 if(dot_fit1 > DOT_DETECT_LIMIT && fabs(dotpos1_err) < 0.25*cwbit_pts)
3718 {
3719 if(dot1_chk < 0.25)
3720 {
3721 t3=0.75;
3722 }
3723 else
3724 {
3725 t3=0.5;
3726 }
3727 }
3728 t2=1-t3;
3729 cg_wave_midpoint=dotpos1+t2*dotpos1_err;
3730 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3731 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3732 ia=cg_wave_midpoint;
3733 cg_wave_coh_re=t3*dot1_re+t2*baseb_envelope[2*ia ];
3734 cg_wave_coh_im=t3*dot1_im+t2*baseb_envelope[2*ia+1];
3735 PRT04"\nstore dot %f",cg_wave_midpoint);
3736 insert_item(CW_DOT);
3737 if(kill_all_flag)return;
3738 cw_ptr++;
3739 t3=0;
3740 if(dot_fit2 > DOT_DETECT_LIMIT && fabs(dotpos2_err) < 0.25*cwbit_pts)
3741 {
3742 if(dot2_chk < 0.25)
3743 {
3744 t3=0.75;
3745 }
3746 else
3747 {
3748 t3=0.5;
3749 }
3750 }
3751 t2=1-t3;
3752 cg_wave_midpoint=dotpos2+t2*dotpos2_err;
3753 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3754 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3755 ia=cg_wave_midpoint;
3756 cg_wave_coh_re=t3*dot2_re+t2*baseb_envelope[2*ia ];
3757 cg_wave_coh_im=t3*dot2_im+t2*baseb_envelope[2*ia+1];
3758 PRT04"\nstore dot %f",cg_wave_midpoint);
3759 insert_item(CW_DOT);
3760 if(kill_all_flag)return;
3761 cw_ptr++;
3762 break;
3763
3764
3765 case 5:
3766 // Store word separator
3767 // ---_____--- 8 ity=5
3768 cg_wave_midpoint=dashpos1_nom;
3769 PRT04"\nstore word sep %f",cg_wave_midpoint);
3770 insert_item(CW_WORDSEP);
3771 if(kill_all_flag)return;
3772 cw_ptr++;
3773 break;
3774 }
3775 break;
3776
3777 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3778
3779 default:
3780 if(k==10)
3781 {
3782 set_region_envelope();
3783 }
3784 else
3785 {
3786 set_long_region_envelope();
3787 }
3788 // See if a dash will fit in the first position.
3789 dashpos1_nom=cw[cw_ptr-1].midpoint+4*cwbit_pts;
3790 if(dashpos1_nom >= baseband_size)dashpos1_nom-=baseband_size;
3791 dash1_chk=check_dash(dashpos1_nom);
3792 cg_wave_start=dashpos1_nom-(dash_pts>>1)+baseband_size;
3793 cg_wave_start&=baseband_mask;
3794 fit_dash();
3795 dash1_re=cg_wave_coh_re;
3796 dash1_im=cg_wave_coh_im;
3797 dashpos1=cg_wave_midpoint;
3798 dashpos1_err=dashpos1_nom-cg_wave_midpoint;
3799 if(dashpos1_err < -sizhalf)dashpos1_err+=baseband_size;
3800 dash_fit1=cg_wave_fit;
3801 PRT05"\n{def.l}CHK DASH %f fit= %f (%f) [%f]",
3802 dash1_chk,cg_wave_fit,dashpos1_nom,cg_wave_midpoint);
3803 ity=0;
3804 if( (dash_fit1 > DASH_DETECT_LIMIT &&
3805 fabs(dashpos1_err) < 0.7*cwbit_pts &&
3806 dash1_chk > 0) ||
3807 (dash_fit1 > DASH_MISFIT_LIMIT &&
3808 fabs(dashpos1_err) < 0.5*cwbit_pts &&
3809 dash1_chk > 0.5) )
3810 {
3811 // A dash fits reasonably well in the lower position.
3812 ity=1;
3813 // Check how well dots would fit at the beginning or end of the dash position.
3814 dotpos1_nom=dashpos1_nom-cwbit_pts;
3815 if(dotpos1_nom < 0)dotpos1_nom+=baseband_size;
3816 dot1_chk=check_dot(dotpos1_nom);
3817 cg_wave_start=dotpos1_nom-(dot_pts>>1)+baseband_size;
3818 cg_wave_start&=baseband_mask;
3819 fit_dot();
3820 dotpos1=cg_wave_midpoint;
3821 dotpos1_err=dotpos1_nom-cg_wave_midpoint;
3822 if(dotpos1_err < -sizhalf)dotpos1_err+=baseband_size;
3823 dot_fit1=cg_wave_fit;
3824 PRT05"\n{def.l}CHK DOT1 %f fit=%f (%f) [%f]",
3825 dot1_chk,cg_wave_fit,dotpos1_nom,cg_wave_midpoint);
3826 if(fabs(dotpos1_err) < 0.5 * cwbit_pts &&
3827 dash_fit1 < dot_fit1+0.05 &&
3828 dot1_chk > 0.25)
3829 {
3830 PRT05"\ndot1.l good, skip dash for now.");
3831 ity=0;
3832 }
3833 else
3834 {
3835 dotpos2_nom=dashpos1_nom+cwbit_pts;
3836 if(dotpos2_nom >= baseband_size)dotpos2_nom-=baseband_size;
3837 dot2_chk=check_dot(dotpos2_nom);
3838 cg_wave_start=dotpos2_nom-(dot_pts>>1)+baseband_size;
3839 cg_wave_start&=baseband_mask;
3840 fit_dot();
3841 dotpos2=cg_wave_midpoint;
3842 dotpos2_err=dotpos2_nom-cg_wave_midpoint;
3843 if(dotpos2_err < -sizhalf)dotpos2_err+=baseband_size;
3844 dot_fit2=cg_wave_fit;
3845 PRT05"\n{def.l}CHK DOT2 %f fit=%f (%f) [%f]",
3846 dot2_chk,cg_wave_fit,dotpos2_nom,cg_wave_midpoint);
3847 if(fabs(dotpos2_err) < 0.5 * cwbit_pts &&
3848 dash_fit1 < dot_fit2+0.05 &&
3849 dot2_chk > 0.25)
3850 {
3851 PRT05"\ndot2.h good, skip dash for now.");
3852 ity=0;
3853 }
3854 }
3855 }
3856 // See if a dash will fit in the upper position.
3857 dashpos2_nom=cw[cw_ptr].midpoint-4*cwbit_pts;
3858 if(dashpos2_nom < 0)dashpos2_nom+=baseband_size;
3859 dash2_chk=check_dash(dashpos2_nom);
3860 cg_wave_start=dashpos2_nom-(dash_pts>>1)+baseband_size;
3861 cg_wave_start&=baseband_mask;
3862 fit_dash();
3863 dash2_re=cg_wave_coh_re;
3864 dash2_im=cg_wave_coh_im;
3865 dashpos2=cg_wave_midpoint;
3866 dashpos2_err=dashpos2_nom-cg_wave_midpoint;
3867 if(dashpos2_err < -sizhalf)dashpos2_err+=baseband_size;
3868 dash_fit2=cg_wave_fit;
3869 PRT05"\n{def.u}CHK DASH %f fit= %f (%f) [%f]",
3870 dash2_chk,cg_wave_fit,dashpos2_nom,cg_wave_midpoint);
3871 if( (dash_fit2 > DASH_DETECT_LIMIT &&
3872 fabs(dashpos2_err) < 0.7*cwbit_pts &&
3873 dash2_chk > 0) ||
3874 (dash_fit2 > DASH_MISFIT_LIMIT &&
3875 fabs(dashpos2_err) < 0.5*cwbit_pts &&
3876 dash2_chk > 0.5) )
3877 {
3878 // A dash fits reasonably well in the upper position.
3879 ity|=2;
3880 // Check how well dots would fit at the beginning or end of the dash position.
3881 dotpos3_nom=dashpos2_nom-cwbit_pts;
3882 if(dotpos3_nom < 0)dotpos3_nom+=baseband_size;
3883 dot3_chk=check_dot(dotpos3_nom);
3884 cg_wave_start=dotpos3_nom-(dot_pts>>1)+baseband_size;
3885 cg_wave_start&=baseband_mask;
3886 fit_dot();
3887 dotpos3=cg_wave_midpoint;
3888 dotpos3_err=dotpos3_nom-cg_wave_midpoint;
3889 if(dotpos3_err < -sizhalf)dotpos3_err+=baseband_size;
3890 dot_fit3=cg_wave_fit;
3891 PRT05"\n{def.h}CHK DOT3 %f fit=%f (%f) [%f]",
3892 dot3_chk,cg_wave_fit,dotpos3_nom,cg_wave_midpoint);
3893
3894 if(fabs(dotpos3_err) < 0.5 * cwbit_pts &&
3895 dash_fit2 < dot_fit3+0.05 &&
3896 dot3_chk > 0.25)
3897 {
3898 PRT05"\ndot3.h good, skip dash for now.");
3899 ity&=1;
3900 }
3901 else
3902 {
3903 dotpos4_nom=dashpos2_nom+cwbit_pts;
3904 if(dotpos4_nom >= baseband_size)dotpos4_nom-=baseband_size;
3905 dot4_chk=check_dot(dotpos4_nom);
3906 cg_wave_start=dotpos4_nom-(dot_pts>>1)+baseband_size;
3907 cg_wave_start&=baseband_mask;
3908 fit_dot();
3909 dotpos4=cg_wave_midpoint;
3910 dotpos4_err=dotpos4_nom-cg_wave_midpoint;
3911 if(dotpos4_err < -sizhalf)dotpos4_err+=baseband_size;
3912 dot_fit4=cg_wave_fit;
3913 PRT05"\n{def.h}CHK DOT4 %f fit=%f (%f) [%f]",
3914 dot4_chk,cg_wave_fit,dotpos4_nom,cg_wave_midpoint);
3915 if(fabs(dotpos4_err) < 0.5 * cwbit_pts &&
3916 dash_fit2 < dot_fit4+0.05 &&
3917 dot4_chk > 0.25)
3918 {
3919 PRT05"\ndot2.h good, skip dash for now.");
3920 ity&=1;
3921 }
3922
3923 }
3924 if( (ity & 3) == 3 && k < 12)
3925 {
3926 // We can not have one dash at each side in a short region.
3927 // choose the best one.
3928 if( fabs(dash_fit1-dash_fit2) > 0.05)
3929 {
3930 if(dash_fit1 > dash_fit2)
3931 {
3932 ity=1;
3933 }
3934 else
3935 {
3936 ity=2;
3937 }
3938 }
3939 else
3940 {
3941 t1=2*dash_fit1-dot_fit1-dot_fit2-2*dash_fit2+dot_fit3+dot_fit4;
3942 if(fabs(t1) < 0.05)
3943 {
3944 ity=0;
3945 }
3946 else
3947 {
3948 if(t1>0)ity=1; else ity=2;
3949 }
3950 }
3951 }
3952 }
3953 if( (ity&1) != 0)
3954 {
3955 cg_wave_midpoint=dashpos1+0.5*dashpos1_err;
3956 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3957 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3958 ia=cg_wave_midpoint;
3959 cg_wave_coh_re=0.5*dash1_re+0.5*baseb_envelope[2*ia ];
3960 cg_wave_coh_im=0.5*dash1_im+0.5*baseb_envelope[2*ia+1];
3961 PRT05"\nstore_dash.l %f",cg_wave_midpoint);
3962 insert_item(CW_DASH);
3963 if(kill_all_flag)return;
3964 cw_ptr++;
3965 }
3966 if( (ity&2) != 0)
3967 {
3968 cg_wave_midpoint=dashpos2+0.5*dashpos2_err;
3969 if(cg_wave_midpoint < 0)cg_wave_midpoint+=baseband_size;
3970 if(cg_wave_midpoint >= baseband_size)cg_wave_midpoint-=baseband_size;
3971 ia=cg_wave_midpoint;
3972 cg_wave_coh_re=0.5*dash2_re+0.5*baseb_envelope[2*ia ];
3973 cg_wave_coh_im=0.5*dash2_im+0.5*baseb_envelope[2*ia+1];
3974 PRT05"\nstore_dash.h %f",cg_wave_midpoint);
3975 insert_item(CW_DASH);
3976 if(kill_all_flag)return;
3977 cw_ptr++;
3978 }
3979 break;
3980 }
3981 cw_ptr++;
3982 }
3983 if(PR05 != 0)show_cw("first_detect exit");
3984 */
3985 }
3986
3987 typedef struct{
3988 float pos;
3989 float s;
3990 float n;
3991 float ston;
3992 float s_avg;
3993 float n_avg;
3994 int cwptr;
3995 }STONDATA;
3996
improve_cwspeed(void)3997 void improve_cwspeed(void)
3998 {
3999 int i, k, n, dashno;
4000 int repeat_flag;
4001 float r1, r3, t1, t2, t3;
4002 //double s_sum;
4003 //, n_sum;
4004 STONDATA *stondt;
4005 stondt=(STONDATA*)(fftn_tmp);
4006 // Collect the average waveform again.
4007 // We probably have some more dashes now and their positions are better
4008 // known as compared to the previous speed determination.
4009 check_cw(362003,1);
4010 if(kill_all_flag)return;
4011 repeat_flag=0;
4012 repeat:;
4013 check_cw(342003,1);
4014 if(kill_all_flag)return;
4015 seldash_cwspeed(0, no_of_cwdat);
4016 cw_ptr=0;
4017 check_cw(2003,1);
4018 if(kill_all_flag)return;
4019 dashno=0;
4020 t3=0;
4021 //s_sum=0;
4022 //n_sum=0;
4023 check_cw(22001,1);
4024 if(kill_all_flag)return;
4025 while(cw_ptr<no_of_cwdat)
4026 {
4027 t3+=cw[cw_ptr].sep;
4028 if(cw[cw_ptr].type == CW_DASH)
4029 {
4030 cg_wave_start=cw[cw_ptr].midpoint-0.5*dash_pts+baseband_size;
4031 cg_wave_start&=baseband_mask;
4032 fit_dash();
4033 PRT01"\n%3d %8.3f improve cwspeed [%8.3f] %8.3f fit=%8.5f",cw_ptr,t3,
4034 cw[cw_ptr].midpoint, cg_wave_midpoint, cg_wave_fit);
4035 if(cg_wave_fit < DASH_MISFIT_LIMIT)
4036 {
4037 PRT01" removed");
4038 remove_dash();
4039 }
4040 else
4041 {
4042 check_cw(22002,1);
4043 if(kill_all_flag)return;
4044 cw[cw_ptr].coh_re=cg_wave_coh_re;
4045 cw[cw_ptr].coh_im=cg_wave_coh_im;
4046 cw[cw_ptr].midpoint=cg_wave_midpoint;
4047 if(cw_ptr > 0)
4048 {
4049 cw[cw_ptr].sep=cg_wave_midpoint-cw[cw_ptr-1].midpoint;
4050 if(cw[cw_ptr].sep < 0)cw[cw_ptr].sep+=baseband_size;
4051 }
4052 if(cw_ptr+1 < no_of_cwdat)
4053 {
4054 cw[cw_ptr+1].sep=cw[cw_ptr+1].midpoint-cg_wave_midpoint;
4055 if(cw[cw_ptr+1].sep < 0)cw[cw_ptr+1].sep+=baseband_size;
4056 }
4057 // s_sum+=cg_wave_dat;
4058 // n_sum+=cg_wave_err;
4059 stondt[dashno].s=cg_wave_dat;
4060 stondt[dashno].n=cg_wave_err;
4061 stondt[dashno].cwptr=cw_ptr;
4062 stondt[dashno].pos=t3;
4063 dashno++;
4064 check_cw(22003,1);
4065 if(kill_all_flag)return;
4066 }
4067 }
4068 cw_ptr++;
4069 }
4070 check_cw(22009,1);
4071 if(kill_all_flag)return;
4072
4073 if(dashno <= MIN_DASHNO)return;
4074 stondt[dashno].pos=t3;
4075 check_cw(200591,1);
4076 if(kill_all_flag)return;
4077 // Use the data in stondt and to decide if the new data
4078 // has worsened the S/N ratio significantly.
4079 // If it has, the cw speed has changed or the
4080 // signal has degraded or disappeared.
4081 // Average S and N over 3 points.
4082 t1=stondt[0].s;
4083 r1=stondt[0].n;
4084 for(i=1; i<3; i++)
4085 {
4086 t1+=stondt[i].s;
4087 r1+=stondt[i].n;
4088 }
4089 stondt[0].s_avg=t1/3;
4090 stondt[0].n_avg=r1/3;
4091 stondt[0].ston=t1/r1;
4092 k=dashno-2;
4093 for(i=1; i<k; i++)
4094 {
4095 stondt[i].s_avg=t1/3;
4096 stondt[i].n_avg=r1/3;
4097 stondt[i].ston=t1/r1;
4098 t1+=stondt[i+2].s;
4099 r1+=stondt[i+2].n;
4100 t1-=stondt[i-1].s;
4101 r1-=stondt[i-1].n;
4102 }
4103 while(k<dashno)
4104 {
4105 stondt[k].s_avg=t1/3;
4106 stondt[k].n_avg=r1/3;
4107 stondt[k].ston=t1/r1;
4108 k++;
4109 }
4110 // Get the center of gravity of S/N assuming S/N is constant
4111 // in each interval (not very clever, but good enough for
4112 // our purpose. We use smoothed data points due to the averaging just done.)
4113 t1=stondt[0].pos;
4114 t3=0;
4115 k=dashno-1;
4116 r3=0;
4117 n=k/10;
4118 if(n<MIN_DASHNO/2)n=MIN_DASHNO/2;
4119 if(k-n < MIN_DASHNO)goto use_everything;
4120 for(i=n; i<k; i++)
4121 {
4122 t2=t1;
4123 t1=stondt[i].pos;
4124 r1=stondt[i-1].ston;
4125 if(r1>stondt[i+1].ston)r1=stondt[i+1].ston;
4126 t3+=(t1-t2)*r1*(t1+t2);
4127 r3+=(t1-t2)*r1;
4128 }
4129 t3/=r3;
4130 // t3 is now twice the center of gravity for the S/N function.
4131 // If it is much smaller than the total interval, the signal
4132 // has degraded significantly.
4133 if(t3 < 0.8*stondt[k].pos)
4134 {
4135 // The signal seems to have degraded.
4136 // Get the average S/N over the interval from 0 to t3 (weighted by S)
4137 PRT01"\nSignal seems to have degraded. %f %f",t3,0.8*stondt[k].pos);
4138 i=0;
4139 t1=0;
4140 t2=0;
4141 while(stondt[i].pos<t3)
4142 {
4143 t1+=stondt[i].s*stondt[i].s/stondt[i].n;
4144 t2+=stondt[i].s;
4145 i++;
4146 }
4147 t1/=t2;
4148 PRT01"\nAvg S/N for good pts= %f ",t1);
4149 // Step backwards until we find the first dash with S/N above the average.
4150 i=dashno-1;
4151 while( stondt[i].ston < t1)i--;
4152 t1=stondt[i].pos/stondt[dashno-1].pos;
4153 PRT01" Good time is %6.2f%%",100*t1);
4154 if(t1 < 0.8)
4155 {
4156 // The signal has degraded for long enough so we better evaluate
4157 // the region up to the point in time defined by t1 before we
4158 // try to proceed with newer data.
4159 check_cw(322003,1);
4160 if(kill_all_flag)return;
4161 no_of_cwdat=stondt[i].cwptr+1;
4162 repeat_flag++;
4163 check_cw(332003,1);
4164 if(kill_all_flag)return;
4165 if( repeat_flag < 3)goto repeat;
4166 }
4167 }
4168 use_everything:;
4169 if(repeat_flag != 0)
4170 {
4171 // Treat old data first. Trying to improve the cw speed by including newer
4172 // data may make us try to fit the morse code to two different stations
4173 // that have different dash waveforms.
4174 // Change baseb_pc to reflect this decision.
4175 baseb_pc=cw[no_of_cwdat-1].midpoint;
4176 while(baseb_ramp[baseb_pc] > 0)baseb_pc =(baseb_pc+1)&baseband_mask;
4177 while(baseb_ramp[baseb_pc] < 0)baseb_pc =(baseb_pc+1)&baseband_mask;
4178 baseb_pc =(baseb_pc+baseband_mask)&baseband_mask;
4179 baseb_pe=baseb_pc;
4180 baseb_pd=baseb_pc;
4181 cw_detect_flag=CWDETECT_LIMITS_FOUND;
4182 PRT01"\n*** SET cw_detect_flag=CWDETECT_LIMITS_FOUND ***");
4183 return;
4184 }
4185 t1=cw_stoninv;
4186 get_wb_average_dashes();
4187 guess_wb_average_dots();
4188 t2=collect_wb_ston();
4189 PRT01"\ncw_stoninv %f old=%f",cw_stoninv,t1);
4190 for(i=0; i<dashno; i++)
4191 {
4192 PRT01"\n%2d [%7.2f] S=%f (S/N) %f %d",i,stondt[i].pos,
4193 0.001*ZZ*stondt[i].s,
4194 stondt[i].s/stondt[i].n,stondt[i].cwptr);
4195 }
4196 check_cw(2007,1);
4197 if(kill_all_flag)return;
4198 if(collect_wb_ston() < CW_WAVEFORM_MINSTON)
4199 {
4200 lirerr(8877266);
4201 }
4202 cw_detect_flag=CWDETECT_REGION_WAVEFORM_OK;
4203 PRT01"\n*** SET cw_detect_flag=CWDETECT_REGION_WAVEFORM_OK ***");
4204 }
4205
4206
first_find_parts(void)4207 void first_find_parts(void)
4208 {
4209 int addno;
4210 // When we arrive here the keying speed and the waveforms are well known.
4211 // We have detected no_of_cwdat waveforms, many of them fit to a dash.
4212 // First look for recent dashes.
4213 check_cw(547203,1);
4214 if(kill_all_flag)return;
4215 if(PR02 == 1)show_cw("first_find_parts 1");
4216 get_recent_dashes();
4217 if(kill_all_flag)return;
4218 if(PR02 == 1)show_cw("first_find_parts 2");
4219 // Then collect old ones (if there are any)
4220 check_cw(552002,1);
4221 if(kill_all_flag)return;
4222 get_old_dashes();
4223 if(kill_all_flag)return;
4224 if(PR02 == 1)show_cw("first_find_parts 3");
4225 // Check S/N and place a pointer at the end of the current
4226 // transmission in case S/N is severely degraded.
4227 check_cw(552001,1);
4228 if(kill_all_flag)return;
4229 improve_cwspeed();
4230 if(kill_all_flag)return;
4231 // **********************************************************
4232 // **********************************************************
4233 // ****** Use the (hopefully) improved waveforms and *******
4234 // ****** search the entire region for good matches *******
4235 // **********************************************************
4236 // **********************************************************
4237 more:;
4238 addno=short_region_guesses(0);
4239 check_cw(2010,1);
4240 if(kill_all_flag)return;
4241 if(PR02 == 1)show_cw("first_find_parts 4");
4242 if(addno > 0)
4243 {
4244 get_wb_average_dashes();
4245 guess_wb_average_dots();
4246 goto more;
4247 }
4248 addno=character_guesses();
4249 addno+=short_region_guesses(0);
4250 if(addno > 0)goto more;
4251 fprintf( dmp,"\nA cwbit_pts %f",cwbit_pts);
4252 decoded_cwspeed();
4253 fprintf( dmp,"\nB cwbit_pts %f",cwbit_pts);
4254 if(PR02 == 1)show_cw("first_find_parts 5");
4255 get_wb_average_dashes();
4256 get_wb_average_dots();
4257 short_region_guesses(0);
4258 mailbox[0]=9;
4259 short_region_guesses(1);
4260
4261 addno=part_guesses();
4262
4263
4264 if(cw_detect_flag >= CWDETECT_LIMITS_FOUND)
4265 {
4266 return;
4267 }
4268 cw_detect_flag=CWDETECT_SOME_PARTS_FITTED;
4269 PRT08"\n*** SET cw_detect_flag=CWDETECT_SOME_PARTS_FITTED ***");
4270 baseb_pe=baseb_pc;
4271 baseb_pd=baseb_pc;
4272 }
4273
set_baseb_pc(void)4274 void set_baseb_pc(void)
4275 {
4276 int ia,ib;
4277 // Make a first decision key up/key down based on signal power.
4278 // This is the conventional approach, a matched filter (the operator
4279 // has to select the optimum bandwidth) followed by a squarelaw detector.
4280 // The threshold is conventionally kept at a fixed level but here it is
4281 // very close to the noise when no signal is present. while it is at
4282 // half the peak amplitude for strong signals.
4283 // Store the result in baseb_ramp as ramps.
4284 // Positive values indicate key down while negative values
4285 // indicate key up (or signal too weak)
4286 ia=baseb_pc;
4287 ib=(ia+baseband_mask)&baseband_mask;
4288 while( ia != baseb_pb )
4289 {
4290 if(baseb_totpwr[ia] > baseb_threshold[ia])
4291 {
4292 if(baseb_ramp[ib]>0)
4293 {
4294 baseb_ramp[ia]=baseb_ramp[ib]+1;
4295 }
4296 else
4297 {
4298 baseb_ramp[ia]=1;
4299 }
4300 }
4301 else
4302 {
4303 if(baseb_ramp[ib]<0)
4304 {
4305 baseb_ramp[ia]=baseb_ramp[ib]-1;
4306 }
4307 else
4308 {
4309 baseb_ramp[ia]=-1;
4310 }
4311 }
4312 ib=ia;
4313 ia=(ia+1)&baseband_mask;
4314 }
4315 if(baseb_ramp[ib]>0)ib=(ib-baseb_ramp[ib]+baseband_size)&baseband_mask;
4316 baseb_pc=ib;
4317 }
4318
second_find_parts(void)4319 void second_find_parts(void)
4320 {
4321 int old_no_of_dashes;
4322 // When we arrive here the keying speed and the waveforms are well known.
4323 // We have detected no_of_cwdat waveforms, most of them dashes, but
4324 // maybe also some dots and spaces.
4325 // First look for recent dashes.
4326 old_no_of_dashes=no_of_cwdat;
4327 set_baseb_pc();
4328 check_cw(252501,1);
4329 if(kill_all_flag)return;
4330 get_recent_dashes();
4331 if(kill_all_flag)return;
4332 // Fit dashes and dots in short gaps and next to
4333 // dashes in the new region.
4334 check_cw(251502,1);
4335 if(kill_all_flag)return;
4336 first_detect(old_no_of_dashes-1);
4337 if(kill_all_flag)return;
4338 if(old_no_of_dashes != no_of_cwdat)
4339 {
4340 improve_cwspeed();
4341 if(kill_all_flag)return;
4342 if(cw_detect_flag >= CWDETECT_LIMITS_FOUND)
4343 {
4344 second_detect();
4345 if(PR08 != 0)
4346 {
4347 char s[80];
4348 sprintf(s,"second_find_parts (flag=%d)",cw_detect_flag);
4349 show_cw(s);
4350 }
4351 return;
4352 }
4353 old_no_of_dashes=no_of_cwdat;
4354 }
4355 // Try to fit more dots and dashes in the whole region from 0 to no_of_cwdat.
4356 second_detect();
4357 if(PR08 != 0)show_cw("second_find_parts (flag unchanged)");
4358 baseb_pe=baseb_pc;
4359 baseb_pd=baseb_pc;
4360 }
4361
4362
4363
4364
cw_decode(void)4365 void cw_decode(void)
4366 {
4367 /*
4368 XZ("------ cw_decode ---------");
4369 if(PR09 != 0)show_cw("cw_decode A");
4370 second_find_parts();
4371 if(PR09 != 0)show_cw("cw_decode B");
4372 decoded_cwspeed();
4373 if(PR09 != 0)show_cw("cw_decode C");
4374 continued_morse_decode();
4375 */
4376
4377 }
4378
cw_decode_region(void)4379 void cw_decode_region(void)
4380 {
4381 XZ("cw_decode_region(do nothing)");
4382 }
4383
4384
4385
init_cw_decode(void)4386 void init_cw_decode(void)
4387 {
4388 // We decode because S/N is already good enough to perhaps allow it.
4389 // Some more information may have arrived.
4390 // Process it first and return if flag says the signal disappeared.
4391 cw_detect_flag=CWDETECT_DEBUG_STOP;
4392 return;
4393
4394 second_find_parts();
4395 if(cw_detect_flag != CWDETECT_REGION_WAVEFORM_OK)
4396 {
4397 XZ("\nEND OF REGION!!!");
4398 return;
4399 }
4400 decoded_cwspeed();
4401 check_cw(256702,1);
4402 if(kill_all_flag)return;
4403 // Try to find complete characters
4404 if(PR09 != 0)show_cw("init_cw_decode 1");
4405 first_morse_decode();
4406 if(kill_all_flag)return;
4407 if(PR09 != 0)show_cw("init_cw_decode 2");
4408 check_cw(256703,1);
4409 if(kill_all_flag)return;
4410 if(cw_decoded_chars != 0)
4411 {
4412 cw_detect_flag=CWDETECT_SOME_ASCII_FITTED;
4413 XZ("\nOKOKOKOKOKOKOK");
4414 //show_cw("Set detect_flag to CWDETECT_SOME_ASCII_FITTED");
4415 }
4416 else
4417 {
4418 fprintf( dmp,"\nno_of_cwdat %d no_of_cwdat-correlate_no_of_cwdat %d",
4419 no_of_cwdat, no_of_cwdat-correlate_no_of_cwdat);
4420 fprintf( dmp,"\n pa %d pb %d pc %d pd %d pe %d",
4421 baseb_pa, baseb_pb, baseb_pc, baseb_pd, baseb_pe);
4422
4423
4424
4425
4426 if(no_of_cwdat > 25 && no_of_cwdat-correlate_no_of_cwdat > 2)
4427 {
4428 correlate_undecoded_baseband();
4429 correlate_no_of_cwdat=no_of_cwdat;
4430
4431 // ö update baseb_px and other pointers as well as cw[] and no_of_cwdat
4432 // if correlate failed and data is becoming too old.
4433
4434 }
4435 }
4436 }
4437
init_cw_decode_region(void)4438 void init_cw_decode_region(void)
4439 {
4440 decoded_cwspeed();
4441 first_morse_decode();
4442 cw_detect_flag=CWDETECT_REGION_INITIATED;
4443 }
4444