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 <ctype.h>
25 #include <unistd.h>
26 #include <string.h>
27 
28 
29 
30 #include "globdef.h"
31 #if(OSNUM == OSNUM_WINDOWS)
32 #include <winsock.h>
33 #define INVSOCK INVALID_SOCKET
34 #endif
35 
36 #if(OSNUM == OSNUM_LINUX)
37 #define INVSOCK -1
38 #include "lconf.h"
39 #if (ALSA_PRESENT == 1)
40 #include <alsa/asoundlib.h>
41 int alsa_get_native_samplerate(int n,int mode,int *line,unsigned int *new_sampling_rate);
42 #endif
43 #endif
44 
45 
46 
47 #include "uidef.h"
48 #include "fft1def.h"
49 #include "fft2def.h"
50 #include "screendef.h"
51 #include "powtdef.h"
52 #include "vernr.h"
53 #include "sigdef.h"
54 #include "seldef.h"
55 #include "rusage.h"
56 #include "thrdef.h"
57 #include "sdrdef.h"
58 #include "caldef.h"
59 #include "conf.h"
60 #include "keyboard_def.h"
61 #include "txdef.h"
62 #include "options.h"
63 #include "hwaredef.h"
64 #include "fft3def.h"
65 #include "padef.h"
66 
67 extern int tune_bytes;
68 #if (USERS_EXTRA_PRESENT == 1)
69 extern void init_users_extra(void);
70 #endif
71 
72 char *parfilnam;
73 int uiparm_save[MAX_UIPARM];
74 int dirflag, iqflag;
75 void lir_fix_bug(int bug);
76 int first_txproc_no;
77 
enable_extio(void)78 void enable_extio(void)
79 {
80 if(diskread_flag == 0 && ui.use_extio != 0)
81   {
82   command_extio_library(EXTIO_COMMAND_LOAD_DLL);
83   first_check_extio();
84   if(ui.use_extio == 0)
85     {
86     lir_status=LIR_SAVE_UIPARM;
87     return;
88     }
89   if(extio_handle==NULL)
90     {
91     lirerr(42977);
92     return;
93     }
94   extio_show_gui=TRUE;
95   command_extio_library(EXTIO_COMMAND_START);
96   }
97 }
98 
disable_extio(void)99 void disable_extio(void)
100 {
101 if(extio_running)command_extio_library(EXTIO_COMMAND_STOP);
102 if(extio_handle != NULL)
103   {
104   clear_screen();
105   lir_text(3,3,"UNLOADING ExtIO LIBRARY");
106   lir_refresh_screen();
107   lir_sleep(100000);
108   command_extio_library(EXTIO_COMMAND_UNLOAD_DLL);
109   }
110 }
111 
radar_routine(void)112 void radar_routine(void)
113 {
114 char s[80];
115 float t1;
116 int i, k, m;
117 use_bfo=1;
118 usercontrol_mode=USR_NORMAL_RX;
119 if(read_txpar_file()==FALSE)use_tx=0;
120 get_wideband_sizes();
121 if(kill_all_flag)return;
122 get_buffers(1);
123 if(kill_all_flag || lir_status != LIR_OK)return;
124 if(!freq_from_file)
125   {
126   read_freq_control_data();
127   }
128 check_filtercorr_direction();
129 init_semaphores();
130 init_wide_graph();
131 if( genparm[SECOND_FFT_ENABLE] != 0 )init_blanker();
132 if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
133 if(genparm[SECOND_FFT_ENABLE] != 0)
134   {
135   init_hires_graph();
136   if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
137   }
138 if(genparm[AFC_ENABLE] != 0)
139   {
140   init_afc_graph();
141   if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
142   }
143 if(ui.rx_rf_channels == 2)
144   {
145   init_pol_graph();
146   if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
147   }
148 init_radar_graph();
149 if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
150 if(!freq_from_file)
151   {
152   init_freq_control();
153   if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
154   }
155 if(use_tx != 0)
156   {
157 // Get the xxproc file that the user stored in tg.spproc_no
158   init_tx_graph();
159   if(read_txpar_file()==FALSE)
160     {
161 // If it failed, read the one that was succesful before.
162     tg.spproc_no=first_txproc_no;
163     read_txpar_file();
164     }
165   }
166 // Make sure users_init_mode is the last window(s) we open.
167 // the avoid collission routine does not know where
168 // users windows are placed.
169 if(ui.soundcard_radio == SOUNDCARD_RADIO_ELEKTOR &&
170        diskread_flag == 0)
171   {
172   if(init_elektor_control_window() != EXIT_SUCCESS)ui.soundcard_radio=0;
173   }
174 #if LIBUDEV_PRESENT == 1
175 if(ui.soundcard_radio == SOUNDCARD_RADIO_FCDPROPLUS &&
176        diskread_flag == 0)
177   {
178   init_fcdproplus_control_window();
179   }
180 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
181        diskread_flag == 0)
182   {
183   open_afedriusb_control();
184   }
185 #endif
186 users_init_mode();
187 if(kill_all_flag || lir_status != LIR_OK) goto radar_x;
188 show_name_and_size();
189 linrad_thread_create(rx_input_thread);
190 lir_sleep(100000);
191 if(lir_status != LIR_OK)
192   {
193   lir_join(rx_input_thread);
194   goto radar_x;
195   }
196 if(kill_all_flag) goto radar_x;
197 linrad_thread_create(THREAD_USER_COMMAND);
198 if(kill_all_flag) goto radar_x;
199 linrad_thread_create(THREAD_RADAR);
200 if(kill_all_flag) goto radar_x;
201 linrad_thread_create(THREAD_WIDEBAND_DSP);
202 if(kill_all_flag) goto radar_x;
203 linrad_thread_create(THREAD_SCREEN);
204 if(kill_all_flag) goto radar_x;
205 if((ui.network_flag&NET_RX_OUTPUT)!=0)
206   {
207   linrad_thread_create(THREAD_LIR_SERVER);
208   if(kill_all_flag) goto radar_x;
209   }
210 if(use_tx != 0 )
211   {
212   init_txmem_cwproc();
213   if(kill_all_flag)goto radar_x;
214   linrad_thread_create(THREAD_TX_INPUT);
215   if(kill_all_flag) goto radar_x;
216   linrad_thread_create(THREAD_TX_OUTPUT);
217   if(kill_all_flag) goto radar_x;
218   }
219 fft1_waterfall_flag=1;
220 lir_refresh_screen();
221 all_threads_started=TRUE;
222 lir_sleep(50000);
223 rxin_block_counter=0;
224 i=0;
225 k=0;
226 t1=50000+2000000./snd[RXAD].interrupt_rate;
227 if(diskread_flag < 2)
228   {
229   while(!kill_all_flag &&
230                     thread_status_flag[THREAD_USER_COMMAND]==THRFLAG_ACTIVE)
231     {
232     m=30;
233     while(!kill_all_flag && m>0 && rxin_block_counter == i)
234       {
235       m--;
236       lir_sleep(t1);
237       }
238    if(rxin_block_counter == i && i!=0)
239       {
240       sprintf(s,"No input %d",k);
241       lir_text(0,screen_last_line,s);
242       lir_refresh_screen();
243       }
244     k++;
245     if(k==10000)k=1;
246     i=rxin_block_counter;
247     }
248   m=30;
249   while(!kill_all_flag && m>0 && rxin_block_counter == i)
250     {
251     m--;
252     lir_sleep(t1);
253     }
254   if(rxin_block_counter == i && i!=0)
255     {
256     sprintf(s,"No input %d",k);
257     lir_text(0,screen_last_line,s);
258     lir_refresh_screen();
259     lirerr(1284);
260     }
261   }
262 lir_join(THREAD_USER_COMMAND);
263 if(use_tx != 0)
264   {
265   linrad_thread_stop_and_join(THREAD_TX_INPUT);
266   linrad_thread_stop_and_join(THREAD_TX_OUTPUT);
267   close_tx_sndin();
268   close_tx_sndout();
269   if(txmem_handle != NULL)free(txmem_handle);
270   txmem_handle=NULL;
271   lir_close_event(EVENT_TX_INPUT);
272   }
273 linrad_thread_stop_and_join(rx_input_thread);
274 linrad_thread_stop_and_join(THREAD_SCREEN);
275 linrad_thread_stop_and_join(THREAD_RADAR);
276 if((ui.network_flag&NET_RX_OUTPUT)!=0)
277   {
278   linrad_thread_stop_and_join(THREAD_LIR_SERVER);
279   }
280 linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
281 radar_x:;
282 #if LIBUDEV_PRESENT == 1
283 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
284        diskread_flag == 0)
285   {
286   close_afedriusb_control();
287   }
288 #endif
289 free_semaphores();
290 }
291 
tune_wse_routine(void)292 void tune_wse_routine(void)
293 {
294 usercontrol_mode=USR_TUNE;
295 genparm[SECOND_FFT_ENABLE]=0;
296 get_wideband_sizes();
297 if(kill_all_flag)return;
298 clear_screen();
299 if(     (ui.rx_input_mode&IQ_DATA) == 0 ||
300               (ui.rx_rf_channels == 1) ||
301                  ui.rx_ad_speed != 96000)
302   {
303   settextcolor(14);
304   lir_text(10,10,"Incorrect soundcard settings");
305   lir_text(5,12,"Set ""Two Rx channels I/Q data"", 96 kHz and 32 bit.");
306   settextcolor(7);
307   lir_text(13,14,press_any_key);
308   await_processed_keyboard();
309   lir_status=LIR_TUNEERR;
310   return;
311    }
312 get_buffers(1);
313 if(kill_all_flag || lir_status != LIR_OK)return;
314 // Collect data during TUNETIME seconds.
315 #define TUNETIME 0.1
316 tune_bytes=96000*TUNETIME;
317 if(tune_bytes < 2*fft1_size)tune_bytes=2*fft1_size;
318 tune_bytes*=snd[RXAD].framesize;
319 tune_bytes/=timf1_blockbytes;
320 tune_bytes++;
321 tune_bytes*=timf1_blockbytes;
322 if(tune_bytes < 2*fft1_size*(int)snd[RXAD].framesize)
323   {
324   lir_text(5,5,"Set fft1 bandwidth higher.");
325   lir_text(5,7,press_any_key);
326   await_processed_keyboard();
327   return;
328   }
329 if(fft1_desired[0] > .99 || bal_updflag == 1)
330   {
331   settextcolor(14);
332   lir_text(3,10,"Calibrate the RX2500 (Read z_CALIBRATE.txt)");
333   settextcolor(7);
334   lir_text(5,13,press_any_key);
335   await_processed_keyboard();
336   return;
337   }
338 lir_inkey=0;
339 init_semaphores();
340 linrad_thread_create(rx_input_thread);
341 lir_sleep(100000);
342 if(lir_status != LIR_OK)
343   {
344   lir_join(rx_input_thread);
345   goto tune_x;
346   }
347 if(kill_all_flag) goto tune_x;
348 linrad_thread_create(THREAD_TUNE);
349 if(kill_all_flag) goto tune_x;
350 linrad_thread_create(THREAD_USER_COMMAND);
351 lir_sleep(50000);
352 lir_refresh_screen();
353 all_threads_started=TRUE;
354 lir_join(THREAD_USER_COMMAND);
355 linrad_thread_stop_and_join(rx_input_thread);
356 linrad_thread_stop_and_join(THREAD_TUNE);
357 tune_x:;
358 free_semaphores();
359 }
360 
361 
rx_adtest_routine(void)362 void rx_adtest_routine(void)
363 {
364 usercontrol_mode=USR_ADTEST;
365 genparm[SECOND_FFT_ENABLE]=0;
366 get_wideband_sizes();
367 if(kill_all_flag)return;
368 get_buffers(1);
369 if(kill_all_flag || lir_status != LIR_OK)return;
370 init_semaphores();
371 linrad_thread_create(rx_input_thread);
372 lir_sleep(100000);
373 if(lir_status != LIR_OK)
374   {
375   lir_join(rx_input_thread);
376   goto adtest_x;
377   }
378 if(kill_all_flag) goto adtest_x;
379 linrad_thread_create(THREAD_USER_COMMAND);
380 if(kill_all_flag) goto adtest_x;
381 linrad_thread_create(THREAD_RX_ADTEST);
382 lir_sleep(50000);
383 lir_refresh_screen();
384 all_threads_started=TRUE;
385 lir_join(THREAD_USER_COMMAND);
386 linrad_thread_stop_and_join(rx_input_thread);
387 linrad_thread_stop_and_join(THREAD_RX_ADTEST);
388 adtest_x:;
389 free_semaphores();
390 }
391 
txtest_routine(void)392 void txtest_routine(void)
393 {
394 int i;
395 usercontrol_mode=USR_TXTEST;
396 if(ui.network_flag != 0 || diskread_flag != 0)
397   {
398   lirerr(1158);
399   return;
400    }
401 if(  (ui.rx_input_mode&IQ_DATA) != 0)
402   {
403   ui.rx_ad_channels=2;
404   }
405 else
406   {
407   ui.rx_ad_channels=1;
408   }
409 ui.rx_input_mode&=-1-TWO_CHANNELS;
410 ui.rx_rf_channels=1;
411 genparm[AFC_ENABLE]=0;
412 genparm[SECOND_FFT_ENABLE]=0;
413 get_wideband_sizes();
414 if(kill_all_flag) return;
415 // Open the graph windows on the screen.
416 // Note that they must be opened in this order because
417 // Each window is placed outside the previous ones and the init
418 // routines assumes the order below and does not check for all possible
419 // conflicts.
420 get_buffers(1);
421 if(kill_all_flag)return;
422 if(lir_status != LIR_OK)return;
423 read_freq_control_data();
424 init_semaphores();
425 init_wide_graph();
426 if(kill_all_flag) goto txtest_x;
427 for(i=0; i<txtest_no_of_segs*wg.spek_avgnum; i++)txtest_power[i]=0;
428 if(lir_status != LIR_OK)goto txtest_x;
429 init_freq_control();
430 // Make sure users_init_mode is the last window(s) we open.
431 // the avoid collission routine does not know where
432 // users windows are placed.
433 if(ui.soundcard_radio == SOUNDCARD_RADIO_ELEKTOR  &&
434        diskread_flag == 0)
435   {
436   if(init_elektor_control_window() != EXIT_SUCCESS)ui.soundcard_radio=0;
437   }
438 #if LIBUDEV_PRESENT == 1
439 if(ui.soundcard_radio == SOUNDCARD_RADIO_FCDPROPLUS  &&
440        diskread_flag == 0)
441   {
442   init_fcdproplus_control_window();
443   }
444 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
445        diskread_flag == 0)
446   {
447   open_afedriusb_control();
448   }
449 #endif
450 users_init_mode();
451 show_name_and_size();
452 settextcolor(7);
453 new_baseb_flag=-1;
454 ampinfo_flag=1;
455 linrad_thread_create(rx_input_thread);
456 lir_sleep(100000);
457 if(lir_status != LIR_OK)
458   {
459   lir_join(rx_input_thread);
460   goto txtest_x;
461   }
462 if(kill_all_flag) goto txtest_x;
463 linrad_thread_create(THREAD_USER_COMMAND);
464 if(kill_all_flag) goto txtest_x;
465 linrad_thread_create(THREAD_TXTEST);
466 if(kill_all_flag) goto txtest_x;
467 linrad_thread_create(THREAD_WIDEBAND_DSP);
468 if(kill_all_flag) goto txtest_x;
469 linrad_thread_create(THREAD_SCREEN);
470 fft1_waterfall_flag=1;
471 lir_refresh_screen();
472 all_threads_started=TRUE;
473 lir_join(THREAD_USER_COMMAND);
474 linrad_thread_stop_and_join(rx_input_thread);
475 linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
476 linrad_thread_stop_and_join(THREAD_TXTEST);
477 linrad_thread_stop_and_join(THREAD_SCREEN);
478 free_semaphores();
479 if(kill_all_flag)return;
480 if(lir_status == LIR_POWTIM)
481   {
482   usercontrol_mode=USR_POWTIM;
483   free_buffers();
484   if(kill_all_flag)return;
485   clear_screen();
486   genparm[SECOND_FFT_ENABLE]=1;
487   genparm[FIRST_BCKFFT_VERNR]=0;
488   genparm[SECOND_FFT_VERNR]=0;
489   genparm[FIRST_FFT_SINPOW] = 2;
490   genparm[SECOND_FFT_SINPOW] = 2;
491   genparm[AFC_ENABLE]=0;
492   get_wideband_sizes();
493   if(kill_all_flag)return;
494   get_buffers(1);
495   if(kill_all_flag)return;
496   set_fft1_endpoints();
497   if(kill_all_flag)return;
498   if(lir_status != LIR_POWTIM)return;
499   genparm[SECOND_FFT_ENABLE]=0;
500   fft1_waterfall_flag=0;
501   init_semaphores();
502   linrad_thread_create(rx_input_thread);
503   lir_sleep(100000);
504   if(lir_status != LIR_OK)
505     {
506     lir_join(rx_input_thread);
507     goto txtest_x;
508     }
509   if(kill_all_flag) goto txtest_x;
510   linrad_thread_create(THREAD_USER_COMMAND);
511   if(kill_all_flag) goto txtest_x;
512   linrad_thread_create(THREAD_POWTIM);
513   if(kill_all_flag) goto txtest_x;
514   linrad_thread_create(THREAD_WIDEBAND_DSP);
515   lir_sleep(50000);
516   fft1_waterfall_flag=0;
517   lir_refresh_screen();
518   all_threads_started=TRUE;
519   lir_join(THREAD_USER_COMMAND);
520   linrad_thread_stop_and_join(THREAD_POWTIM);
521   linrad_thread_stop_and_join(rx_input_thread);
522   linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
523   clear_keyboard();
524   }
525 else
526   {
527   return;
528   }
529 txtest_x:;
530 #if LIBUDEV_PRESENT == 1
531 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
532        diskread_flag == 0)
533   {
534   close_afedriusb_control();
535   }
536 #endif
537 free_semaphores();
538 }
539 
540 
normal_rx_routine(void)541 void normal_rx_routine(void)
542 {
543 char s[256];
544 int i, k, m;
545 int local_block_cnt;
546 int wlcnt, wlcnt_max, local_workload_reset;
547 double total_time1, total_time2;
548 double cpu_time1, cpu_time2;
549 lir_set_title(rxmodes[rx_mode]);
550 workload_counter=0;
551 workload=-1;
552 computation_pause_flag=0;
553 usercontrol_mode=USR_NORMAL_RX;
554 #if RUSAGE_OLD != TRUE
555 #if OSNUM == OSNUM_LINUX
556 for(i=0; i<THREAD_MAX; i++)thread_pid[i]=0;
557 #endif
558 #endif
559 init_semaphores();
560 enable_extio();
561 if(kill_all_flag) goto normal_rx_x;
562 if(ui.network_flag!=0)
563   {
564   init_network();
565   if(kill_all_flag) goto normal_rx_x;
566   if( (ui.network_flag & (NET_RXOUT_FFT2+NET_RXOUT_TIMF2)) != 0 &&
567                                          genparm[SECOND_FFT_ENABLE] == 0)
568     {
569     lirerr(1281);
570     goto normal_rx_x;
571     }
572   }
573 else
574   {
575   get_wideband_sizes();
576   if(kill_all_flag) goto normal_rx_x;
577   get_buffers(1);
578   netfd.rec_rx=INVSOCK;
579   }
580 if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
581 if(!freq_from_file)
582   {
583   read_freq_control_data();
584   }
585 check_filtercorr_direction();
586 init_wide_graph();
587 if( genparm[SECOND_FFT_ENABLE] != 0 )init_blanker();
588 if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
589 if(genparm[SECOND_FFT_ENABLE] != 0)
590   {
591   init_hires_graph();
592   if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
593   }
594 if(genparm[AFC_ENABLE] != 0)
595   {
596   init_afc_graph();
597   if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
598   }
599 if(ui.rx_rf_channels == 2)
600   {
601   init_pol_graph();
602   if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
603   }
604 init_baseband_graph();
605 if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
606 init_coherent_graph();
607 if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
608 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER && eme_flag != 0)
609   {
610   init_eme_graph();
611   if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
612   }
613 if(!freq_from_file)
614   {
615   init_freq_control();
616   if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
617   }
618 if(use_tx != 0)
619   {
620 // Get the xxproc file that the user stored in tg.spproc_no
621   init_tx_graph();
622   if(read_txpar_file()==FALSE)
623     {
624 // If it failed, read the one that was succesful before.
625     tg.spproc_no=first_txproc_no;
626     read_txpar_file();
627     }
628   }
629 // Make sure users_init_mode is the last window(s) we open.
630 // the avoid collission routine does not know where
631 // users windows are placed.
632 if(ui.soundcard_radio == SOUNDCARD_RADIO_ELEKTOR  &&
633        diskread_flag == 0)
634   {
635   if(init_elektor_control_window() != EXIT_SUCCESS)ui.soundcard_radio=0;
636   }
637 #if LIBUDEV_PRESENT == 1
638 if(ui.soundcard_radio == SOUNDCARD_RADIO_FCDPROPLUS  &&
639        diskread_flag == 0)
640   {
641   init_fcdproplus_control_window();
642   }
643 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
644        diskread_flag == 0)
645   {
646   open_afedriusb_control();
647   }
648 #endif
649 users_init_mode();
650 if(kill_all_flag || lir_status != LIR_OK) goto normal_rx_x;
651 show_name_and_size();
652 lir_refresh_screen();
653 fft3_show_time=current_time();
654 fft1_show_time=fft3_show_time;
655 sys_func(THRFLAG_PORTAUDIO_STARTSTOP);
656 linrad_thread_create(THREAD_RX_OUTPUT);
657 while(!kill_all_flag &&
658                thread_status_flag[THREAD_RX_OUTPUT]!=THRFLAG_ACTIVE)
659   {
660   lir_sleep(3000);
661   }
662 if(kill_all_flag)
663   {
664   linrad_thread_stop_and_join(THREAD_RX_OUTPUT);
665   goto normal_rx_x;
666   }
667 thread_command_flag[THREAD_RX_OUTPUT]=THRFLAG_IDLE;
668 i=0;
669 while(thread_status_flag[THREAD_RX_OUTPUT] != THRFLAG_IDLE)
670   {
671   lir_sleep(10000);
672   i++;
673   if(kill_all_flag) goto normal_rx_x;
674   if(i>100)
675     {
676     lirerr(1167);
677     goto normal_rx_x;
678     }
679   }
680 thread_command_flag[THREAD_RX_OUTPUT]=THRFLAG_SEMCLEAR;
681 if(kill_all_flag) goto normal_rx_x;
682 linrad_thread_create(THREAD_USER_COMMAND);
683 if(kill_all_flag) goto normal_rx_x;
684 linrad_thread_create(THREAD_NARROWBAND_DSP);
685 if(kill_all_flag) goto normal_rx_x;
686 linrad_thread_create(THREAD_WIDEBAND_DSP);
687 if(kill_all_flag) goto normal_rx_x;
688 linrad_thread_create(THREAD_SCREEN);
689 if(kill_all_flag) goto normal_rx_x;
690 if((ui.network_flag&NET_RX_OUTPUT)!=0)
691   {
692   linrad_thread_create(THREAD_LIR_SERVER);
693   if(kill_all_flag) goto normal_rx_x;
694   }
695 // Make sure that all the threads are running before
696 // opening inputs in order to avoid overrun errors.
697 // Some system calls they might do could cause overrun
698 // errors if the input were open.
699 while(thread_status_flag[THREAD_RX_OUTPUT]!=THRFLAG_SEMCLEAR &&
700           thread_status_flag[THREAD_USER_COMMAND]!=THRFLAG_ACTIVE &&
701           thread_status_flag[THREAD_NARROWBAND_DSP]!=THRFLAG_SEM_WAIT &&
702           thread_status_flag[THREAD_WIDEBAND_DSP]!=THRFLAG_ACTIVE )
703   {
704   if(kill_all_flag) goto normal_rx_x;
705   lir_sleep(3000);
706   }
707 mailbox[0]=0;
708 mailbox[1]=0;
709 mailbox[2]=0;
710 if(kill_all_flag) goto normal_rx_x;
711 linrad_thread_create(rx_input_thread);
712 lir_sleep(100000);
713 if(lir_status != LIR_OK)
714   {
715   linrad_thread_stop_and_join(THREAD_USER_COMMAND);
716   goto normal_rx_join;
717   }
718 if(kill_all_flag) goto normal_rx_x;
719 if(use_tx != 0 )
720   {
721   switch (rx_mode)
722     {
723     case MODE_SSB:
724     init_txmem_spproc();
725     break;
726 
727     case MODE_WCW:
728     case MODE_NCW:
729     case MODE_HSMS:
730     case MODE_QRSS:
731     init_txmem_cwproc();
732     break;
733 
734     case MODE_RADAR:
735     init_txmem_cwproc();
736     break;
737     }
738   if(kill_all_flag)goto normal_rx_x;
739   linrad_thread_create(THREAD_TX_OUTPUT);
740   while(thread_status_flag[THREAD_TX_OUTPUT]!=THRFLAG_ACTIVE)
741     {
742     if(kill_all_flag) goto normal_rx_x;
743     lir_sleep(3000);
744     }
745   if(kill_all_flag) goto normal_rx_x;
746   lir_refresh_screen();
747   linrad_thread_create(THREAD_TX_INPUT);
748   while(thread_status_flag[THREAD_TX_INPUT]!=THRFLAG_ACTIVE)
749     {
750     if(kill_all_flag) goto normal_rx_x;
751     lir_sleep(3000);
752     }
753   }
754 lir_refresh_screen();
755 lir_sched_yield();
756 #if OSNUM == OSNUM_WINDOWS
757 if(ui.timer_resolution > 0)timeBeginPeriod(ui.timer_resolution);
758 #endif
759 fft1_waterfall_flag=1;
760 setup_thread_affinities();
761 lir_sleep(50000);
762 if(kill_all_flag) goto normal_rx_x;
763 lir_refresh_screen();
764 all_threads_started=TRUE;
765 rxin_block_counter=0;
766 i=0;
767 k=0;
768 wlcnt_max=1+snd[RXAD].interrupt_rate;
769 wlcnt=wlcnt_max;
770 local_workload_reset=workload_reset_flag;
771 #if RUSAGE_OLD != TRUE
772 lir_system_times(&cpu_time1, &total_time1);
773 #if OSNUM == OSNUM_LINUX
774 current_time();
775 for(i=0; i<THREAD_MAX; i++)
776   {
777   thread_tottim1[i]=recent_time;
778   thread_cputim1[i]=0;
779   }
780 #endif
781 #endif
782 local_block_cnt=0;
783 while( !kill_all_flag &&
784                thread_status_flag[THREAD_USER_COMMAND]==THRFLAG_ACTIVE &&
785                thread_status_flag[rx_input_thread] != THRFLAG_RETURNED)
786   {
787   m=60;
788   lir_sleep(50000);
789   while(!kill_all_flag && m>0 && rxin_block_counter == local_block_cnt)
790     {
791     m--;
792     if(local_workload_reset != workload_reset_flag)goto loadprt;
793     lir_sleep(50000);
794     }
795   if( (diskread_flag < 2 || diskread_pause_flag==0) &&
796         rxin_block_counter == local_block_cnt && local_block_cnt==0)
797     {
798     wlcnt=0;
799     sprintf(s,"No input %d",k);
800     lir_text(20,screen_last_line,s);
801     lir_refresh_screen();
802     }
803   if(diskwrite_flag)
804     {
805     lir_sync();
806     }
807   wlcnt-=rxin_block_counter-local_block_cnt;
808   if(wlcnt <= 0)
809     {
810 loadprt:;
811     fix_thread_affinities();
812     wlcnt=wlcnt_max;
813 // *******************************************************************
814 // Compute the workload. We should arrive here at a rate of about 1 Hz.
815 // Modern Linux kernels (2.6.8 or 2.6.9 and later) as well as Windows
816 // allow us to compute the work load from here.
817 // For old Linux kernels with RUSAGE_OLD == TRUE we use get_rusage to
818 // get the work load for each individual thread by calling from inside
819 // each one of the threads.
820 #if RUSAGE_OLD != TRUE
821     current_time();
822     for(i=0; i<THREAD_MAX; i++)
823       {
824 #if OSNUM == OSNUM_LINUX
825       if(thread_pid[i] != 0)
826 #endif
827 #if OSNUM == OSNUM_WINDOWS
828       if(thread_command_flag[i]!=THRFLAG_NOT_ACTIVE)
829 #endif
830         {
831         thread_tottim2[i]=recent_time;
832         thread_cputim2[i]=lir_get_thread_time(i);
833         thread_workload[i]=100*(thread_cputim2[i]-thread_cputim1[i])/
834                                   (thread_tottim2[i]-thread_tottim1[i]);
835         }
836       }
837 #endif
838 #if RUSAGE_OLD == TRUE
839     workload=lir_get_cpu_time();
840 #else
841     lir_system_times(&cpu_time2, &total_time2);
842     workload=100*(cpu_time2-cpu_time1)/(total_time2-total_time1);
843 #endif
844 #if OSNUM == OSNUM_LINUX
845     workload/=no_of_processors;
846 #endif
847     if(workload<0)workload=0;
848     lir_fix_bug(1);
849     if(local_workload_reset != workload_reset_flag)
850       {
851       local_workload_reset=workload_reset_flag;
852       total_time1=total_time2;
853       cpu_time1=cpu_time2;
854       for(i=0; i<THREAD_MAX; i++)
855         {
856         if(thread_command_flag[i]!=THRFLAG_NOT_ACTIVE)
857           {
858           thread_tottim1[i]=thread_tottim2[i];
859           thread_cputim1[i]=thread_cputim2[i];
860           }
861         }
862       }
863     workload_counter++;
864     lir_set_event(EVENT_SCREEN);
865     }
866   k++;
867   if(k==10000)k=1;
868   local_block_cnt=rxin_block_counter;
869   }
870 lir_join(THREAD_USER_COMMAND);
871 if(diskwrite_flag != 0)disksave_stop();
872 #if OSNUM == OSNUM_WINDOWS
873 if(ui.timer_resolution > 0)timeEndPeriod(ui.timer_resolution);
874 #endif
875 if(use_tx != 0)
876   {
877   linrad_thread_stop_and_join(THREAD_TX_INPUT);
878   linrad_thread_stop_and_join(THREAD_TX_OUTPUT);
879   close_tx_sndin();
880   close_tx_sndout();
881   if(txmem_handle != NULL)free(txmem_handle);
882   txmem_handle=NULL;
883   lir_close_event(EVENT_TX_INPUT);
884   }
885 normal_rx_join:;
886 linrad_thread_stop_and_join(THREAD_RX_OUTPUT);
887 linrad_thread_stop_and_join(rx_input_thread);
888 linrad_thread_stop_and_join(THREAD_SCREEN);
889 linrad_thread_stop_and_join(THREAD_NARROWBAND_DSP);
890 if((ui.network_flag&NET_RX_OUTPUT)!=0)
891   {
892   linrad_thread_stop_and_join(THREAD_LIR_SERVER);
893   }
894 linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
895 normal_rx_x:;
896 #if LIBUDEV_PRESENT == 1
897 if(ui.soundcard_radio == SOUNDCARD_RADIO_AFEDRI_USB &&
898        diskread_flag == 0)
899   {
900   close_afedriusb_control();
901   }
902 #endif
903 disable_extio();
904 free_semaphores();
905 }
906 
prompt_reason(char * s)907 void prompt_reason(char *s)
908 {
909 clear_screen();
910 lir_text(5,8,"You are prompted to the parameter selection screens");
911 lir_text(15,10,"for the following reason:");
912 lir_text(5,13,s);
913 lir_text(20,16,press_any_key);
914 clear_keyboard();
915 await_keyboard();
916 }
917 
check_output_no_of_channels(void)918 void check_output_no_of_channels(void)
919 {
920 int i;
921 i=1+((genparm[OUTPUT_MODE]>>1)&1);
922 if(i<ui.rx_min_da_channels)i=ui.rx_min_da_channels;
923 if(i>ui.rx_max_da_channels)i=ui.rx_max_da_channels;
924 i--;
925 genparm[OUTPUT_MODE]&=-3;
926 genparm[OUTPUT_MODE]|=i<<1;
927 }
928 
fix_limits(int * k,int * m,int parnum)929 void fix_limits(int *k, int *m, int parnum)
930 {
931 int i;
932 k[0]=genparm_max[parnum];
933 m[0]=genparm_min[parnum];
934 if(parnum == FIRST_FFT_VERNR)
935   {
936   k[0]=0;
937   fft1mode=(ui.rx_input_mode&(TWO_CHANNELS+IQ_DATA))/2;
938   while( fft1_version[fft1mode][k[0]+1] >= 0 &&
939                                 k[0] < MAX_FFT1_VERNR-1)k[0]++;
940   if(simd_present == 0)
941     {
942     while( fft_cntrl[fft1_version[fft1mode][k[0]]].simd != 0)k[0]--;
943     }
944   if(mmx_present == 0)
945     {
946     while( fft_cntrl[fft1_version[fft1mode][k[0]]].mmx != 0)k[0]--;
947     }
948   }
949 if(parnum == FIRST_BCKFFT_VERNR)
950   {
951   i=0;
952   while(fft1_back_version[ui.rx_rf_channels-1][i+1] > 0 &&
953                               i < MAX_FFT1_BCKVERNR-1)i++;
954   if(mmx_present == 0)
955     {
956     while( fft_cntrl[fft1_back_version[ui.rx_rf_channels-1][i]].mmx != 0)i--;
957     }
958   k[0]=i;
959   }
960 if(parnum == FIRST_BCKFFT_ATT_N)
961   {
962   k[0]=(fft1_n-4)&0xfffe;
963   }
964 if(parnum == SECOND_FFT_ATT_N)
965   {
966   k[0]=fft2_n-2;
967   }
968 // Please check if index is within constaints *BEFORE* using it.
969 // This error was caught by GCC5 diagnostics marino@FreeBSD.org
970 if(parnum == SECOND_FFT_VERNR)
971   {
972   i=0;
973   while( i < MAX_FFT2_VERNR-1 &&
974          fft2_version[ui.rx_rf_channels-1][i+1] > 0)i++;
975   if(mmx_present == 0)
976     {
977     while( fft_cntrl[fft2_version[ui.rx_rf_channels-1][i]].mmx != 0)i--;
978     }
979   k[0]=i;
980   }
981 if(parnum == MIX1_BANDWIDTH_REDUCTION_N)
982   {
983   if(genparm[SECOND_FFT_ENABLE] == 0)
984     {
985     k[0]=fft1_n-3;
986     }
987   else
988     {
989     k[0]=fft2_n-3;
990     }
991   }
992 if(parnum == DA_OUTPUT_SPEED)
993   {
994   m[0]=ui.rx_min_da_speed;
995   k[0]=ui.rx_max_da_speed;
996   }
997 if(parnum == MAX_NO_OF_SPURS)
998   {
999   if(genparm[AFC_ENABLE]==0)
1000     {
1001     k[0]=0;
1002     }
1003   else
1004     {
1005     if(genparm[SECOND_FFT_ENABLE] == 0)
1006       {
1007       k[0]=2*fft1_size/SPUR_WIDTH;
1008       }
1009     else
1010       {
1011       k[0]=2*fft2_size/SPUR_WIDTH;
1012       }
1013     }
1014   }
1015 if(parnum == SPUR_TIMECONSTANT)
1016   {
1017   if(genparm[SECOND_FFT_ENABLE] == 0)
1018     {
1019     k[0]=5*genparm[FFT1_STORAGE_TIME];
1020     }
1021   else
1022     {
1023     k[0]=5*genparm[FFT2_STORAGE_TIME];
1024     }
1025   }
1026 // In case fft sizes are not set.
1027 if(k[0] < m[0] || m[0]<genparm_min[parnum] || k[0]>genparm_max[parnum])
1028   {
1029   k[0]=genparm_max[parnum];
1030   m[0]=genparm_min[parnum];
1031   }
1032 }
1033 
modify_parms(char * line1,int first,int last)1034 void modify_parms(char *line1, int first, int last)
1035 {
1036 unsigned int new_sample_rate;
1037 char s[80];
1038 int line1_len, line;
1039 int i, j, k, m, no, mouse_line,parnum;
1040 line1_len=strlen(line1)+8;
1041 no=last-first+1;
1042 start:;
1043 hide_mouse(0,screen_width,0,screen_height);
1044 clear_screen();
1045 settextcolor(14);
1046 lir_text(5,1, line1);
1047 // Make sure fft1_n and fft2_n are defined and
1048 // in agreement with current parameters.
1049 get_wideband_sizes();
1050 if( first <= FIRST_FFT_SINPOW && last >= FIRST_FFT_SINPOW)
1051   {
1052   sprintf(s,"fft1 size=%d (Bw=%fHz) %s",fft1_size,fft1_bandwidth,
1053                                               fft_cntrl[FFT1_CURMODE].text);
1054   lir_text(line1_len,1,s);
1055   }
1056 if( first <= SECOND_FFT_SINPOW && last >= SECOND_FFT_SINPOW)
1057   {
1058   sprintf(s,"fft2 size=%d (Bw=%fHz)",fft2_size,fft2_bandwidth);
1059   lir_text(line1_len,1,s);
1060   }
1061 if(kill_all_flag) return;
1062 if( first <= DA_OUTPUT_SPEED && last >= DA_OUTPUT_SPEED)
1063   {
1064   if(genparm[DA_OUTPUT_SPEED] < ui.rx_min_da_speed)
1065                               genparm[DA_OUTPUT_SPEED]=ui.rx_min_da_speed;
1066 
1067   if(genparm[DA_OUTPUT_SPEED] > ui.rx_max_da_speed)
1068                              genparm[DA_OUTPUT_SPEED]=ui.rx_max_da_speed;
1069 
1070   }
1071 if( first <= CW_DECODE_ENABLE && last >= CW_DECODE_ENABLE)
1072   {
1073   if(rx_mode==MODE_WCW || rx_mode==MODE_NCW || rx_mode==MODE_HSMS)
1074     {
1075     if(genparm[CW_DECODE_ENABLE] != 0)
1076       {
1077       settextcolor(12);
1078       lir_text(1,14,"WARNING: The Morse decode routines are incomplete.");
1079       lir_text(1,15,"They will not produce any useful output and may cause");
1080       lir_text(1,16,"a program crasch. Use only for development and perhaps");
1081       lir_text(1,17,"for some evaluation of chirp and other keying defects");
1082       lir_text(1,18,"with the coherent graph oscilloscope.");
1083       }
1084     }
1085   else
1086     {
1087     genparm[CW_DECODE_ENABLE]=0;
1088     }
1089   }
1090 if( first <= FIRST_BCKFFT_ATT_N && last >= FIRST_BCKFFT_ATT_N)
1091   {
1092   k=(fft1_n-4)&0xfffe;
1093   if(genparm[FIRST_BCKFFT_ATT_N]>k)genparm[FIRST_BCKFFT_ATT_N]=k;
1094   if(genparm[FIRST_BCKFFT_ATT_N]<0)genparm[FIRST_BCKFFT_ATT_N]=
1095                                              genparm_min[FIRST_BCKFFT_ATT_N];
1096   }
1097 if( first <= SECOND_FFT_ATT_N && last >= SECOND_FFT_ATT_N)
1098   {
1099   k=fft2_n-2;
1100   if(genparm[SECOND_FFT_ATT_N]>k)genparm[SECOND_FFT_ATT_N]=k;
1101   }
1102 settextcolor(7);
1103 line=0;
1104 for(i=0; i<no; i++)
1105   {
1106   j=i+first;
1107   if(ui.operator_skil == OPERATOR_SKIL_NEWCOMER && newco_genparm[j] ==0)
1108     {
1109     settextcolor(8);
1110     }
1111   else
1112     {
1113     settextcolor(7);
1114     }
1115   sprintf(s,"%s [%d] ",genparm_text[j],genparm[j]);
1116   lir_text(1,3+i, s);
1117   }
1118 lir_text(1,5+no,"Use left mouse button to select line");
1119 lir_text(1,3+no,"CONTINUE");
1120 settextcolor(15);
1121 show_mouse();
1122 modloop:;
1123 if( new_mouse_x!=mouse_x || new_mouse_y!=mouse_y)
1124   {
1125   lir_move_mouse_cursor();
1126   show_mouse();
1127   }
1128 lir_refresh_screen();
1129 lir_sleep(10000);
1130 if(new_lbutton_state==1)lbutton_state=1;
1131 if(new_lbutton_state==0 && lbutton_state==1)
1132   {
1133   lbutton_state=0;
1134   mouse_line=mouse_y/text_height-3;
1135   if(mouse_line == no)goto loopx;
1136   if(mouse_line >= 0 && mouse_line <no)
1137     {
1138     parnum=mouse_line+first;
1139     clear_screen();
1140     settextcolor(14);
1141     lir_text(5,1, line1);
1142     line=3;
1143     settextcolor(15);
1144     sprintf(s,"Old value = %d",genparm[parnum]);
1145     lir_text(1,line, s);
1146     line++;
1147     lir_text(1,line,"Enter new value for:");
1148     line++;
1149     fix_limits(&k, &m, parnum);
1150     sprintf(s," %s (%d to %d)",genparm_text[parnum], m,k);
1151     lir_text(1,line, s);
1152     i=line+1;
1153     line+=4;
1154     msg_filename="help.lir";
1155     write_from_msg_file(&line, 201+mouse_line+first, TRUE, HELP_VERNR);
1156     if(parnum == DA_OUTPUT_SPEED && ui.rx_dadev_no != DISABLED_DEVICE_CODE)
1157       {
1158 #if(OSNUM == OSNUM_LINUX)
1159 #if (ALSA_PRESENT == 1)
1160       if (( (ui.use_alsa&NATIVE_ALSA_USED) != 0)  && ((ui.use_alsa&PORTAUDIO_RX_OUT)== 0) )
1161         {
1162         alsa_get_native_samplerate(ui.rx_dadev_no,SND_PCM_STREAM_PLAYBACK,&line,&new_sample_rate);
1163         genparm[parnum]=new_sample_rate;
1164         goto modify_parms_next_a;
1165         }
1166       else
1167 #endif
1168 #endif
1169         {
1170         if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0 &&
1171              ui.rx_dadev_no != DISABLED_DEVICE_CODE)
1172           {
1173           pa_get_valid_samplerate(ui.rx_dadev_no,RXDA,&line,&new_sample_rate);
1174           genparm[parnum]=new_sample_rate;
1175           goto modify_parms_next_p;
1176           }
1177         }
1178       }
1179     lir_text(7,i,"=>");
1180     genparm[parnum]=lir_get_integer(10, i, 8, m,k);
1181 modify_parms_next_p:;
1182 #if(OSNUM == OSNUM_LINUX)
1183 #if (ALSA_PRESENT == 1)
1184 modify_parms_next_a:;
1185 #endif
1186 #endif
1187 
1188     if(kill_all_flag) return;
1189     if(parnum == OUTPUT_MODE)check_output_no_of_channels();
1190     goto start;
1191     }
1192   }
1193 test_keyboard();
1194 if(kill_all_flag) return;
1195 if(lir_inkey != 0)
1196   {
1197   process_current_lir_inkey();
1198   if(kill_all_flag) return;
1199   }
1200 if(lir_inkey == F1_KEY || lir_inkey == '!')
1201   {
1202   mouse_line=mouse_y/text_height-3;
1203   if(mouse_line >= 0 && mouse_line <no)
1204     {
1205     help_message(201+mouse_line+first);
1206     }
1207   else
1208     {
1209     help_message(200);
1210     }
1211   if(kill_all_flag) return;
1212   goto start;
1213   }
1214 if(lir_inkey != 10 && lir_inkey!= 'X')goto modloop;
1215 loopx:;
1216 }
1217 
set_general_parms(char * mode)1218 void set_general_parms(char *mode)
1219 {
1220 char s[80];
1221 sprintf(s,"%s: Rx channels=%d",mode,ui.rx_rf_channels);
1222 if(lir_status < LIR_OK)goto bufreduce;
1223 setfft1:;
1224 if(kill_all_flag) return;
1225 modify_parms(s, 0, SECOND_FFT_ENABLE);
1226 if(kill_all_flag) return;
1227 if(lir_inkey == 'X')return;
1228 // Make sure fft1_n and fft2_n are defined and that we can
1229 // allocate memory.
1230 get_wideband_sizes();
1231 if(kill_all_flag) return;
1232 get_buffers(0);
1233 if(kill_all_flag) return;
1234 if(fft1_handle != NULL)fft1_handle=chk_free(fft1_handle);
1235 if(lir_status != LIR_OK)goto bufreduce;
1236 if(genparm[SECOND_FFT_ENABLE]==1)
1237   {
1238   modify_parms(s, FIRST_BCKFFT_VERNR, FFT2_STORAGE_TIME);
1239   if(kill_all_flag) return;
1240   if(lir_inkey == 'X')return;
1241   get_wideband_sizes();
1242   if(kill_all_flag) return;
1243   get_buffers(0);
1244   if(kill_all_flag) return;
1245   if(fft1_handle != NULL)fft1_handle=chk_free(fft1_handle);
1246   if(lir_status != LIR_OK)
1247     {
1248 bufreduce:;
1249     clear_screen();
1250     settextcolor(15);
1251     switch (lir_status)
1252       {
1253       case LIR_FFT1ERR:
1254       lir_text(5,5,"Out of memory !!!");
1255       lir_text(10,10,"Storage times are set to minimum.");
1256       settextcolor(14);
1257       lir_text(10,13,"Check memory allocations in waterfall window");
1258       lir_text(10,14,"to decide how much you may increase storage times.");
1259       genparm[FFT1_STORAGE_TIME]=genparm_min[FFT1_STORAGE_TIME];
1260       genparm[FFT2_STORAGE_TIME]=genparm_min[FFT2_STORAGE_TIME];
1261       genparm[BASEBAND_STORAGE_TIME]=genparm_min[BASEBAND_STORAGE_TIME];
1262       lir_status=LIR_OK;
1263       break;
1264 
1265       case LIR_SPURERR:
1266       sprintf(s,"fft1 storage time too short for spur removal");
1267       if(genparm[SECOND_FFT_ENABLE] != 0)s[3]='2';
1268       lir_text(7,7,s);
1269       lir_text(7,8,"Spur removal disabled");
1270       genparm[MAX_NO_OF_SPURS]=0;
1271       lir_status=LIR_OK;
1272       break;
1273 
1274       case LIR_NEW_SETTINGS:
1275       goto setfft1;
1276       }
1277     settextcolor(7);
1278     lir_text(10,17,"Press ESC to quit, any other key to continue");
1279     await_processed_keyboard();
1280     if(kill_all_flag) return;
1281     goto setfft1;
1282     }
1283   }
1284 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
1285   {
1286   modify_parms(s, AFC_ENABLE, AFC_ENABLE);
1287   if(kill_all_flag) return;
1288   if(lir_inkey == 'X')return;
1289   if(genparm[AFC_ENABLE] != 0)modify_parms(s, AFC_ENABLE+1, SPUR_TIMECONSTANT);
1290   if(kill_all_flag) return;
1291   if(lir_inkey == 'X')return;
1292   }
1293 modify_parms(s, MIX1_BANDWIDTH_REDUCTION_N, MAX_GENPARM-1);
1294 if(kill_all_flag) return;
1295 if(lir_inkey == 'X')return;
1296 clear_screen();
1297 }
1298 
cal_package(void)1299 void cal_package(void)
1300 {
1301 char s[80], ss[80];
1302 int single_run;
1303 int i, ia, ib, ic;
1304 float t1,t2;
1305 calibrate_flag = 1;
1306 // **************************************************************
1307 // Set fft1_direction positive.
1308 // The calibration routine does not want to know if the fft1 routine
1309 // will invert the frequency scale.
1310 fft1_direction=1;
1311 single_run=0;
1312 // Get normal buffers with minimum for all parameters.
1313 // Everything selectable becomes deselected.
1314 // Save fft1 version, window and bandwidth.
1315 ia=genparm[FIRST_FFT_VERNR];
1316 ib=genparm[FIRST_FFT_SINPOW];
1317 ic=genparm[FIRST_FFT_BANDWIDTH];
1318 for(i=0; i<MAX_GENPARM; i++)genparm[i]=genparm_min[i];
1319 // Select the correct fft version for the current rx_mode
1320 // This is not really needed for versions above Linrad-01.xx
1321 // because the approximate fft has been removed. None of the
1322 // fft implementations contains a filter any more.
1323 genparm[FIRST_FFT_VERNR]=ia;
1324 // Force fft1_size to be 4 times larger than specified for the current
1325 // rx_mode by dividing bandwidth by 4.
1326 t2=ic/4;
1327 // Compensate for not using the specified window
1328 // We use sin power 4 to suppress wideband noise that otherwise would
1329 // be produced by discontinuities in matching between transform ends.
1330 t1=pow(0.5,1.0/ib);
1331 t2*=(1-2*asin(t1)/PI_L);
1332 t1=pow(0.5,1.0/4);
1333 t2/=(1-2*asin(t1)/PI_L);
1334 genparm[FIRST_FFT_SINPOW]=4;
1335 i=t2+0.5;
1336 if(i < genparm_min[FIRST_FFT_BANDWIDTH])i=genparm_min[FIRST_FFT_BANDWIDTH];
1337 genparm[FIRST_FFT_BANDWIDTH]=i;
1338 clear_screen();
1339 get_wideband_sizes();
1340 if(kill_all_flag) return;
1341 get_buffers(1);
1342 if(kill_all_flag) return;
1343 if(lir_status != LIR_OK)return;
1344 wg.first_xpoint=0;
1345 wg.xpoints=fft1_size;
1346 set_fft1_endpoints();
1347 if(fft1afc_flag == 0)fft1afc_flag=-1;
1348 init_memalloc(calmem, MAX_CAL_ARRAYS);
1349 mem( 1,&cal_graph,2*MAX_ADCHAN*screen_width*sizeof(short int),0);
1350 mem( 2,&cal_table,fft1_size*sizeof(COSIN_TABLE )/2,0);
1351 mem( 3,&cal_permute,fft1_size*sizeof(short int),0);
1352 mem(22,&fft2_tab,fft1_size*sizeof(COSIN_TABLE )/2,0);
1353 mem(23,&fft2_permute,fft1_size*sizeof(short int),0);
1354 mem( 4,&cal_win,(1+fft1_size/2)*sizeof(float),0);
1355 mem( 5,&cal_tmp,twice_rxchan*fft1_size*sizeof(float),0);
1356 mem( 6,&cal_buf,twice_rxchan*fft1_size*sizeof(float),0);
1357 mem( 7,&bal_flag,(BAL_MAX_SEG+1)*sizeof(int),0);
1358 mem( 8,&bal_pos,BAL_AVGNUM*(BAL_MAX_SEG+1)*ui.rx_rf_channels*sizeof(int),0);
1359 mem( 9,&bal_phsum,BAL_AVGNUM*(BAL_MAX_SEG+1)*ui.rx_rf_channels*sizeof(float),0);
1360 mem(10,&bal_amprat,BAL_AVGNUM*(BAL_MAX_SEG+1)*ui.rx_rf_channels*sizeof(float),0);
1361 mem(11,&contracted_iq_foldcorr,8*(BAL_MAX_SEG+1)*ui.rx_rf_channels*
1362                                                             sizeof(float),0);
1363 mem(12,&cal_buf2,twice_rxchan*fft1_size*sizeof(float),0);
1364 mem(13,&cal_buf3,twice_rxchan*fft1_size*sizeof(float),0);
1365 mem(14,&cal_buf4,twice_rxchan*fft1_size*sizeof(float),0);
1366 mem(15,&cal_buf5,twice_rxchan*fft1_size*sizeof(float),0);
1367 mem(16,&cal_buf6,twice_rxchan*fft1_size*sizeof(float),0);
1368 mem(17,&cal_buf7,twice_rxchan*fft1_size*sizeof(float),0);
1369 mem(47,&cal_fft1_filtercorr,twice_rxchan*fft1_size*sizeof(float),0);
1370 mem(48,&cal_fft1_desired,fft1_size*sizeof(float),0);
1371 mem(49,&cal_fft1_sumsq,fft1_size*ui.rx_rf_channels*sizeof(float),0);
1372 mem(50,&cal_fft1_slowsum,fft1_size*ui.rx_rf_channels*sizeof(float),0);
1373 i=memalloc(&calmem_handle,"calmem");
1374 if(i==0)
1375   {
1376   lirerr(1188);
1377   return;
1378   }
1379 if(ui.rx_rf_channels == 1)
1380   {
1381   cal_ymax=.25;
1382   cal_yzer=.65;
1383   }
1384 else
1385   {
1386   cal_ymax=.15;
1387   cal_yzer=.5;
1388   }
1389 init_fft(0,fft1_n, fft1_size, cal_table, cal_permute);
1390 make_window(2,fft1_size/2, 4, cal_win);
1391 iqbeg:;
1392 single_run++;
1393 if(single_run >=2)goto cal_skip;
1394 fft1_pa=fft1_block;
1395 fft1_na=1;
1396 fft1_pb=0;
1397 fft1_px=0;
1398 fft1_nx=0;
1399 timf1p_pa=snd[RXAD].block_bytes;
1400 rxin_isho=(short int*)(&timf1_char[timf1p_pa]);
1401 rxin_int=(int*)(&timf1_char[timf1p_pa]);
1402 rxin_char=(char*)(&timf1_char[timf1p_pa]);
1403 timf1p_px=0;
1404 if(kill_all_flag) goto cal_skip;
1405 cal_type=CAL_TYPE_MENU;
1406 cal_initscreen();
1407 if( (ui.rx_input_mode&IQ_DATA) != 0)
1408   {
1409   if( (ui.rx_input_mode&DIGITAL_IQ) == 0)
1410     {
1411     lir_text(0, 5,"Running in IQ mode (direct conversion receiver)");
1412     lir_text(0, 6,"The I/Q phase and amplitude should be calibrated before");
1413     lir_text(0, 7,"the total amplitude and phase response is calibrated");
1414     lir_text(5, 9,"A=> Calibrate I/Q phase and amplitude.");
1415     }
1416   lir_text(5,10,"B=> Calibrate total amplitude and phase");
1417   lir_text(5,11,"C=> Remove center discontinuity");
1418   lir_text(5,12,"D=> Refine amplitude and phase correction");
1419   lir_text(5,13,"X=> Skip");
1420   lir_text(5,14,"F1 or !=> Help");
1421 get_kbd:;
1422   await_processed_keyboard();
1423   if(kill_all_flag) goto cal_skip;
1424   switch (lir_inkey)
1425     {
1426     case 'X':
1427     goto cal_skip;
1428 
1429     case 'A':
1430     if( (ui.rx_input_mode&DIGITAL_IQ) != 0)break;
1431     if( (fft1_calibrate_flag&CALAMP)==CALAMP)
1432       {
1433       clear_screen();
1434       lir_text(5,5,"The amplitudes are already calibrated.");
1435       make_filfunc_filename(s);
1436       sprintf(ss,"Exit from Linrad and remove the file %s",s);
1437       lir_text(1,6,ss);
1438       lir_text(5,8,press_any_key);
1439       await_keyboard();
1440       break;
1441       }
1442     usercontrol_mode=USR_IQ_BALANCE;
1443     init_semaphores();
1444     ampinfo_flag=1;
1445     linrad_thread_create(rx_input_thread);
1446     lir_sleep(100000);
1447     if(lir_status != LIR_OK)
1448       {
1449       lir_join(rx_input_thread);
1450       goto cal_skip_freesem;
1451       }
1452     if(kill_all_flag) goto cal_skip_freesem;
1453     linrad_thread_create(THREAD_USER_COMMAND);
1454     if(kill_all_flag) goto iqbal;
1455     linrad_thread_create(THREAD_CAL_IQBALANCE);
1456     if(kill_all_flag) goto iqbal;
1457     linrad_thread_create(THREAD_WIDEBAND_DSP);
1458 iqbal:;
1459     lir_sleep(50000);
1460     lir_refresh_screen();
1461     lir_join(THREAD_USER_COMMAND);
1462     linrad_thread_stop_and_join(rx_input_thread);
1463     linrad_thread_stop_and_join(THREAD_CAL_IQBALANCE);
1464     linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
1465     free_semaphores();
1466     if(kill_all_flag) goto cal_skip;
1467     break;
1468 
1469     case 'B':
1470     goto pulsecal;
1471 
1472     case 'C':
1473     if(remove_iq_notch() == 0)goto cal_skip;
1474     break;
1475 
1476     case 'D':
1477     final_filtercorr_init();
1478     goto cal_skip;
1479 
1480     case F1_KEY:
1481     case '!':
1482     help_message(302);
1483     break;
1484 
1485     default:
1486     goto get_kbd;
1487     }
1488   }
1489 else
1490   {
1491   lir_text(5, 9,"A=> Calibrate frequency response");
1492   lir_text(5,10,"B=> Refine amplitude and phase correction");
1493   lir_text(5,11,"X=> Skip");
1494   lir_text(5,12,"F1 or !=> Help");
1495 get_valid_keypress:;
1496   await_processed_keyboard();
1497   if(kill_all_flag) goto cal_skip;
1498   switch (lir_inkey)
1499     {
1500     case 'X':
1501     goto cal_skip;
1502 
1503     case 'A':
1504     goto pulsecal;
1505 
1506     case 'B':
1507     final_filtercorr_init();
1508     goto cal_skip;
1509 
1510     case F1_KEY:
1511     case '!':
1512     help_message(303);
1513     break;
1514 
1515     default:
1516     goto get_valid_keypress;
1517     }
1518   }
1519 goto iqbeg;
1520 pulsecal:;
1521 enable_extio();
1522 timf1p_pa=0;
1523 rxin_isho=(short int*)timf1_char;
1524 rxin_int=(int*)timf1_char;
1525 rxin_char=(char*)timf1_char;
1526 usercontrol_mode=USR_CAL_INTERVAL;
1527 init_semaphores();
1528 ampinfo_flag=1;
1529 linrad_thread_create(rx_input_thread);
1530 lir_sleep(100000);
1531 if(lir_status != LIR_OK)
1532   {
1533   lir_join(rx_input_thread);
1534   goto cal_skip_freesem;
1535   }
1536 if(kill_all_flag) goto cal_skip_freesem;
1537 linrad_thread_create(THREAD_USER_COMMAND);
1538 if(kill_all_flag) goto calint;
1539 linrad_thread_create(THREAD_CAL_INTERVAL);
1540 if(kill_all_flag)goto cal_skip;
1541 calint:;
1542 lir_sleep(50000);
1543 lir_refresh_screen();
1544 lir_join(THREAD_USER_COMMAND);
1545 linrad_thread_stop_and_join(rx_input_thread);
1546 linrad_thread_stop_and_join(THREAD_CAL_INTERVAL);
1547 free_semaphores();
1548 if(kill_all_flag)goto cal_skip;
1549 clear_screen();
1550 lir_refresh_screen();
1551 if(usercontrol_mode != USR_CAL_FILTERCORR)
1552   {
1553   disable_extio();
1554   goto iqbeg;
1555   }
1556 if( (ui.rx_input_mode&IQ_DATA) == 0)cal_interval/=2;
1557 #define ERRLINE 5
1558 if(cal_interval > fft1_size/5)
1559   {
1560   lir_text(5,ERRLINE,"Pulse repetition frequency too low.");
1561   lir_text(5,ERRLINE+1,"Increase PRF or set fft1 bandwidth lower to");
1562   lir_text(5,ERRLINE+2,"increase transform size.");
1563 err1:;
1564   lir_text(5,ERRLINE+5,press_any_key);
1565   await_keyboard();
1566   disable_extio();
1567   goto iqbeg;
1568   }
1569 if(cal_signal_level > 0.9)
1570   {
1571   lir_text(5,ERRLINE,"Pulses too strong (above 90%)");
1572   goto err1;
1573   }
1574 timf1p_pa=0;
1575 rxin_isho=(short int*)timf1_char;
1576 rxin_int=(int*)timf1_char;
1577 rxin_char=(char*)timf1_char;
1578 timf1p_px=0;
1579 init_semaphores();
1580 linrad_thread_create(rx_input_thread);
1581 lir_sleep(100000);
1582 if(lir_status != LIR_OK)
1583   {
1584   lir_join(rx_input_thread);
1585   goto cal_skip_freesem;
1586   }
1587 if(kill_all_flag) goto cal_skip_freesem;
1588 linrad_thread_create(THREAD_WIDEBAND_DSP);
1589 if(kill_all_flag) goto calfil;
1590 linrad_thread_create(THREAD_CAL_FILTERCORR);
1591 if(kill_all_flag) goto calfil;
1592 linrad_thread_create(THREAD_USER_COMMAND);
1593 calfil:;
1594 lir_sleep(50000);
1595 lir_refresh_screen();
1596 lir_join(THREAD_USER_COMMAND);
1597 linrad_thread_stop_and_join(rx_input_thread);
1598 linrad_thread_stop_and_join(THREAD_CAL_FILTERCORR);
1599 linrad_thread_stop_and_join(THREAD_WIDEBAND_DSP);
1600 free_semaphores();
1601 if(kill_all_flag)goto cal_skip;
1602 disable_extio();
1603 goto iqbeg;
1604 // ********************************
1605 cal_skip_freesem:;
1606 free_semaphores();
1607 cal_skip:;
1608 disable_extio();
1609 memcheck(199,calmem,&calmem_handle);
1610 calmem_handle=chk_free(calmem_handle);
1611 free_buffers();
1612 }
1613 
restore_uiparm(void)1614 void restore_uiparm(void)
1615 {
1616 int i;
1617 int *uiparm;
1618 uiparm=(int*)(&ui);
1619 for(i=0; i<MAX_UIPARM; i++)uiparm[i]=uiparm_save[i];
1620 }
1621 
save_uiparm(void)1622 void save_uiparm(void)
1623 {
1624 int i;
1625 int *uiparm;
1626 uiparm=(int*)(&ui);
1627 for(i=0; i<MAX_UIPARM; i++)uiparm_save[i]=uiparm[i];
1628 }
1629 
set_wav_parms(void)1630 void set_wav_parms(void)
1631 {
1632 if( wav_read_flag != 0)
1633   {
1634   if(ui.rx_ad_channels == 2)
1635     {
1636     if(iqflag==1)
1637       {
1638       ui.rx_rf_channels=1;
1639       ui.rx_input_mode|=IQ_DATA;
1640       }
1641     else
1642       {
1643       ui.rx_input_mode|=TWO_CHANNELS;
1644       ui.rx_rf_channels=2;
1645       }
1646     if(dirflag == 1)
1647       {
1648       fg.passband_direction=-1;
1649       }
1650     else
1651       {
1652       fg.passband_direction=1;
1653       }
1654     }
1655   else
1656     {
1657     ui.rx_rf_channels=1;
1658     fg.passband_direction=1;
1659     }
1660   fft1_direction=fg.passband_direction;
1661   }
1662 }
1663 
init_genparm(int upd)1664 void init_genparm(int upd)
1665 {
1666 char s[256],ss[80];
1667 FILE *file;
1668 int  i, j, k, kmax, imin, imax;
1669 int parwrite_flag, parfile_flag;
1670 float t1;
1671 char *parinfo;
1672 parinfo=NULL;
1673 parwrite_flag=0;
1674 if(upd == TRUE) goto updparm;
1675 file=NULL;
1676 // Start by reading general parameters for the selected rx mode.
1677 // If no parameters found, go to the parameter select routine because
1678 // we can not guess what hardware will be in use so default parameters
1679 // are likely to be very far from what will be needed.
1680 parfile_flag=0;
1681 if(savefile_parname[0] != 0)
1682   {
1683 // We use disk input and there is a parameter file name supplied
1684 // for this particular recording.
1685   file = fopen(savefile_parname, "r");
1686   if (file == NULL)goto saverr;
1687   parfilnam=savefile_parname;
1688   parfile_flag=1;
1689 // First read the mode flag, an extra line in the userint par file
1690 // placed above the normal lines.
1691 // This line specifies receive mode and whether the file should be
1692 // repeated endlessly
1693 // Stereo .wav files have more flags. Whether it is two RF channels
1694 // or I and Q from direct conversion. In the latter case what
1695 // direction to use for the frequency scale.
1696   i=fread(s,1,1,file);
1697   if(i != 1)goto saverr_close;
1698   rx_mode=to_upper(s[0])-'A';
1699   if(rx_mode < 0 || rx_mode >= MAX_RX_MODE)goto saverr_close;
1700   i=fread(s,1,1,file);
1701   if(i != 1)goto saverr_close;
1702   if(s[0]=='1')
1703     {
1704     savefile_repeat_flag=1;
1705     }
1706   else
1707     {
1708     if(s[0]!='0')goto saverr_close;
1709     savefile_repeat_flag=0;
1710     }
1711   if(wav_read_flag==0)goto skip_modlin;
1712   i=fread(s,1,1,file);
1713   if(i != 1)goto saverr_close;
1714   if(s[0]=='1')
1715     {
1716     iqflag=1;
1717     ui.rx_rf_channels=ui.rx_ad_channels/2;
1718     i=fread(s,1,1,file);
1719     if(i != 1)goto saverr_close;
1720     if(s[0]=='1')
1721       {
1722       dirflag=1;
1723       }
1724     else
1725       {
1726       if(s[0]!='0')goto saverr_close;
1727       dirflag=0;
1728       }
1729     }
1730   else
1731     {
1732     if(s[0]!='0')goto saverr_close;
1733     iqflag=0;
1734     ui.rx_rf_channels=ui.rx_ad_channels;
1735     }
1736 skip_modlin:;
1737 // We use disk input and something was wrong with the first line.
1738 // Read until end of line, then ask the user for the desired mode.
1739   i=fread(s,1,1,file);
1740   if(s[0]=='\n') goto fileok;
1741   if(i==1)goto skip_modlin;
1742 saverr_close:;
1743   fclose(file);
1744 saverr:;
1745   parwrite_flag=1;
1746   }
1747 if(diskread_flag == 2)
1748   {
1749   clear_screen();
1750   for(i=0; i<MAX_RX_MODE; i++)
1751     {
1752     sprintf(s,"%c=%s",i+'A',rxmodes[i]);
1753     lir_text(0, i+2,s);
1754     }
1755   settextcolor(15);
1756   lir_text(5, MAX_RX_MODE+3, "Select Rx mode");
1757   rx_mode=-1;
1758   while(rx_mode < 0 || rx_mode > MAX_RX_MODE)
1759     {
1760     to_upper_await_keyboard();
1761     if(kill_all_flag) return;
1762     rx_mode=lir_inkey-'A';
1763     }
1764   clear_screen();
1765   lir_text(5,5,"Repeat recording endlessly (Y/N)?");
1766 savrpt:;
1767   to_upper_await_keyboard();
1768   if(kill_all_flag) return;
1769   if(lir_inkey=='Y')
1770     {
1771     savefile_repeat_flag=1;
1772     }
1773   else
1774     {
1775     if(lir_inkey != 'N')goto savrpt;
1776     savefile_repeat_flag=0;
1777     }
1778   if( wav_read_flag != 0)
1779     {
1780     if(ui.rx_ad_channels == 2)
1781       {
1782       lir_text(5,6,"Stereo recording. Interpret as I/Q data (Y/N) ?");
1783 wawiq:;
1784       to_upper_await_keyboard();
1785       if(kill_all_flag) return;
1786       if(lir_inkey=='Y')
1787         {
1788         iqflag=1;
1789         lir_text(5,7,"Invert frequency scale (Y/N) ?");
1790 diriq:;
1791         to_upper_await_keyboard();
1792         if(kill_all_flag) return;
1793         if(lir_inkey=='Y')
1794           {
1795           dirflag=1;
1796           }
1797         else
1798           {
1799           if(lir_inkey != 'N')goto diriq;
1800           dirflag=0;
1801           }
1802         }
1803       else
1804         {
1805         if(lir_inkey != 'N')goto wawiq;
1806         iqflag=0;
1807         fg.passband_center=0.000001*ui.rx_ad_speed/4;
1808         freq_from_file=TRUE;
1809         }
1810       }
1811     else
1812       {
1813       ui.rx_rf_channels=1;
1814       fg.passband_center=0.000001*ui.rx_ad_speed/4;
1815       freq_from_file=TRUE;
1816       }
1817     }
1818   if(savefile_parname[0]!=0)
1819     {
1820     file = fopen( savefile_parname, "r");
1821     if(file == NULL) parwrite_flag=1;
1822     }
1823   settextcolor(7);
1824   }
1825 set_wav_parms();
1826 if(parfile_flag == 0)parfilnam=rxpar_filenames[rx_mode];
1827 file = fopen(rxpar_filenames[rx_mode], "r");
1828 if(file == NULL)
1829   {
1830   sprintf(s,"%s file missing",rxpar_filenames[rx_mode]);
1831   prompt_reason(s);
1832 iniparm:;
1833   if(kill_all_flag) return;
1834   for(i=0; i<MAX_GENPARM; i++)
1835     {
1836     genparm[i]=genparm_default[rx_mode][i];
1837     }
1838 // The default mix1 bandwidth reduction will be fine when
1839 // the sampling rate is 96 kHz I/Q.
1840   t1=96000;
1841   if( (ui.rx_input_mode&IQ_DATA) == 0)t1*=2;
1842   t1=ui.rx_ad_speed/t1;
1843   if(t1 > 1)
1844     {
1845     while(t1>1.5)
1846       {
1847       t1*=0.5;
1848       genparm[MIX1_BANDWIDTH_REDUCTION_N]++;
1849       }
1850     }
1851   if(t1 < 1)
1852     {
1853     while(t1<0.7)
1854       {
1855       t1*=2;
1856       genparm[MIX1_BANDWIDTH_REDUCTION_N]--;
1857       }
1858     genparm[MIX1_BANDWIDTH_REDUCTION_N]-=make_power_of_two(&i);
1859     }
1860   fix_limits(&imax, &imin,MIX1_BANDWIDTH_REDUCTION_N);
1861   if(genparm[MIX1_BANDWIDTH_REDUCTION_N] > imax)
1862                            genparm[MIX1_BANDWIDTH_REDUCTION_N]= imax;
1863   if(genparm[MIX1_BANDWIDTH_REDUCTION_N] < imin)
1864                            genparm[MIX1_BANDWIDTH_REDUCTION_N]= imin;
1865   genparm[MAX_GENPARM]=ui.rx_ad_speed;
1866 updparm:;
1867   if(diskread_flag == 4)
1868     {
1869     if(init_diskread(-1) != 0)
1870       {
1871       lirerr(3641);
1872       return;
1873       }
1874     }
1875   set_wav_parms();
1876   set_general_parms(rxmodes[rx_mode]);
1877   if(kill_all_flag)return;
1878   genparm[MAX_GENPARM+1]=GENPARM_VERNR;
1879   if(diskread_flag == 0)save_uiparm();
1880   if(savefile_parname[0]!=0)
1881     {
1882 write_savefile_parms:;
1883     parwrite_flag=0;
1884     parfilnam=savefile_parname;
1885     file = fopen(parfilnam, "w");
1886     if(file == NULL)goto wrerr;
1887     fprintf(file,"%c%c",rx_mode+'A',savefile_repeat_flag+'0');
1888     if( wav_read_flag != 0)
1889       {
1890       fprintf(file,"%c%c", iqflag+'0', dirflag+'0');
1891       }
1892     fprintf(file,"\n");
1893     goto wrok;
1894     }
1895   file = fopen(parfilnam, "w");
1896   if(file == NULL)
1897     {
1898 wrerr:;
1899     clear_screen();
1900     could_not_create(parfilnam,0);
1901     return;
1902     }
1903 wrok:;
1904   for(i=0; i<MAX_GENPARM+2; i++)
1905     {
1906     fprintf(file,"%s [%d]\n",genparm_text[i],genparm[i]);
1907     }
1908   parfile_end(file);
1909   file=NULL;
1910   }
1911 else
1912   {
1913   parfilnam=rxpar_filenames[rx_mode];
1914 fileok:;
1915   parinfo=malloc(4096);
1916   if(parinfo == NULL)
1917     {
1918     fclose(file);
1919     lirerr(1081);
1920     return;
1921     }
1922   for(i=0; i<4096; i++)parinfo[i]=0;
1923   kmax=fread(parinfo,1,4095,file);
1924   fclose(file);
1925   file=NULL;
1926   if(kmax >= 4095)
1927     {
1928     sprintf(ss,"Excessive file size");
1929 daterr:;
1930     sprintf(s,"%s Data error in file %s",ss,parfilnam);
1931     prompt_reason(s);
1932     goto iniparm;
1933     }
1934   k=0;
1935   for(i=0; i<MAX_GENPARM+2; i++)
1936     {
1937     while(k <= kmax && (parinfo[k]==' ' || parinfo[k]== '\n' ))k++;
1938     if(k > kmax)
1939       {
1940       sprintf(ss,"Premature end of file");
1941 daterr_free:;
1942       parinfo=chk_free(parinfo);
1943       goto daterr;
1944       }
1945     j=0;
1946     while(parinfo[k]== genparm_text[i][j])
1947       {
1948       k++;
1949       j++;
1950       }
1951     sprintf(ss,"Error: %s  ",genparm_text[i]);
1952     if(genparm_text[i][j] != 0 || k > kmax)
1953       {
1954       goto daterr_free;
1955       }
1956     while(k <= kmax && parinfo[k]!='[')k++;
1957     if(k > kmax)
1958       {
1959       goto daterr_free;
1960       }
1961     sscanf(&parinfo[k],"[%d]",&genparm[i]);
1962     while(k <= kmax && parinfo[k]!='\n')k++;
1963     if(k > kmax)
1964       {
1965       goto daterr_free;
1966       }
1967     }
1968   parinfo=chk_free(parinfo);
1969   if(diskread_flag == 4)
1970     {
1971     if(init_diskread(-1) != 0)
1972       {
1973       lirerr(3641);
1974       free(parinfo);
1975       return;
1976       }
1977     }
1978   else
1979     {
1980     if( fabs( (float)(genparm[MAX_GENPARM] - ui.rx_ad_speed)/
1981              (genparm[MAX_GENPARM] + ui.rx_ad_speed)) > 0.0002)
1982       {
1983       sprintf(s,"Input sampling speed changed %d  (old=%d)",
1984                                        ui.rx_ad_speed, genparm[MAX_GENPARM]);
1985       prompt_reason(s);
1986       goto iniparm;
1987       }
1988     }
1989   set_wav_parms();
1990   if(genparm[MAX_GENPARM+1] != (int)(GENPARM_VERNR))
1991     {
1992     prompt_reason("GENPARM version changed");
1993     goto iniparm;
1994     }
1995   if(rx_mode!=MODE_WCW && rx_mode!=MODE_NCW && rx_mode!=MODE_HSMS &&
1996                                          genparm[CW_DECODE_ENABLE] != 0)
1997     {
1998     prompt_reason("Mode not compatible with morse decode");
1999     goto iniparm;
2000     }
2001   for(i=0; i<MAX_GENPARM; i++)
2002     {
2003     if(genparm[i] < genparm_min[i] || genparm[i] > genparm_max[i])
2004       {
2005 illegal_value:;
2006       sprintf(s,"Illegal value for %s: %d (%d to %d)",genparm_text[i],
2007                                    genparm[i],genparm_min[i], genparm_max[i]);
2008       prompt_reason(s);
2009       goto iniparm;
2010       }
2011     }
2012   fft1mode=(ui.rx_input_mode&(TWO_CHANNELS+IQ_DATA))/2;
2013   i=fft1_version[fft1mode][genparm[FIRST_FFT_VERNR]];
2014   if( i < 0 || i>=MAX_FFT_VERSIONS)
2015     {
2016     prompt_reason("FFT1 version incompatible with A/D mode");
2017     goto iniparm;
2018     }
2019   if(simd_present == 0)
2020     {
2021     if( fft_cntrl[i].simd != 0)
2022       {
2023       prompt_reason("Parameters say use SIMD - not supported by computer!");
2024       goto iniparm;
2025       }
2026     }
2027   if(genparm[SECOND_FFT_ENABLE] != 0)
2028     {
2029     if(mmx_present == 0)
2030       {
2031       if( fft_cntrl[i].mmx != 0)
2032         {
2033 nommx:;
2034 #if IA64 == 0
2035         prompt_reason("Parameters say use MMX - not supported by computer!");
2036 #else
2037         prompt_reason("Parameters say use MMX - not (yet?) supported on IA64!");
2038 #endif
2039         goto iniparm;
2040         }
2041       }
2042     i=fft1_back_version[ui.rx_rf_channels-1][genparm[FIRST_BCKFFT_VERNR]];
2043     if( i < 0 || i>=MAX_FFT_VERSIONS)
2044       {
2045       prompt_reason("Backwards FFT1 version incompatible with no of channels");
2046       goto iniparm;
2047       }
2048     if(mmx_present == 0)
2049       {
2050       if( fft_cntrl[i].mmx != 0)goto nommx;
2051       }
2052     i=fft2_version[ui.rx_rf_channels-1][genparm[SECOND_FFT_VERNR]];
2053     if( i < 0 || i>=MAX_FFT_VERSIONS)
2054       {
2055       prompt_reason("FFT2 version incompatible with no of channels");
2056       goto iniparm;
2057       }
2058     if(mmx_present == 0)
2059       {
2060       if( fft_cntrl[i].mmx != 0)goto nommx;
2061       }
2062 // Make sure fft1_n and fft2_n are defined.
2063     get_wideband_sizes();
2064     if(kill_all_flag) return;
2065     k=(fft1_n-4)&0xfffe;
2066     if(genparm[FIRST_BCKFFT_ATT_N]>k)
2067       {
2068       i=FIRST_BCKFFT_ATT_N;
2069       goto illegal_value;
2070       }
2071     k=fft2_n-2;
2072     if(genparm[SECOND_FFT_ATT_N]>k)
2073       {
2074       i=SECOND_FFT_ATT_N;
2075       goto illegal_value;
2076       }
2077     }
2078   if(genparm[DA_OUTPUT_SPEED] > ui.rx_max_da_speed||
2079                genparm[DA_OUTPUT_SPEED] < ui.rx_min_da_speed)
2080     {
2081     sprintf(s,"Output sampling speed out of range %d  (%d to %d)",
2082                               genparm[DA_OUTPUT_SPEED],ui.rx_min_da_speed,
2083                                                           ui.rx_max_da_speed);
2084     prompt_reason(s);
2085     goto iniparm;
2086     }
2087   check_output_no_of_channels();
2088   }
2089 if( wav_read_flag != 0)
2090   {
2091   if(iqflag==1)
2092     {
2093     ui.rx_rf_channels=1;
2094     ui.rx_input_mode|=IQ_DATA;
2095     }
2096   else
2097     {
2098     ui.rx_input_mode|=TWO_CHANNELS;
2099     }
2100   if(dirflag == 1)
2101     {
2102     fg.passband_direction=-1;
2103     }
2104   else
2105     {
2106     fg.passband_direction=1;
2107     }
2108   fft1_direction=fg.passband_direction;
2109   }
2110 if(genparm[AFC_ENABLE] == 0)
2111   {
2112   genparm[CW_DECODE_ENABLE]=0;
2113   }
2114 if(parwrite_flag!=0)goto write_savefile_parms;
2115 }
2116 
2117 
main_menu(void)2118 void main_menu(void)
2119 {
2120 int rx_rf_channels;
2121 int first_keypress;
2122 int i, j, k;
2123 int uiupd, line;
2124 char s[256], ss[80];
2125 int message_line;
2126 FILE *file;
2127 int *uiparm;
2128 uiparm=(int*)(&ui);
2129 rx_rf_channels=ui.rx_rf_channels;
2130 lir_mutex_init();
2131 eme_flag=0;
2132 first_keypress=0;
2133 iqflag=0;
2134 dirflag=0;
2135 read_eme_database();
2136 linrad_thread_create(THREAD_SYSCALL);
2137 if(kill_all_flag) goto menu_x;
2138 // Save the ui parameters.
2139 // The user has set up the sound cards for normal operation
2140 // with his hardware but some routines, e.g. txtest may change
2141 // the A/D parameters and/or other parameters.
2142 // We will always start here with the initial ui parameters.
2143 if (ui.max_dma_rate < MIN_DMA_RATE || ui.max_dma_rate > MAX_DMA_RATE)
2144   {
2145   ui.max_dma_rate=DEFAULT_MAX_DMA_RATE;
2146   }
2147 if (ui.min_dma_rate < MIN_DMA_RATE || ui.min_dma_rate > ui.max_dma_rate)
2148   {
2149   ui.min_dma_rate=DEFAULT_MIN_DMA_RATE;
2150   }
2151 if ( ui.min_dma_rate > ui.max_dma_rate)
2152   {
2153   ui.min_dma_rate=ui.max_dma_rate;
2154   }
2155 compute_converter_parameters();
2156 verify_network(FALSE);
2157 save_uiparm();
2158 menu_loop:;
2159 if(kill_all_flag)goto menu_x;
2160 tx_setup_flag=FALSE;
2161 lir_set_title("");
2162 restore_uiparm();
2163 clear_screen();
2164 settextcolor(12);
2165 display_rx_input_source(ss);
2166 sprintf(s,"%s   %s",PROGRAM_NAME, ss);
2167 lir_text(14,0,s);
2168 if((ui.network_flag&NET_RX_OUTPUT) != 0)lir_text(0,0,"NETSEND");
2169 lir_refresh_screen();
2170 if(kill_all_flag)goto menu_x;
2171 line=2;
2172 settextcolor(14);
2173 if(ui.operator_skil == OPERATOR_SKIL_NEWCOMER)
2174   {
2175   lir_text(14,1,"newcomer mode");
2176   line++;
2177   }
2178 if(ui.operator_skil == OPERATOR_SKIL_EXPERT)
2179   {
2180   lir_text(14,1,"expert mode");
2181   line++;
2182   }
2183 message_line=line;
2184 settextcolor(7);
2185 button_color=7;
2186 if(ui.rx_addev_no != DISABLED_DEVICE_CODE)
2187   {
2188   for(i=0; i<MAX_RX_MODE; i++)
2189     {
2190     if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER || newcomer_rx_modes[i] != 0)
2191       {
2192       if(ui.operator_skil == OPERATOR_SKIL_EXPERT || i != MODE_TUNE)
2193         {
2194         sprintf(s,"%c=%s",i+'A',rxmodes[i]);
2195         lir_text(0, line, s);
2196         line++;
2197         }
2198       }
2199     }
2200   }
2201 if((ui.network_flag&NET_RX_INPUT) == 0)
2202   {
2203   lir_text(30,message_line,"1=Process first file named in 'adfile'");
2204   message_line++;
2205   lir_text(30,message_line,"2=Process first file named in 'adwav'");
2206   message_line++;
2207   lir_text(30,message_line,"3=Select file from 'adfile'");
2208   message_line++;
2209   lir_text(30,message_line,"4=Select file from 'adwav'");
2210   message_line++;
2211   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2212     {
2213     lir_text(30,message_line,"5=File converter .raw to .wav");
2214     message_line++;
2215     }
2216   }
2217 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2218   {
2219   lir_text(30,message_line,"T=Toggle network output");
2220   message_line++;
2221   }
2222 if(message_line > line)line=message_line;
2223 line++;
2224 settextcolor(3);
2225 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2226   {
2227   lir_text(0, line  , "M=Init moon tracking and EME database");
2228   line++;
2229   lir_text(0, line, "N=Network set up");
2230   line++;
2231   }
2232 lir_text(0, line, "S=Global parms set up");
2233 line++;
2234 lir_text(0, line, "U=A/D and D/A set up for RX");
2235 line++;
2236 if(ui.operator_skil == OPERATOR_SKIL_EXPERT)
2237   {
2238   lir_text(0, line, "V=TX mode set up");
2239   line++;
2240   }
2241 lir_text(0, line, "W=Save current parameters in par_userint");
2242 line++;
2243 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER &&
2244                                    (ui.network_flag&NET_RX_INPUT) == 0)
2245   {
2246   switch (ui.soundcard_radio)
2247     {
2248     case SOUNDCARD_RADIO_WSE:
2249     lir_text(0, line, "Z=WSE hardware interface test");
2250     line++;
2251     break;
2252 
2253     default:
2254     break;
2255     }
2256   }
2257 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2258   {
2259   lir_text(0, line, "F9=Emergency light");
2260   line++;
2261   }
2262 lir_text(0, line, "ESC=Quit program");
2263 settextcolor(14);
2264 lir_text(0, line, "F1 or !=Show keyboard commands (HELP)");
2265 line++;
2266 if(kill_all_flag)goto menu_x;
2267 message_line=line+1;
2268 if(uiparm_change_flag==TRUE)
2269   {
2270   settextcolor(15);
2271   lir_text(5,message_line+1,"PARAMETERS NOT SAVED Press ""W"" to save");
2272   }
2273 settextcolor(7);
2274 if(kill_all_flag) goto menu_x;
2275 if(ui.operator_skil == OPERATOR_SKIL_EXPERT && first_keypress == 0 &&
2276                            ui.autostart >= 'A' && ui.autostart <= 'G')
2277   {
2278   lir_inkey=ui.autostart;
2279   }
2280 else
2281   {
2282   if(first_keypress > 1)
2283     {
2284     lir_inkey=first_keypress;
2285     lir_sleep(300000);
2286     }
2287   else
2288     {
2289     to_upper_await_keyboard();
2290     if(kill_all_flag) goto menu_x;
2291     }
2292   }
2293 first_keypress=1;
2294 savefile_parname[0]=0;
2295 calibrate_flag=0;
2296 diskread_flag=0;
2297 file_start_block=-1;
2298 file_stop_block=-1;
2299 diskwrite_flag=FALSE;
2300 freq_from_file=FALSE;
2301 if(ui.use_extio != 0 && ui.extio_type != 4)
2302   {
2303   rx_input_thread = THREAD_EXTIO_INPUT;
2304   }
2305 else
2306   {
2307   rx_input_thread=THREAD_RX_ADINPUT;
2308   if(ui.rx_addev_no == SDR14_DEVICE_CODE ||
2309      ui.rx_addev_no == SDRIQ_DEVICE_CODE )rx_input_thread=THREAD_SDR14_INPUT;
2310   if(ui.rx_addev_no == PERSEUS_DEVICE_CODE)rx_input_thread=THREAD_PERSEUS_INPUT;
2311   if(ui.rx_addev_no == SDRIP_DEVICE_CODE)rx_input_thread=THREAD_SDRIP_INPUT;
2312   if(ui.rx_addev_no == EXCALIBUR_DEVICE_CODE)
2313                                        rx_input_thread=THREAD_EXCALIBUR_INPUT;
2314   if(ui.rx_addev_no == RTL2832_DEVICE_CODE)
2315                                        rx_input_thread=THREAD_RTL2832_INPUT;
2316   if(ui.rx_addev_no == MIRISDR_DEVICE_CODE)
2317                                        rx_input_thread=THREAD_MIRISDR_INPUT;
2318   if(ui.rx_addev_no == BLADERF_DEVICE_CODE)
2319                                        rx_input_thread=THREAD_BLADERF_INPUT;
2320   if(ui.rx_addev_no == PCIE9842_DEVICE_CODE)
2321                                        rx_input_thread=THREAD_PCIE9842_INPUT;
2322   if(ui.rx_addev_no == OPENHPSDR_DEVICE_CODE)
2323                                        rx_input_thread=THREAD_OPENHPSDR_INPUT;
2324   if(ui.rx_addev_no == NETAFEDRI_DEVICE_CODE)rx_input_thread=THREAD_NETAFEDRI_INPUT;
2325   }
2326 if(kill_all_flag)goto menu_x;
2327 sys_func(THRFLAG_PORTAUDIO_STARTSTOP);
2328 ampinfo_reset=workload_reset_flag-1;
2329 curv_xpixel=0;
2330 flat_xpixel=0;
2331 parfilnam=NULL;
2332 lir_status=LIR_OK;
2333 wg_freq_x1=-1;
2334 wav_read_flag=0;
2335 switch ( lir_inkey )
2336   {
2337   case 'T':
2338   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2339     {
2340     if( (ui.network_flag&NET_RX_OUTPUT) == 0)
2341       {
2342       ui.network_flag|=NET_RX_OUTPUT;
2343       }
2344     else
2345       {
2346       ui.network_flag&=NET_RX_INPUT;
2347       }
2348     verify_network(FALSE);
2349     save_uiparm();
2350     uiparm_change_flag=TRUE;
2351     }
2352   break;
2353 
2354   case 'M':
2355   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2356     {
2357     init_eme_database();
2358     if(kill_all_flag) goto menu_x;
2359     }
2360   break;
2361 
2362   case F1_KEY:
2363   case '!':
2364   help_message(1);
2365   if(kill_all_flag) goto menu_x;
2366   break;
2367 
2368   case F8_KEY:
2369   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2370     {
2371     clear_screen();
2372     lir_text(0,0,"Currently selected font (see fonts.c)");
2373     for(i=0; i<16; i++)
2374       {
2375       for(j=0; j<16; j++)
2376         {
2377         k=16*i+j;
2378         sprintf(s,"%c[%2x]",k,k);
2379         lir_text(j*8,i+2,s);
2380         }
2381       }
2382     while(!kill_all_flag)
2383       {
2384       await_keyboard();
2385       sprintf(s,"lir_inkey=%d =0x%02x",lir_inkey,lir_inkey);
2386       clear_lines(22,22);
2387       lir_text(0,22,s);
2388       }
2389     }
2390   break;
2391 
2392   case F9_KEY:
2393   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2394     {
2395     lir_fillbox(0,0,screen_width,screen_height,15);
2396     await_keyboard();
2397     }
2398   break;
2399 
2400   case '1':
2401   case '3':
2402   if((ui.network_flag&NET_RX_INPUT) == 0)
2403     {
2404     if(ui.rx_dadev_no == -1)goto setad;
2405     rx_input_thread=THREAD_RX_FILE_INPUT;
2406     if(init_diskread(lir_inkey-'1') == 0)
2407       {
2408       goto do_pc_radio;
2409       }
2410     }
2411   break;
2412 
2413   case '2':
2414   case '4':
2415   if((ui.network_flag&NET_RX_INPUT) == 0)
2416     {
2417     if(ui.rx_dadev_no == -1)goto setad;
2418     wav_read_flag=1;
2419     rx_input_thread=THREAD_RX_FILE_INPUT;
2420     if(init_diskread(lir_inkey-'2') == 0)
2421       {
2422       goto do_pc_radio;
2423       }
2424     }
2425   break;
2426 
2427   case '5':
2428   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2429     {
2430     wav_read_flag=0;
2431     raw2wav();
2432     }
2433   break;
2434 
2435   case 'U':
2436 setad:;
2437   sys_func(THRFLAG_SET_RX_IO);
2438   if(kill_all_flag) goto menu_x;
2439   verify_network(FALSE);
2440   save_uiparm();
2441   uiparm_change_flag=TRUE;
2442   break;
2443 
2444   case 'V':
2445   if(ui.operator_skil == OPERATOR_SKIL_EXPERT)
2446     {
2447     tx_setup_flag=TRUE;
2448     sys_func(THRFLAG_TX_SETUP);
2449     tx_setup_flag=FALSE;
2450     if(kill_all_flag) goto menu_x;
2451     save_uiparm();
2452     uiparm_change_flag=TRUE;
2453     }
2454   break;
2455 
2456   case 'Z':
2457   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2458     {
2459     switch (ui.soundcard_radio)
2460       {
2461       case SOUNDCARD_RADIO_WSE:
2462       hware_interface_test();
2463       if(kill_all_flag) goto menu_x;
2464       break;
2465 
2466       default:
2467       break;
2468       }
2469     }
2470   break;
2471 
2472   case 'N':
2473   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
2474     {
2475     ui.network_flag=NET_RX_INPUT;
2476     verify_network(TRUE);
2477     if(kill_all_flag) goto menu_x;
2478     save_uiparm();
2479     uiparm_change_flag=TRUE;
2480     }
2481   break;
2482 
2483   case 'S':
2484   switch (os_flag)
2485     {
2486     case OS_FLAG_SVGALIB:
2487     lin_global_uiparms(1);
2488     break;
2489 
2490     case OS_FLAG_WINDOWS:
2491     win_global_uiparms(1);
2492     break;
2493 
2494     case OS_FLAG_X:
2495     x_global_uiparms(1);
2496     break;
2497     }
2498   if(kill_all_flag) goto menu_x;
2499   save_uiparm();
2500   uiparm_change_flag=TRUE;
2501   break;
2502 
2503   case 'W':
2504   file = fopen(userint_filename, "w");
2505   if (file == NULL)
2506     {
2507     lirerr(1029);
2508     goto menu_x;
2509     }
2510   ui.check=UI_VERNR;
2511   for(i=0; i<MAX_UIPARM; i++)
2512     {
2513     fprintf(file,"%s [%d]\n",uiparm_text[i],uiparm[i]);
2514     }
2515   parfile_end(file);
2516   if(kill_all_flag) goto menu_x;
2517   settextcolor(15);
2518   clear_lines(message_line+1,message_line+1);
2519   lir_text(0, message_line, "User interface setup saved");
2520   k=message_line;
2521   for(i=0; i<MAX_UIPARM-1; i+=2)
2522     {
2523     if( k < screen_last_line)
2524       {
2525       k++;
2526       sprintf(s,"%s [%d] ",uiparm_text[i],uiparm[i]);
2527       lir_text(5,k, s);
2528       sprintf(s,"%s [%d] ",uiparm_text[i+1],uiparm[i+1]);
2529       lir_text(40,k, s);
2530       }
2531     }
2532   if(i < MAX_UIPARM-1)
2533     {
2534     i++;
2535     sprintf(s,"%s [%d] ",uiparm_text[i],uiparm[i]);
2536     if( (message_line+i+1) <= screen_last_line)lir_text(5,message_line+i+1, s);
2537     }
2538   settextcolor(7);
2539   await_processed_keyboard();
2540   if(kill_all_flag) goto menu_x;
2541   first_keypress=lir_inkey;
2542   uiparm_change_flag=FALSE;
2543   goto menu_loop;
2544 
2545   default:
2546   if(ui.rx_addev_no == DISABLED_DEVICE_CODE)break;
2547   if(ui.rx_addev_no == UNDEFINED_DEVICE_CODE)goto setad;
2548   rx_mode=(lir_inkey-'A');
2549   if( rx_mode < 0 || rx_mode>=MAX_RX_MODE)goto menu_loop;
2550   if(ui.operator_skil == OPERATOR_SKIL_NEWCOMER && newcomer_rx_modes[rx_mode]==0)goto menu_loop;
2551   if(ui.operator_skil != OPERATOR_SKIL_EXPERT && rx_mode == MODE_TUNE)goto menu_loop;
2552   if( (ui.network_flag&NET_RX_INPUT)==0 && ui.rx_input_mode < 0)goto setad;
2553 do_pc_radio:;
2554   if(ui.rx_dadev_no == DISABLED_DEVICE_CODE)
2555     {
2556     ui.rx_max_da_speed=1000000;
2557     ui.rx_min_da_speed=5000;
2558     ui.rx_max_da_channels=2;
2559     ui.rx_min_da_channels=2;
2560     }
2561   if(ui.rx_max_da_channels==0)goto setad;
2562   if( ui.rx_min_da_speed < 1000  ||
2563      ui.rx_max_da_speed < ui.rx_min_da_speed)
2564     {
2565     clear_screen();
2566     lir_text(3,3,"ERROR: illegal limits for Rx D/A speed");
2567     lir_text(5,5,press_any_key);
2568     await_keyboard();
2569     goto setad;
2570     }
2571   calibrate_flag=0;
2572   parfilnam=NULL;
2573   open_mouse();
2574   uiupd=FALSE;
2575   if((ui.network_flag&NET_RX_INPUT) == 0)
2576     {
2577 updparm:;
2578     init_genparm(uiupd);
2579     if(kill_all_flag) goto menu_x;
2580     }
2581   clear_screen();
2582   settextcolor(7);
2583 #if (USERS_EXTRA_PRESENT == 1)
2584   init_users_extra();
2585 #endif
2586   lir_status=LIR_OK;
2587   lir_rxout_status=LIR_OK;
2588   lir_rxin_status=LIR_OK;
2589   fft1_waterfall_flag=0;
2590   all_threads_started=FALSE;
2591   cg.oscill_on=0;
2592   first_txproc_no=tg.spproc_no;
2593   use_tx=ui.tx_enable;
2594   if(diskread_flag >= 2 ||
2595      ui.tx_addev_no == UNDEFINED_DEVICE_CODE ||
2596      ui.tx_dadev_no == UNDEFINED_DEVICE_CODE)use_tx=0;
2597   if(read_txpar_file()==FALSE)use_tx=0;
2598   if(!ftdi_library_flag)
2599     {
2600     if( ui.soundcard_radio == SOUNDCARD_RADIO_ELEKTOR ||
2601         ui.soundcard_radio == SOUNDCARD_RADIO_SOFT66)
2602       {
2603       i=load_ftdi_library();
2604       if(i != 0)goto menu_loop;
2605       }
2606     if(ui.soundcard_radio == SOUNDCARD_RADIO_SOFT66)
2607       {
2608       load_soft66_library();
2609       if(!soft66_library_flag)goto menu_loop;
2610       }
2611     }
2612   switch (rx_mode)
2613     {
2614     case MODE_WCW:
2615     case MODE_NCW:
2616     case MODE_HSMS:
2617     case MODE_SSB:
2618     case MODE_QRSS:
2619     use_bfo=1;
2620     goto do_normal_rx;
2621 
2622     case MODE_FM:
2623     case MODE_AM:
2624     use_bfo=0;
2625 do_normal_rx:;
2626     i=ui.rx_ad_speed;
2627     normal_rx_routine();
2628     if(i != ui.rx_ad_speed)
2629       {
2630       save_uiparm();
2631       uiparm_change_flag=TRUE;
2632       }
2633     if(lir_status == LIR_DLL_FAILED)goto menu_loop;
2634     break;
2635 
2636     case MODE_TXTEST:
2637     txtest_routine();
2638     if(lir_status == LIR_DLL_FAILED)goto menu_loop;
2639     if(kill_all_flag)goto menu_x;
2640     goto txtest_exit;
2641 
2642 // Soundcard test mode
2643     case MODE_RX_ADTEST:
2644     rx_adtest_routine();
2645     if(lir_status == LIR_DLL_FAILED)goto menu_loop;
2646     break;
2647 
2648 // Tune WSE hardware.
2649     case MODE_TUNE:
2650     tune_wse_routine();
2651     if(lir_status == LIR_DLL_FAILED)goto menu_loop;
2652     break;
2653 
2654     case MODE_RADAR:
2655     radar_routine();
2656     if(lir_status == LIR_DLL_FAILED)goto menu_loop;
2657     break;
2658 
2659     default:
2660     lirerr(436);
2661     }
2662 rx_modes_exit:;
2663   if(kill_all_flag) goto menu_x;
2664   close_network_sockets();
2665   rx_rf_channels=ui.rx_rf_channels;
2666   if( (diskread_flag&(2+4+8)) != 0)
2667     {
2668     restore_uiparm();
2669     diskread_flag=4;
2670     fclose(save_rd_file);
2671     save_rd_file=NULL;
2672     }
2673 txtest_exit:;
2674   free_buffers();
2675 // *******************************************************************
2676 // ******************* main exit from processing modes ***************
2677   if(lir_rxout_status != LIR_OK)
2678     {
2679     clear_screen();
2680     lir_text(5,5,"Soundcard for Rx output disabled");
2681     lir_text(5,6,"Could not be opened at specified speed");
2682     lir_text(5,7,"In duplex mode the same speed may be necessary for");
2683     lir_text(5,8,"output and input. The device speed may be locked");
2684     lir_text(5,9,"by Linrad input or some other application.");
2685     lir_text(10,12,press_any_key);
2686     await_keyboard();
2687     if(kill_all_flag) goto menu_x;
2688     lir_status = LIR_OK;
2689     goto menu_loop;
2690     }
2691   switch(lir_status)
2692     {
2693     case LIR_TUNEERR:
2694     goto menu_loop;
2695 
2696     case LIR_SAVE_UIPARM:
2697     save_uiparm();
2698     goto menu_loop;
2699 
2700     case LIR_FFT1ERR:
2701     clear_screen();
2702     lir_text(5,5,"Out of memory. Try less demanding parameters");
2703     lir_text(5,8,press_any_key);
2704     await_keyboard();
2705     if(kill_all_flag) goto menu_x;
2706 go_updparm:;
2707     uiupd=TRUE;
2708     restore_uiparm();
2709     goto updparm;
2710 
2711     case LIR_NEW_POL:
2712     clear_screen();
2713     select_pol_default();
2714     if(kill_all_flag) goto menu_x;
2715     lir_status = LIR_OK;
2716     goto do_pc_radio;
2717 
2718     case LIR_POWTIM:
2719     goto do_pc_radio;
2720     }
2721   if(lir_status < LIR_OK)
2722     {
2723     goto go_updparm;
2724     }
2725   fft1_waterfall_flag=0;
2726 wt_kbd:;
2727   clear_screen();
2728   line=0;
2729   settextcolor(12);
2730   lir_text(25,line,PROGRAM_NAME);
2731   if(diskread_flag >=2 )
2732     {
2733     settextcolor(14);
2734     lir_text(40,line,savefile_name);
2735     }
2736   line+=2;
2737   settextcolor(15);
2738   sprintf(s,"F1 = Info about the %s mode",rxmodes[rx_mode]);
2739   lir_text(11,line,s);
2740   line++;
2741   sprintf(s,"B = Back to %s without change",rxmodes[rx_mode]);
2742   lir_text(12,line,s);
2743   line++;
2744   lir_text(12,line,"P = Change parameters");
2745   line++;
2746   lir_text(12,line,"C = Calibrate");
2747   line++;
2748   if(rx_rf_channels == 2)
2749     {
2750     lir_text(12,line,"D = Select Pol. default");
2751     line++;
2752     }
2753   line++;
2754   settextcolor(7);
2755   sprintf(s,"Current parameters (file: %s)",parfilnam);
2756   lir_text(2,line,s);
2757   line++;
2758   for(i=0; i<MAX_GENPARM+1; i++)
2759     {
2760     sprintf(s,"%s [%d] ",genparm_text[i],genparm[i]);
2761     if( line <= screen_last_line)lir_text(2,line, s);
2762     line++;
2763     }
2764   await_processed_keyboard();
2765   if(kill_all_flag) goto menu_x;
2766   switch (lir_inkey)
2767     {
2768     case 'B':
2769     goto do_pc_radio;
2770 
2771     case 'C':
2772     if((ui.network_flag&NET_RX_INPUT) == 0)
2773       {
2774       init_genparm(FALSE);
2775       if(kill_all_flag) goto menu_x;
2776       }
2777     cal_package();
2778     lir_status=LIR_OK;
2779     goto rx_modes_exit;
2780 
2781     case 'D':
2782     if(rx_rf_channels == 2)select_pol_default();
2783     if(kill_all_flag) goto menu_x;
2784     break;
2785 
2786     case 'P':
2787     uiupd=TRUE;
2788     goto updparm;
2789 
2790     case F1_KEY:
2791     case '!':
2792     help_message(280+rx_mode);
2793     break;
2794 
2795     case 'X':
2796     goto menu_loop;
2797     }
2798   goto wt_kbd;
2799   }
2800 if(!kill_all_flag)goto menu_loop;
2801 menu_x:;
2802 close_mouse();
2803 free_buffers();
2804 close_network_sockets();
2805 if(portaudio_active_flag)sys_func(THRFLAG_PORTAUDIO_STOP);
2806 linrad_thread_stop_and_join(THREAD_SYSCALL);
2807 lir_mutex_destroy();
2808 show_errmsg(1);
2809 if(lir_errcod != 0)
2810   {
2811   lir_inkey=1;
2812   while(lir_inkey == 1)
2813     {
2814     await_keyboard();
2815     }
2816   }
2817 command_extio_library(EXTIO_COMMAND_KILL_ALL);
2818 unload_ftdi_library();
2819 unload_soft66_library();
2820 }
2821 
2822