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 "fft1def.h"
27 #include "sigdef.h"
28 #include "screendef.h"
29
30 #define ZZ 0.0000001
31
32 // Variables and definitions for morse decoding in sigdef.h.
33 // typedef struct {
34 // unsigned char type; // Part type (CW_DOT, CW_SPACE,....A,B,C,...)
35 // unsigned char unkn; // Number of unknown states before this part
36 // unsigned char len; // Length of character in states
37 // float midpoint;
38 // float sep;
39 // float re;
40 // float im;
41 // float tmp;
42 // }MORSE_DECODE_DATA;
43 //
44 // Defines for MORSE_DECODE_DATA.type (cw.type)
45 // Note that CW_DASH must have the lowest value.
46 // The data in cw_item_len[255-CW_DASH]; must agree with these definitions!
47 //
48 // #define CW_WORDSEP 255
49 // #define CW_SPACE 254
50 // #define CW_DOT 253
51 // #define CW_DASH 252
52
53 // name data length
54 // CW_DASH |---_| 4
55 // ^
56 // CW_DOT |-_| 2
57 // ^
58 // CW_SPACE |__| 2
59 // ^
60 // CW_WORDSEP |____| 4
61 // ^
62 // The way the midpoint is defined does not include the trailing
63 // key-up of each cw part.
64 // For characters, midpoint points to the first dash or dot
65 // of the decoded character.
66
67
68
69 void check_cw(int num,int type);
70 void show_cw(char *s);
71 void find_preceeding_part(void);
72 void find_prev_char_part(void);
73 void extrapolate_region_downwards(void);
74 int mr_dotpos_nom, mr_dashpos_nom;
75
insert_char(int charbits,int charlen,int charval)76 void insert_char(int charbits, int charlen, int charval)
77 {
78 char chr;
79 int i, j;
80 float r1;
81 if(charbits > 6)
82 {
83 chr=(char)243;
84 }
85 else
86 {
87 cw_decoded_chars++;
88 chr=morsascii[charbits-1][charval];
89 }
90 // The current character extends from cw_ptr-charbits to cw_ptr-1
91 // Include the trailing space at cw_ptr in the character,
92 // but leave trailing word separators unchanged.
93 // If a word separator preceeded by a character is present
94 // at cw_ptr-charbits-1, replace the word separator by a blank.
95 i=cw_ptr-charbits;
96 if(i >= 2)
97 {
98 if(cw[i-1].type == CW_WORDSEP && cw[i-2].type < CW_DASH)
99 {
100 cw[i-1].type=' ';
101 }
102 }
103 cw[i].type=chr;
104 cw[i].len=charlen;
105 j=cw_ptr;
106 if(cw[cw_ptr].type == CW_SPACE)j++;
107 cw_ptr=i;
108 i++;
109 if(j < no_of_cwdat)
110 {
111 r1=cw[j].midpoint-cw[cw_ptr].midpoint;
112 if(r1 < 0)r1+=baseband_size;
113 cw[j].sep=r1;
114 }
115 while(j < no_of_cwdat)
116 {
117 cw[i]=cw[j];
118 i++;
119 j++;
120 }
121 no_of_cwdat=i-1;
122 }
123
detect_previous_character(int char_pos)124 void detect_previous_character(int char_pos)
125 {
126 int i, j, charlen, charbits, charval;
127 if(char_pos < 1)
128 {
129 lirerr(674421);
130 return;
131 }
132 if(cw[char_pos].type != CW_SPACE && cw[char_pos].type != CW_WORDSEP)
133 {
134 show_cw("ERROR in detect_previous_character");
135 lirerr(674422);
136 return;
137 }
138 // We have been called properly with the pointer on a space.
139 // Step backwards and see if it is preceeded by something
140 // we are likely to interpret correctly.
141 cw_ptr=char_pos-1;
142 restart:;
143 charlen=0;
144 charbits=0;
145 collect_parts:;
146 while(cw_ptr >= 0 && (cw[cw_ptr].type==CW_DASH || cw[cw_ptr].type==CW_DOT))
147 {
148 charbits++;
149 charlen+=cw[cw_ptr].len;
150 cw_ptr--;
151 }
152 if(charbits==0)return;
153 cw_ptr++;
154 XZ("xx1");
155 if( cw[cw_ptr].unkn > 0 &&
156 cw[cw_ptr].type != CW_SPACE &&
157 cw[cw_ptr].type != CW_WORDSEP)
158 {
159 XZ("xx2");
160 // We do not know what preceeds this sequence of dots and dashes
161 // and whatever it was, it was not good enough to give a morse decode.
162 // Try to fit a dot or a dash in the appropriate position.
163 i=no_of_cwdat;
164 find_preceeding_part();
165 if(kill_all_flag)return;
166 if(i != no_of_cwdat)
167 {
168 XZ("xx3");
169 goto collect_parts;
170 }
171 }
172 //show_cw(" XXXX ");
173 if( cw[cw_ptr-1].type == CW_SPACE || cw[cw_ptr-1].type == CW_WORDSEP)
174 {
175 charlen=0;
176 charval=0;
177 j=charbits;
178 while(j > 0)
179 {
180 j--;
181 charlen+=cw[cw_ptr].len;
182 charval<<=1;
183 if(cw[cw_ptr].type==CW_DASH)charval++;
184 cw_ptr++;
185 }
186 insert_char(charbits, charlen, charval);
187 // Our search for code parts begins by a search for dashes.
188 // A sequence without dashes or with very poor ones may
189 // preceed what we now have detected.
190 cw_ptr--;
191 if(cw[cw_ptr].unkn > 0)
192 {
193 i=no_of_cwdat;
194 find_prev_char_part();
195 if(kill_all_flag)return;
196 if(i != no_of_cwdat)
197 {
198 XZ("goto restart");
199 goto restart;
200 }
201 }
202 }
203 else
204 {
205 DEB"\nWARNING: ROUTINE NOT COMPLETED ");
206 lirerr(564397);
207 }
208 }
209
conditional_insert_dashdot(void)210 void conditional_insert_dashdot(void)
211 {
212 lirerr(8888002);
213 return;
214 /*
215 int sizhalf;
216 float dash_re, dash_im, dashpos, dashpos_err, dash_fit;
217 float dot_re, dot_im, dotpos, dotpos_err, dot_fit;
218 sizhalf=baseband_size>>1;
219 cg_wave_start=mr_dashpos_nom-(dash_pts>>1)+baseband_size;
220 cg_wave_start&=baseband_mask;
221 fit_dash();
222 dash_re=cg_wave_coh_re;
223 dash_im=cg_wave_coh_im;
224 dashpos=cg_wave_midpoint;
225 dashpos_err=mr_dashpos_nom-cg_wave_midpoint;
226 if(dashpos_err < -sizhalf)dashpos_err+=baseband_size;
227 dash_fit=cg_wave_fit;
228 cg_wave_start=mr_dotpos_nom-(dot_pts>>1)+baseband_size;
229 cg_wave_start&=baseband_mask;
230 fit_dot();
231 dot_re=cg_wave_coh_re;
232 dot_im=cg_wave_coh_im;
233 dotpos=cg_wave_midpoint;
234 dotpos_err=mr_dotpos_nom-cg_wave_midpoint;
235 if(dotpos_err < -sizhalf)dotpos_err+=baseband_size;
236 dot_fit=cg_wave_fit;
237 //fprintf( dmp,"\n(fit) dot: %f dash: %f",dot_fit,dash_fit);
238 //fprintf( dmp,"\n(err) dot: %f dash: %f",dotpos_err,dashpos_err);
239 if( dash_fit >DASH_DETECT_LIMIT &&
240 dash_fit - dot_fit > 0.05 &&
241 fabs(dashpos_err) < 0.9 * cwbit_pts &&
242 cw[cw_ptr].unkn > 4)
243 {
244 insert_item(CW_DASH);
245 if(kill_all_flag)return;
246 cw[cw_ptr].unkn-=4;
247 cw[cw_ptr+1].unkn=0;
248 XZ("insert dash");
249 return;
250 }
251 if( dot_fit > DOT_DETECT_LIMIT &&
252 dot_fit-dash_fit > 0.05 &&
253 fabs(dotpos_err) < 0.9 * cwbit_pts)
254 {
255 insert_item(CW_DOT);
256 if(kill_all_flag)return;
257 cw[cw_ptr].unkn-=2;
258 cw[cw_ptr+1].unkn=0;
259 XZ("insert dot");
260 return;
261 }
262 */
263 }
264
265
266
find_prev_char_part(void)267 void find_prev_char_part(void)
268 {
269 int i;
270 float t1;
271 if(cw[cw_ptr].type == CW_SPACE)
272 {
273 i=3;
274 }
275 else // CW_WORDSEP
276 {
277 i=4;
278 }
279 t1=baseband_size+cw[cw_ptr].midpoint-i*cwbit_pts+0.5;
280 mr_dotpos_nom=((int)t1)&baseband_mask;
281 t1-=cwbit_pts;
282 mr_dashpos_nom=((int)t1)&baseband_mask;
283 conditional_insert_dashdot();
284 }
285
286
find_preceeding_part(void)287 void find_preceeding_part(void)
288 {
289 lirerr(888100);
290 /*
291 int i;
292 float dash_chk, dot_chk;
293 if( cw_ptr > 0 && cw[cw_ptr].unkn < 8 &&
294 (cw[cw_ptr-1].type == CW_DOT || cw[cw_ptr-1].type == CW_DASH))
295 {
296 set_region_envelope();
297 }
298 else
299 {
300 extrapolate_region_downwards();
301 }
302 if(cw[cw_ptr].type == CW_DASH)
303 {
304 i=4;
305 }
306 else // CW_DOT
307 {
308 i=3;
309 }
310 mr_dashpos_nom=cw[cw_ptr].midpoint+baseband_size-i*cwbit_pts+0.5;
311 mr_dashpos_nom&=baseband_mask;
312 mr_dotpos_nom=(mr_dashpos_nom+(int)(cwbit_pts+0.5))&baseband_mask;
313 dot_chk=check_dot(mr_dotpos_nom);
314 if(cw[cw_ptr].unkn > 2)
315 {
316 // See if a dash will fit well.
317 dash_chk=check_dash(mr_dashpos_nom);
318 if(dash_chk < -0.25 && dot_chk < -0.25)
319 {
320 cg_wave_midpoint=mr_dashpos_nom;
321 cg_wave_coh_re=baseb_envelope[2*mr_dashpos_nom];
322 cg_wave_coh_im=baseb_envelope[2*mr_dashpos_nom+1];
323 insert_item(CW_WORDSEP);
324 if(kill_all_flag)return;
325 cw[cw_ptr].unkn-=4;
326 cw[cw_ptr+1].unkn=0;
327 return;
328 }
329 }
330 else
331 {
332 dash_chk=-1;
333 }
334 if(dash_chk < 0.25 && dot_chk < 0.25)return;
335 conditional_insert_dashdot();
336 */
337 }
338
decoded_cwspeed(void)339 void decoded_cwspeed(void)
340 {
341 float t1, t2, r1, lsum_real, lsum_ideal;
342 int i, k;
343 cw_ptr=1;
344 lsum_real=0;
345 lsum_ideal=0;
346 t1=0;
347 t2=0;
348 while(cw_ptr < no_of_cwdat)
349 {
350 // Get the length of the gap between decoded dots and dashes.
351 r1=cw[cw_ptr].sep/cwbit_pts;
352 r1-=0.5*(cw[cw_ptr].len+cw[cw_ptr-1].len);
353 if(r1 < 0) r1=0;
354 k=(int)(r1)&0xfffffffe;
355 if(r1-k > 1)k+=2;
356 // Accumulate regions where we see the keying reasonably well.
357 if(k<=8 && fabs(r1-k) < 0.5)
358 {
359 lsum_real+=cw[cw_ptr].sep;
360 lsum_ideal+=k+0.5*(cw[cw_ptr].len+cw[cw_ptr-1].len);
361 }
362 else
363 {
364 t1+=lsum_ideal*lsum_real; //ideal*ideal*(real/ideal)
365 t2+=lsum_ideal*lsum_ideal;
366 lsum_real=0;
367 lsum_ideal=0;
368 }
369 cw_ptr++;
370 }
371 t1+=lsum_ideal*lsum_real; //ideal*ideal*(real/ideal)
372 t2+=lsum_ideal*lsum_ideal;
373 // Get the average ratio of real to ideal, weighted by ideal squared.
374 // Store as an improved value for cw speed
375 fprintf( dmp,"\ndecoded_cwspeed t1 %f t2 %f",t1,t2);
376 cwbit_pts=t1/t2;
377 // Compute the length of un-decoded regions and store in cw[].unkn
378 i=baseband_size+cw[0].midpoint-baseb_px;
379 i&=baseband_mask;
380 cw[0].unkn=(float)(i)/cwbit_pts-cw[0].len/2;
381 cw_ptr=1;
382 while(cw_ptr < no_of_cwdat)
383 {
384 r1=cw[cw_ptr].sep/cwbit_pts;
385 r1-=0.5*(cw[cw_ptr].len+cw[cw_ptr-1].len);
386 if(r1 < 0) r1=0;
387 k=(int)(r1)&0xfffffffe;
388 if(r1-k > 1)k+=2;
389 cw[cw_ptr].unkn=k;
390 cw_ptr++;
391 }
392 }
393
394
continued_morse_decode(void)395 void continued_morse_decode(void)
396 {
397 int charflag,charlen,charval,charbits;
398 cw_ptr=1;
399 charflag=0;
400 charlen=0;
401 charval=0;
402 charbits=0;
403 while(cw_ptr < no_of_cwdat)
404 {
405 if(cw[cw_ptr].unkn != 0)charflag=0;
406 if(charbits != 0 && charflag == 1 &&
407 (cw[cw_ptr].type == CW_WORDSEP || cw[cw_ptr].type == CW_SPACE))
408 {
409 // This is a character surrounded by spaces.
410 // Get an ascii character from the table.
411 insert_char(charbits, charlen, charval);
412 }
413 if(cw[cw_ptr].type != CW_DASH && cw[cw_ptr].type != CW_DOT)
414 {
415 charflag=1;
416 charlen=0;
417 charval=0;
418 charbits=0;
419 }
420 else
421 {
422 charbits++;
423 charlen+=cw[cw_ptr].len;
424 charval<<=1;
425 if(cw[cw_ptr].type==CW_DASH)charval++;
426 }
427 cw_ptr++;
428 }
429 }
430
431
first_morse_decode(void)432 void first_morse_decode(void)
433 {
434 int charflag,charlen,charval,charbits;
435 int first_char_pos;
436 // We have stored dashes and dots that are next to a dash.
437 // Look through the data and see if we can find characters.
438 //show_cw(" AAAA ");
439 cw_decoded_chars=0;
440 first_char_pos=-1;
441 cw_ptr=1;
442 charflag=0;
443 charlen=0;
444 charval=0;
445 charbits=0;
446 while(cw_ptr < no_of_cwdat)
447 {
448 if(cw[cw_ptr].unkn != 0)charflag=0;
449 if(charbits != 0 && charflag == 1 &&
450 (cw[cw_ptr].type == CW_WORDSEP || cw[cw_ptr].type == CW_SPACE))
451 {
452 // This is a character surrounded by spaces.
453 // Get an ascii character from the table.
454 insert_char(charbits, charlen, charval);
455 if(first_char_pos==-1)first_char_pos=cw_ptr;
456 }
457 if(cw[cw_ptr].type != CW_DASH && cw[cw_ptr].type != CW_DOT)
458 {
459 charflag=1;
460 charlen=0;
461 charval=0;
462 charbits=0;
463 }
464 else
465 {
466 charbits++;
467 charlen+=cw[cw_ptr].len;
468 charval<<=1;
469 if(cw[cw_ptr].type==CW_DASH)charval++;
470 }
471 cw_ptr++;
472 }
473 if(cw_decoded_chars > 0)
474 {
475 if(first_char_pos > 1)
476 DEB"\nFirst char pos: %d",first_char_pos);
477 detect_previous_character(first_char_pos-1);
478 }
479 }
480
481
482
483
484
remove_dash(void)485 void remove_dash(void)
486 {
487 float t1;
488 int ia, ib;
489 ia=cw[cw_ptr].midpoint-0.5*dash_pts+baseband_size;
490 ia&=baseband_mask;
491 ib=(ia+dash_pts+1)&baseband_mask;
492 while(ia != ib)
493 {
494 baseb_fit[2*ia]=0;
495 baseb_fit[2*ia+1]=0;
496 ia=(ia+1)&baseband_mask;
497 }
498 ia=cw_ptr+1;
499 while(ia < no_of_cwdat)
500 {
501 cw[ia-1]=cw[ia];
502 ia++;
503 }
504 if(cw_ptr !=0)
505 {
506 t1=cw[cw_ptr].midpoint-cw[cw_ptr-1].midpoint;
507 if(t1 < 0)t1+=baseband_size;
508 cw[cw_ptr].sep=t1;
509 }
510 no_of_cwdat--;
511 }
512
513
set_long_region_envelope(void)514 void set_long_region_envelope(void)
515 {
516 int i, ia, ib, len;
517 float t1,t2,r1,r2;
518 // We have two dashes pointed to by cw_ptr and cw_ptr-1.
519 // We know the envelope at these points but the separation is large.
520 // Set envelope at both ends by extrapolation.
521 ia=cw[cw_ptr-1].midpoint;
522 ia+=(dash_pts>>2);
523 ia&=baseband_mask;
524 ib=cw[cw_ptr].midpoint;
525 t1=cw[cw_ptr-1].coh_re;
526 r1=cw[cw_ptr-1].coh_im;
527 t2=cw[cw_ptr].coh_re;
528 r2=cw[cw_ptr].coh_im;
529 ib+=baseband_size-(dash_pts>>2);
530 ib&=baseband_mask;
531 len=10*cwbit_pts;
532 i=0;
533 while( i < len )
534 {
535 baseb_envelope[2*ia]=t1;
536 baseb_envelope[2*ia+1]=r1;
537 baseb_envelope[2*ib]=t2;
538 baseb_envelope[2*ib+1]=r2;
539 ia=(ia+1)&baseband_mask;
540 if(ia == ib)goto avgenv;
541 ib=(ib+baseband_mask)&baseband_mask;
542 if(ia == ib)goto avgenv;
543 i++;
544 }
545 return;
546 avgenv:;
547 t1=0.5*(t1+t2);
548 r1=0.5*(r1+r2);
549 while( i < len )
550 {
551 baseb_envelope[2*ia]=t1;
552 baseb_envelope[2*ia+1]=r1;
553 baseb_envelope[2*ib]=t1;
554 baseb_envelope[2*ib+1]=r1;
555 ia=(ia+1)&baseband_mask;
556 ib=(ib+baseband_mask)&baseband_mask;
557 i++;
558 }
559 }
560
extrapolate_region_downwards(void)561 void extrapolate_region_downwards(void)
562 {
563 lirerr(8888003);
564 /*
565 int ia, ib;
566 float t1, r1;
567 // We have a dash or dot pointed to by cw_ptr.
568 // We know the envelope at this point.
569 // Set envelope at points preceeding this code part by extrapolation.
570 ib=cw[cw_ptr].midpoint+baseband_size;
571 ia=ib-6*cwbit_pts;
572 ia&=baseband_mask;
573 t1=cw[cw_ptr].coh_re;
574 r1=cw[cw_ptr].coh_im;
575 if(cw[cw_ptr].type == CW_DASH)
576 {
577 ib-=dash_pts>>2;
578 }
579 else
580 {
581 ib-=dot_pts>>2;
582 }
583 ib&=baseband_mask;
584 while( ia != ib )
585 {
586 baseb_envelope[2*ia]=t1;
587 baseb_envelope[2*ia+1]=r1;
588 ia=(ia+1)&baseband_mask;
589 }
590 */
591 }
592
set_region_envelope(void)593 void set_region_envelope(void)
594 {
595 lirerr(8888005);
596 /*
597 int ia, ib, len;
598 float t1,t2,r1,r2;
599 // We have two dashes/dots pointed to by cw_ptr and cw_ptr-1.
600 // We know the envelope at these points.
601 // Set a reasonable envelope across the interval by linear interpolation.
602 ia=cw[cw_ptr-1].midpoint;
603 if(cw[cw_ptr-1].type == CW_DASH)
604 {
605 ia+=(dash_pts>>2);
606 }
607 else
608 {
609 ia+=(dot_pts>>2);
610 }
611 ia&=baseband_mask;
612 ib=baseband_size+cw[cw_ptr].midpoint;
613 if(cw[cw_ptr].type == CW_DASH)
614 {
615 ib-=(dash_pts>>2);
616 }
617 else
618 {
619 ib-=(dot_pts>>2);
620 }
621 ib&=baseband_mask;
622 t1=cw[cw_ptr-1].coh_re;
623 r1=cw[cw_ptr-1].coh_im;
624 len=(ib-ia+baseband_size)&baseband_mask;
625 t2=(cw[cw_ptr].coh_re-t1)/len;
626 r2=(cw[cw_ptr].coh_im-r1)/len;
627 while(ia != ib)
628 {
629 t1+=t2;
630 r1+=r2;
631 baseb_envelope[2*ia]=t1;
632 baseb_envelope[2*ia+1]=r1;
633 ia=(ia+1)&baseband_mask;
634 }
635 */
636 }
637
clear_region(void)638 void clear_region(void)
639 {
640 int ia, ib;
641 // We have two dashes pointed to by cw_ptr and cw_ptr-1.
642 // We know the envelope at these points.
643 // Clear baseb_fit across the interval.
644 ia=cw[cw_ptr-1].midpoint+0.5*dash_pts+baseband_size;
645 ib=cw[cw_ptr].midpoint-0.5*dash_pts+1+baseband_size;
646 ia&=baseband_mask;
647 ib&=baseband_mask;
648 while(ia != ib)
649 {
650 baseb_fit[2*ia]=0;
651 baseb_fit[2*ia+1]=0;
652 ia=(ia+1)&baseband_mask;
653 }
654 }
655
check_dash(float pos)656 float check_dash(float pos)
657 {
658 int ia, ib, ja, sw;
659 float c0, t1, t2, r1, r2, f1, f2;
660 float p,err1,err2;
661 // Place a dash at pos using the phase/amplitude information
662 // in baseb_envelope.
663 // Calculate the transformation required for optimum similarity
664 // between the observed waveform in baseb and the dash we have stored.
665 err1=0;
666 err2=0;
667 p=0;
668 ib=pos;
669 if( pos-ib < 0.001)pos+=0.001;
670 ia=(ib+1)&baseband_mask;
671 if( (dash_pts&1) == 0)
672 {
673 c0=0.5*(dash_pts-1);
674 }
675 else
676 {
677 c0=(dash_pts>>1)+1;
678 }
679 // pos is the center of where we want to place a dash.
680 sw=0;
681 while( sw!=2)
682 {
683 sw=0;
684 t1=ia-pos;
685 if(t1<0)t1+=baseband_size;
686 t1=c0+t1;
687 if(t1 >= dash_pts-1)
688 {
689 baseb_fit[2*ia ]=0;
690 baseb_fit[2*ia+1]=0;
691 sw++;
692 }
693 else
694 {
695 ja=t1;
696 t1-=ja;
697 t2=1-t1;
698 f1=t2*dash_waveform[2*ja ]+t1*dash_waveform[2*ja+2];
699 f2=t2*dash_waveform[2*ja+1]+t1*dash_waveform[2*ja+3];
700 r1=baseb_envelope[2*ia ];
701 r2=baseb_envelope[2*ia+1];
702 baseb_fit[2*ia ]=r1*f1+r2*f2;
703 baseb_fit[2*ia+1]=r1*f2-r2*f1;
704 }
705 err1+=baseb_totpwr[ia];
706 p+=baseb_fit[2*ia ]*baseb_fit[2*ia ]+baseb_fit[2*ia+1]*baseb_fit[2*ia+1];
707 err2+=(baseb_fit[2*ia ]-baseb[2*ia ])*(baseb_fit[2*ia ]-baseb[2*ia ])+
708 (baseb_fit[2*ia+1]-baseb[2*ia+1])*(baseb_fit[2*ia+1]-baseb[2*ia+1]);
709 t1=pos-ib;
710 if(t1<0)t1+=baseband_size;
711 t1=c0-t1;
712 if(t1 < 1)
713 {
714 baseb_fit[2*ib ]=0;
715 baseb_fit[2*ib+1]=0;
716 sw++;
717 }
718 else
719 {
720 ja=t1;
721 t1-=ja;
722 t2=1-t1;
723 f1=t2*dash_waveform[2*ja ]+t1*dash_waveform[2*ja+2];
724 f2=t2*dash_waveform[2*ja+1]+t1*dash_waveform[2*ja+3];
725 r1=baseb_envelope[2*ib ];
726 r2=baseb_envelope[2*ib+1];
727 baseb_fit[2*ib ]=r1*f1+r2*f2;
728 baseb_fit[2*ib+1]=r1*f2-r2*f1;
729 }
730 err1+=baseb_totpwr[ib];
731 p+=baseb_fit[2*ib ]*baseb_fit[2*ib ]+baseb_fit[2*ib+1]*baseb_fit[2*ib+1];
732 err2+=(baseb_fit[2*ib ]-baseb[2*ib ])*(baseb_fit[2*ib ]-baseb[2*ib ])+
733 (baseb_fit[2*ib+1]-baseb[2*ib+1])*(baseb_fit[2*ib+1]-baseb[2*ib+1]);
734 ia=(ia+1)&baseband_mask;
735 ib=(ib+baseband_mask)&baseband_mask;
736 }
737 // In a perfect fit (noise free) we expect this result:
738 //
739 // Case err1 err2
740 // dash p 0
741 // space 0 p
742 //
743 // Due to the presence of noise we expect this instead:
744 //
745 // Case err1 err2 err1-err2
746 // dash p+n n p
747 // space n p+n -p
748
749 return (err1-err2)/p;
750 }
751
752
store_dash(void)753 void store_dash(void)
754 {
755 short int ir;
756 int ia,ib;
757 float t2,r2;
758 // We calculated the dot product between the current waveform and
759 // the average waveform for a dash when cg_wave_start was computed.
760 // Normalise and use to set up fitted waveforms.
761 ia=cg_wave_midpoint-0.5*dash_pts+baseband_size;
762 ia&=baseband_mask;
763 ib=(ia+dash_pts)&baseband_mask;
764 t2=cg_wave_coh_re;
765 r2=cg_wave_coh_im;
766 // Store the average waveform at the optimum phase and amplitude giving
767 // the smallest residue when subtracted from baseb.
768 ir=0;
769 while(ia != ib)
770 {
771 baseb_fit[2*ia ]=t2*dash_waveform[2*ir ]+r2*dash_waveform[2*ir+1];
772 baseb_fit[2*ia+1]=t2*dash_waveform[2*ir+1]-r2*dash_waveform[2*ir ];
773 ir++;
774 ia=(ia+1)&baseband_mask;
775 }
776 }
777
778