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