1 
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 "globdef.h"
27 #include "uidef.h"
28 #include "screendef.h"
29 #include "vernr.h"
30 #include "sigdef.h"
31 #include "fft1def.h"
32 #include "fft2def.h"
33 #include "rusage.h"
34 #include "thrdef.h"
35 #include "caldef.h"
36 #include "powtdef.h"
37 #include "keyboard_def.h"
38 #include "sdrdef.h"
39 #include "conf.h"
40 #include "txdef.h"
41 #include "options.h"
42 
43 
44 extern void make_new_daout_upsamp(void);
45 
46 
47 #if(OSNUM == OSNUM_LINUX)
48 #include <pthread.h>
49 #include <semaphore.h>
50 #include "lconf.h"
51 #include "xdef.h"
52 #include "ldef.h"
53 
54 
55 #if (ALSA_PRESENT == 1)
56 // alsa definitions start
57 #include <alsa/asoundlib.h>
58 extern snd_pcm_t *rx_ad_handle, *rx_da_handle;
59 extern snd_pcm_t *tx_ad_handle, *tx_da_handle;
60 
61 extern int  alsa_dev_seq_nmbr;
62 extern char alsa_dev_soundcard_name [256];
63 extern char alsa_dev_name [64];
64 extern char alsa_dev_hw_pcm_name[16];
65 extern char alsa_dev_plughw_pcm_name[16];
66 
67 extern int  alsa_dev_min_rate;
68 extern int  alsa_dev_max_rate;
69 extern int  alsa_dev_min_channels;
70 extern int  alsa_dev_max_channels;
71 extern int  alsa_dev_min_bytes;
72 extern int  alsa_dev_max_bytes;
73 #endif
74 #endif
75 
76 #if(OSNUM == OSNUM_WINDOWS)
77 #include "wdef.h"
78 void win_semaphores(void);
79 #endif
80 
81 void set_sdrip_att(void);
82 void set_sdrip_frequency(void);
83 void set_netafedri_att(void);
84 void set_netafedri_frequency(void);
85 
86 
87 
do_syscall(void)88 void do_syscall(void)
89 {
90 thread_status_flag[THREAD_SYSCALL]=THRFLAG_ACTIVE;
91 while(thread_command_flag[THREAD_SYSCALL] != THRFLAG_KILL)
92   {
93   thread_status_flag[THREAD_SYSCALL]=THRFLAG_SEM_WAIT;
94   lir_await_event(EVENT_SYSCALL);
95   thread_status_flag[THREAD_SYSCALL]=THRFLAG_SEMCLEAR;
96   switch (thread_command_flag[THREAD_SYSCALL])
97     {
98     case THRFLAG_PORTAUDIO_STARTSTOP:
99     portaudio_startstop();
100     break;
101 
102     case THRFLAG_OPEN_RX_SNDIN:
103     open_rx_sndin(FALSE);
104     break;
105 
106     case THRFLAG_CLOSE_RX_SNDIN:
107     close_rx_sndin();
108     break;
109 
110     case THRFLAG_OPEN_RX_SNDOUT:
111     open_rx_sndout();
112     break;
113 
114     case THRFLAG_CLOSE_RX_SNDOUT:
115     close_rx_sndout();
116     break;
117 
118     case THRFLAG_OPEN_TX_SNDIN:
119     open_tx_sndin();
120     break;
121 
122     case THRFLAG_CLOSE_TX_SNDIN:
123     close_tx_sndin();
124     break;
125 
126     case THRFLAG_OPEN_TX_SNDOUT:
127     open_tx_sndout();
128     break;
129 
130     case THRFLAG_CLOSE_TX_SNDOUT:
131     close_tx_sndout();
132     break;
133 
134     case THRFLAG_SET_RX_IO:
135     set_rx_io();
136     break;
137 
138     case THRFLAG_TX_SETUP:
139     tx_setup();
140     break;
141 
142     case THRFLAG_PORTAUDIO_STOP:
143     portaudio_stop();
144     break;
145 
146     case THRFLAG_SET_SDRIP_ATT:
147     set_sdrip_att();
148     break;
149 
150     case THRFLAG_SET_SDRIP_FREQUENCY:
151     set_sdrip_frequency();
152     break;
153 
154     case THRFLAG_SET_NETAFEDRI_ATT:
155     set_netafedri_att();
156     break;
157 
158     case THRFLAG_SET_NETAFEDRI_FREQUENCY:
159     set_netafedri_frequency();
160     break;
161 
162     case THRFLAG_CALIBRATE_BLADERF_RX:
163     calibrate_bladerf_rx();
164     break;
165 
166     default:
167     goto nothing;
168     }
169   thread_status_flag[THREAD_SYSCALL]=THRFLAG_IDLE;
170   while(thread_command_flag[THREAD_SYSCALL]!=THRFLAG_KILL &&
171         thread_command_flag[THREAD_SYSCALL]!=THRFLAG_ACTIVE)
172     {
173     lir_await_event(EVENT_SYSCALL);
174     }
175 nothing:;
176   }
177 thread_status_flag[THREAD_SYSCALL]=THRFLAG_RETURNED;
178 }
179 
sys_func(int no)180 void sys_func(int no)
181 {
182 while(thread_status_flag[THREAD_SYSCALL] != THRFLAG_SEM_WAIT)
183   {
184   lir_sleep(3000);
185   if(kill_all_flag)return;
186   }
187 thread_command_flag[THREAD_SYSCALL]=(signed char)no;
188 lir_set_event(EVENT_SYSCALL);
189 while( thread_status_flag[THREAD_SYSCALL] != THRFLAG_IDLE)
190   {
191   lir_sleep(3000);
192   if(kill_all_flag)return;
193   }
194 thread_command_flag[THREAD_SYSCALL]=THRFLAG_ACTIVE;
195 lir_set_event(EVENT_SYSCALL);
196 }
197 
update_snd(int sound_type)198 void update_snd(int sound_type)
199 {
200 int i, k;
201 #if(OSNUM == OSNUM_LINUX)
202 #if (ALSA_PRESENT == 1)
203 int err;
204 #endif
205 #endif
206 #if(OSNUM == OSNUM_WINDOWS)
207 WAVEHDR *whdr;
208 #endif
209 i=0;
210 buftest:;
211 // This routine updates all the buffer info abut one sound device
212 // It replaces several routines in Linrad versions 03.08 and
213 // earlier.
214 // ********************************************************************
215 // ********************************************************************
216 //typedef struct audio_buf_info  in OSS
217 //	int fragments;     / # of available fragments (partially usend ones not counted)/
218 //	int fragstotal;    / Total # of fragments allocated in buffer/
219 //	int fragsize;      / Size of a fragment in bytes /
220 //	int bytes;         / Available space in bytes (includes partially used fragments) /
221 //
222 // A fragment in OSS is called a period in ALSA
223 // Unit of measurement in OSS for fragments is bytes
224 // Unit of measurement in ALSA  for periods and buffersizes is frames
225 //
226 // frame(alsa) == sample(oss) is the number of bytes for one sample.
227 // snd[xxx].framesize=#channels * #bytes for the selected format
228 //
229 // block(linrad) == period(alsa) == fragment(oss) is the block size
230 // that we believe the hardware DMA is using. We try to read and write
231 // to our devices one full block at a time.
232 // snd[xxx].block_bytes=the number of bytes in one block/period/fragment.
233 // snd[xxx].block_frames=the number of frames in one block/period/fragment.
234 //
235 
236 /*
237   rx_da_info.fragments=(int)frame_avail/(int) snd[RXDA].block_frames;
238   rx_da_info.fragstotal=((int)snd[RXDA].tot_frames)/(int) snd[RXDA].block_frames;
239   rx_da_info.fragsize=(int)snd[RXDA].block_frames*snd[RXDA].framesize;
240   rx_da_info.bytes=(int)frame_avail*snd[RXDA].framesize;
241 */
242 
243 
244 // ********************************************************
245 /*
246 // Structure for soundcard info. Buffer pointers etc.
247 typedef struct {
248 int no_of_blocks;
249 int valid_frames;
250 int valid_bytes;
251 int empty_frames;
252 int min_empty_frames;
253 int empty_bytes;
254 int tot_frames;
255 int tot_bytes;
256 int framesize;
257 int block_bytes;
258 int block_frames;
259 float interrupt_rate;
260 int newbuf_ptr;
261 int open_flag;
262 }SOUNDCARD_PARM;
263 */
264 // Count how many free blocks or frames we have.
265 k=0;
266 switch (sound_type)
267   {
268   case RXDA:
269   if(rx_audio_out == -1) return;
270   if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
271     {
272     snd[sound_type].empty_frames=
273                   snd[sound_type].tot_frames-snd[sound_type].block_frames;
274     k=snd[sound_type].no_of_blocks-1;
275     break;
276     }
277 #if(OSNUM == OSNUM_WINDOWS)
278   for(i=0; i< snd[RXDA].no_of_blocks; i++)
279     {
280     whdr=rxdaout_newbuf[i];
281     if( (whdr[0].dwFlags&WHDR_INQUEUE) == 0)k++;
282     }
283   snd[sound_type].empty_frames=k*snd[sound_type].block_frames;
284   break;
285 #else
286 #if (ALSA_PRESENT == 1)
287   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
288     {
289 //Try to synchronize stream position with hardware
290     err=snd_pcm_hwsync(rx_da_handle);
291 //Get # of frames available (for read or write.)
292     if(err != 0)
293       {
294       k=0;
295       }
296     else
297       {
298       k=snd_pcm_avail_update(rx_da_handle);
299       }
300     if(k < 0)k=0;
301     snd[sound_type].empty_frames=k;
302     }
303   else
304 #endif
305 #if(HAVE_OSS == 1)
306     {
307     if(ioctl(rx_audio_out,SNDCTL_DSP_GETOSPACE, &rx_da_info) == -1)
308       {
309       k=0;
310       }
311     else
312       {
313       k=rx_da_info.bytes;
314       }
315     snd[sound_type].empty_frames=k/snd[sound_type].framesize;
316     }
317 #endif
318 #endif
319   break;
320 
321   default:
322   break;
323   }
324 //************************************************************
325 // The number of bytes we can write is incorrectly zero sometimes
326 // in 4Front OSS. Maybe it could happen in other systems as well.
327 // wait a little and see if we get a correct value to return.
328 if(k == 0 && (sound_type == RXDA || sound_type == TXDA) )
329   {
330   lir_sleep(3000);
331   if(kill_all_flag)return;
332   i++;
333   if(i<5)goto buftest;
334   }
335 
336 snd[sound_type].empty_bytes=
337                   snd[sound_type].empty_frames*snd[sound_type].framesize;
338 snd[sound_type].valid_frames=
339                 snd[sound_type].tot_frames-snd[sound_type].empty_frames;
340 snd[sound_type].valid_bytes=
341                  snd[sound_type].tot_bytes-snd[sound_type].empty_bytes;
342 // ***************************************************************
343 if(snd[sound_type].min_valid_frames > snd[sound_type].valid_frames)
344                snd[sound_type].min_valid_frames=snd[sound_type].valid_frames;
345 }
346 
347 double q_time;
348 static double q_sum_time=0;
349 static int q_sumnum=0;
350 static int q_reset=-1;
351 
qt3(void)352 void qt3(void)
353 {
354 char s[80];
355 double dd;
356 if(q_reset != workload_reset_flag)
357   {
358   q_reset=workload_reset_flag;
359   q_sum_time=0;
360   q_sumnum=0;
361   return;
362   }
363 dd=current_time();
364 q_sum_time+=dd-q_time;
365 q_sumnum++;
366 if(q_sumnum%32==0)
367   {
368   sprintf(s,"[%f] ",q_sum_time/q_sumnum);
369   qq(s);
370   }
371 }
372 
qt0(void)373 void qt0(void)
374 {
375 q_time=current_time();
376 }
377 
qt1(char * cc)378 void qt1(char *cc)
379 {
380 double dd;
381 dd=current_time();
382 DEB"\n%s %f",cc,dd-q_time);
383 q_time=dd;
384 }
385 
qt2(char * cc)386 void qt2(char *cc)
387 {
388 double dd;
389 dd=current_time();
390 DEB"\n%s %f",cc,dd-q_time);
391 }
392 
kill_all(void)393 void kill_all(void)
394 {
395 int i,j,k;
396 kill_all_flag=TRUE;
397 lir_sleep(10000);
398 // Sleep for a while to make sure that the first error
399 // code (if any) has been saved by lirerr.
400 // When we start to stop threads we may induce new errors
401 // and they must not overwrite the original error code
402 // which is ensured by lirerr watching kill_all_flag.
403 // *******************************************************
404 close_network_sockets();
405 k=0;
406 if(dmp != NULL)
407   {
408   fflush(dmp);
409   lir_sync();
410   }
411 for(i=0; i<THREAD_MAX; i++)
412   {
413   if(i != THREAD_SYSCALL && thread_command_flag[i] != THRFLAG_NOT_ACTIVE)
414     {
415     if(thread_waitsem[i] != -2)
416       {
417       k++;
418       thread_command_flag[i]=THRFLAG_KILL;
419       if(thread_waitsem[i] != -1)
420         {
421         lir_set_event(thread_waitsem[i]);
422         }
423       if(i == THREAD_RX_OUTPUT)lir_set_event(EVENT_BASEB);
424       lir_sleep(100);
425       }
426     }
427   }
428 #if(OSNUM == OSNUM_WINDOWS)
429 win_semaphores();
430 #endif
431 if(k==0)goto ok_exit;
432 j=0;
433 while(j<500)
434   {
435   j++;
436   lir_sleep(20000);
437   k=0;
438   for(i=0; i<THREAD_MAX; i++)
439     {
440     if(i != THREAD_SYSCALL)
441       {
442       if(thread_status_flag[i] == THRFLAG_RETURNED  ||
443          thread_status_flag[i] == THRFLAG_NOT_ACTIVE)
444         {
445         thread_command_flag[i]=THRFLAG_NOT_ACTIVE;
446         }
447       else
448         {
449         if(thread_command_flag[i] != THRFLAG_NOT_ACTIVE)
450           {
451           k++;
452           if(thread_waitsem[i] != -2)
453             {
454             if(thread_waitsem[i] != -1)
455               {
456               lir_set_event(thread_waitsem[i]);
457               }
458             if(i == THREAD_RX_OUTPUT)lir_set_event(EVENT_BASEB);
459             thread_command_flag[i]=THRFLAG_KILL;
460             }
461           }
462         }
463       }
464     }
465   if(k==0)
466     {
467 ok_exit:;
468     threads_running=FALSE;
469     return;
470     }
471   }
472 if(dmp != 0)
473   {
474   PERMDEB"\n\nTHREAD(S) FAIL TO STOP");
475   for(i=0; i<THREAD_MAX; i++)
476     {
477     PERMDEB"\nThr=%d status=%d   cmd=%d",i,thread_status_flag[i],
478                                          thread_command_flag[i]);
479     }
480   PERMDEB"\n");
481   fflush(dmp);
482   }
483 // Stay here until ctrlC or kill button in Windows or X11
484 show_errmsg(2);
485 lir_refresh_screen();
486 zz:;
487 lir_sleep(10000);
488 goto zz;
489 }
490 
pause_thread(int no)491 void pause_thread(int no)
492 {
493 int i;
494 lir_sched_yield();
495 if( thread_command_flag[no]==THRFLAG_NOT_ACTIVE ||
496     thread_status_flag[no]==THRFLAG_RETURNED || kill_all_flag)return;
497 i=0;
498 if(thread_command_flag[no]==THRFLAG_IDLE)
499   {
500   while(i<100 && thread_command_flag[no] == THRFLAG_IDLE)
501     {
502     lir_sleep(5000);
503     if(kill_all_flag)return;
504     i++;
505     }
506   if(i >= 100)
507     {
508     lirerr(1224);
509     return;
510     }
511   }
512 thread_command_flag[no]=THRFLAG_IDLE;
513 if( no ==THREAD_RX_OUTPUT)
514   {
515   lir_set_event(EVENT_BASEB);
516   }
517 for(i=0; i<4; i++)
518   {
519   if( (ui.network_flag&NET_RXIN_FFT1) != 0 && no==THREAD_SCREEN &&
520                     thread_status_flag[THREAD_SCREEN] == THRFLAG_SEM_WAIT)
521     {
522     lir_set_event(EVENT_SCREEN);
523     }
524   lir_sched_yield();
525   if(thread_status_flag[no] == THRFLAG_IDLE)return;
526   }
527 while(thread_status_flag[no] != THRFLAG_IDLE  && !kill_all_flag)
528   {
529   if( no==THREAD_SCREEN &&
530                     thread_status_flag[THREAD_SCREEN] == THRFLAG_SEM_WAIT)
531     {
532     lir_set_event(EVENT_SCREEN);
533     }
534   if( no ==THREAD_RX_OUTPUT)
535     {
536     lir_set_event(EVENT_BASEB);
537     }
538   lir_sleep(3000);
539   }
540 }
541 
resume_thread(int no)542 void resume_thread(int no)
543 {
544 // Make sure the input is allowed to take care of its data
545 // before heavy processing is released.
546 // This is occasionally needed for the sdr-14.
547 lir_sched_yield();
548 if(thread_command_flag[no]!=THRFLAG_IDLE || kill_all_flag)return;
549 thread_command_flag[no]=THRFLAG_ACTIVE;
550 }
551 
pause_screen_and_hide_mouse(void)552 void pause_screen_and_hide_mouse(void)
553 {
554 pause_thread(THREAD_SCREEN);
555 unconditional_hide_mouse();
556 }
557 
linrad_thread_stop_and_join(int no)558 void linrad_thread_stop_and_join(int no)
559 {
560 int k;
561 if(thread_command_flag[no] == THRFLAG_NOT_ACTIVE)
562   {
563   if(kill_all_flag)return;
564   lirerr(765934);
565   return;
566   }
567 thread_command_flag[no]=THRFLAG_KILL;
568 if(thread_waitsem[no] != -1)
569   {
570   lir_set_event(thread_waitsem[no]);
571   }
572 if(no == THREAD_RX_OUTPUT)lir_set_event(EVENT_BASEB);
573 lir_sched_yield();
574 k=0;
575 while(thread_status_flag[no] != THRFLAG_RETURNED)
576   {
577   if(thread_waitsem[no] != -1)
578     {
579     lir_set_event(thread_waitsem[no]);
580     }
581   lir_sleep(3000);
582   k++;
583   if(no==THREAD_SDR14_INPUT)
584     {
585     if(k==100 && sdr!=-1)close_sdr14();
586     }
587   if(no==THREAD_PERSEUS_INPUT)
588     {
589     if(k==1000 && sdr!=-1)close_perseus();
590     }
591   }
592 thread_command_flag[no]=THRFLAG_NOT_ACTIVE;
593 lir_join(no);
594 thread_status_flag[no]=THRFLAG_NOT_ACTIVE;
595 }
596 
lir_text(int x,int y,char * txt)597 void lir_text(int x, int y, char *txt)
598 {
599 char s[512];
600 int i,j;
601 if(x<0 || y<0 || y > screen_last_line)return;
602 i=0;
603 while(txt[i] != 0)i++;
604 if(x+i <= screen_last_col)
605   {
606   lir_pixwrite(x*text_width, y*text_height+1,txt);
607   }
608 else
609   {
610   j=1+screen_last_col-x;
611   if(j > 0)
612     {
613     for(i=0; i<j; i++)s[i]=txt[i];
614     s[j]=0;
615     lir_pixwrite(x*text_width, y*text_height,s);
616     }
617   }
618 }
619 
lir_pixwrite(int x0,int y,char * txt)620 void lir_pixwrite(int x0, int y, char *txt)
621 {
622 int i, x;
623 unsigned int k;
624 i=-1;
625 if(x0>=0)
626   {
627   if(y>=0)
628     {
629     if(y+text_height-font_ysep < screen_height)
630       {
631       i=0;
632       x=x0;
633       while(txt[i] != 0)
634         {
635         k=(unsigned char)(txt[i]);
636         if(x+text_width > screen_width)goto errx;
637         lir_putbox(x,
638                    y,
639                    font_w,
640                    font_h,
641                    (MEMREF_T*)(&vga_font[(int)k*font_size]));
642         i++;
643         x+=text_width;
644         }
645       return;
646       }
647     }
648   }
649 errx:;
650 DEB"\nScreen write error");
651 DEB"\n[%s]   x=%d   y=%d   (%d  %d)",txt,x0,y,screen_width,screen_height);
652 if(dmp == NULL)lirerr(1258);
653 }
654 
aw_keyb(void)655 void aw_keyb(void)
656 {
657 while(keyboard_buffer_ptr == keyboard_buffer_used)
658   {
659   if(keyboard_buffer_ptr == keyboard_buffer_used)
660     {
661     lir_await_event(EVENT_KEYBOARD);
662     if(kill_all_flag) return;
663     }
664   }
665 lir_inkey = keyboard_buffer[keyboard_buffer_used];
666 keyboard_buffer_used=(keyboard_buffer_used+1)&(KEYBOARD_BUFFER_SIZE-1);
667 lir_sleep(10000);
668 }
669 
670 
await_keyboard(void)671 void await_keyboard(void)
672 {
673 lir_refresh_screen();
674 aw_keyb();
675 }
676 
init_semaphores(void)677 void init_semaphores(void)
678 {
679 int i;
680 for(i=0; i<EVENT_AUTOINIT_MAX; i++)lir_init_event(i);
681 }
682 
free_semaphores(void)683 void free_semaphores(void)
684 {
685 int i;
686 // For some bizarre reason we have to wait here.
687 // Windows XP will crash when EVENT_SCREEN is closed
688 // even though all threads using it have been closed. (???)
689 // This problemoccurs on some platforms when input is
690 // from a disk file.
691 lir_sleep(50000);
692 //if(FBDEV == 0)fflush(NULL);
693 lir_sleep(50000);
694 for(i=0; i<EVENT_AUTOINIT_MAX; i++)lir_close_event(i);
695 }
696 
do_xshift(int dir)697 void do_xshift(int dir)
698 {
699 float t1;
700 if(cal_domain == 0)
701   {
702   t1=(float)fft2_size;
703   }
704 else
705   {
706   t1=(float)fft1_size;
707   }
708 t1*=0.1F*cal_xgain;
709 cal_xshift=(int)((float)cal_xshift+t1*(float)dir);
710 }
711 
712 
user_command(void)713 void user_command(void)
714 {
715 #if RUSAGE_OLD == TRUE
716 int local_workload_counter;
717 #endif
718 int i, m, flag;
719 #if OSNUM == OSNUM_LINUX
720 clear_thread_times(THREAD_USER_COMMAND);
721 #endif
722 #if RUSAGE_OLD == TRUE
723 local_workload_counter=workload_counter;
724 #endif
725 thread_status_flag[THREAD_USER_COMMAND]=THRFLAG_ACTIVE;
726 while(thread_command_flag[THREAD_USER_COMMAND] == THRFLAG_ACTIVE)
727   {
728 #if RUSAGE_OLD == TRUE
729   if(local_workload_counter != workload_counter)
730     {
731     local_workload_counter=workload_counter;
732     make_thread_times(THREAD_USER_COMMAND);
733     }
734 #endif
735 // **********************************************
736 // Get input from the user and do whatever.......
737   if( usercontrol_mode != USR_NORMAL_RX)lir_refresh_screen();
738   aw_keyb();
739   process_current_lir_inkey();
740   lir_sleep(5000);
741   if(kill_all_flag)
742     {
743     goto user_error_exit;
744     }
745   if(numinput_flag != TEXT_PARM)
746     {
747     if(lir_inkey == 'X')
748       {
749       DEB"\n'X' Pressed");
750       goto user_exit;
751       }
752     if(lir_inkey == 'Z')
753       {
754       workload_reset_flag++;
755       goto ignore;
756       }
757     }
758   if(numinput_flag != 0)
759     {
760     get_numinput_chars();
761     }
762   else
763     {
764     switch(usercontrol_mode)
765       {
766       case USR_NORMAL_RX:
767       switch (lir_inkey)
768         {
769         case 'A':
770         pause_thread(THREAD_SCREEN);
771         ampinfo_flag^=1;
772         amp_info_texts();
773         timinfo_flag=0;
774         resume_thread(THREAD_SCREEN);
775         workload_reset_flag++;
776         break;
777 
778         case '+':
779         m=bg.wheel_stepn;
780         m++;
781         if(m>30)m=30;
782         bg.wheel_stepn=m;
783         make_modepar_file(GRAPHTYPE_BG);
784         sc[SC_SHOW_WHEEL]++;
785         break;
786 
787         case '-':
788         m=bg.wheel_stepn;
789         m--;
790         if(m<-30)m=-30;
791         if(genparm[AFC_ENABLE]==0 && m<0)m=0;
792         bg.wheel_stepn=m;
793         make_modepar_file(GRAPHTYPE_BG);
794         sc[SC_SHOW_WHEEL]++;
795         break;
796 
797         case 'E':
798         if(genparm[AFC_ENABLE] == 1)spurinit_flag++;
799         break;
800 
801         case 'F':
802         if(diskread_flag >= 2  && thread_status_flag[THREAD_RX_FILE_INPUT]
803                                      == THRFLAG_ACTIVE)edit_diskread_times();
804         break;
805 
806         case 'C':
807         if(genparm[AFC_ENABLE] != 0)spurcancel_flag++;
808         break;
809 
810         case 'Q':
811         userdefined_q();
812         break;
813 
814         case 'S':
815         if(abs(fg.passband_direction) != 1)break;
816         if(diskwrite_flag == 0)
817           {
818           disksave_start();
819           }
820         else
821           {
822           disksave_stop();
823           }
824         break;
825 
826         case 'T':
827         timinfo_flag^=1;
828         if(timinfo_flag!=0)time_info_time=current_time();
829         pause_thread(THREAD_SCREEN);
830         timing_info_texts();
831         resume_thread(THREAD_SCREEN);
832         workload_reset_flag++;
833         break;
834 
835         case 'U':
836         userdefined_u();
837         break;
838 
839         case 'W':
840         wavsave_start_stop(0);
841         if( wav_write_flag < 0)wav_write_flag=0;
842         break;
843 
844         case F1_KEY:
845         case '!':
846         help_screen_objects();
847         break;
848 
849         case F2_KEY:
850         if(s_meter_avgnum <0)
851           {
852           s_meter_avg=0;
853           s_meter_avgnum=0;
854           }
855         else
856           {
857           s_meter_avgnum=-1;
858           }
859         break;
860 
861         case F3_KEY:
862         audio_dump_flag^=1;
863         audio_dump_flag&=1;
864         lir_fillbox(0,0,6,6,(unsigned char)(12*audio_dump_flag));
865         lir_refresh_screen();
866         break;
867 
868         case F5_KEY:
869         computation_pause_flag^=1;
870         computation_pause_flag&=1;
871         lir_fillbox(16,0,6,6,(unsigned char)(13*computation_pause_flag));
872         break;
873 
874 
875         case F8_KEY:
876         internal_generator_att++;
877         if(internal_generator_att > 12)internal_generator_att=0;
878         break;
879 
880         case F9_KEY:
881         truncate_flag<<=1;
882         truncate_flag++;
883         if( (ui.rx_input_mode&DWORD_INPUT) == 0)
884           {
885           if(truncate_flag > 0x3ff)truncate_flag=0;
886           }
887         else
888           {
889           if(truncate_flag > 0x3ffff)truncate_flag=0;
890           }
891         break;
892 
893         case F11_KEY:
894         internal_generator_flag^=1;
895         break;
896 
897         case F10_KEY:
898         if(OSNUM == OSNUM_LINUX)
899           {
900           internal_generator_noise++;
901           if( (ui.rx_input_mode&DWORD_INPUT) == 0)
902             {
903             if(internal_generator_noise > 8)internal_generator_noise=0;
904             }
905           else
906             {
907             if(internal_generator_noise <8)internal_generator_noise=8;
908             if(internal_generator_noise > 24)internal_generator_noise=0;
909             }
910           }
911         break;
912 
913         case SHIFT_F3_KEY:
914         diskread_pause_flag^=1;
915         diskread_pause_flag&=1;
916         lir_fillbox(8,0,6,6,(unsigned char)(14*diskread_pause_flag));
917         lir_refresh_screen();
918         break;
919 
920         case ARROW_UP_KEY:
921         if(genparm[CW_DECODE_ENABLE] != 0)
922           {
923           i=cg_osc_offset_inc;
924           cg_osc_offset_inc=(int)((float)(cg_osc_offset_inc)*1.3F);
925           if(i==cg_osc_offset_inc)cg_osc_offset_inc++;
926           if(cg_osc_offset_inc>(baseband_size<<3) )
927                                           cg_osc_offset_inc=baseband_size<<3;
928           pause_thread(THREAD_SCREEN);
929           shift_cg_osc_track(0);
930           resume_thread(THREAD_SCREEN);
931           }
932         else
933           {
934           bg.filter_flat=(float)(bg_hz_per_pixel*(bg_flatpoints*1.2+2));
935           bg_update_filter++;
936           }
937         break;
938 
939         case ARROW_DOWN_KEY:
940         if(genparm[CW_DECODE_ENABLE] != 0)
941           {
942           i=cg_osc_offset_inc;
943           cg_osc_offset_inc=(int)((float)(cg_osc_offset_inc)/1.3F);
944           if(cg_osc_offset_inc==0)cg_osc_offset_inc=1;
945           pause_thread(THREAD_SCREEN);
946           shift_cg_osc_track(0);
947           resume_thread(THREAD_SCREEN);
948           }
949         else
950           {
951           if(bg_flatpoints > 1)
952             {
953             bg.filter_flat=bg_hz_per_pixel*((float)(bg_flatpoints)*0.85F-2);
954             bg_update_filter++;
955             }
956           }
957         break;
958 
959         case ARROW_RIGHT_KEY:
960         if(genparm[CW_DECODE_ENABLE] != 0)
961           {
962           pause_thread(THREAD_SCREEN);
963           shift_cg_osc_track(cg_osc_offset_inc);
964           resume_thread(THREAD_SCREEN);
965           }
966         else
967           {
968           step_rx_frequency(1);
969           }
970         break;
971 
972         case ARROW_LEFT_KEY:
973         if(genparm[CW_DECODE_ENABLE] != 0)
974           {
975           pause_thread(THREAD_SCREEN);
976           shift_cg_osc_track(-cg_osc_offset_inc);
977           resume_thread(THREAD_SCREEN);
978           }
979         else
980           {
981           step_rx_frequency(-1);
982           }
983         break;
984 
985         case ' ':
986         copy_rxfreq_to_tx();
987         break;
988 
989         case 'V':
990         case 'B':
991         case 'N':
992         copy_txfreq_to_rx();
993         break;
994 
995         case 'M':
996         bg.horiz_arrow_mode++;
997         if(bg.horiz_arrow_mode > 2)bg.horiz_arrow_mode=0;
998         make_modepar_file(GRAPHTYPE_BG);
999         sc[SC_BG_BUTTONS]++;
1000         break;
1001 
1002         }
1003       break;
1004 
1005       case USR_TXTEST:
1006       switch (lir_inkey)
1007         {
1008         case F4_KEY:
1009         lir_status=LIR_POWTIM;
1010         goto user_exit;
1011         }
1012       break;
1013 
1014       case USR_POWTIM:
1015       switch (lir_inkey)
1016         {
1017         case '+':
1018         powtim_gain*=2;
1019         break;
1020 
1021         case '-':
1022         powtim_gain/=1.8F;
1023         break;
1024 
1025         case ARROW_UP_KEY:
1026         powtim_fgain*=2;
1027         break;
1028 
1029         case ARROW_DOWN_KEY:
1030         powtim_fgain/=1.8F;
1031         break;
1032 
1033         case 'D':
1034         if(powtim_xstep < 5)
1035           {
1036           powtim_xstep--;
1037           }
1038         else
1039           {
1040           powtim_xstep=(int)(powtim_xstep/1.5);
1041           }
1042         if(powtim_xstep<1)powtim_xstep=1;
1043         break;
1044 
1045         case 'I':
1046         if(powtim_xstep < 5)
1047           {
1048           powtim_xstep++;
1049           }
1050         else
1051           {
1052           powtim_xstep*=2;
1053           }
1054         if(powtim_xstep>timf2pow_mask/16)powtim_xstep=timf2pow_mask/16;
1055         break;
1056 
1057         case 'L':
1058         powtim_displaymode^=1;
1059         break;
1060 
1061         case 'W':
1062         powtim_displaymode^=2;
1063         break;
1064 
1065         case 'M':
1066         powtim_trigmode++;
1067         if(powtim_trigmode >= POWTIM_TRIGMODES)powtim_trigmode=0;
1068         break;
1069 
1070         case 'P':
1071         powtim_pause_flag=1;
1072         break;
1073 
1074         case 'R':
1075         powtim_pause_flag=0;
1076         break;
1077 
1078         if(powtim_pause_flag != 0)
1079           {
1080           case ARROW_RIGHT_KEY:
1081           timf2_pn2=(timf2_pn2-screen_width*powtim_xstep/4+timf2_mask+1)&timf2_mask;
1082           break;
1083 
1084           case ARROW_LEFT_KEY:
1085           timf2_pn2=(timf2_pn2+screen_width*powtim_xstep/5)&timf2_mask;
1086           break;
1087           }
1088         }
1089       if(kill_all_flag) goto user_error_exit;
1090       powtim_parmwrite();
1091       if(powtim_pause_flag != 0) powtim_screen();
1092       break;
1093 
1094       case USR_ADTEST:
1095       adtest_new++;
1096       switch (lir_inkey)
1097         {
1098         case '+':
1099         if(adtest_scale < BIG)adtest_scale*=2;
1100         break;
1101 
1102         case '-':
1103         if(adtest_scale > 1/BIG)adtest_scale/=2;
1104         break;
1105 
1106         case 'C':
1107         if(ui.rx_rf_channels == 2)adtest_channel^=1;
1108         break;
1109 
1110         case 'P':
1111         powtim_pause_flag=1;
1112         break;
1113 
1114         case 'R':
1115         powtim_pause_flag=0;
1116         break;
1117 
1118         case 'W':
1119         powtim_displaymode^=1;
1120         break;
1121         }
1122       break;
1123 
1124       case USR_IQ_BALANCE:
1125       pause_thread(THREAD_CAL_IQBALANCE);
1126       caliq_clear_flag=TRUE;
1127       switch (lir_inkey)
1128         {
1129         case '+':
1130         bal_segments*=2;
1131         break;
1132 
1133         case '-':
1134         bal_segments/=2;
1135         break;
1136 
1137         case 'S':
1138         write_iq_foldcorr();
1139         break;
1140 
1141         case 'U':
1142         update_iq_foldcorr();
1143         break;
1144 
1145         case 'C':
1146         clear_iq_foldcorr();
1147         break;
1148 
1149         case F1_KEY:
1150         case '!':
1151         help_message(311);
1152         caliq_clear_flag=FALSE;
1153         break;
1154 
1155         default:
1156         caliq_clear_flag=FALSE;
1157         break;
1158         }
1159       clear_keyboard();
1160       resume_thread(THREAD_CAL_IQBALANCE);
1161       break;
1162 
1163       case USR_CAL_INTERVAL:
1164       pause_thread(THREAD_CAL_INTERVAL);
1165       switch (lir_inkey)
1166         {
1167         case '+':
1168         cal_ygain*=2;
1169         break;
1170 
1171         case '-':
1172         cal_ygain/=2;
1173         break;
1174 
1175         case 'E':
1176         cal_xgain*=2;
1177         break;
1178 
1179         case 'C':
1180         cal_xgain/=2;
1181         break;
1182 
1183         case F1_KEY:
1184         case '!':
1185         help_message(304);
1186         break;
1187 
1188         case 10:
1189         DEB"\nENTER Pressed");
1190         usercontrol_mode=USR_CAL_FILTERCORR;
1191         goto user_exit;
1192         }
1193       clear_keyboard();
1194       resume_thread(THREAD_CAL_INTERVAL);
1195       break;
1196 
1197       case USR_CAL_FILTERCORR:
1198       pause_thread(THREAD_CAL_FILTERCORR);
1199       flag=THRFLAG_ACTIVE;
1200       switch (lir_inkey)
1201         {
1202         case '+':
1203         cal_ygain*=2;
1204         break;
1205 
1206         case '-':
1207         cal_ygain/=2;
1208         break;
1209 
1210         case 'A':
1211         clear_fft1_filtercorr();
1212         make_cal_fft1_filtercorr();
1213         flag=THRFLAG_RESET;
1214         break;
1215 
1216         case 'E':
1217         cal_xgain*=2;
1218         break;
1219 
1220         case 'C':
1221         cal_xgain/=2;
1222         break;
1223 
1224         case 'S':
1225         write_filcorr(-1);
1226         break;
1227 
1228         case 'T':
1229         cal_domain++;
1230         if(cal_domain > MAX_CAL_DEBUG)cal_domain=0;
1231         break;
1232 
1233         case 'I':
1234         break;
1235 
1236         case 'U':
1237         if(cal_buf4[0]>=0)
1238           {
1239           if(cal_update_ram() == 0)
1240             {
1241             linrad_thread_stop_and_join(THREAD_CAL_FILTERCORR);
1242             goto user_exit;
1243             }
1244           flag=THRFLAG_RESET;
1245           }
1246         break;
1247 
1248         case ARROW_LEFT_KEY:
1249         do_xshift(1);
1250         break;
1251 
1252         case ARROW_RIGHT_KEY:
1253         do_xshift(-1);
1254         break;
1255 
1256         case F1_KEY:
1257         case '!':
1258         help_message(305);
1259         flag=THRFLAG_RESET;
1260         break;
1261 
1262         }
1263       thread_command_flag[THREAD_CAL_FILTERCORR]=(char)flag;
1264       while(thread_status_flag[THREAD_CAL_FILTERCORR] != THRFLAG_ACTIVE)
1265         {
1266         lir_sleep(2000);
1267         if(kill_all_flag) goto user_error_exit;
1268         }
1269       break;
1270 
1271       case USR_TUNE:
1272       if(thread_command_flag[THREAD_TUNE]==THRFLAG_ACTIVE)
1273         {
1274         thread_command_flag[THREAD_TUNE]=THRFLAG_IDLE;
1275         while(thread_status_flag[THREAD_TUNE]!=THRFLAG_IDLE)
1276           {
1277           lir_sleep(5000);
1278           if(kill_all_flag) goto user_error_exit;
1279           }
1280         switch(lir_inkey)
1281           {
1282           case '+':
1283           tune_yzer-=100;
1284           break;
1285 
1286           case '-':
1287           tune_yzer+=100;
1288           break;
1289           }
1290         thread_command_flag[THREAD_TUNE]=THRFLAG_ACTIVE;
1291         while(thread_status_flag[THREAD_TUNE]!=THRFLAG_ACTIVE)
1292           {
1293           lir_sleep(5000);
1294           if(kill_all_flag) goto user_error_exit;
1295           }
1296         }
1297       break;
1298       }
1299     }
1300 ignore:;
1301   if(kill_all_flag) goto user_error_exit;
1302   }
1303 user_exit:;
1304 thread_status_flag[THREAD_USER_COMMAND]=THRFLAG_RETURNED;
1305 return;
1306 user_error_exit:;
1307 if(dmp!=NULL)fflush(dmp);
1308 thread_status_flag[THREAD_USER_COMMAND]=THRFLAG_RETURNED;
1309 while(thread_command_flag[THREAD_USER_COMMAND] != THRFLAG_NOT_ACTIVE)
1310   {
1311   lir_sleep(1000);
1312   }
1313 }
1314 
xz(char * s)1315 void xz(char *s)
1316 {
1317 if(dmp == NULL)
1318   {
1319   lirerr(1074);
1320   lir_sleep(100000);
1321   return;
1322   }
1323 PERMDEB" %s\n",s);
1324 fflush(dmp);
1325 lir_sync();
1326 }
1327 
xq(char * s)1328 void xq(char *s)
1329 {
1330 if(dmp == NULL)
1331   {
1332   lirerr(1074);
1333   lir_sleep(100000);
1334   return;
1335   }
1336 fprintf( stderr," %s\n",s);
1337 fflush(stderr);
1338 lir_sync();
1339 }
1340 
1341 
timerr(int line,char * txt)1342 void timerr(int line, char*txt)
1343 {
1344 char s[80];
1345 settextcolor(15);
1346 sprintf(s,"Premature call to %s",txt);
1347 lir_text(0,line,s);
1348 settextcolor(7);
1349 }
1350 
test_keyboard(void)1351 void test_keyboard(void)
1352 {
1353 if(kill_all_flag!=0)return;
1354 if(keyboard_buffer_ptr != keyboard_buffer_used)
1355   {
1356   lir_await_event(EVENT_KEYBOARD);
1357   lir_inkey = keyboard_buffer[keyboard_buffer_used];
1358   keyboard_buffer_used=(keyboard_buffer_used+1)&(KEYBOARD_BUFFER_SIZE-1);
1359   }
1360 else
1361   {
1362   lir_inkey=0;
1363   }
1364 }
1365 
1366 
clear_keyboard(void)1367 void clear_keyboard(void)
1368 {
1369 test_keyboard();
1370 if(kill_all_flag) return;
1371 while(lir_inkey != 0)
1372   {
1373   test_keyboard();
1374   if(kill_all_flag) return;
1375   }
1376 }
1377 
1378 
clear_await_keyboard(void)1379 void clear_await_keyboard(void)
1380 {
1381 clear_keyboard();
1382 if(kill_all_flag) return;
1383 await_keyboard();
1384 }
1385 
1386 
1387 
1388 int qnqcnt=0;
1389 int qnqcnt1=0;
1390 int qnqcnt2=0;
1391 #define QQLINE 0
qq(char * s)1392 void qq(char *s)
1393 {
1394 char w[80];
1395 sprintf(w,"%s%3d",s,qnqcnt);
1396 lir_text(5,QQLINE,w);
1397 lir_refresh_screen();
1398 qnqcnt++;
1399 if(qnqcnt > 999)qnqcnt=0;
1400 }
1401 
qq1(char * s)1402 void qq1(char *s)
1403 {
1404 char w[80];
1405 sprintf(w,"%s%3d",s,qnqcnt1);
1406 lir_text(15,QQLINE,w);
1407 lir_refresh_screen();
1408 qnqcnt1++;
1409 if(qnqcnt1 > 999)qnqcnt1=0;
1410 }
1411 
qq2(char * s)1412 void qq2(char *s)
1413 {
1414 char w[80];
1415 sprintf(w,"%s%3d",s,qnqcnt2);
1416 lir_text(25,QQLINE,w);
1417 lir_refresh_screen();
1418 qnqcnt2++;
1419 if(qnqcnt2 > 999)qnqcnt2=0;
1420 }
1421 
show_button(BUTTONS * butt,char * s)1422 void show_button(BUTTONS *butt, char *s)
1423 {
1424 int ix1, ix2, iy1, iy2;
1425 ix1=butt[0].x1;
1426 ix2=butt[0].x2;
1427 iy1=butt[0].y1;
1428 iy2=butt[0].y2;
1429 if( ix1 < 0 ||
1430     ix1 >= screen_width ||
1431     iy1 < 0 ||
1432     iy2 >= screen_height )
1433   {
1434   return;
1435   }
1436 lir_hline(ix1,iy1,ix2,button_color);
1437 if(kill_all_flag) return;
1438 lir_hline(ix1,iy2,ix2,button_color);
1439 if(kill_all_flag) return;
1440 lir_line(ix1,iy1,ix1,iy2,button_color);
1441 if(kill_all_flag) return;
1442 lir_line(ix2,iy1,ix2,iy2,button_color);
1443 if(kill_all_flag) return;
1444 lir_pixwrite(ix1+3,iy1+2,s);
1445 }
1446 
1447 
update_bar(int x1,int x2,int yzer,int newy,int oldy,unsigned char color,char * buf)1448 void update_bar(int x1, int x2, int yzer, int newy,
1449                 int oldy, unsigned char color,char* buf)
1450 {
1451 int i, k, height, width;
1452 if(newy == oldy)return;
1453 if(oldy < 0)oldy=yzer;
1454 width=x2-x1+1;
1455 if(newy < oldy)
1456   {
1457   height=oldy-newy+1;
1458   lir_getbox(x1,newy,width,height,(MEMREF_T*)buf);
1459   k=width*height;
1460   for(i=0; i<k; i++)
1461     {
1462     if(buf[i] != 7)
1463       {
1464       buf[i]=(char)color;
1465       }
1466     }
1467   lir_putbox(x1,newy,width,height, (MEMREF_T*)buf);
1468   }
1469 else
1470   {
1471   height=newy-oldy+1;
1472   lir_getbox(x1,oldy,width,height, (MEMREF_T*)buf);
1473   k=width*height;
1474   for(i=0; i<k; i++)
1475     {
1476     if(buf[i] != 7)
1477       {
1478       buf[i]=0;
1479       }
1480     }
1481   lir_putbox(x1,oldy,width,height, (MEMREF_T*)buf);
1482   }
1483 }
1484 
make_power_of_two(int * i)1485 int make_power_of_two( int *i)
1486 {
1487 int k;
1488 k=-1;
1489 i[0]+=i[0]-1;
1490 while(i[0] != 0)
1491   {
1492   i[0]/=2;
1493   k++;
1494   }
1495 i[0]=1<<k;
1496 return k;
1497 }
1498 
chk_free(void * p)1499 void *chk_free(void *p)
1500 {
1501 if(p==NULL)return NULL;
1502 free(p);
1503 return NULL;
1504 }
1505 
process_current_lir_inkey(void)1506 void process_current_lir_inkey(void)
1507 {
1508 if(lir_inkey == 13)lir_inkey = 10;
1509 lir_inkey=toupper(lir_inkey);
1510 if(lir_inkey == 'G')
1511   {
1512   if(fft1_handle==NULL)
1513     {
1514     save_screen_image();
1515     }
1516   else
1517     {
1518     if( numinput_flag != TEXT_PARM)
1519       {
1520       save_screen_image();
1521       lir_inkey=0;
1522       }
1523     }
1524   }
1525 }
1526 
1527 
1528 
lir_get_filename(int x,int y,char * name)1529 int lir_get_filename(int  x, int y, char *name)
1530 {
1531 int len;
1532 len=0;
1533 next_char:;
1534 name[len]=0;
1535 lir_text(x,y,name);
1536 await_keyboard();
1537 if(kill_all_flag)return 0;
1538 if(lir_inkey == 10) return len;
1539 if(lir_inkey == 8 ||
1540    lir_inkey == ARROW_LEFT_KEY ||
1541    lir_inkey == 127)
1542   {
1543   if(len==0)goto next_char;
1544   name[len-1]=' ';
1545   lir_text(x,y,name);
1546   len--;
1547   goto next_char;
1548   }
1549 if(  (lir_inkey >=  '.' && lir_inkey <= '9') ||
1550      (lir_inkey >= 'A' && lir_inkey <= 'Z') ||
1551      lir_inkey == '_' ||
1552      lir_inkey == '-' ||
1553      lir_inkey == '+' ||
1554 #if(OSNUM == OSNUM_WINDOWS)
1555      lir_inkey == ':' ||
1556      lir_inkey == '\\' ||
1557 #endif
1558      (lir_inkey >= 'a' && lir_inkey <= 'z'))
1559   {
1560   name[len]=(char)lir_inkey;
1561   if(len<79)len++;
1562   }
1563 goto next_char;
1564 }
1565 
lir_get_text(int x,int y,char * txtbuf)1566 int lir_get_text(int  x, int y, char *txtbuf)
1567 {
1568 int len;
1569 len=0;
1570 next_char:;
1571 txtbuf[len]='_';
1572 txtbuf[len+1]=0;
1573 lir_text(x,y,txtbuf);
1574 await_keyboard();
1575 if(kill_all_flag)return 0;
1576 if(lir_inkey == 10)
1577   {
1578   txtbuf[len]=0;
1579   return len;
1580   }
1581 if(lir_inkey == 8 ||
1582    lir_inkey == ARROW_LEFT_KEY ||
1583    lir_inkey == 127)
1584   {
1585   if(len==0)goto next_char;
1586   txtbuf[len]=' ';
1587   len--;
1588   txtbuf[len]='_';
1589   lir_text(x,y,txtbuf);
1590   txtbuf[len+1]=0;
1591   goto next_char;
1592   }
1593 if(lir_inkey >= ' ' && lir_inkey <= 'z')
1594   {
1595   txtbuf[len]=(char)lir_inkey;
1596   if(len<78)len++;
1597   }
1598 goto next_char;
1599 }
1600 
1601 
lir_get_integer(int x,int y,int len,int min,int max)1602 int lir_get_integer(int  x, int y, int len, int min, int max)
1603 {
1604 char s[16];
1605 int i, j, pos;
1606 if(len < 1 || len > 15)
1607   {
1608   lirerr(8);
1609   return min;
1610   }
1611 for(i=1; i<len; i++)s[i]=' ';
1612 s[0]='_';
1613 s[len]=0;
1614 lir_text(x,y,s);
1615 pos=0;
1616 digin:;
1617 await_processed_keyboard();
1618 if(kill_all_flag)return min;
1619 switch (lir_inkey)
1620   {
1621   case F1_KEY:
1622   case '!':
1623   return min;
1624 
1625   case 10:
1626   if(pos != 0)
1627     {
1628     j=atoi(s);
1629     s[pos]=' ';
1630     if(j < min)
1631       {
1632       j=min;
1633       sprintf(s,"%d ",min);
1634       }
1635     lir_text(x,y,s);
1636     return j;
1637     }
1638   break;
1639 
1640   case 8:
1641   case 127:
1642   case ARROW_LEFT_KEY:
1643   if(pos > 0)
1644     {
1645     s[pos+1]=0;
1646     s[pos]=' ';
1647     pos--;
1648     s[pos]='_';
1649     lir_text(x,y,s);
1650     s[pos+1]=0;
1651     }
1652   break;
1653 
1654   case '-':
1655   if(min < 0)
1656     {
1657     if(pos == 0)
1658       {
1659       s[pos]='-';
1660       pos++;
1661       s[pos]=0;
1662       }
1663     lir_text(x,y,s);
1664     }
1665   break;
1666 
1667   default:
1668   if(lir_inkey>='0' && lir_inkey <='9')
1669     {
1670     if(pos < len)
1671       {
1672       s[pos]=(char)lir_inkey;
1673       pos++;
1674       s[pos]=0;
1675       j=atoi(s);
1676       if(s[0] != '-')
1677         {
1678         if(j > max)sprintf(s,"%d",max);
1679         }
1680       else
1681         {
1682         if(j < min)sprintf(s,"%d",min);
1683         }
1684       pos=0;
1685       while(s[pos] != 0 && s[pos] != ' ')pos++;
1686       s[pos]='_';
1687       j=pos+1;
1688       while( j< len)
1689         {
1690         s[j]=' ';
1691         j++;
1692         }
1693       s[len]=0;
1694       lir_text(x,y,s);
1695       s[pos+1]=0;
1696       }
1697     }
1698   break;
1699   }
1700 goto digin;
1701 }
1702 
lir_get_float(int x,int y,int len,double min,double max)1703 double lir_get_float(int  x, int y, int len, double min, double max)
1704 {
1705 char s[16];
1706 int i, j, pos;
1707 double t1;
1708 if(len < 1 || len > 15)
1709   {
1710   lirerr(8);
1711   return min;
1712   }
1713 for(i=1; i<len; i++)s[i]=' ';
1714 s[0]='_';
1715 s[len]=0;
1716 lir_text(x,y,s);
1717 pos=0;
1718 digin:;
1719 await_processed_keyboard();
1720 if(kill_all_flag)return min;
1721 switch (lir_inkey)
1722   {
1723   case 10:
1724   if(pos != 0)
1725     {
1726     t1=atof(s);
1727     if(t1 < min)
1728       {
1729       sprintf(s,"%f",min);
1730       t1=min;
1731       lir_text(x,y,s);
1732       }
1733     return t1;
1734     }
1735   break;
1736 
1737   case '-':
1738   if(pos == 0)
1739     {
1740     s[pos]='-';
1741     pos++;
1742     s[pos]=0;
1743     lir_text(x,y,s);
1744     }
1745   break;
1746 
1747   case 8:
1748   case 127:
1749   case ARROW_LEFT_KEY:
1750   if(pos > 0)
1751     {
1752     s[pos]=' ';
1753     pos--;
1754     s[pos]='_';
1755     lir_text(x,y,s);
1756     }
1757   break;
1758 
1759   case '.':
1760   j=0;
1761   while(j < pos && s[j] != '.')j++;
1762   if(j < len)
1763     {
1764     s[pos]=' ';
1765     pos=j;
1766     s[pos]='.';
1767     goto show;
1768     }
1769   break;
1770 
1771   default:
1772   if(lir_inkey>='0' && lir_inkey <='9')
1773     {
1774     if(pos < len)
1775       {
1776       s[pos]=(char)lir_inkey;
1777 show:;
1778       pos++;
1779       s[pos]=0;
1780       t1=atof(s);
1781       if(t1 > max)sprintf(s,"%f",max);
1782       pos=0;
1783       while(s[pos] != 0 && s[pos] != ' ' && pos < len)pos++;
1784       s[pos]='_';
1785       j=pos+1;
1786       s[j]=0;
1787       lir_text(x,y,s);
1788       }
1789     }
1790   break;
1791   }
1792 goto digin;
1793 }
1794 
clear_lines(int i,int j)1795 void clear_lines(int i, int j)
1796 {
1797 int k;
1798 if(i > j)
1799   {
1800   k=i;
1801   i=j;
1802   j=k;
1803   }
1804 lir_fillbox(0,i*text_height,screen_width-1,(j-i+1)*text_height,0);
1805 }
1806 
await_processed_keyboard(void)1807 void await_processed_keyboard(void)
1808 {
1809 await_keyboard();
1810 process_current_lir_inkey();
1811 }
1812 
to_upper(int c)1813 int to_upper(int c)
1814 {
1815 if(c>96 && c<123)c-=32;
1816 return c;
1817 }
1818 
to_upper_await_keyboard(void)1819 void to_upper_await_keyboard(void)
1820 {
1821 await_keyboard();
1822 lir_inkey=toupper(lir_inkey);
1823 }
1824 
adjust_scale(double * step)1825 int adjust_scale(double *step)
1826 {
1827 int pot,i;
1828 double t1;
1829 // Make step the nearest larger of 1, 2 or 5 in the same power of 10
1830 t1=step[0];
1831 pot=0;
1832 while(t1 > 10)
1833   {
1834   t1/=10;
1835   pot++;
1836   }
1837 if(t1<0.00001)t1=.00001;
1838 while(t1 < 1)
1839   {
1840   t1*=10;
1841   pot--;
1842   }
1843 if(t1 <= 2)
1844   {
1845   t1=2;
1846   i=2;
1847   goto asx;
1848   }
1849 if(t1 <= 5)
1850   {
1851   t1=5;
1852   i=5;
1853   goto asx;
1854   }
1855 t1=10;
1856 i=1;
1857 asx:;
1858 while(pot > 0)
1859   {
1860   t1*=10;
1861   pot--;
1862   }
1863 while(pot < 0)
1864   {
1865   t1/=10;
1866   pot++;
1867   }
1868 step[0]=t1;
1869 return i;
1870 }
1871 
clear_button(BUTTONS * butt,int max)1872 void clear_button(BUTTONS *butt, int max)
1873 {
1874 int i;
1875 for(i=0; i<max; i++)
1876   {
1877   butt[i].x1=-1;
1878   butt[i].x2=-1;
1879   butt[i].y1=-1;
1880   butt[i].y2=-1;
1881   }
1882 }
1883 
make_button(int x,int y,BUTTONS * butt,int m,char chr)1884 void make_button(int x, int y, BUTTONS *butt, int m, char chr)
1885 {
1886 char s[2];
1887 s[0]=chr;
1888 s[1]=0;
1889 butt[m].x1=x-text_width/2-2;
1890 butt[m].x2=x+text_width/2+2;
1891 butt[m].y1=y-text_height/2-1;
1892 lir_pixwrite(butt[m].x1+3,butt[m].y1+2,s);
1893 butt[m].y2=y+text_height/2;
1894 lir_hline(butt[m].x1,butt[m].y1,butt[m].x2,7);
1895 if(kill_all_flag) return;
1896 lir_hline(butt[m].x1,butt[m].y2,butt[m].x2,7);
1897 if(kill_all_flag) return;
1898 lir_line(butt[m].x1,butt[m].y1,butt[m].x1,butt[m].y2,7);
1899 if(kill_all_flag) return;
1900 lir_line(butt[m].x2,butt[m].y1,butt[m].x2,butt[m].y2,7);
1901 }
1902 
set_graph_minwidth(WG_PARMS * a)1903 void set_graph_minwidth(WG_PARMS *a)
1904 {
1905 int i;
1906 i=a[0].xright-a[0].xleft;
1907 if(i!=current_graph_minw)
1908   {
1909   a[0].xleft=(a[0].xleft+a[0].xright-current_graph_minw)/2;
1910   a[0].xright=a[0].xleft+current_graph_minw;
1911   }
1912 if(a[0].xright>screen_last_xpixel)
1913   {
1914   a[0].xright=screen_last_xpixel;
1915   a[0].xleft=a[0].xright-current_graph_minw;
1916   }
1917 if(a[0].xleft<0)
1918   {
1919   a[0].xleft=0;
1920   a[0].xright=a[0].xleft+current_graph_minw;
1921   }
1922 i=a[0].ybottom-a[0].ytop;
1923 if(i!=current_graph_minh)
1924   {
1925   a[0].ybottom=(a[0].ybottom+a[0].ytop+current_graph_minh)/2;
1926   a[0].ytop=a[0].ybottom-current_graph_minh;
1927   }
1928 if(a[0].ybottom>=screen_height)
1929   {
1930   a[0].ybottom=screen_height-1;
1931   a[0].ytop=a[0].ybottom-current_graph_minh;
1932   }
1933 if(a[0].ytop <0)
1934   {
1935   a[0].ytop=0;
1936   a[0].ybottom=a[0].ytop+current_graph_minh;
1937   }
1938 }
1939 
1940 
graph_mincheck(WG_PARMS * a)1941 void graph_mincheck(WG_PARMS *a)
1942 {
1943 if(a[0].ybottom-a[0].ytop < current_graph_minh)
1944   {
1945   a[0].ybottom=(a[0].ybottom+a[0].ytop+current_graph_minh)>>1;
1946   a[0].ytop=a[0].ybottom-current_graph_minh;
1947   }
1948 if(a[0].xright-a[0].xleft < current_graph_minw)
1949   {
1950   a[0].xright=(a[0].xright+a[0].xleft+current_graph_minw)>>1;
1951   a[0].xleft=a[0].xright-current_graph_minw;
1952   }
1953 if(a[0].xleft<0)
1954   {
1955   a[0].xleft=0;
1956   if(a[0].xright<current_graph_minw)a[0].xright=current_graph_minw;
1957   }
1958 if(a[0].ytop<0)
1959   {
1960   a[0].ytop=0;
1961   if(a[0].ybottom<current_graph_minh)a[0].ybottom=current_graph_minh;
1962   }
1963 if(a[0].xright>screen_last_xpixel)
1964   {
1965   a[0].xright=screen_last_xpixel;
1966   if(a[0].xright-a[0].xleft<current_graph_minw)
1967                                   a[0].xleft=a[0].xright-current_graph_minw;
1968   }
1969 if(a[0].ybottom>screen_height-1)
1970   {
1971   a[0].ybottom=screen_height-1;
1972   if(a[0].ybottom-a[0].ytop<current_graph_minh)
1973                                   a[0].ytop=a[0].ybottom-current_graph_minh;
1974   }
1975 }
1976 
avoid_graph_collision(WG_PARMS * a,WG_PARMS * b)1977 void avoid_graph_collision(WG_PARMS *a, WG_PARMS *b)
1978 {
1979 int ix,jx,iy,jy;
1980 int la,ra,ta,ba;
1981 // One border line of graph a has been changed.
1982 // Check if graph a now is on top of graph b.
1983 // If there is a collission, find out what border line to move which
1984 // will cause minimum loss of graph area.
1985 // This routine is also called every time a graph is placed on the
1986 // screen when the program is started.
1987 // During start, this simple procedure may fail, therefore
1988 // some security is added at the end of this routine.
1989 if(a==b)return;
1990 ix=b[0].xright-a[0].xleft+1;
1991 jx=b[0].xleft-a[0].xright+1;
1992 if(ix*jx>0)goto check;
1993 iy=b[0].ybottom-a[0].ytop+1;
1994 jy=b[0].ytop-a[0].ybottom+1;
1995 if(iy*jy>0)goto check;
1996 la=ix*(a[0].ybottom-a[0].ytop);
1997 ra=-jx*(a[0].ybottom-a[0].ytop);
1998 ta=iy*(a[0].xright-a[0].xleft);
1999 ba=-jy*(a[0].xright-a[0].xleft);
2000 if(la<ra)
2001   {
2002   if(ta<ba)
2003     {
2004     if(la<ta)
2005       {
2006       a[0].xleft=b[0].xright+1;
2007       }
2008     else
2009       {
2010       a[0].ytop=b[0].ybottom+1;
2011       }
2012     }
2013   else
2014     {
2015     if(la<ba)
2016       {
2017       a[0].xleft=b[0].xright+1;
2018       }
2019     else
2020       {
2021       a[0].ybottom=b[0].ytop-1;
2022       }
2023     }
2024   }
2025 else
2026   {
2027   if(ta<ba)
2028     {
2029     if(ra<ta)
2030       {
2031       a[0].xright=b[0].xleft-1;
2032       }
2033     else
2034       {
2035       a[0].ytop=b[0].ybottom+1;
2036       }
2037     }
2038   else
2039     {
2040     if(ra<ba)
2041       {
2042       a[0].xright=b[0].xleft-1;
2043       }
2044     else
2045       {
2046       a[0].ybottom=b[0].ytop-1;
2047       }
2048     }
2049   }
2050 // Make sure we are always within the screen.
2051 // Don't care if graphs overlay now.
2052 check:;
2053 graph_mincheck(a);
2054 }
2055 
check_graph_placement(WG_PARMS * a)2056 void check_graph_placement(WG_PARMS *a)
2057 {
2058 graph_mincheck(a);
2059 if(fg_flag)avoid_graph_collision(a,(void*)(&fg));
2060 if(wg_flag)avoid_graph_collision(a,&wg);
2061 if(hg_flag)avoid_graph_collision(a,(void*)(&hg));
2062 if(bg_flag)avoid_graph_collision(a,(void*)(&bg));
2063 if(ag_flag)avoid_graph_collision(a,(void*)(&ag));
2064 if(cg_flag)avoid_graph_collision(a,(void*)(&cg));
2065 if(pg_flag)avoid_graph_collision(a,(void*)(&pg));
2066 if(eg_flag)avoid_graph_collision(a,(void*)(&eg));
2067 if(mg_flag)avoid_graph_collision(a,(void*)(&mg));
2068 if(tg_flag)avoid_graph_collision(a,(void*)(&tg));
2069 if(rg_flag)avoid_graph_collision(a,(void*)(&rg));
2070 }
2071 
graph_borders(WG_PARMS * a,unsigned char color)2072 void graph_borders(WG_PARMS *a,unsigned char color)
2073 {
2074 lir_hline(a[0].xleft,a[0].ytop,a[0].xright,color);
2075 if(kill_all_flag) return;
2076 lir_hline(a[0].xleft,a[0].ybottom,a[0].xright,color);
2077 if(kill_all_flag) return;
2078 lir_line(a[0].xleft,a[0].ytop,a[0].xleft,a[0].ybottom,color);
2079 if(kill_all_flag) return;
2080 lir_line(a[0].xright,a[0].ytop,a[0].xright,a[0].ybottom,color);
2081 }
2082 
dual_graph_borders(WG_PARMS * a,unsigned char color)2083 void dual_graph_borders(WG_PARMS *a, unsigned char color)
2084 {
2085 graph_borders(a,color);
2086 if(kill_all_flag) return;
2087 lir_hline(a[0].xleft, a[0].yborder, a[0].xright, color);
2088 }
2089 
compute_converter_parameters(void)2090 void compute_converter_parameters(void)
2091 {
2092 if( (ui.converter_mode & (CONVERTER_LO_BELOW+CONVERTER_UP)) == 0)
2093   {
2094   ui_converter_direction=-1;
2095   }
2096 else
2097   {
2098   ui_converter_direction=1;
2099   }
2100 converter_offset_mhz=ui.converter_mhz+0.000001*ui.converter_hz;
2101 }
2102 
2103