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