1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22
23
24 #include <unistd.h>
25 #include <ctype.h>
26 #include <string.h>
27
28 #include "globdef.h"
29 #include "uidef.h"
30 #include "fft1def.h"
31 #include "fft2def.h"
32 #include "fft3def.h"
33 #include "sigdef.h"
34 #include "screendef.h"
35 #include "seldef.h"
36 #include "rusage.h"
37 #include "thrdef.h"
38 #include "txdef.h"
39 #include "vernr.h"
40 #include "hwaredef.h"
41 #include "keyboard_def.h"
42
set_default_cwproc_parms(void)43 void set_default_cwproc_parms(void)
44 {
45 txcw.rise_time=10000;
46 txcw.radar_pulse=txcw.rise_time/1000;
47 txcw.radar_interval=25*txcw.radar_pulse;
48 }
49
make_txproc_filename(void)50 void make_txproc_filename(void)
51 {
52 switch (rx_mode)
53 {
54 case MODE_SSB:
55 sprintf(&ssbproc_filename[11],"%02d",tg.spproc_no);
56 txproc_filename=ssbproc_filename;
57 tx_mode=TXMODE_SSB;
58 break;
59
60 case MODE_WCW:
61 case MODE_NCW:
62 case MODE_HSMS:
63 case MODE_QRSS:
64 case MODE_RADAR:
65 sprintf(&cwproc_filename[10],"%02d",tg.spproc_no);
66 txproc_filename=cwproc_filename;
67 tx_mode=TXMODE_CW;
68 break;
69
70 default:
71 tx_mode=TXMODE_OFF;
72 txproc_filename=NULL;
73 break;
74 }
75 }
76
77
save_tx_parms(char verbose)78 void save_tx_parms(char verbose)
79 {
80 int *wgi;
81 char s[80];
82 char **partext;
83 int i, nn, line;
84 FILE *txpar_file;
85 wgi=NULL;
86 nn=0;
87 partext=NULL;
88 line=4;
89 make_txproc_filename();
90 txpar_file=fopen(txproc_filename,"w");
91 if(txpar_file == NULL)
92 {
93 lirerr(381164);
94 return;
95 }
96 switch (rx_mode)
97 {
98 case MODE_SSB:
99 wgi=(int*)(&txssb);
100 txssb.check=SSBPROC_VERNR;
101 partext=ssbprocparm_text;
102 nn=MAX_SSBPROC_PARM;
103 break;
104
105 case MODE_WCW:
106 case MODE_NCW:
107 case MODE_HSMS:
108 case MODE_QRSS:
109 case MODE_RADAR:
110 wgi=(int*)(&txcw);
111 txcw.check=CWPROC_VERNR;
112 partext=cwprocparm_text;
113 nn=MAX_CWPROC_PARM;
114 break;
115
116 default:
117 lirerr(918453);
118 break;
119 }
120 for(i=0; i<nn; i++)
121 {
122 sprintf(s,"%s [%d]",partext[i],wgi[i]);
123 fprintf(txpar_file,"%s\n",s);
124 if(verbose && line<screen_last_line)lir_text(5,line,s);
125 line++;
126 }
127 parfile_end(txpar_file);
128 sprintf(s,"Parameters saved to %s. %s",txproc_filename, press_any_key);
129 lir_text(10,line+3,s);
130 await_keyboard();
131 }
132
133
134
check_tx_devices(void)135 int check_tx_devices(void)
136 {
137 if(ui.tx_addev_no < 0 ||
138 ui.tx_addev_no >= MAX_DEVNAMES ||
139 ui.tx_dadev_no < 0 ||
140 ui.tx_dadev_no >= MAX_DEVNAMES ||
141 ui.tx_da_channels < 1 ||
142 ui.tx_da_channels > 2 ||
143 (ui.tx_da_bytes !=2 && ui.tx_da_bytes !=4) ||
144 (ui.tx_ad_bytes !=2 && ui.tx_ad_bytes !=4) ) return FALSE;
145 return TRUE;
146 }
147
148
read_txpar_file(void)149 int read_txpar_file(void)
150 {
151 int i, j, k, nn;
152 int *wgi;
153 int rdbytes;
154 FILE *txpar_file;
155 char *testbuff;
156 char **partext;
157 partext=NULL;
158 wgi=NULL;
159 nn=0;
160 if(check_tx_devices() == FALSE)return FALSE;
161 testbuff = malloc(4096);
162 if(testbuff == NULL)
163 {
164 lirerr(1286);
165 return FALSE;
166 }
167 for(i=0; i<4096; i++)testbuff[i]=0;
168 make_txproc_filename();
169 if(txproc_filename == NULL)return FALSE;
170 txpar_file=fopen(txproc_filename,"r");
171 if(txpar_file != NULL)
172 {
173 rdbytes=fread(testbuff,1,4095,txpar_file);
174 fclose(txpar_file);
175 if(rdbytes >= 4095)goto reterr;
176 switch (rx_mode)
177 {
178 case MODE_SSB:
179 wgi=(int*)(&txssb);
180 partext=ssbprocparm_text;
181 nn=MAX_SSBPROC_PARM;
182 break;
183
184 case MODE_WCW:
185 case MODE_NCW:
186 case MODE_HSMS:
187 case MODE_QRSS:
188 case MODE_RADAR:
189 wgi=(int*)(&txcw);
190 partext=cwprocparm_text;
191 nn=MAX_CWPROC_PARM;
192 break;
193
194 default:
195 lirerr(918453);
196 break;
197 }
198 k=0;
199 for(i=0; i<nn; i++)
200 {
201 while( (testbuff[k]==' ' || testbuff[k]== '\n' ) && k<rdbytes)k++;
202 j=0;
203 while(testbuff[k]== partext[i][j] && k<rdbytes)
204 {
205 k++;
206 j++;
207 }
208 if(partext[i][j] != 0)goto reterr;
209 while(testbuff[k]!='[' && k<rdbytes)k++;
210 if(k>=rdbytes)goto reterr;
211 sscanf(&testbuff[k],"[%d]",&wgi[i]);
212 while(testbuff[k]!='\n' && k<rdbytes)k++;
213 if(k>=rdbytes)goto reterr;
214 }
215 switch (rx_mode)
216 {
217 case MODE_SSB:
218 if(txssb.check!=SSBPROC_VERNR ||
219 txssb.minfreq < SSB_MINFQ_LOW ||
220 txssb.minfreq > SSB_MINFQ_HIGH ||
221 txssb.maxfreq < SSB_MAXFQ_LOW ||
222 txssb.maxfreq > SSB_MAXFQ_HIGH ||
223 txssb.slope > SSB_MAXSLOPE ||
224 txssb.slope < SSB_MINSLOPE ||
225 txssb.bass > SSB_MAXBASS ||
226 txssb.bass < SSB_MINBASS ||
227 txssb.treble > SSB_MAXTREBLE ||
228 txssb.treble < SSB_MINTREBLE ||
229 txssb.mic_f_threshold < 0 ||
230 txssb.mic_f_threshold > SSB_MAX_MICF ||
231 txssb.mic_t_threshold < 0 ||
232 txssb.mic_t_threshold > SSB_MAX_MICT ||
233 txssb.mic_gain < 0 ||
234 txssb.mic_gain > SSB_MAX_MICGAIN ||
235 txssb.mic_agc_time < 0 ||
236 txssb.mic_agc_time > SSB_MAX_MICAGC_TIME ||
237 txssb.mic_out_gain < 0 ||
238 txssb.mic_out_gain > SSB_MAX_MICOUT_GAIN ||
239 txssb.rf1_gain < SSB_MIN_RF1_GAIN ||
240 txssb.rf1_gain > SSB_MAX_RF1_GAIN )
241 {
242 goto reterr;
243 }
244 break;
245
246 case MODE_WCW:
247 case MODE_NCW:
248 case MODE_HSMS:
249 case MODE_QRSS:
250 case MODE_RADAR:
251 if( txcw.check != CWPROC_VERNR ||
252 txcw.rise_time < 1000*CW_MIN_TIME_CONSTANT ||
253 txcw.rise_time > 1000*CW_MAX_TIME_CONSTANT ||
254 txcw.radar_pulse < 0.0001*txcw.rise_time ||
255 txcw.radar_pulse > 9999 ||
256 txcw.radar_interval < 4*txcw.radar_pulse ||
257 txcw.radar_interval > 99999)
258 {
259 goto reterr;
260 }
261 break;
262 }
263 }
264 else
265 {
266 reterr:;
267 free(testbuff);
268 return FALSE;
269 }
270 free(testbuff);
271 return TRUE;
272 }
273
set_default_spproc_parms(void)274 void set_default_spproc_parms(void)
275 {
276 txssb.minfreq=200;
277 txssb.maxfreq=2600;
278 txssb.slope=6;
279 txssb.bass=-8;
280 txssb.treble=0;
281 txssb.mic_f_threshold=15;
282 }
283
check_tg_borders(void)284 void check_tg_borders(void)
285 {
286 current_graph_minh=TG_VSIZ;
287 current_graph_minw=TG_HSIZ;
288 check_graph_placement((void*)(&tg));
289 set_graph_minwidth((void*)(&tg));
290 }
291
new_ssbproc_no(void)292 void new_ssbproc_no(void)
293 {
294 int oldno;
295 oldno=tg.spproc_no;
296 tg.spproc_no=numinput_int_data;
297 if(read_txpar_file() == FALSE)
298 {
299 tg.spproc_no=oldno;
300 read_txpar_file();
301 }
302 sc[SC_SHOW_TX_FQ]++;
303 make_modepar_file(GRAPHTYPE_TG);
304 }
305
copy_rxfreq_to_tx(void)306 void copy_rxfreq_to_tx(void)
307 {
308 tg.freq=0.001*hwfreq;
309 set_hardware_tx_frequency();
310 sc[SC_SHOW_TX_FQ]++;
311 make_modepar_file(GRAPHTYPE_TG);
312 }
313
314
new_tx_frequency(void)315 void new_tx_frequency(void)
316 {
317 tg.freq=numinput_float_data;
318 set_hardware_tx_frequency();
319 sc[SC_SHOW_TX_FQ]++;
320 make_modepar_file(GRAPHTYPE_TG);
321 }
322
new_tx_signal_level(void)323 void new_tx_signal_level(void)
324 {
325 tg.level_db=numinput_float_data;
326 if(tg.level_db<0)tg.level_db=0;
327 if(tg.level_db>120)tg.level_db=120;
328 tx_output_amplitude=pow(10.0,-0.05*tg.level_db);
329 sc[SC_SHOW_TX_FQ]++;
330 make_modepar_file(GRAPHTYPE_TG);
331 }
332
help_on_tx_graph(void)333 void help_on_tx_graph(void)
334 {
335 int msg_no;
336 int event_no;
337 // Set msg invalid in case we are not in any select area.
338 msg_no=-1;
339 for(event_no=0; event_no<MAX_TGBUTT; event_no++)
340 {
341 if( tgbutt[event_no].x1 <= mouse_x &&
342 tgbutt[event_no].x2 >= mouse_x &&
343 tgbutt[event_no].y1 <= mouse_y &&
344 tgbutt[event_no].y2 >= mouse_y)
345 {
346 switch (event_no)
347 {
348 case TG_TOP:
349 case TG_BOTTOM:
350 case TG_LEFT:
351 case TG_RIGHT:
352 msg_no=101;
353 break;
354
355 case TG_INCREASE_FQ:
356 msg_no=104;
357 break;
358
359 case TG_DECREASE_FQ:
360 msg_no=103;
361 break;
362
363 case TG_NEW_TX_FREQUENCY:
364 msg_no=105;
365 break;
366
367 case TG_SET_SIGNAL_LEVEL:
368 msg_no=107;
369 break;
370
371 case TG_CHANGE_SSBPROC_NO:
372 msg_no=106;
373 break;
374 }
375 }
376 }
377 help_message(msg_no);
378 }
379
380
381
382
mouse_continue_tx_graph(void)383 void mouse_continue_tx_graph(void)
384 {
385 int i, j;
386 switch (mouse_active_flag-1)
387 {
388 case TG_TOP:
389 if(tg.ytop!=mouse_y)goto tgm;
390 break;
391
392 case TG_BOTTOM:
393 if(tg.ybottom!=mouse_y)goto tgm;
394 break;
395
396 case TG_LEFT:
397 if(tg.xleft!=mouse_x)goto tgm;
398 break;
399
400 case TG_RIGHT:
401 if(tg.xright==mouse_x)break;
402 tgm:;
403 pause_screen_and_hide_mouse();
404 dual_graph_borders((void*)&tg,0);
405 if(tg_oldx==-10000)
406 {
407 tg_oldx=mouse_x;
408 tg_oldy=mouse_y;
409 }
410 else
411 {
412 i=mouse_x-tg_oldx;
413 j=mouse_y-tg_oldy;
414 tg_oldx=mouse_x;
415 tg_oldy=mouse_y;
416 tg.ytop+=j;
417 tg.ybottom+=j;
418 tg.xleft+=i;
419 tg.xright+=i;
420 check_tg_borders();
421 }
422 graph_borders((void*)&tg,15);
423 resume_thread(THREAD_SCREEN);
424 break;
425
426 default:
427 goto await_release;
428 }
429 if(leftpressed == BUTTON_RELEASED)goto finish;
430 return;
431 await_release:;
432 if(leftpressed != BUTTON_RELEASED) return;
433 if(ui.network_flag != 2)
434 {
435 switch (mouse_active_flag-1)
436 {
437 case TG_INCREASE_FQ:
438 if(hware_flag == 0)
439 {
440 tg.freq+=tg.band_increment;
441 set_hardware_tx_frequency();
442 }
443 break;
444
445 case TG_DECREASE_FQ:
446 if(hware_flag == 0)
447 {
448 tg.freq-=tg.band_increment;
449 set_hardware_tx_frequency();
450 }
451 break;
452
453 case TG_NEW_TX_FREQUENCY:
454 if(hware_flag == 0)
455 {
456 numinput_xpix=tgbutt[TG_NEW_TX_FREQUENCY].x1+3;
457 numinput_ypix=tgbutt[TG_NEW_TX_FREQUENCY].y2-text_height+1;
458 numinput_chars=FREQ_MHZ_DIGITS+7;
459 erase_numinput_txt();
460 numinput_flag=FIXED_FLOAT_PARM;
461 par_from_keyboard_routine=new_tx_frequency;
462 }
463 return;
464
465 case TG_SET_SIGNAL_LEVEL:
466 if(hware_flag == 0)
467 {
468 numinput_xpix=tgbutt[TG_SET_SIGNAL_LEVEL].x1+3;
469 numinput_ypix=tgbutt[TG_SET_SIGNAL_LEVEL].y2-text_height+1;
470 numinput_chars=5;
471 erase_numinput_txt();
472 numinput_flag=FIXED_FLOAT_PARM;
473 par_from_keyboard_routine=new_tx_signal_level;
474 }
475 return;
476
477 case TG_CHANGE_SSBPROC_NO:
478 if(hware_flag == 0)
479 {
480 numinput_xpix=tgbutt[TG_CHANGE_SSBPROC_NO].x1+3+5*text_width;
481 numinput_ypix=tgbutt[TG_CHANGE_SSBPROC_NO].y2-text_height+1;
482 numinput_chars=2;
483 erase_numinput_txt();
484 numinput_flag=FIXED_INT_PARM;
485 par_from_keyboard_routine=new_ssbproc_no;
486 }
487 return;
488 break;
489
490 case TG_ONOFF:
491 tx_onoff_flag^=1;
492 break;
493
494 default:
495 lirerr(872);
496 break;
497 }
498 }
499 finish:;
500 leftpressed=BUTTON_IDLE;
501 mouse_active_flag=0;
502 make_tx_graph(TRUE);
503 tg_oldx=-10000;
504 }
505
mouse_on_tx_graph(void)506 void mouse_on_tx_graph(void)
507 {
508 int event_no;
509 // First find out is we are on a button or border line.
510 for(event_no=0; event_no<MAX_TGBUTT; event_no++)
511 {
512 if( tgbutt[event_no].x1 <= mouse_x &&
513 tgbutt[event_no].x2 >= mouse_x &&
514 tgbutt[event_no].y1 <= mouse_y &&
515 tgbutt[event_no].y2 >= mouse_y)
516 {
517 tg_old_y1=tg.ytop;
518 tg_old_y2=tg.ybottom;
519 tg_old_x1=tg.xleft;
520 tg_old_x2=tg.xright;
521 mouse_active_flag=1+event_no;
522 current_mouse_activity=mouse_continue_tx_graph;
523 return;
524 }
525 }
526 // Not button or border.
527 current_mouse_activity=mouse_nothing;
528 mouse_active_flag=1;
529 }
530
531
make_tx_graph(int clear_old)532 void make_tx_graph(int clear_old)
533 {
534 pause_thread(THREAD_SCREEN);
535 if(clear_old)
536 {
537 hide_mouse(tg_old_x1,tg_old_x2,tg_old_y1,tg_old_y2);
538 lir_fillbox(tg_old_x1,tg_old_y1,tg_old_x2-tg_old_x1+1,
539 tg_old_y2-tg_old_y1+1,0);
540 }
541 tg_flag=1;
542 check_tg_borders();
543 clear_button(tgbutt, MAX_TGBUTT);
544 hide_mouse(tg.xleft,tg.xright,tg.ytop,tg.ybottom);
545 scro[tx_graph_scro].no=TRANSMIT_GRAPH;
546 scro[tx_graph_scro].x1=tg.xleft;
547 scro[tx_graph_scro].x2=tg.xright;
548 scro[tx_graph_scro].y1=tg.ytop;
549 scro[tx_graph_scro].y2=tg.ybottom;
550 tgbutt[TG_LEFT].x1=tg.xleft;
551 tgbutt[TG_LEFT].x2=tg.xleft;
552 tgbutt[TG_LEFT].y1=tg.ytop;
553 tgbutt[TG_LEFT].y2=tg.ybottom;
554 tgbutt[TG_RIGHT].x1=tg.xright;
555 tgbutt[TG_RIGHT].x2=tg.xright;
556 tgbutt[TG_RIGHT].y1=tg.ytop;
557 tgbutt[TG_RIGHT].y2=tg.ybottom;
558 tgbutt[TG_TOP].x1=tg.xleft;
559 tgbutt[TG_TOP].x2=tg.xright;
560 tgbutt[TG_TOP].y1=tg.ytop;
561 tgbutt[TG_TOP].y2=tg.ytop;
562 tgbutt[TG_BOTTOM].x1=tg.xleft;
563 tgbutt[TG_BOTTOM].x2=tg.xright;
564 tgbutt[TG_BOTTOM].y1=tg.ybottom;
565 tgbutt[TG_BOTTOM].y2=tg.ybottom;
566 // Draw the border lines
567 graph_borders((void*)&tg,7);
568 tg_oldx=-10000;
569 settextcolor(7);
570 make_button(tg.xleft+text_width,tg.ybottom-text_height/2-2,
571 tgbutt,TG_DECREASE_FQ,25);
572 tgbutt[TG_NEW_TX_FREQUENCY].x1=tgbutt[TG_DECREASE_FQ].x2+0.5*text_width-2;
573 tgbutt[TG_NEW_TX_FREQUENCY].x2=tgbutt[TG_NEW_TX_FREQUENCY].x1+
574 (FREQ_MHZ_DIGITS+9)*text_width;
575 tgbutt[TG_NEW_TX_FREQUENCY].y1=tgbutt[TG_DECREASE_FQ].y1;
576 tgbutt[TG_NEW_TX_FREQUENCY].y2=tgbutt[TG_DECREASE_FQ].y2;
577 make_button(tgbutt[TG_NEW_TX_FREQUENCY].x2+text_width,
578 tg.ybottom-text_height/2-2, tgbutt,TG_INCREASE_FQ,24);
579 tgbutt[TG_CHANGE_SSBPROC_NO].x1=tg.xleft+2;
580 tgbutt[TG_CHANGE_SSBPROC_NO].x2=tg.xleft+2+7.5*text_width;
581 tgbutt[TG_CHANGE_SSBPROC_NO].y2=tgbutt[TG_DECREASE_FQ].y1-2;
582 tgbutt[TG_CHANGE_SSBPROC_NO].y1=tgbutt[TG_CHANGE_SSBPROC_NO].y2-text_height-1;
583
584 tgbutt[TG_SET_SIGNAL_LEVEL].x1=tgbutt[TG_CHANGE_SSBPROC_NO].x2+text_width/2;
585 tgbutt[TG_SET_SIGNAL_LEVEL].x2=tgbutt[TG_SET_SIGNAL_LEVEL].x1+7.5*text_width;
586 tgbutt[TG_SET_SIGNAL_LEVEL].y1=tgbutt[TG_CHANGE_SSBPROC_NO].y1;
587 tgbutt[TG_SET_SIGNAL_LEVEL].y2=tgbutt[TG_CHANGE_SSBPROC_NO].y2;
588
589 tgbutt[TG_ONOFF].x1=tg.xleft+2;
590 tgbutt[TG_ONOFF].x2=tg.xleft+2+3.5*text_width;
591 tgbutt[TG_ONOFF].y2=tgbutt[TG_CHANGE_SSBPROC_NO].y1-2;
592 tgbutt[TG_ONOFF].y1=tgbutt[TG_ONOFF].y2-text_height-2;
593 if(rx_mode == MODE_RADAR)
594 {
595 tgbutt[TG_RADAR_INTERVAL].x1=tgbutt[TG_ONOFF].x2+2;
596 tgbutt[TG_RADAR_INTERVAL].x2=tgbutt[TG_RADAR_INTERVAL].x1+5.5*text_width;
597 tgbutt[TG_RADAR_INTERVAL].y1=tgbutt[TG_ONOFF].y1;
598 tgbutt[TG_RADAR_INTERVAL].y2=tgbutt[TG_ONOFF].y2;
599 }
600 resume_thread(THREAD_SCREEN);
601 sc[SC_SHOW_TX_FQ]++;
602 make_modepar_file(GRAPHTYPE_TG);
603 }
604
605
init_tx_graph(void)606 void init_tx_graph(void)
607 {
608 if (read_modepar_file(GRAPHTYPE_TG) == 0)
609 {
610 tg.xright=screen_width-text_width;;
611 tg.xleft=tg.xright-TG_HSIZ;
612 tg.ybottom=screen_height-4*text_height;
613 tg.ytop=tg.ybottom-TG_VSIZ;
614 }
615 if(tg.spproc_no<0)tg.spproc_no=0;
616 if(tg.spproc_no>MAX_SSBPROC_FILES)tg.spproc_no=MAX_SSBPROC_FILES;
617 tx_graph_scro=no_of_scro;
618 tx_onoff_flag=0;
619 make_tx_graph(FALSE);
620 no_of_scro++;
621 if(no_of_scro >= MAX_SCRO)lirerr(89);
622 set_hardware_tx_frequency();
623 }
624