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