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 <unistd.h>
25 #include <ctype.h>
26 #include <string.h>
27 
28 #include "globdef.h"
29 #include "uidef.h"
30 #include "fft1def.h"
31 #include "fft2def.h"
32 #include "fft3def.h"
33 #include "sigdef.h"
34 #include "screendef.h"
35 #include "seldef.h"
36 #include "rusage.h"
37 #include "thrdef.h"
38 #include "txdef.h"
39 #include "vernr.h"
40 #include "hwaredef.h"
41 #include "options.h"
42 #include "keyboard_def.h"
43 
44 #if OSNUM == OSNUM_LINUX
45 #include "fcntl.h"
46 #endif
47 
48 #define TX_WRBLOCK_MAXCNT 200
49 
50 #define TX_DA_MARGIN 0.97
51 #define PILOT_TONE_CONTROL 0.00000000001
52 
53 #if BUFBARS == TRUE
54 #define TX_INDICATOR_MAXNUM 4
55 int tx_indicator_bufpos[TX_INDICATOR_MAXNUM];
56 #endif
57 
58 int radar_cnt;
59 int radar_pulse_cnt;
60 int radar_cnt_max;
61 
62 extern fpos_t file_startpos;
63 int rx_ad_bytes;
64 FILE *txfile;
65 
do_tx_open(void)66 int do_tx_open(void)
67 {
68 #if OSNUM == OSNUM_LINUX
69 char s[80];
70 if(ui.rx_addev_no == ui.tx_dadev_no && ui.rx_admode == O_RDWR )
71   {
72   if(ui.tx_da_bytes != rx_ad_bytes ||
73      ui.tx_da_channels != ui.rx_ad_channels ||
74      ui.tx_da_speed != ui.rx_ad_speed)
75     {
76     clear_screen();
77     lir_text(5,5,
78          "RXAD and TXDA set to use the same soundcard in RDWR mode");
79     lir_text(5,7,"Not possible since formats differ. Check setup.");
80     lir_text(5,9,press_any_key);
81 
82 
83 sprintf(s,"ui.tx_da_bytes %d  rx_ad_bytes %d",ui.tx_da_bytes, rx_ad_bytes);
84 lir_text(0,11,s);
85 sprintf(s,"ui.tx_da_channels %d  ui.rx_ad_channels %d",
86                                     ui.tx_da_channels, ui.rx_ad_channels);
87 lir_text(0,12,s);
88 sprintf(s,"ui.tx_da_speed %d ui.rx_ad_speed %d",
89                          ui.tx_da_speed, ui.rx_ad_speed);
90 lir_text(0,13,s);
91 
92     await_processed_keyboard();
93     return FALSE;
94     }
95   snd[RXAD]=snd[TXDA];
96   open_rx_sndin(FALSE);
97   snd[TXDA]=snd[RXAD];
98   }
99 #endif
100 open_tx_sndout();
101 if(kill_all_flag)return FALSE;
102 txout_pa=0;
103 txout_px=0;
104 tx_pilot_tone=pow(10.0,-0.05*ui.tx_pilot_tone_db);
105 fgetpos(txfile,&file_startpos);
106 return TRUE;
107 }
108 
109 double txphase=0;
110 
fix_24bit_data(int * buf)111 void  fix_24bit_data(int *buf)
112 {
113 signed char *ch;
114 int ip, cp;
115 ch=(signed char*) buf;
116 //i=fread(&rdbuf4[txout_pa], 1, 3*snd[TXDA].block_bytes/4, txfile);
117 
118 ip=snd[TXDA].block_bytes/4-1;
119 cp=3*ip;
120 while(ip >= 0)
121   {
122 
123   ch[4*ip+3]=ch[cp+2];
124   ch[4*ip+2]=ch[cp+1];
125   ch[4*ip+1]=ch[cp];
126   if(ch[4*ip+3]>=0)
127     {
128     ch[4*ip]=0;
129     }
130   else
131     {
132     ch[4*ip]=-1;
133     }
134 buf[ip]*=3;
135   if( (ip&2)==0)
136     {
137     buf[ip]+=tx_pilot_tone;
138     }
139   else
140     {
141     buf[ip]-=tx_pilot_tone;
142     }
143   ip--;
144   cp-=3;
145   }
146 
147 
148 
149 
150 /*
151 for(ip=0; ip<snd[TXDA].block_bytes/4; ip+=2)
152   {
153   buf[ip  ]=0x7f000000*cos(txphase);
154   buf[ip+1]=0x7f000000*sin(txphase);
155   if( (ip&2)==0)
156     {
157     buf[ip]+=tx_pilot_tone;
158     buf[ip+1]-=tx_pilot_tone;
159     }
160   else
161     {
162     buf[ip]-=tx_pilot_tone;
163     buf[ip+1]+=tx_pilot_tone;
164     }
165   txphase+=0.5;
166   if(txphase > PI_L)txphase-=2*PI_L;
167   }
168 */
169 
170 
171 
172 }
173 
disk2tx(void)174 void disk2tx(void)
175 {
176 char wavfilenam[256];
177 char s[300];
178 int i, k, errnr;
179 int bufsize, blksize, bufmask;
180 int line, chunk_size;
181 short int ishort, format_tag;
182 short int * rdbuf2;
183 int * rdbuf4;
184 clear_screen();
185 lir_text(5,5,"Specify file name of file to transmit");
186 lir_text(5,7,"->");
187 i=lir_get_filename(8,7,wavfilenam);
188 if(i==0 || kill_all_flag)return;
189 txfile=fopen(wavfilenam, "rb");
190 if(txfile == NULL)
191   {
192   sprintf(s,"Could not open %s",wavfilenam);
193   lir_text(5,10,s);
194   lir_text(5,11,press_any_key);
195   await_processed_keyboard();
196   return;
197   }
198 line=10;
199 // Read the WAV file header.
200 // First 4 bytes should be "RIFF"
201 k=fread(&i,sizeof(int),1,txfile);
202 errnr=0;
203 if(k !=1)
204   {
205   errnr=1;
206 headerr:;
207   sprintf(s,"Error in .wav file header [%d]",errnr);
208   lir_text(5,line,s);
209   line +=2;
210   lir_text(5,line,press_any_key);
211   await_processed_keyboard();
212   goto txfile_x;
213   }
214 if(i != 0x46464952)
215   {
216   errnr=2;
217   goto headerr;
218   }
219 // Read file size (we do not need it)
220 k=fread(&i,sizeof(int),1,txfile);
221 if(k!=1)
222   {
223   errnr=3;
224   goto headerr;
225   }
226 // Now we should read "WAVE"
227 k=fread(&i,sizeof(int),1,txfile);
228 errnr=4;
229 if(k !=1 || i != 0x45564157)goto headerr;
230 // Now we should read "fmt "
231 k=fread(&i,sizeof(int),1,txfile);
232 errnr=5;
233 if(k !=1 || i != 0x20746d66)goto headerr;
234 // read the size of the format chunk.
235 k=fread(&chunk_size,sizeof(int),1,txfile);
236 errnr=6;
237 if(k !=1 )goto headerr;
238 // read the type of data (Format Tag).
239 k=fread(&format_tag,sizeof(short int),1,txfile);
240 errnr=7;
241 if(k !=1 )goto headerr;
242 if(format_tag != 1 && format_tag != 3)
243   {
244   lir_text(5,line,"Unknown wFormatTag.");
245   line++;
246   goto headerr;
247   }
248 // Read no of channels
249 k=fread(&ishort,sizeof(short int),1,txfile);
250 errnr=8;
251 if(k !=1 )goto headerr;
252 if(ishort != ui.tx_da_channels)
253   {
254   lir_text(5,line,"The number of channels does not agree with your TX setup.");
255   line++;
256   goto headerr;
257   }
258 // Read the sampling speed.
259 k=fread(&i,sizeof(int),1,txfile);
260 errnr=9;
261 if(k !=1 )goto headerr;
262 if(i != ui.tx_da_speed)
263   {
264   lir_text(5,line,"The sampling speed does not agree with your TX setup.");
265   line++;
266   goto headerr;
267   }
268 // Read average bytes per second (do not care what it is)
269 errnr=10;
270 k=fread(&i,sizeof(int),1,txfile);
271 if(k !=1 )goto headerr;
272 // Read block align to get 8 or 16 bit format.
273 k=fread(&ishort,sizeof(short int),1,txfile);
274 errnr=11;
275 if(k !=1 )goto headerr;
276 ishort/=ui.tx_da_channels;
277 // We use rx_ad_bytes only in RDWR mode with OSS.
278 // Then the possible formats are 16 bit and 32 bit only.
279 rx_ad_bytes=ishort;
280 if(rx_ad_bytes == 3)rx_ad_bytes=4;
281 switch (ishort)
282   {
283   case 1:
284 // byte int input
285   errnr=12;
286   if(format_tag != 1)goto headerr;
287   tx_disk_mode=BYTE_INPUT;
288   break;
289 
290   case 2:
291 // 16 bit int input
292   errnr=13;
293   if(format_tag != 1)goto headerr;
294   tx_disk_mode=0;
295   break;
296 
297   case 3:
298 // 24 bit int input
299   errnr=14;
300   if(format_tag != 1)goto headerr;
301   tx_disk_mode=BYTE_INPUT+DWORD_INPUT;
302   break;
303 
304   case 4:
305   errnr=15;
306   if(format_tag == 1)
307     {
308 // 32 bit int input
309     tx_disk_mode=QWORD_INPUT+DWORD_INPUT;
310     break;
311     }
312   if(format_tag != 3)goto headerr;
313 // 32 bit float input
314   tx_disk_mode=FLOAT_INPUT+DWORD_INPUT;
315   break;
316 
317   default:
318   errnr=16;
319   goto headerr;
320   }
321 // Skip extra bytes if present.
322 chunk_size-=14;
323 skip_chunk:;
324 errnr=17;
325 while(chunk_size != 0)
326   {
327   k=fread(&i,1,1,txfile);
328   if(k !=1 )goto headerr;
329   chunk_size--;
330   }
331 // Read chunks until we encounter the "data" string (=0x61746164).
332 errnr=18;
333 k=fread(&i,sizeof(int),1,txfile);
334 if(k !=1 )goto headerr;
335 errnr=19;
336 // Look for DATA
337 if(i != 0x61746164)
338   {
339 // Unknown. Get the size and skip.
340   k=fread(&chunk_size,sizeof(int),1,txfile);
341   if(k !=1 )goto headerr;
342   goto skip_chunk;
343   }
344 // Read how much data we have (do not care)
345 k=fread(&i,sizeof(int),1,txfile);
346 errnr=20;
347 if(k !=1 )goto headerr;
348 snd[TXDA].framesize=ui.tx_da_bytes*ui.tx_da_channels;
349 snd[TXDA].block_bytes=(1000+ui.tx_da_speed)*snd[TXDA].framesize/1000;
350 make_power_of_two((int*)&snd[TXDA].block_bytes);
351 test_keyboard();
352 switch(tx_disk_mode)
353   {
354   case 0:
355   if(do_tx_open() == FALSE)goto txfile_x;
356 // 16 bit integers.
357   rdbuf2=malloc(8*snd[TXDA].block_bytes);
358   bufsize=8*snd[TXDA].block_bytes/2;
359   blksize=snd[TXDA].block_bytes/2;
360   bufmask=bufsize-1;
361   while(txout_pa < bufsize-2*blksize)
362     {
363     i=fread(&rdbuf2[txout_pa], 1, snd[TXDA].block_bytes, txfile);
364     txout_pa+=blksize;
365     if(i != snd[TXDA].block_bytes)
366       {
367       clear_screen();
368       lir_text(5,5,"Short read. File empty???");
369       lir_text(5,9,press_any_key);
370       await_processed_keyboard();
371       goto txfile_x;
372       }
373     }
374   while(lir_inkey == 0 && !kill_all_flag)
375     {
376     for(i=0; i<blksize; i+=2)
377       {
378       rdbuf2[txout_px+i]+=tx_pilot_tone;
379       rdbuf2[txout_px+i+1]-=tx_pilot_tone;
380       }
381     lir_tx_dawrite((char*)&rdbuf2[txout_px]);
382     txout_px=(txout_px+blksize)&bufmask;
383     i=fread(&rdbuf2[txout_pa], snd[TXDA].block_bytes, 1, txfile);
384     if(i!=snd[TXDA].block_bytes)
385       {
386       i/=2;
387       while(i < blksize)
388         {
389         rdbuf2[txout_pa+i]=0;
390         i++;
391         }
392       fsetpos(txfile,&file_startpos);
393       txout_pa=(txout_pa+blksize)&bufmask;
394       }
395     test_keyboard();
396     }
397   break;
398 
399   case BYTE_INPUT+DWORD_INPUT:
400   if(do_tx_open() == FALSE)goto txfile_x;
401 // 24 bit integers.
402   rdbuf4=malloc(8*snd[TXDA].block_bytes);
403   bufsize=8*snd[TXDA].block_bytes/4;
404   blksize=snd[TXDA].block_bytes/4;
405   bufmask=bufsize-1;
406   while(txout_pa < bufsize-3*blksize)
407     {
408     i=fread(&rdbuf4[txout_pa], 1, 3*snd[TXDA].block_bytes/4, txfile);
409     if(i != 3*snd[TXDA].block_bytes/4)
410       {
411       clear_screen();
412       lir_text(5,5,"Short read. File empty???");
413       lir_text(5,9,press_any_key);
414       await_processed_keyboard();
415       goto txfile_x;
416       }
417     fix_24bit_data(&rdbuf4[txout_pa]);
418     txout_pa+=blksize;
419     }
420   while(lir_inkey == 0 && !kill_all_flag)
421     {
422     i=fread(&rdbuf4[txout_pa], 1, 3*snd[TXDA].block_bytes/4, txfile);
423     fix_24bit_data(&rdbuf4[txout_pa]);
424     if(i!=3*snd[TXDA].block_bytes/4)
425       {
426       i/=3;
427       while(i < blksize)
428         {
429         rdbuf4[txout_pa+i]=0;
430         i++;
431         }
432       fsetpos(txfile,&file_startpos);
433       }
434     txout_pa=(txout_pa+blksize)&bufmask;
435     if(ui.tx_da_bytes == 4)
436       {
437       lir_tx_dawrite((char*)&rdbuf4[txout_px]);
438       txout_px=(txout_px+blksize)&bufmask;
439       }
440     else
441       {
442       lirerr(229513);
443       return;
444       }
445     test_keyboard();
446     }
447   break;
448 
449 
450   default:
451   clear_screen();
452   lir_text(5,5,"This .wav file format is not yet supported for TX output.");
453   lir_text(5,7,press_any_key);
454   await_processed_keyboard();
455   goto txfile_x;
456   }
457 
458 lir_text(1,20,"OKOKOKOK");
459 await_keyboard();
460 
461 txfile_x:;
462 fclose(txfile);
463 }
464 
tx_ssb_buftim(char cc)465 void tx_ssb_buftim(char cc)
466 {
467 int i1,i2,i3,i4,i5,i6,i7,j;
468 i1=2*lir_tx_input_samples();
469 fprintf( dmp,"\n%c in %d",cc,i1);
470 i2=2*(mictimf_pa-mictimf_px+mictimf_bufsiz)&mictimf_mask;
471 fprintf( dmp," m.timf %d",i2);
472 i3=((micfft_pa-micfft_px+micfft_bufsiz)&micfft_mask)/2;
473 fprintf( dmp," m.fft %d",i3);
474 i4=((cliptimf_pa-cliptimf_px+micfft_bufsiz)&micfft_mask);
475 fprintf( dmp," cl.timf %d",i4);
476 i5=((clipfft_pa-clipfft_px+alc_bufsiz)&alc_mask)/(2*tx_pre_resample);
477 fprintf( dmp," cl.fft %d",i5);
478 i6=((alctimf_pa-((int)(alctimf_fx))+4+alc_bufsiz)&alc_mask)/tx_pre_resample;
479 fprintf( dmp," alctimf %d",i6);
480 i7=lir_tx_output_samples()/(tx_resample_ratio*tx_output_upsample);
481 fprintf( dmp," out %d",i7);
482 j=i1+i2+i3+i4+i5+i6+i7;
483 fprintf( dmp," tot %d tim %f",j,(float)(j)/ui.tx_ad_speed);
484 }
485 
tx_cw_buftim(char cc)486 void tx_cw_buftim(char cc)
487 {
488 int i,j,k,n,m;
489 i=lir_tx_input_samples();
490 fprintf( dmp,"\n%c input %d",cc,i);
491 j=((mic_key_pa-mic_key_px+mic_key_bufsiz)&mic_key_mask)*tx_pre_resample;
492 fprintf( dmp," mic_key %d",j);
493 k=lir_tx_output_samples()/(tx_resample_ratio);
494 fprintf( dmp," output %d",k);
495 n=txout_pa/(tx_resample_ratio);
496 fprintf( dmp," txout %d",n);
497 m=i+j+k+n;
498 fprintf( dmp,"  tot %d  tim %f %f",m,(float)(m)/ui.tx_ad_speed,
499                           current_time());
500 }
501 
do_cw_keying(void)502 void do_cw_keying(void)
503 {
504 int i, k, nn, mm;
505 float amplitude, pilot_ampl;
506 float r1, r2;
507 double dt1;
508 pilot_ampl=0;
509 dt1=1/sqrt(tx_daout_sin*tx_daout_sin+tx_daout_cos*tx_daout_cos);
510 tx_daout_sin*=dt1;
511 tx_daout_cos*=dt1;
512 // Find out how many points we should place in the output buffer.
513 mm=(mic_key_pa-mic_key_px+mic_key_bufsiz)&mic_key_mask;
514 #if BUFBARS == TRUE
515 if(timinfo_flag!=0)
516   {
517   i=mm/mic_key_indicator_block;
518   if(i != tx_indicator_bufpos[0])
519     {
520     tx_indicator_bufpos[0]=i;
521     lir_hline(tx_indicator_first_pixel,indicator_ypix,
522                                  tx_indicator_first_pixel+i-1,15);
523     lir_hline(tx_indicator_first_pixel+i,indicator_ypix,
524                                  tx_indicator_first_pixel+INDICATOR_SIZE-1,2);
525     }
526   }
527 #endif
528 repeat:;
529 r2=1.0000/(tx_resample_ratio*tx_pre_resample);
530 r1=(mm-mic_key_fx)/r2;
531 nn=r1;
532 // tx_cw_buftim('B');
533 
534 for(i=0; i<nn; i++)
535   {
536   mic_key_fx+=r2;
537   if(mic_key_fx > 1)
538     {
539     mic_key_fx-=1;
540     mic_key_px=(mic_key_px+1)&mic_key_mask;
541     if(tx_mic_key[mic_key_px] > 1)
542       {
543       tone_key=1;
544       }
545     else
546       {
547       tone_key=0;
548       }
549     }
550   if(tx_waveform_pointer==0 ||
551                 tx_waveform_pointer==tx_cw_waveform_points)
552     {
553     if(rx_mode == MODE_RADAR)
554       {
555       tot_key=tone_key;
556       }
557     else
558       {
559       hware_hand_key();
560       tot_key=(hand_key&txcw.enable_hand_key)|
561              (tone_key&txcw.enable_tone_key);
562       }
563     }
564   amplitude=txout_waveform[tx_waveform_pointer];
565   tx_pilot_tone=-tx_pilot_tone;
566   if(amplitude == 0)
567     {
568     pilot_ampl=0;
569     }
570   else
571     {
572     pilot_ampl=tx_pilot_tone;
573     }
574   if(tot_key)
575     {
576     if(tx_waveform_pointer == 0 && old_cw_rise_time != txcw.rise_time)
577       {
578       make_tx_cw_waveform();
579       }
580     if(tx_waveform_pointer < tx_cw_waveform_points)tx_waveform_pointer++;
581     }
582   else
583     {
584     if(tx_waveform_pointer > 0)
585       {
586       tx_waveform_pointer--;
587       }
588     if(amplitude < PILOT_TONE_CONTROL)pilot_ampl=0;
589     }
590   dt1=tx_daout_cos;
591   tx_daout_cos= tx_daout_cos*tx_daout_phstep_cos+tx_daout_sin*tx_daout_phstep_sin;
592   tx_daout_sin= tx_daout_sin*tx_daout_phstep_cos-dt1*tx_daout_phstep_sin;
593   amplitude*=tx_output_amplitude*tx_onoff_flag;
594 
595   txout[2*txout_pa  ]=amplitude*tx_daout_cos+pilot_ampl;
596   txout[2*txout_pa+1]=amplitude*tx_daout_sin-pilot_ampl;
597   txout_pa++;
598   if(txout_pa == txout_sizhalf)
599     {
600     if( (hand_key|tone_key) )
601       {
602       rxtx_state=TRUE;
603       }
604     else
605       {
606       rxtx_state=FALSE;
607       }
608     if(old_rxtx_state == FALSE && rxtx_state == TRUE)
609       {
610       hware_set_rxtx(TRUE);
611       old_rxtx_state=TRUE;
612       }
613     if(rxtx_state == TRUE) rxtx_wait=16+lir_tx_output_samples()/txout_sizhalf;
614     if(old_rxtx_state == TRUE && rxtx_state == FALSE)
615       {
616       rxtx_wait--;
617       if(rxtx_wait == 0)
618         {
619         old_rxtx_state=FALSE;
620         hware_set_rxtx(FALSE);
621         }
622       }
623 // Compute the total time from tx input to tx output and
624 // express it as samples of the tx input clock and store in tx_wsamps.
625     tx_wsamps=lir_tx_input_samples();
626     k=(mic_key_pa-mic_key_px+mic_key_bufsiz)&mic_key_mask;
627     tx_wsamps+=k*tx_pre_resample;
628     tx_send_to_da();
629     txout_pa=0;
630     goto new_resamp;
631     }
632   }
633 new_resamp:;
634 mm=(mic_key_pa-mic_key_px+mic_key_bufsiz)&mic_key_mask;
635 if(mm > 1 && lir_tx_output_samples() < snd[TXDA].tot_frames-
636                                 snd[TXDA].block_frames)goto repeat;
637 // tx_cw_buftim('X');
638 
639 }
640 
tx_send_to_da(void)641 void tx_send_to_da(void)
642 {
643 int i;
644 float t1, t2;
645 
646 //tx_ssb_buftim('W');
647 
648 switch(tx_output_mode)
649   {
650   case 0:
651   for(i=0; i<txout_sizhalf; i++)
652     {
653     t1=txout[2*i  ];
654     tx_out_shi[i]=TX_DA_MARGIN*0x7fff*t1;
655     }
656   lir_tx_dawrite((char*)tx_out_shi);
657   break;
658 
659   case 1:
660   for(i=0; i<txout_sizhalf; i++)
661     {
662     t1=txout[2*i  ];
663     t2=txout[2*i+1];
664     tx_out_shi[2*i]=TX_DA_MARGIN*0x7fff*t2;
665     tx_out_shi[2*i+1]=TX_DA_MARGIN*0x7fff*t1;
666     }
667   lir_tx_dawrite((char*)tx_out_shi);
668   break;
669 
670   case 2:
671   for(i=0; i<txout_sizhalf; i++)
672     {
673     t1=txout[2*i  ];
674     tx_out_int[i]=TX_DA_MARGIN*0x7fff0000*t1;
675     }
676   lir_tx_dawrite((char*)tx_out_int);
677   break;
678 
679   case 3:
680   for(i=0; i<txout_sizhalf; i++)
681     {
682     t1=txout[2*i  ];
683     t2=txout[2*i+1];
684     tx_out_int[2*i  ]=TX_DA_MARGIN*0x7fff0000*t2;
685     tx_out_int[2*i+1]=TX_DA_MARGIN*0x7fff0000*t1;
686 
687     }
688   lir_tx_dawrite((char*)tx_out_int);
689   break;
690   }
691 tx_wsamps+=(float)(lir_tx_output_samples())/
692               (tx_resample_ratio*tx_output_upsample);
693 tx_wttim=(float)(tx_wsamps)/ui.tx_ad_speed;
694 tx_wttim_sum+=tx_wttim;
695 tx_wrblock_no++;
696 
697 /*
698 char s[80];
699 sprintf(s,"wttim=%f   %f",tx_wttim,1/snd[TXDA].interrupt_rate);
700 lir_text(0,0,s);
701 //fprintf( dmp,"\ntx_wttim %f  sumavg %f",tx_wttim,tx_wttim_sum/tx_wrblock_no);
702 */
703 if(tx_wrblock_no == TX_WRBLOCK_MAXCNT)
704   {
705   tx_wrblock_no=0;
706   tx_wttim_sum/=TX_WRBLOCK_MAXCNT;
707   t1=tx_wttim_sum-tx_ideal_delay;
708 
709 /*
710 sprintf(s,"wttim_sum=%f   t1=%f  (%f)",tx_wttim_sum,t1,tx_ideal_delay);
711 lir_text(0,1,s);
712 //fprintf( dmp,"\n%s",s);
713 */
714 
715   t2=t1-tx_wttim_diff;
716   tx_wttim_diff=t1;
717 // We have accumulated an error of t1 seconds while writing
718 // TX_WRBLOCK_MAXCNT data blocks. Each block spans a time of
719 // txout_sizhalf/txssb.output speed so the relative error is
720 // X=t1/(TX_WRBLOCK_MAXCNT*txout_sizhalf/txssb.output speed);
721 // Therefore we should multiply the output
722 // speed by (1-X)
723 // Use half the correction and add in a small part of t1,
724 // the deviation from the initial time delay.
725   new_tx_resample_ratio=tx_resample_ratio*(1-0.5*(t2+0.2*t1)*
726                            ui.tx_da_speed/(TX_WRBLOCK_MAXCNT*txout_sizhalf));
727   tx_resample_ratio=0.9*tx_resample_ratio+0.1*new_tx_resample_ratio;
728   tx_wttim_sum=0;
729   }
730 }
731 
732 
733 
run_tx_output(void)734 void run_tx_output(void)
735 {
736 int i, k;
737 float t1, t2, r2, prat;
738 #if BUFBARS == TRUE
739 for(i=0; i<TX_INDICATOR_MAXNUM; i++)tx_indicator_bufpos[i]=-1;
740 #endif
741 tot_key=0;
742 thread_status_flag[THREAD_TX_OUTPUT]=THRFLAG_ACTIVE;
743 // Allow the receive side to use the CPU for a while.
744 if(!kill_all_flag)lir_await_event(EVENT_TX_INPUT);
745 switch (rx_mode)
746   {
747   case MODE_SSB:
748   micfft_px=micfft_pa;
749   while(micfft_px == micfft_pa && !kill_all_flag)lir_await_event(EVENT_TX_INPUT);
750   for(i=0;i<8; i++)
751     {
752     if(!kill_all_flag)lir_await_event(EVENT_TX_INPUT);
753     }
754   micfft_px=micfft_pa;
755   while(!kill_all_flag &&
756                     thread_command_flag[THREAD_TX_OUTPUT] == THRFLAG_ACTIVE)
757     {
758 //    tx_ssb_buftim('A');
759     lir_await_event(EVENT_TX_INPUT);
760 #if BUFBARS == TRUE
761     if(timinfo_flag!=0)
762       {
763       i=(micfft_pa-micfft_px+micfft_bufsiz)&micfft_mask;
764       i/=micfft_indicator_block;
765       if(i != tx_indicator_bufpos[0])
766         {
767         tx_indicator_bufpos[0]=i;
768         lir_hline(tx_indicator_first_pixel,indicator_ypix,
769                                  tx_indicator_first_pixel+i-1,15);
770         lir_hline(tx_indicator_first_pixel+i,indicator_ypix,
771                                  tx_indicator_first_pixel+INDICATOR_SIZE-1,2);
772         }
773       }
774 #endif
775     tx_agc_factor=tx_agc_decay*tx_agc_factor+(1-tx_agc_decay);
776     micfft_bin_minpower=micfft_bin_minpower_ref*tx_agc_factor*tx_agc_factor;
777     micfft_minpower=micfft_minpower_ref*tx_agc_factor*tx_agc_factor;
778     k=tx_ssb_step2(&t1);
779     if(k!=0)
780       {
781       tx_ssb_step3(&t1);
782       }
783 // In case AGC has reduced the gain by more than 20 dB, set the
784 // AGC factor to -20 dB immediately because voice should never
785 // be as loud. This is to avoid the agc release time constant
786 // for impulse sounds caused by hitting the microphone etc.
787     if(tx_agc_factor < 0.1)tx_agc_factor=0.1;
788     if(k!=0)
789       {
790       fftback(mic_fftsize, mic_fftn, &micfft[micfft_px],
791                              micfft_table, micfft_permute,FALSE);
792       r2=0;
793       for(i=0; i<mic_fftsize; i++)
794         {
795         t2=micfft[micfft_px+2*i  ]*micfft[micfft_px+2*i  ]+
796            micfft[micfft_px+2*i+1]*micfft[micfft_px+2*i+1];
797         if(t2>r2)r2=t2;
798         }
799       if(r2 > 0.01*MAX_DYNRANGE)
800         {
801         r2=1/sqrt(r2);
802         if(r2>10/tx_agc_factor)r2=10/tx_agc_factor;
803         }
804       else
805         {
806         r2=0;
807         }
808       }
809     else
810       {
811       r2=0;
812       }
813 //    tx_ssb_buftim('B');
814     tx_ssb_step4(r2,&t1,&prat);
815 //    tx_ssb_buftim('C');
816     tx_ssb_step5();
817 //    tx_ssb_buftim('D');
818     if(lir_tx_output_samples() < snd[TXDA].tot_frames-2*snd[TXDA].block_frames)
819       {
820       while(clipfft_px != clipfft_pa)
821         {
822         tx_ssb_step6(&prat);
823         }
824       while( ((alctimf_pa-alctimf_pb+alc_bufsiz)&alc_mask) >= 3*alc_fftsize)
825         {
826         tx_ssb_step7(&prat);
827         }
828       tx_ssb_step8();
829       }
830     }
831   break;
832 
833   case MODE_WCW:
834   case MODE_NCW:
835   case MODE_HSMS:
836   case MODE_QRSS:
837   case MODE_RADAR:
838   mic_key_px=mic_key_pa;
839   while(mic_key_px == mic_key_pa && !kill_all_flag)lir_await_event(EVENT_TX_INPUT);
840   for(i=0;i<8; i++)
841     {
842     if(!kill_all_flag)lir_await_event(EVENT_TX_INPUT);
843     }
844   mic_key_px=mic_key_pa;
845 // Fill one extra buffer before starting the output.
846 
847   lir_await_event(EVENT_TX_INPUT);
848   while(!kill_all_flag &&
849                     thread_command_flag[THREAD_TX_OUTPUT] == THRFLAG_ACTIVE)
850     {
851   lir_await_event(EVENT_TX_INPUT);
852 //    tx_cw_buftim('A');
853     do_cw_keying();
854     }
855   break;
856   }
857 thread_status_flag[THREAD_TX_OUTPUT]=THRFLAG_RETURNED;
858 while(thread_command_flag[THREAD_TX_OUTPUT] != THRFLAG_NOT_ACTIVE)
859   {
860   lir_sleep(1000);
861   }
862 }
863 
cwproc_setup(void)864 void cwproc_setup(void)
865 {
866 char color;
867 char *onoff[]={"Disabled", "Enabled"};
868 char s[256];
869 int i, k, pa, default_cwproc_no;
870 int old_tone_key, old_hand_key;
871 int isum;
872 float t1, t2, t3;
873 rx_mode=MODE_NCW;
874 tg.spproc_no=0;
875 set_hardware_tx_frequency();
876 default_cwproc_no=tg.spproc_no;
877 if(read_txpar_file()==FALSE)
878   {
879   set_default_cwproc_parms();
880   }
881 if(txcw.rise_time < 1000*CW_MIN_TIME_CONSTANT)
882                          txcw.rise_time=1000*CW_MIN_TIME_CONSTANT;
883 if(txcw.rise_time > 1000*CW_MAX_TIME_CONSTANT)
884                          txcw.rise_time=1000*CW_MAX_TIME_CONSTANT;
885 if(ui.tx_pilot_tone_prestart > 1000*CW_MAX_TIME_CONSTANT)
886   {
887   lirerr(1070);
888   return;
889   }
890 init_txmem_cwproc();
891 if(kill_all_flag)return;
892 lir_mutex_init();
893 lir_sleep(50000);
894 linrad_thread_create(THREAD_TX_INPUT);
895 restart:;
896 tx_waveform_pointer=0;
897 if(txcw.rise_time < 1000*CW_MIN_TIME_CONSTANT)
898                          txcw.rise_time=1000*CW_MIN_TIME_CONSTANT;
899 if(txcw.rise_time > 1000*CW_MAX_TIME_CONSTANT)
900                          txcw.rise_time=1000*CW_MAX_TIME_CONSTANT;
901 make_tx_cw_waveform();
902 old_tone_key=-1;
903 old_hand_key=-1;
904 tot_key=0;
905 clear_screen();
906 lir_text(20,0,"Setup for CW keying.");
907 lir_text(0,2,"There are three ways to produce Morse code in Linrad:");
908 if(txcw.enable_tone_key == 0)settextcolor(7); else settextcolor(14);
909 sprintf(s,"Tone into the microphone input. (Fast keying)  [%s]",
910                     onoff[txcw.enable_tone_key]);
911 lir_text(0,4,s);
912 if(txcw.enable_hand_key == 0)settextcolor(7); else settextcolor(14);
913 sprintf(s,"Parallel port pin 13. (Hand keying)  [%s]",
914                                           onoff[txcw.enable_hand_key]);
915 lir_text(0,5,s);
916 if(txcw.enable_ascii == 0)settextcolor(7); else settextcolor(14);
917 sprintf(s,"Computer generated from ascii on keyboard.  [%s]",
918                                           onoff[txcw.enable_ascii]);
919 lir_text(0,6,s);
920 settextcolor(7);
921 lir_text(0,7,"Press 'T', 'H' or 'C' to toggle Enable/Disable");
922 sprintf(s,"Rise time = %.2f ms. ('A' to change)",txcw.rise_time*0.001);
923 lir_text(0,9,s);
924 make_txproc_filename();
925 sprintf(s,"Press 'S' to save %s, 'R' to read.  '+' or '-' to change file no.",
926                                                  txproc_filename);
927 lir_text(0,10,s);
928 
929 k=screen_last_col;
930 if(k>255)k=255;
931 for(i=0; i<k; i++)s[i]='-';
932 s[k]=0;
933 lir_text(0,MIC_KEY_LINE,s);
934 lir_text(0,MIC_KEY_LINE+8,s);
935 //                         0123456789012345678901234567890
936 lir_text(0,MIC_KEY_LINE+1,"Average       Max        Min");
937 lir_text(0,MIC_KEY_LINE+3,
938 "Set tone level and frequency for numbers well above 1.0 with key down.");
939 lir_text(0,MIC_KEY_LINE+4,
940 "Make sure the numbers are well below 1.0 with key up.");
941 lir_text(0,MIC_KEY_LINE+5,
942 "Typically Min(key down) > 10.0 and Max(key up) < 0.1.");
943 sprintf(s,
944   "Your Nyquist frequency is %.1f kHz so you should use a keying tone",
945                                                      0.0005*ui.tx_ad_speed);
946 lir_text(0,MIC_KEY_LINE+6,s);
947 lir_text(0,MIC_KEY_LINE+7,"that is a little lower than this.");
948 for(i=0; i<4; i++)lir_await_event(EVENT_TX_INPUT);
949 t1=0;
950 t2=0;
951 t3=BIG;
952 isum=0;
953 while(!kill_all_flag)
954   {
955   lir_refresh_screen();
956   lir_await_event(EVENT_TX_INPUT);
957   pa=mic_key_px;
958   while(pa != mic_key_pa)
959     {
960     isum++;
961     t1+=tx_mic_key[pa];
962     if(t2 < tx_mic_key[pa])t2=tx_mic_key[pa];
963     if(t3 > tx_mic_key[pa])t3=tx_mic_key[pa];
964     pa=(pa+1)&mic_key_mask;
965     }
966   if(isum > 4000)
967     {
968     t1/=isum;
969     sprintf(s,"%.3f",t1);
970     lir_text(1,MIC_KEY_LINE+2,s);
971     sprintf(s,"%.3f",t2);
972     lir_text(12,MIC_KEY_LINE+2,s);
973     sprintf(s,"%.3f",t3);
974     lir_text(23,MIC_KEY_LINE+2,s);
975     if(t1 < 1)
976       {
977       tone_key=0;
978       }
979     else
980       {
981       tone_key=1;
982       }
983     if(tone_key != old_tone_key)
984       {
985       old_tone_key=tone_key;
986       if(tone_key == 0)
987         {
988         color=7;
989         }
990       else
991         {
992         color=12;
993         }
994       lir_fillbox(5*text_width, KEY_INDICATOR_LINE*text_height, 10*text_width,
995                                                         3*text_height,color);
996       lir_text(8,KEY_INDICATOR_LINE+1,"TONE");
997       lir_sched_yield();
998       }
999     t1=0;
1000     t2=0;
1001     t3=BIG;
1002     isum=0;
1003     }
1004   hware_hand_key();
1005   if(hand_key != old_hand_key)
1006     {
1007     old_hand_key=hand_key;
1008     if(hand_key == 0)
1009       {
1010       color=7;
1011       }
1012     else
1013       {
1014       color=12;
1015       }
1016     lir_fillbox(20*text_width, KEY_INDICATOR_LINE*text_height, 10*text_width,
1017                                                         3*text_height,color);
1018     lir_text(22,KEY_INDICATOR_LINE+1,"HAND");
1019     lir_sched_yield();
1020     }
1021   do_cw_keying();
1022   test_keyboard();
1023   if(lir_inkey != 0)
1024     {
1025     process_current_lir_inkey();
1026     if(lir_inkey=='X')goto end_tx_setup;
1027     switch (lir_inkey)
1028       {
1029       case 'A':
1030       lir_text(0,TXCW_INPUT_LINE,"Rise time (ms):");
1031       t1=lir_get_float(15,TXCW_INPUT_LINE,6,
1032                                   CW_MIN_TIME_CONSTANT,CW_MAX_TIME_CONSTANT);
1033       txcw.rise_time=1000*t1;
1034       break;
1035 
1036       case 'T':
1037       txcw.enable_tone_key^=1;
1038       txcw.enable_tone_key&=1;
1039       break;
1040 
1041       case 'H':
1042       txcw.enable_hand_key^=1;
1043       txcw.enable_hand_key&=1;
1044       break;
1045 
1046       case 'C':
1047       txcw.enable_ascii^=1;
1048       txcw.enable_ascii&=1;
1049       break;
1050 
1051       case 'S':
1052       clear_screen();
1053       save_tx_parms(TRUE);
1054       break;
1055 
1056       case 'R':
1057       clear_screen();
1058       read_txpar_file();
1059       break;
1060 
1061       case '+':
1062       tg.spproc_no++;
1063       if(tg.spproc_no > MAX_CWPROC_FILES)tg.spproc_no=MAX_CWPROC_FILES;
1064       break;
1065 
1066       case '-':
1067       tg.spproc_no--;
1068       if(tg.spproc_no < 0)tg.spproc_no=0;
1069       break;
1070       }
1071     goto restart;
1072     }
1073   }
1074 end_tx_setup:;
1075 close_tx_sndout();
1076 linrad_thread_stop_and_join(THREAD_TX_INPUT);
1077 close_tx_sndin();
1078 if(txmem_handle != NULL)free(txmem_handle);
1079 txmem_handle=NULL;
1080 lir_close_event(EVENT_TX_INPUT);
1081 lir_mutex_destroy();
1082 tg.spproc_no=default_cwproc_no;
1083 }
1084 
make_tx_phstep(void)1085 void make_tx_phstep(void)
1086 {
1087 float t1;
1088 t1=2*PI_L*(tg_basebfreq*1000000+tx_hware_fqshift+
1089                                             tx_ssbproc_fqshift)/ui.tx_da_speed;
1090 tx_daout_phstep_cos=cos(t1);
1091 tx_daout_phstep_sin=sin(t1);
1092 }
1093 
init_txmem_common(float micblock_time)1094 void init_txmem_common(float micblock_time)
1095 {
1096 tx_pilot_tone=pow(10.0,-0.05*ui.tx_pilot_tone_db);
1097 tx_output_amplitude=pow(10.0,-0.05*tg.level_db);
1098 tx_indicator_first_pixel=indicator_first_pixel+INDICATOR_SIZE+2*text_width;
1099 tx_daout_cos=1;
1100 tx_daout_sin=0;
1101 micsize=ui.tx_ad_speed*micblock_time;
1102 make_power_of_two(&micsize);
1103 snd[TXAD].framesize=ui.tx_ad_channels*ui.tx_ad_bytes;
1104 snd[TXAD].block_bytes=snd[TXAD].framesize*micsize;
1105 lir_init_event(EVENT_TX_INPUT);
1106 lir_sleep(200000);
1107 }
1108 
set_txmem_sizes(void)1109 void set_txmem_sizes(void)
1110 {
1111 int i;
1112 mictimf_block=snd[TXAD].block_bytes/ui.tx_ad_bytes;
1113 micsize=mictimf_block/ui.tx_ad_channels;
1114 micn=0;
1115 i=micsize;
1116 while(i>1)
1117   {
1118   i>>=1;
1119   micn++;
1120   }
1121 mic_sizhalf=micsize/2;
1122 mictimf_bufsiz=16*mictimf_block;
1123 mictimf_mask=mictimf_bufsiz-1;
1124 }
1125 
init_txmem_cwproc(void)1126 void init_txmem_cwproc(void)
1127 {
1128 int i;
1129 init_txmem_common(MICBLOCK_CWTIME);
1130 if(tx_setup_flag)
1131   {
1132   open_tx_sndin();
1133   }
1134 else
1135   {
1136   sys_func(THRFLAG_OPEN_TX_SNDIN);
1137   }
1138 if(kill_all_flag)return;
1139 // Allow the input buffer to hold 80 milliseconds of data (or more)
1140 // Keying with a tone into the microphone input should
1141 // be done with a tone frequency near, but below the Nyquist frequency
1142 // which is ui.tx_ad_speed/2.
1143 // We do not want faster rise times than 1 ms for a dot length
1144 // of 2 ms minimum or a dot rate of 250 Hz maximum.
1145 // With at least 4 points on the rise time we need a sampling
1146 // rate of 4kHz.
1147 set_txmem_sizes();
1148 tx_pre_resample=1;
1149 i=1.05*ui.tx_ad_speed/2;
1150 mic_key_block=mictimf_block;
1151 if(rx_mode == MODE_RADAR)i/=2;
1152 while(i > 4000)
1153   {
1154   i/=2;
1155   mic_key_block/=2;
1156   tx_pre_resample*=2;
1157   }
1158 if(tx_pre_resample < 4 && rx_mode != MODE_RADAR)lirerr(1147);
1159 tx_resample_ratio=(float)(ui.tx_da_speed)/ui.tx_ad_speed;
1160 new_tx_resample_ratio=tx_resample_ratio;
1161 mic_key_bufsiz=16*mic_key_block;
1162 mic_key_mask=mic_key_bufsiz-1;
1163 mic_key_indicator_block=mic_key_bufsiz/INDICATOR_SIZE;
1164 txout_fftsize=2*mic_key_block*tx_resample_ratio*tx_pre_resample;
1165 make_power_of_two(&txout_fftsize);
1166 snd[TXDA].framesize=ui.tx_da_bytes*ui.tx_da_channels;
1167 snd[TXDA].block_bytes=txout_fftsize*snd[TXDA].framesize/2;
1168 if(tx_setup_flag)
1169   {
1170   open_tx_sndout();
1171   }
1172 else
1173   {
1174   sys_func(THRFLAG_OPEN_TX_SNDOUT);
1175   }
1176 if(kill_all_flag)return;
1177 tx_ssb_resamp_block_factor=1;
1178 tx_output_upsample=1;
1179 txout_sizhalf=snd[TXDA].block_bytes/snd[TXDA].framesize;
1180 txout_fftsize=2*txout_sizhalf;
1181 tx_ideal_delay=1.2/snd[TXDA].interrupt_rate+1.2/snd[TXAD].interrupt_rate+0.002;
1182 //fprintf( dmp,"\nideal  del %f\n",tx_ideal_delay);
1183 
1184 max_tx_cw_waveform_points=ui.tx_da_speed*(0.0022*CW_MAX_TIME_CONSTANT);
1185 init_memalloc(txmem, MAX_TXMEM_ARRAYS);
1186 if(ui.tx_ad_bytes == 2)
1187   {
1188   mem(51,&mictimf_shi,mictimf_bufsiz*sizeof(short int),0);
1189   }
1190 else
1191   {
1192   mem(51,&mictimf_int,mictimf_bufsiz*sizeof(int),0);
1193   }
1194 mem(52,&tx_mic_key,mic_key_bufsiz*sizeof(float),0);
1195 mem(53,&txout,2*txout_fftsize*sizeof(float),0);
1196 mem(54,&txout_waveform,max_tx_cw_waveform_points*sizeof(float),0);
1197 if(ui.tx_da_bytes==4)
1198   {
1199   mem(55,&tx_out_int,ui.tx_da_channels*txout_fftsize*sizeof(int)/2,0);
1200   }
1201 else
1202   {
1203   mem(56,&tx_out_shi,ui.tx_da_channels*txout_fftsize*sizeof(int)/2,0);
1204   }
1205 txmem_size=memalloc(&txmem_handle,"txmem");
1206 if(txmem_size == 0)
1207   {
1208   lirerr(1261);
1209   return;
1210   }
1211 tx_wrblock_no=0;
1212 tx_wttim_ref=0;
1213 tx_wttim_sum=0;
1214 tx_wttim_diff=0;
1215 tx_ssbproc_fqshift=0;
1216 make_tx_phstep();
1217 make_tx_modes();
1218 make_tx_cw_waveform();
1219 mic_key_pa=0;
1220 mic_key_px=0;
1221 mictimf_pa=0;
1222 mictimf_px=0;
1223 txout_pa=0;
1224 mic_key_fx=0;
1225 tx_waveform_pointer=0;
1226 }
1227 
init_txmem_spproc(void)1228 void init_txmem_spproc(void)
1229 {
1230 int j;
1231 int i, k;
1232 float t1;
1233 // Speech processing is done in both the time domain and in the
1234 // frequency domain.
1235 // The length of an FFT block determines the frequency
1236 // resolution as well as the total time delay through
1237 // the processes.
1238 // Set micsize to span a suitable time and suggest the same
1239 // time span for a dma buffer to the tx input soundcard.
1240 init_txmem_common(MICBLOCK_SSBTIME);
1241 if(tx_setup_flag)
1242   {
1243   open_tx_sndin();
1244   }
1245 else
1246   {
1247   sys_func(THRFLAG_OPEN_TX_SNDIN);
1248   }
1249 if(kill_all_flag)return;
1250 // The open function may have changed the block size.
1251 // Set micsize to fit the dma buffer we actually have.
1252 set_txmem_sizes();
1253 txad_hz_per_bin=(0.5*ui.tx_ad_speed)/micsize;
1254 tx_lowest_bin=txssb.minfreq/txad_hz_per_bin;
1255 if(tx_lowest_bin > micsize/3)tx_lowest_bin=micsize/3;
1256 if(tx_lowest_bin < 1)tx_lowest_bin=1;
1257 tx_highest_bin=txssb.maxfreq/txad_hz_per_bin;
1258 if(tx_highest_bin > micsize/2-2)tx_highest_bin=micsize/2-2;
1259 if(tx_highest_bin < tx_lowest_bin+1)tx_highest_bin=tx_lowest_bin+1;
1260 t1=(tx_highest_bin-tx_lowest_bin+1)*txad_hz_per_bin;
1261 if(ui.tx_da_channels == 1)t1*=2;
1262 if(t1 > 0.75*ui.tx_da_speed)
1263   {
1264   t1=ui.tx_da_speed;
1265   if(ui.tx_da_channels == 1)t1/=2;
1266   t1/=txad_hz_per_bin;
1267   tx_highest_bin=tx_lowest_bin+t1;
1268   if(tx_highest_bin > micsize/2-2)tx_highest_bin=micsize/2-2;
1269   }
1270 mic_fftsize=micsize;
1271 mic_fftn=micn;
1272 k=1.2*(tx_highest_bin-tx_lowest_bin);
1273 // The microphone sampling speed may be low since we have no interest
1274 // in frequencies above 2.5 kHz or so.
1275 // An amplitude clipper on a complex-valued signal must however
1276 // be oversampled.
1277 // Oversampling by 16 will place most of the overtones generated by
1278 // the clipping process outside the passband. Without oversampling
1279 // all the overtones will alias into the passband and destroy the
1280 // clipping process.
1281 k*=16;
1282 while(k < mic_fftsize)
1283   {
1284   mic_fftsize/=2;
1285   mic_fftn--;
1286   }
1287 mic_sizhalf=mic_fftsize/2;
1288 micfft_block=2*mic_fftsize;
1289 micfft_bufsiz=32*mic_fftsize;
1290 micfft_indicator_block=micfft_bufsiz/INDICATOR_SIZE;
1291 micfft_mask=micfft_bufsiz-1;
1292 i=(tx_lowest_bin-tx_highest_bin)/2;
1293 if(i>-1)i=-1;
1294 tx_filter_ia1=mic_fftsize+i-1;
1295 tx_filter_ib1=tx_filter_ia1-2*i-mic_fftsize+1;
1296 
1297 k=mic_fftsize/tx_filter_ib1;
1298 alc_fftn=mic_fftn;
1299 alc_fftsize=mic_fftsize;
1300 tx_pre_resample=1;
1301 k++;
1302 while(k<8)
1303   {
1304   tx_pre_resample*=2;
1305   k*=2;
1306   alc_fftn++;
1307   alc_fftsize*=2;
1308   }
1309 // We allow data to stack up in the alc buffer when the resampler
1310 // runs too fast. Make a big buffer.
1311 alc_bufsiz=64*alc_fftsize;
1312 alc_mask=alc_bufsiz-1;
1313 alc_sizhalf=alc_fftsize/2;
1314 alc_block=2*alc_fftsize;
1315 tx_resample_ratio=(float)(2*ui.tx_da_speed)/ui.tx_ad_speed;
1316 tx_output_upsample=0.5;
1317 txout_fftsize=micsize;
1318 txout_fftn=micn;
1319 while(tx_resample_ratio > 1.5)
1320   {
1321   tx_resample_ratio/=2;
1322   tx_output_upsample*=2;
1323   txout_fftsize*=2;
1324   txout_fftn++;
1325   }
1326 
1327 snd[TXDA].framesize=ui.tx_da_bytes*ui.tx_da_channels;
1328 snd[TXDA].block_bytes=txout_fftsize*snd[TXDA].framesize/2;
1329 j=snd[TXDA].block_bytes;
1330 if(tx_setup_flag)
1331   {
1332   open_tx_sndout();
1333   }
1334 else
1335   {
1336   sys_func(THRFLAG_OPEN_TX_SNDOUT);
1337   }
1338 if(kill_all_flag)return;
1339 tx_ssb_resamp_block_factor=1;
1340 while(j < snd[TXDA].block_bytes)
1341   {
1342   j*=2;
1343   txout_fftsize*=2;
1344   tx_ssb_resamp_block_factor*=2;
1345   txout_fftn++;
1346   }
1347 while(j > snd[TXDA].block_bytes)
1348   {
1349   j/=2;
1350   txout_fftsize/=2;
1351   tx_ssb_resamp_block_factor/=2;
1352   txout_fftn--;
1353   }
1354 // Time for minimum delay data expressed as samples of txad.
1355 t1=1.5*mic_fftsize;  // Samples in mictimf and cliptimf.
1356 
1357 t1+=0.5*(1+SSB_DELAY_EXTRA)*alc_fftsize/tx_pre_resample;
1358 tx_ideal_delay=2/snd[TXDA].interrupt_rate+2*t1/ui.tx_ad_speed;
1359 //fprintf( dmp,"\nideal samps %f  del %f\n",t1, tx_ideal_delay);
1360 
1361 new_tx_resample_ratio=tx_resample_ratio;
1362 txout_sizhalf=txout_fftsize/2;
1363 init_memalloc(txmem, MAX_TXMEM_ARRAYS);
1364 if(ui.tx_ad_bytes == 2)
1365   {
1366   mem(1,&mictimf_shi,mictimf_bufsiz*sizeof(short int),0);
1367   }
1368 else
1369   {
1370   mem(1,&mictimf_int,mictimf_bufsiz*sizeof(int),0);
1371   }
1372 mem(2,&micfft,micfft_bufsiz*sizeof(float),0);
1373 mem(3,&cliptimf,micfft_bufsiz*sizeof(float),0);
1374 mem(4,&mic_tmp,2*micsize*sizeof(float),0);
1375 mem(5,&mic_table,micsize*sizeof(COSIN_TABLE),0);
1376 mem(6,&mic_permute,2*micsize*sizeof(short int),0);
1377 mem(7,&mic_win,(1+micsize)*sizeof(float),0);
1378 mem(8,&mic_filter,micsize*sizeof(float),0);
1379 mem(9,&micfft_table,micsize*sizeof(COSIN_TABLE)/2,0);
1380 mem(10,&micfft_permute,micsize*sizeof(short int),0);
1381 mem(11,&micfft_win,(1+mic_sizhalf)*sizeof(float),0);
1382 mem(12,&clipfft,alc_bufsiz*sizeof(float),0);
1383 mem(13,&alctimf,alc_bufsiz*sizeof(float),0);
1384 mem(14,&alctimf_pwrf,alc_bufsiz*sizeof(float)/2,0);
1385 mem(15,&alctimf_pwrd,alc_bufsiz*sizeof(float)/2,0);
1386 mem(16,&tx_resamp,2*txout_fftsize*sizeof(float),0);
1387 mem(17,&resamp_tmp,alc_fftsize*sizeof(float),0);
1388 mem(18,&alc_permute,alc_fftsize*sizeof(short int),0);
1389 mem(19,&alc_table,alc_sizhalf*sizeof(COSIN_TABLE),0);
1390 mem(20,&alc_win,(1+alc_sizhalf)*sizeof(float),0);
1391 mem(21,&txout,2*txout_fftsize*sizeof(float),0);
1392 mem(22,&txout_permute,txout_fftsize*sizeof(short int),0);
1393 mem(23,&txout_table,txout_sizhalf*sizeof(COSIN_TABLE),0);
1394 mem(24,&txout_tmp,txout_fftsize*sizeof(float),0);
1395 if(ui.tx_da_bytes==4)
1396   {
1397   mem(25,&tx_out_int,ui.tx_da_channels*txout_fftsize*sizeof(int)/2,0);
1398   }
1399 else
1400   {
1401   mem(25,&tx_out_shi,ui.tx_da_channels*txout_fftsize*sizeof(int)/2,0);
1402   }
1403 mem(26,&cliptimf_mute,micfft_bufsiz*sizeof(char)/mic_fftsize,0);
1404 mem(27,&clipfft_mute,alc_bufsiz*sizeof(char)/alc_block,0);
1405 mem(28,&alctimf_mute,alc_bufsiz*sizeof(char)/alc_fftsize,0);
1406 txmem_size=memalloc(&txmem_handle,"txmem");
1407 if(txmem_size == 0)
1408   {
1409   lirerr(1261);
1410   return;
1411   }
1412 make_permute(2, micn, micsize, mic_permute);
1413 make_window(2,micsize, 2, mic_win);
1414 if(ui.tx_ad_bytes != 2)
1415   {
1416   for(i=0; i<micsize; i++)mic_win[i]/=0x10000;
1417   }
1418 t1=1/(1.62*0x7fff*mic_sizhalf);
1419 for(i=0; i<micsize; i++)mic_win[i]*=t1;
1420 make_sincos(2, micsize, mic_table);
1421 init_fft(0,mic_fftn, mic_fftsize, micfft_table, micfft_permute);
1422 make_window(2,mic_sizhalf, 2, micfft_win);
1423 micfft_winfac=1.62*mic_fftsize;
1424 t1=1/micfft_winfac;
1425 for(i=0; i<mic_sizhalf; i++)
1426   {
1427   micfft_win[i]*=t1;
1428   }
1429 for(i=0; i<micfft_bufsiz; i++)
1430   {
1431   micfft[i]=0;
1432   cliptimf[i]=0;
1433   }
1434 init_fft(0,alc_fftn, alc_fftsize, alc_table, alc_permute);
1435 make_window(2,alc_sizhalf, 2, alc_win);
1436 t1=1/(1.62*alc_fftsize);
1437 for(i=0; i<alc_sizhalf; i++)
1438   {
1439   alc_win[i]*=t1;
1440   }
1441 for(i=0; i<alc_bufsiz; i++)
1442   {
1443   alctimf[i]=0;
1444   clipfft[i]=0;
1445   }
1446 for(i=0; i<alc_bufsiz/alc_block; i++)clipfft_mute[i]=0;
1447 for(i=0; i<alc_bufsiz/2; i++)alctimf_pwrf[i]=0;
1448 init_fft(0,txout_fftn, txout_fftsize, txout_table, txout_permute);
1449 for(i=0; i<2*txout_fftsize; i++)tx_resamp[i]=0;
1450 tx_filter_ia1=mic_fftsize+(tx_lowest_bin/2-tx_highest_bin/2-1);
1451 tx_filter_ia2=alc_fftsize+(tx_lowest_bin/2-tx_highest_bin/2-1);
1452 tx_filter_ia3=txout_fftsize+(tx_lowest_bin/2-tx_highest_bin/2-1);
1453 tx_filter_ib1=tx_filter_ia1+tx_highest_bin-tx_lowest_bin-mic_fftsize;
1454 tx_filter_ib2=tx_filter_ia2+tx_highest_bin-tx_lowest_bin-alc_fftsize;
1455 tx_filter_ib3=tx_filter_ia3+tx_highest_bin-tx_lowest_bin-txout_fftsize;
1456 tx_ssbproc_fqshift=(float)(tx_highest_bin-tx_filter_ib1)*txad_hz_per_bin;
1457 // Construct the microphone input filter from the
1458 // parameters supplied by the user.
1459 for(i=0; i<mic_fftsize; i++)mic_filter[i]=0;
1460 // Store the desired frequency response in dB.
1461 t1=0;
1462 for(i=tx_lowest_bin; i<=tx_highest_bin; i++)
1463   {
1464   mic_filter[i]=t1;
1465   t1+=0.001*txssb.slope*txad_hz_per_bin;
1466   }
1467 k=(tx_highest_bin-tx_lowest_bin)/4;
1468 t1=0;
1469 for(i=tx_lowest_bin+k; i>=tx_lowest_bin; i--)
1470   {
1471   t1+=0.001*txssb.bass*txad_hz_per_bin;
1472   mic_filter[i]+=t1;
1473   }
1474 t1=0;
1475 for(i=tx_highest_bin-k; i<=tx_highest_bin; i++)
1476   {
1477   t1+=0.001*txssb.treble*txad_hz_per_bin;
1478   mic_filter[i]+=t1;
1479   }
1480 // Convert from dB to linear scale (amplitude) and normalize
1481 // the filter curve.
1482 t1=0;
1483 for(i=tx_lowest_bin; i<=tx_highest_bin; i++)
1484   {
1485   mic_filter[i]=pow(10.,0.05*mic_filter[i]);
1486   t1+=mic_filter[i]*mic_filter[i];
1487   }
1488 t1=1/sqrt(t1/(tx_highest_bin-tx_lowest_bin+1));
1489 for(i=tx_lowest_bin; i<=tx_highest_bin; i++)
1490   {
1491   mic_filter[i]*=t1;
1492   }
1493 mic_filter[tx_lowest_bin]*=0.5;
1494 mic_filter[tx_highest_bin]*=0.5;
1495 micfft_bin_minpower_ref=pow(10.,0.1*(txssb.mic_f_threshold-100));
1496 micfft_minpower_ref=pow(10.,0.1*(txssb.mic_t_threshold+txssb.mic_f_threshold-90));
1497 tx_agc_factor=1;
1498 tx_agc_decay=pow(2.718,-100.0/(txssb.mic_agc_time*txad_hz_per_bin));
1499 txpwr_decay=pow(2.718,-1/(ui.tx_ad_speed*0.025));
1500 tx_forwardpwr=0;
1501 tx_backpwr=0;
1502 tx_ph1=1;
1503 tx_wrblock_no=0;
1504 tx_wttim_ref=0;
1505 tx_wttim_sum=0;
1506 tx_wttim_diff=0;
1507 memcheck(1,txmem,&txmem_handle);
1508 make_tx_modes();
1509 make_tx_phstep();
1510 tx_resamp_ampfac1=1;
1511 tx_resamp_ampfac2=1;
1512 micfft_pa=0;
1513 micfft_px=0;
1514 mictimf_pa=0;
1515 mictimf_px=0;
1516 cliptimf_pa=0;
1517 cliptimf_px=0;
1518 clipfft_pa=0;
1519 clipfft_px=0;
1520 alctimf_pa=SSB_DELAY_EXTRA*alc_fftsize;
1521 alctimf_pa=0;//öö
1522 alctimf_pb=0;
1523 alctimf_fx=0;
1524 tx_output_flag=0;
1525 }
1526 
tx_input(void)1527 void tx_input(void)
1528 {
1529 int i, ia, ib, pa, pb, pc;
1530 int k;
1531 int twosiz, ssb_bufmin;
1532 float *z;
1533 float t1;
1534 twosiz=2*micsize;
1535 ssb_bufmin=twosiz*ui.tx_ad_channels;
1536 pb=mictimf_px;
1537 thread_status_flag[THREAD_TX_INPUT]=THRFLAG_ACTIVE;
1538 while(!kill_all_flag &&
1539                     thread_command_flag[THREAD_TX_INPUT] == THRFLAG_ACTIVE)
1540   {
1541   if(ui.tx_ad_bytes == 2)
1542     {
1543     lir_tx_adread((char*)&mictimf_shi[mictimf_pa]);
1544     }
1545   else
1546     {
1547     lir_tx_adread((char*)&mictimf_int[mictimf_pa]);
1548     }
1549   mictimf_pa=(mictimf_pa+mictimf_block)&mictimf_mask;
1550   switch (rx_mode)
1551     {
1552     case MODE_SSB:
1553     if( ((mictimf_pa-mictimf_px+mictimf_bufsiz)&mictimf_mask) >= ssb_bufmin)
1554       {
1555 // Copy the input to micfft while multiplying with the window function.
1556       ib=twosiz-1;
1557       pa=mictimf_px;
1558       switch(tx_input_mode)
1559         {
1560         case 0:
1561 // One channel, two bytes.
1562         pb=(pa+ib)&mictimf_mask;
1563         for( ia=0; ia<micsize; ia++)
1564           {
1565           mic_tmp[mic_permute[ia]]=(float)(mictimf_shi[pa])*mic_win[ia];
1566           if(abs(mictimf_shi[pa]) > tx_ad_maxamp)
1567             {
1568             tx_ad_maxamp=abs(mictimf_shi[pa]);
1569             }
1570           mic_tmp[mic_permute[ib]]=(float)(mictimf_shi[pb])*mic_win[ia];
1571           if(abs(mictimf_shi[pb]) > tx_ad_maxamp)
1572             {
1573             tx_ad_maxamp=abs(mictimf_shi[pb]);
1574             }
1575           ib--;
1576           pa=(pa+1)&mictimf_mask;
1577           pb=(pb+mictimf_mask)&mictimf_mask;
1578           }
1579         break;
1580 
1581         case 1:
1582 // In case there are two channels for the microphone, just use one of them!!
1583         pb=(pa+2*ib)&mictimf_mask;
1584         for( ia=0; ia<micsize; ia++)
1585           {
1586           mic_tmp[mic_permute[ia]]=mictimf_shi[pa]*mic_win[ia];
1587           if(abs(mictimf_shi[pa]) > tx_ad_maxamp)
1588             {
1589             tx_ad_maxamp=abs(mictimf_shi[pa]);
1590             }
1591           mic_tmp[mic_permute[ib]]=mictimf_shi[pb]*mic_win[ia];
1592           if(abs(mictimf_shi[pb]) > tx_ad_maxamp)
1593             {
1594             tx_ad_maxamp=abs(mictimf_shi[pb]);
1595             }
1596           ib--;
1597           pa=(pa+2)&mictimf_mask;
1598           pb=(pb+mictimf_mask-1)&mictimf_mask;
1599           }
1600         break;
1601 
1602         case 2:
1603         pb=(pa+ib)&mictimf_mask;
1604         for( ia=0; ia<micsize; ia++)
1605           {
1606           mic_tmp[mic_permute[ia]]=mictimf_int[pa]*mic_win[ia];
1607           if(abs(mictimf_int[pa]) > tx_ad_maxamp)
1608             {
1609             tx_ad_maxamp=abs(mictimf_int[pa]);
1610             }
1611           mic_tmp[mic_permute[ib]]=mictimf_int[pb]*mic_win[ia];
1612           if(abs(mictimf_int[pb]) > tx_ad_maxamp)
1613             {
1614             tx_ad_maxamp=abs(mictimf_int[pb]);
1615             }
1616           ib--;
1617           pa=(pa+1)&mictimf_mask;
1618           pb=(pb+mictimf_mask)&mictimf_mask;
1619           }
1620         break;
1621 
1622         case 3:
1623 // In case there are two channels for the microphone, just use one of them!!
1624         pb=(pa+2*ib)&mictimf_mask;
1625         for( ia=0; ia<micsize; ia++)
1626           {
1627           mic_tmp[mic_permute[ia]]=mictimf_int[pa]*mic_win[ia];
1628           if(abs(mictimf_int[pa]) > tx_ad_maxamp)
1629             {
1630             tx_ad_maxamp=abs(mictimf_int[pa]);
1631             }
1632           mic_tmp[mic_permute[ib]]=mictimf_int[pb]*mic_win[ia];
1633           if(abs(mictimf_int[pb]) > tx_ad_maxamp)
1634             {
1635             tx_ad_maxamp=abs(mictimf_int[pb]);
1636             }
1637           ib--;
1638           pa=(pa+2)&mictimf_mask;
1639           pb=(pb+mictimf_mask-1)&mictimf_mask;
1640           }
1641         }
1642 // The microphone signal should be maximum 0x7fff or 0x7fffffffffff
1643 // depending on whether 16 or 32 bit format is selected.
1644       mictimf_px=(mictimf_px+mictimf_block)&mictimf_mask;
1645       fft_real_to_hermitian( mic_tmp, twosiz, micn, mic_table);
1646 // Output is {Re(z^[0]),...,Re(z^[n/2),Im(z^[n/2-1]),...,Im(z^[1]).
1647 // Clear those parts of the spectrum that we do not want and
1648 // transfer the rest of the points to micfft while multiplying
1649 // with our filter function.
1650 // Place the spectrum center at frequency zero so we can use
1651 // the lowest possible sampling rate in further processing steps.
1652       z=&micfft[micfft_pa];
1653       pc=2*(tx_highest_bin/2-tx_lowest_bin/2);
1654       k=micfft_block-pc-2;
1655       while(pc < k)
1656         {
1657         z[pc  ]=0;
1658         z[pc+1]=0;
1659         pc+=2;
1660         }
1661       k=tx_lowest_bin;
1662       pc=2*tx_filter_ia1;
1663       while(pc < 2*mic_fftsize)
1664         {
1665         z[pc+1]=mic_tmp[k  ]*mic_filter[k];
1666         z[pc  ]=mic_tmp[twosiz-k]*mic_filter[k];
1667         pc+=2;
1668         k++;
1669         }
1670       pc=0;
1671       while(k <= tx_highest_bin)
1672         {
1673         z[pc+1]=mic_tmp[k  ]*mic_filter[k];
1674         z[pc  ]=mic_tmp[twosiz-k]*mic_filter[k];
1675         pc+=2;
1676         k++;
1677         }
1678       micfft_pa=(micfft_pa+micfft_block)&micfft_mask;
1679       }
1680     break;
1681 
1682     case MODE_WCW:
1683     case MODE_NCW:
1684     case MODE_HSMS:
1685     case MODE_QRSS:
1686     switch(tx_input_mode)
1687       {
1688       case 0:
1689       while(mictimf_px != mictimf_pa)
1690         {
1691         t1=0;
1692         for(i=0; i<tx_pre_resample; i++)
1693           {
1694           t1+=abs(mictimf_shi[mictimf_px]-mictimf_shi[pb]);
1695           pb=mictimf_px;
1696           mictimf_px++;
1697           }
1698         mictimf_px=mictimf_px&mictimf_mask;
1699         tx_mic_key[mic_key_pa]=t1/(tx_pre_resample*1000);
1700         mic_key_pa=(mic_key_pa+1)&mic_key_mask;
1701         }
1702       break;
1703 
1704       case 1:
1705 // In case there are two channels for the microphone, just use one of them!!
1706       while(mictimf_pa != mictimf_px)
1707         {
1708         t1=0;
1709         for(i=0; i<tx_pre_resample; i++)
1710           {
1711           t1+=abs(mictimf_shi[mictimf_px]-mictimf_shi[pb]);
1712           pb=mictimf_px;
1713           mictimf_px+=2;
1714           }
1715         mictimf_px=mictimf_px&mictimf_mask;
1716         tx_mic_key[mic_key_pa]=t1/(tx_pre_resample*1000);
1717         mic_key_pa=(mic_key_pa+1)&mic_key_mask;
1718         }
1719       break;
1720 
1721       case 2:
1722       while(mictimf_pa != mictimf_px)
1723         {
1724         t1=0;
1725         for(i=0; i<tx_pre_resample; i++)
1726           {
1727           t1+=abs(mictimf_int[mictimf_px]-mictimf_int[pb]);
1728           pb=mictimf_px;
1729           mictimf_px++;
1730           }
1731         mictimf_px=mictimf_px&mictimf_mask;
1732         tx_mic_key[mic_key_pa]=(t1/tx_pre_resample)/(0x7fff*1000);
1733         mic_key_pa=(mic_key_pa+1)&mic_key_mask;
1734         }
1735       break;
1736 
1737       case 3:
1738       while(mictimf_pa != mictimf_px)
1739         {
1740         t1=0;
1741         for(i=0; i<tx_pre_resample; i++)
1742           {
1743           t1+=abs(mictimf_int[mictimf_px]-mictimf_int[pb]);
1744           pb=mictimf_px;
1745           mictimf_px+=2;
1746           }
1747         mictimf_px=mictimf_px&mictimf_mask;
1748         tx_mic_key[mic_key_pa]=t1/(tx_pre_resample*1000);
1749         mic_key_pa=(mic_key_pa+1)&mic_key_mask;
1750         }
1751       break;
1752       }
1753     break;
1754 
1755     case MODE_RADAR:
1756     while(mictimf_px != mictimf_pa)
1757       {
1758       mictimf_px=(mictimf_px+tx_pre_resample)&mictimf_mask;
1759       if(radar_cnt < radar_pulse_cnt)
1760         {
1761         i=10;
1762         }
1763       else
1764         {
1765         i=0;
1766         }
1767       radar_cnt++;
1768       if(radar_cnt >= radar_cnt_max)radar_cnt=0;
1769       tx_mic_key[mic_key_pa]=i;
1770       mic_key_pa=(mic_key_pa+1)&mic_key_mask;
1771       }
1772     break;
1773     }
1774   lir_set_event(EVENT_TX_INPUT);
1775   }
1776 thread_status_flag[THREAD_TX_INPUT]=THRFLAG_RETURNED;
1777 lir_set_event(EVENT_TX_INPUT);
1778 while(thread_command_flag[THREAD_TX_INPUT] != THRFLAG_NOT_ACTIVE)
1779   {
1780   lir_sleep(1000);
1781   }
1782 }
1783 
make_tx_modes(void)1784 void make_tx_modes(void)
1785 {
1786 if(ui.tx_ad_bytes == 2)
1787   {
1788   if(ui.tx_ad_channels==1)
1789     {
1790     tx_input_mode=0;
1791     }
1792   else
1793     {
1794     tx_input_mode=1;
1795     }
1796   }
1797 else
1798   {
1799   if(ui.tx_ad_channels==1)
1800     {
1801     tx_input_mode=2;
1802     }
1803   else
1804     {
1805     tx_input_mode=3;
1806     }
1807   }
1808 if(ui.tx_da_bytes == 2)
1809   {
1810   if(ui.tx_da_channels==1)
1811     {
1812     tx_output_mode=0;
1813     }
1814   else
1815     {
1816     tx_output_mode=1;
1817     }
1818   }
1819 else
1820   {
1821   if(ui.tx_da_channels==1)
1822     {
1823     tx_output_mode=2;
1824     }
1825   else
1826     {
1827     tx_output_mode=3;
1828     }
1829   }
1830 }
1831 
make_tx_cw_waveform(void)1832 void make_tx_cw_waveform(void)
1833 {
1834 int i, n1, n2;
1835 double dt1, dt2;
1836 // Use the (complementary) error function erfc(x) to get the optimum
1837 // shape for the rise time.
1838 // Start at erfc(-3.3) and go to erfc(3.3). In this interval the function
1839 // goes from  1.9999969423 to 0.0000030577 and jumping abruptly to 0 or
1840 // 2.0 respectively corresponds to an abrupt keying of another signal
1841 // that is 117 dB below the main signal.
1842 n1=ui.tx_da_speed*(0.000001*ui.tx_pilot_tone_prestart);
1843 n2=ui.tx_da_speed*(0.000001*txcw.rise_time);
1844 n2&=-2;
1845 tx_cw_waveform_points=n1+n2-1;
1846 if(tx_cw_waveform_points >= max_tx_cw_waveform_points)
1847   {
1848   lirerr(1076);
1849   return;
1850   }
1851 // Set a very small (non-zero) amplitude for use by the pilot tone
1852 // so it will start the desired time before the actual output
1853 // signal will start to follow the erfc function.
1854 for(i=1; i<=n1; i++) txout_waveform[i]=0.5*PILOT_TONE_CONTROL;
1855 dt1=3.3;
1856 dt2=6.6/(n2-3);
1857 for(i=n1+1; i<=tx_cw_waveform_points; i++)
1858   {
1859   txout_waveform[i]=erfc(dt1)/2;
1860   dt1-=dt2;
1861   }
1862 txout_waveform[0]=0;
1863 old_cw_rise_time=txcw.rise_time;
1864 radar_cnt_max=0.001*txcw.radar_interval*ui.tx_ad_speed/tx_pre_resample;
1865 radar_pulse_cnt=0.001*txcw.radar_pulse*ui.tx_ad_speed/tx_pre_resample;
1866 radar_cnt=radar_cnt_max-radar_pulse_cnt;
1867 }
1868 
tx_setup(void)1869 int tx_setup(void)
1870 {
1871 int return_flag;
1872 return_flag=FALSE;
1873 if(read_txpar_file() == FALSE)set_default_spproc_parms();
1874 snd[RXAD].framesize=2*ui.rx_ad_channels;
1875 if( (ui.rx_input_mode&DWORD_INPUT) != 0) snd[RXAD].framesize*=2;
1876 snd[RXAD].block_frames=ui.rx_ad_speed/1000;
1877 if(snd[RXAD].block_frames < 4)snd[RXAD].block_frames=4;
1878 make_power_of_two((int*)&snd[RXAD].block_frames);
1879 snd[RXAD].block_bytes=2*ui.rx_ad_channels*snd[RXAD].block_frames;
1880 if( (ui.rx_input_mode&DWORD_INPUT) != 0)snd[RXAD].block_bytes*=2;
1881 genparm[DA_OUTPUT_SPEED]=ui.rx_min_da_speed;
1882 if(genparm[DA_OUTPUT_SPEED] < 8000)genparm[DA_OUTPUT_SPEED]=8000;
1883 rx_daout_bytes=ui.rx_max_da_bytes;
1884 rx_daout_channels=ui.rx_max_da_channels;
1885 snd[RXDA].framesize=rx_daout_bytes*rx_daout_channels;
1886 snd[TXDA].framesize=ui.tx_da_bytes*ui.tx_da_channels;
1887 snd[TXDA].block_bytes=(snd[TXDA].framesize*ui.tx_da_speed)/1000;
1888 if(check_tx_devices() == FALSE)goto do_tx_setup;
1889 // *******************************************************
1890 // ***   The A/D and D/A setup for Rx is already done.
1891 // ***   Ask the user what he wants.
1892 // ***   The transmit functions of Linrad are in a very early stage
1893 // ***   and there is not much to choose from yet............
1894 // ******************************************************
1895 repeat_menu:;
1896 if(kill_all_flag) goto txend;
1897 clear_screen();
1898 if(check_tx_devices() == FALSE)goto do_tx_setup;
1899 lir_text(5,6,"B=Soundcard setup for Tx.");
1900 lir_text(5,7,"C=Speech processor setup.");
1901 lir_text(5,8,"D=CW setup.");
1902 lir_text(5,9,"E=Send disk file to Tx output");
1903 lir_text(5,10,"X=Return to main menu");
1904 await_processed_keyboard();
1905 if(kill_all_flag) goto txend;
1906 switch (lir_inkey)
1907   {
1908   case 'B':
1909 do_tx_setup:;
1910   set_tx_io();
1911   return_flag=check_tx_devices();
1912   goto txend;
1913 
1914   case 'C':
1915   open_rx_sndin(FALSE);
1916   open_rx_sndout();
1917   spproc_setup();
1918   close_rx_sndout();
1919   close_rx_sndin();
1920   break;
1921 
1922   case 'D':
1923   open_rx_sndin(FALSE);
1924   open_rx_sndout();
1925   cwproc_setup();
1926   close_rx_sndout();
1927   close_rx_sndin();
1928   break;
1929 
1930   case 'E':
1931   disk2tx();
1932   break;
1933 
1934   case 'X':
1935 txend:;
1936   lir_inkey=0;
1937   return return_flag;
1938   }
1939 goto repeat_menu;
1940 }
1941 
1942