1 
2 // program users_tr.c for CAT control with Linrad
3 // supported transeivers: ELCRAFT K3
4 //                        ICOM    IC-275/IC-706
5 //                        KENWOOD TS-850/TS-2000
6 //                        YAESU   FT-450/FT-736/FT-817/FT-897/FT-920/FT-950/FT-1000/FT-2000
7 // Runs under Windows and Linux
8 // Based on input from DL3IAE/IK7EZN/K1JT/ON4IY/ON7EH/W3SZ/YO4AUL/NH7O
9 // with the support of Leif SM5BSZ
10 // All errors are mine
11 // Use at your own risk and enjoy
12 // Pierre/ON5GN
13 //
14 // UPDATE HISTORY
15 //
16 //   4 may   2007  first version for linrad 02.31
17 //                 FT-736 tested by DL3IAE
18 //                 TS-850 tested by ON7EH
19 //                 ICOM tested by IK7EZN
20 //  22 july  2008  update for linrad-02.48
21 //                 added FT-897, tested by YO4AUL and ON4KHG
22 //  23 may   2010  bug correction and documentation updates
23 //   8 july  2010  added FT-920 (NH7O)
24 //  20 july  2010  added FT-817, tested by DL3IAE
25 //                 changed parameter file (uses now the Linrad standards)
26 //  28 aug   2011  added Elecraft K3 (NH7O)
27 //   4 nov   2013  Initial RTS status in the transceiver structure and
28 //                 frequency int k changed to double kxx.
29 //
30 // INSTALLATION
31 //
32 // To install under Linux for Linux:
33 //   download lirxx-xx.tbz and extract it to your linrad directory
34 //   rename users_tr.c to users_hwaredriver.c in your linrad directory
35 //   run ./configure and  make xlinrad (or make linrad) from your linrad
36 //   directory
37 //
38 // To generate a windows version under Linux:
39 //   install mingw32 from Leif's website
40 //   download lirxx-xx.tbz and extract it to your linrad directory
41 //   rename  users_tr.c to wusers_hwaredriver.c in your linrad directory
42 //   run ./configure and  make linrad.exe from your linrad directory
43 //
44 // To generate a windows version under Windows:
45 //   Install mingw and nasm from Leif's website in the C:\MinGW  directory
46 //   Download lirxx-xx.zip and unpack the linrad sources in your linrad
47 //   directory
48 //   Rename  users_tr.c to wusers_hwaredriver.c in your linrad directory
49 //   Start a MS-DOS Command Window on your computer: click the Windows Start
50 //   menu and enter the "cmd.exe" command into the run box
51 //   In the MS-DOS Command Window issue a "cd" command to your linrad directory
52 //   followed by a "configure.exe" and "make.bat" command
53 //
54 // USERGUIDE
55 //
56 // Moving the usergraph:
57 //   Move the usergraph on the screen by hitting the left side of the graph
58 //   with the mousepointer, holding the left mouse button down, and dragging
59 //   it to the desired position.
60 //
61 // Setting the VFO frequency:
62 //   Select first the transceiver-type with the arrow buttons in the upper
63 //   right corner of the usergraph.
64 //
65 //   Next select the serial port number with the arrow buttons next to the
66 //   SERIAL PORT field:
67 //   Under Windows one can select COM1 to COM8.
68 //   Under Linux one can select /devttyS0 to /dev/ttyS3
69 //   or /dev/ttyUSB0 to /dev/ttyUSB3 for USB-serial devices.
70 //   Under BSD one can select /dev/ttyd0 to /dev/ttyd7.
71 //
72 //   Enter the values for Offset-raw (Khz) and Offset-fine (Hz) in the
73 //   corresponding fields and use the corresponding arrow buttons for fine
74 //   tuning. This offset is intended for transverter usage or for the
75 //   correction of small frequency offsets between Linrad and the transceiver.
76 //
77 //   Select a frequency on the Linrad waterfall graph.
78 //   Hit the Q-key to transfer the Linrad frequency, incremented with the
79 //   total offset, to the transceiver VFO.
80 //
81 //   Note: The graph position, the serial port number, the transceiver-type,
82 //         and the offset values for 12 frequency bands are saved in a
83 //         parameterfile and retrieved afterwards when Linrad is (re)started.
84 //         The file name is "par_xxx_hwd_ug" (with xxx = rx_mode) and its
85 //         content can be displayed with an editor.
86 //         The frequency bands are defined by the variable bandlim.
87 //
88 // Calibration procedure:
89 //   This function sets automatically the values for Offset-raw and Offset-fine
90 //   by reading the VFO frequency from the transceiver, calculating the
91 //   difference with the Linrad frequency and storing this difference in
92 //   the offset variables:
93 //
94 //   Tune the TRX receiver and Linrad to the same carrier (zero beat).
95 //   Click on the blue 'calibration' box with the mouse.
96 //   Hit the Q-key to -read the VFO frequency from the transceiver
97 //                    -calculate the frequency-offset between Linrad and the
98 //                     transceiver VFO
99 //                    -store this offset in Offset-raw and Offset-fine.
100 //
101 // CUSTOMIZATION
102 //
103 // To add support for a new transceiver:
104 //   1.Add an entry to the list of supported transceivers between line 149 and
105 //     line 164 with the name of the transceiver, its  serial port parameters
106 //     and its frequency range. Use the  existing lines as examples.
107 //   2.Add the corresponding 'SET VFO' and 'CALIBRATION' code (only a few
108 //     lines of coding ) for the new transceiver:
109 //     Get the technical specifications for the CAT commands for the new
110 //     transceiver and use the existing code for transceivers from the same
111 //     transceiver-family as a framework/guideline:
112 //       For a new YAESU transceiver p.e. have a look at the code for the
113 //       FT-450/FT-950/FT-2000 :
114 //       look at lines 1577-1595 for the 'SET VFO' code and lines 1299-1353
115 //       for the 'CALIBRATION' code.
116 //     The 'CALIBRATION' code is not mandatory. If not present, an error
117 //     message will be displayed in the usergraph.
118 //
119 // ****************************************************************************
120 // Change the define for RX_HARDWARE and modify the dummy routines
121 // in the prototype section to fit your needs.
122 // The routines in wse_sdrxx.c can serve as a starting point.
123 #define RX_HARDWARE 0
124 // ****************************************************************************
125 
126 #include <string.h>
127 
128 int serport_open_status;
129 int serport_number = 1 ;
130 int transceiver_number = 0 ;
131 int chnge_serport_switch =0;
132 int chnge_calibr_switch =0;
133 double offset_hz;
134 double offset_khz;
135 double old_hwfreq;
136 
137 #define MAX_NO_OF_TRANSCEIVERS 32
138 
139 struct transceiver
140 {
141  char name[16];
142  int serport_baudrate;
143  int serport_stopbits;
144  double min_transceiver_freq;
145  double max_transceiver_freq;
146  int serport_rts_mode;
147  };
148 
149 // List of supported transceivers and corresponding values for
150 //   serport_baudrate (valid values between 110 and  57600 )
151 //   serport_stopbits (0 for one stopbit or 1 for two stopbits )
152 //   min and max transceiver_frequency(Hz)
153 // check the transceiver manual to get the correct values
154 const struct transceiver list[MAX_NO_OF_TRANSCEIVERS] =
155 {{"K3         ",38400, 1,  1800000.,  54000000., 0},
156  {"FT-450     ", 4800, 1,    30000.,  56000000., 0},
157  {"FT-736     ", 4800, 1,144000000., 146000000., 0},
158  {"FT-817     ",38400, 1,  1500000., 470000000., 0},
159  {"FT-897     ",38400, 1,  1500000., 470000000., 0},
160  {"FT-920     ", 4800, 1,   100000.,  56000000., 0},
161  {"FT-950     ", 4800, 1,    30000.,  56000000., 0},
162  {"FT-1000    ", 4800, 1,  1600000.,  30000000., 0},
163  {"FT-2000    ", 4800, 1,    30000.,  60000000., 0},
164  {"IC-275     ", 9600, 0,144000000., 146000000., 0},
165  {"ICOM-all   ", 9600, 0,  1800000.,2450000000., 0},
166  {"IC-706     ", 9600, 0,  1800000., 148000000., 0},
167  {"IC-706MKII ", 9600, 0,  1800000., 148000000., 0},
168  {"IC-706MKIIG", 9600, 0,  1800000., 148000000., 0},
169  {"TS-850     ", 4800, 1,  1600000.,  30000000., 0},
170  {"TS-2000    ", 9600, 0,  1600000., 148000000., 0},
171  {"END LIST   ",    0, 0,        0.,         0., 0}};
172 // ***************************************************************************
173 // ***************************************************************************
174 // ROUTINES FOR THE PROCESSING OF A 'MOVABLE' FIXED SIZE USERGRAPH
175 // the screenposition of the usergraph and its variables are saved
176 // in the parameterfile "par_xxx_hwd_ug" ( with xxx = rx_mode) in the linrad directory
177 // ****************************************************************************
178 // ****************************************************************************
179 
180 #define MAX_HWAREDRIVER_PARM 28
181 
182 char *users_hwaredriver_parm_text[MAX_HWAREDRIVER_PARM]={
183                                        "ug_xleft             ",
184                                        "ug_ytop              ",
185                                        "serport_number       ",
186                                        "transceiver_number   ",
187                                        "offs_hz_band_0-2.5   ",
188                                        "offs_hz_band_2.5-5   ",
189                                        "offs_hz_band_5-9     ",
190                                        "offs_hz_band_9-12    ",
191                                        "offs_hz_band_12-16   ",
192                                        "offs_hz_band_16-19   ",
193                                        "offs_hz_band_19-23   ",
194                                        "offs_hz_band_23-26   ",
195                                        "offs_hz_band_26-40   ",
196                                        "offs_hz_band_40-100  ",
197                                        "offs_hz_band_100-300 ",
198                                        "offs_hz_band_BIG     ",
199                                        "offs_khz_band_0-2.5  ",
200                                        "offs_khz_band_2.5-5  ",
201                                        "offs_khz_band_5-9    ",
202                                        "offs_khz_band_9-12   ",
203                                        "offs_khz_band_12-16  ",
204                                        "offs_khz_band_16-19  ",
205                                        "offs_khz_band_19-23  ",
206                                        "offs_khz_band_23-26  ",
207                                        "offs_khz_band_26-40  ",
208                                        "offs_khz_band_40-100 ",
209                                        "offs_khz_band_100-300",
210                                        "offs_khz_band_BIG    ",
211                                        };
212 
213 #define NO_OF_BANDS 12
214 float bandlim[]={2.5,  //0
215                  5.0,  //1
216                  9.0,  //2
217                 12.0,  //3
218                 16.0,  //4
219                 19.0,  //5
220                 23.0,  //6
221                 26.0,  //7
222                 40.0,  //8
223                100.0,  //9
224                300.0,  //10
225                BIG};   //11
226 
227 typedef struct {
228 int ug_xleft;
229 int ug_ytop;
230 int serport_number;
231 int transceiver_number;
232 int offs_hz[NO_OF_BANDS];
233 int offs_khz[NO_OF_BANDS];
234 } HWAREDRIVER_PARMS;
235 HWAREDRIVER_PARMS hwaredriver;
236 
237 #define USERS_GRAPH_TYPE1 64
238 typedef struct {
239 int ytop;
240 int ybottom;
241 int xleft;
242 int xright;
243 int yborder;    // required for move graph
244 } UG_PARMS;
245 UG_PARMS ug;
246 
247 #define UG_TOP 0
248 #define UG_BOTTOM 1
249 #define UG_LEFT 2
250 #define UG_RIGHT 3
251 #define UG_INCREASE_OFFS_HZ 4
252 #define UG_DECREASE_OFFS_HZ 5
253 #define UG_INCREASE_OFFS_KHZ 6
254 #define UG_DECREASE_OFFS_KHZ 7
255 #define UG_INCREASE_SERPORT_NMBR 8
256 #define UG_DECREASE_SERPORT_NMBR 9
257 #define UG_INCREASE_TRANSCEIVER_NMBR 10
258 #define UG_DECREASE_TRANSCEIVER_NMBR 11
259 #define MAX_UGBUTT 12
260 
261 BUTTONS ugbutt[MAX_UGBUTT];
262 
263 int ug_old_y1;
264 int ug_old_y2;
265 int ug_old_x1;
266 int ug_old_x2;
267 int users_graph_scro;
268 
269 int ug_oldx;     // required for move graph
270 int ug_oldy;     // required for move graph
271 int ug_yborder;  // required for move graph
272 int ug_hsiz;     // required for move graph
273 int ug_vsiz;     // required for move graph
274 
275 int ug_band_no;
276 
277 #define MAX_MSGSIZE 30     //Size of messages. min size=30
278 char ug_msg0[MAX_MSGSIZE]; //messages in usergraph
279 char ug_msg1[MAX_MSGSIZE];
280 char ug_msg2[MAX_MSGSIZE];
281 int ug_msg_color;   //switch for message-color in usergraph
282 double min_transceiver_freq=0;
283 double max_transceiver_freq=0;
284 
set_press_q_key_new_freq_msg(void)285 void set_press_q_key_new_freq_msg(void)
286 {
287 ug_msg_color=14;
288 strcpy(ug_msg0,"PRESS Q-KEY TO SET TRX FREQ.");
289 ug_msg1[0]=0;
290 ug_msg2[0]=0;
291 }
292 
set_press_q_key_chnge_port_msg(void)293 void set_press_q_key_chnge_port_msg(void)
294 {
295 //change the name of the serial port
296 char s[80];
297 if (strncmp(serport_name,"COM",3)==0)
298 // this is windows
299  {
300  sprintf(&serport_name[3],"%d",serport_number);
301  }
302 if (strncmp(serport_name,"/dev/ttyd",9)==0)
303 //this is BSD
304   {
305   sprintf(&serport_name[9],"%d",serport_number-1);
306   }
307 if (strncmp(serport_name,"/dev/ttyS",9)==0)
308 // this is linux
309 // use either /dev/ttyS0 to /dev/ttyS3
310 //         or /dev/ttyUSB0 to /dev/ttyUSB3
311  {
312  if (serport_number <= 4)                   //
313   {
314   sprintf(&serport_name[9],"%d",serport_number-1);
315   }
316  else                                       //
317   {
318   sprintf(&serport_name[0],"%s","/dev/ttyUSB");
319   sprintf(&serport_name[11],"%d",serport_number-5);
320   }
321  }
322 if (strncmp(serport_name,"/dev/ttyUSB",11)==0)
323 // this is linux
324 // use either /dev/ttyS0 to /dev/ttyS3
325 //         or /dev/ttyUSB0 to /dev/ttyUSB3
326  {
327  if (serport_number > 4)
328   {
329   sprintf(&serport_name[11],"%d",serport_number-5);
330   }
331  else
332   {
333   sprintf(&serport_name[0],"%s","/dev/ttyS");
334   sprintf(&serport_name[9],"%d",serport_number-1);
335   }
336  }
337 sprintf(s," SERIAL PORT:%s ",serport_name);
338 lir_pixwrite(ug.xleft+.5*text_width,ug.ytop+1.5*text_height,s);
339 ug_msg_color=15;
340 strcpy(ug_msg0,"PRESS Q-KEY TO OPEN SER. PORT");
341 ug_msg1[0]=0;
342 ug_msg2[0]=0;
343 chnge_serport_switch=1;
344 }
345 
check_ug_borders(void)346 void check_ug_borders(void)  // required for move graph
347 {
348 current_graph_minh=ug_vsiz;
349 current_graph_minw=ug_hsiz;
350 check_graph_placement((void*)(&ug));
351 set_graph_minwidth((void*)(&ug));
352 }
353 
users_show_offset(void)354 void users_show_offset(void)
355 {
356 char s[80];
357 settextcolor(15);
358 sprintf(s,"Offset-fine(Hz): %d        ",hwaredriver.offs_hz[ug_band_no]);
359 s[25]=0;
360 lir_pixwrite(ug.xleft+1.5*text_width,ug.ytop+1+3.5*text_height,s);
361 sprintf(s,"Offset-raw(Khz): %d        ",hwaredriver.offs_khz[ug_band_no]);
362 s[25]=0;
363 lir_pixwrite(ug.xleft+1.5*text_width,ug.ytop+2.5*text_height,s);
364 settextcolor(7);
365 offset_hz= hwaredriver.offs_hz[ug_band_no];
366 offset_khz=hwaredriver.offs_khz[ug_band_no];
367 }
368 
blankfill_ugmsg(char * msg)369 void blankfill_ugmsg(char *msg)
370 {
371 int i;
372 i=strlen(msg);
373 if(i>=MAX_MSGSIZE)lirerr(3413400);
374 while(i<MAX_MSGSIZE-1)
375   {
376   msg[i]=' ';
377   i++;
378   }
379 msg[MAX_MSGSIZE-1]=0;
380 }
381 
show_user_parms(void)382 void show_user_parms(void)
383 {
384 int i;
385 char s[80];
386 extern char serport_name[14];
387 // Show the user parameters on screen
388 // and issue hardware commands if required.
389 // Use hware_flag to direct calls to control_hware() when cpu time
390 // is available in case whatever you want to do takes too much time
391 // to be done immediately.
392 // Note that mouse control is done in the narrowband processing thread
393 // and that you can not use lir_sleep to wait for hardware response here.
394 hide_mouse(ug.xleft, ug.xright,ug.ytop,ug.ybottom);
395 sprintf(s,"CALIBRATE");
396 settextcolor(11);
397 lir_pixwrite(ug.xleft+.5*text_width,ug.ytop+0.35*text_height,s);
398 sprintf(s,"   CAT FREQUENCY CONTROL FOR TRX: %s ",list[transceiver_number].name);
399 settextcolor(14);
400 lir_pixwrite(ug.xleft+10.5*text_width,ug.ytop+0.35*text_height,s);
401 settextcolor(15);
402 sprintf(s," SERIAL PORT:%s ",serport_name);
403 lir_pixwrite(ug.xleft+.5*text_width,ug.ytop+1.5*text_height,s);
404 
405 settextcolor(7);
406 users_show_offset();
407 
408 //DISPLAY MESSAGES IN  MESSAGE-AREA OF USERGRAPH
409 
410 // Fill message with blanks up to character MAX_MSGSIZE-2
411 blankfill_ugmsg(ug_msg0);
412 blankfill_ugmsg(ug_msg1);
413 blankfill_ugmsg(ug_msg2);
414 settextcolor(ug_msg_color);
415 lir_pixwrite(ug.xleft+31*text_width,ug.ytop+1.5*text_height,ug_msg0);
416 lir_pixwrite(ug.xleft+31*text_width,ug.ytop+2.5*text_height,ug_msg1);
417 lir_pixwrite(ug.xleft+31*text_width,ug.ytop+3.5*text_height,ug_msg2);
418 settextcolor(7);
419 
420 // save screenposition, serport_number, transceiver_number and offset-values
421 // to the parameterfile on disk
422 
423 char hwaredriver_parfil_name[20];
424 sprintf(hwaredriver_parfil_name,"%s_hwd_ug",rxpar_filenames[rx_mode]);
425 FILE *hwaredriver_file;
426 int *sdr_pi;
427 hwaredriver_file=fopen(hwaredriver_parfil_name,"w");
428 hwaredriver.ug_xleft=ug.xleft;
429 hwaredriver.ug_ytop=ug.ytop;
430 hwaredriver.serport_number=serport_number;
431 hwaredriver.transceiver_number=transceiver_number;
432 sdr_pi=(int*)(&hwaredriver);
433 for(i=0; i<MAX_HWAREDRIVER_PARM; i++)
434   {
435   fprintf(hwaredriver_file,"%s [%d]\n",users_hwaredriver_parm_text[i],sdr_pi[i]);
436   }
437 parfile_end(hwaredriver_file);
438 }
439 
users_set_band_no(void)440 void users_set_band_no(void)
441 {
442 ug_band_no=0;
443 while(bandlim[ug_band_no] < fg.passband_center)ug_band_no++;
444 if(all_threads_started == TRUE)
445   {
446   pause_thread(THREAD_SCREEN);
447   set_press_q_key_new_freq_msg();
448   show_user_parms();
449   resume_thread(THREAD_SCREEN);
450   }
451 }
452 
make_users_control_graph(void)453 void make_users_control_graph(void)
454 {
455 pause_thread(THREAD_SCREEN);
456 // Set a negative number here.
457 // In case several windows are desired, give them different
458 // negative numbers and use scro[m].no to decide what to do
459 // in your mouse_on_users_graph routine.
460 check_ug_borders();  // required for move graph
461 scro[users_graph_scro].no=USERS_GRAPH_TYPE1;
462 // These are the coordinates of the border lines.
463 scro[users_graph_scro].x1=ug.xleft;
464 scro[users_graph_scro].x2=ug.xright;
465 scro[users_graph_scro].y1=ug.ytop;
466 scro[users_graph_scro].y2=ug.ybottom;
467 // Each border line is treated as a button.
468 // That is for the mouse to get hold of them so the window can be moved.
469 ugbutt[UG_LEFT].x1=ug.xleft;
470 ugbutt[UG_LEFT].x2=ug.xleft+2;
471 ugbutt[UG_LEFT].y1=ug.ytop;
472 ugbutt[UG_LEFT].y2=ug.ybottom;
473 ugbutt[UG_RIGHT].x1=ug.xright;
474 ugbutt[UG_RIGHT].x2=ug.xright-2;
475 ugbutt[UG_RIGHT].y1=ug.ytop;
476 ugbutt[UG_RIGHT].y2=ug.ybottom;
477 ugbutt[UG_TOP].x1=ug.xleft;
478 ugbutt[UG_TOP].x2=ug.xright;
479 ugbutt[UG_TOP].y1=ug.ytop;
480 ugbutt[UG_TOP].y2=ug.ytop+2;
481 ugbutt[UG_BOTTOM].x1=ug.xleft;
482 ugbutt[UG_BOTTOM].x2=ug.xright;
483 ugbutt[UG_BOTTOM].y1=ug.ybottom;
484 ugbutt[UG_BOTTOM].y2=ug.ybottom-2;
485 // Draw the border lines
486 graph_borders((void*)&ug,7);
487 ug_oldx=-10000;                   //from freq_control
488 settextcolor(7);
489 make_button(ug.xleft+27.5*text_width+2,ug.ybottom-1*text_height/2-1,
490                                          ugbutt,UG_DECREASE_OFFS_HZ,25);
491 make_button(ug.xleft+29*text_width+2,ug.ybottom-1*text_height/2-1,
492                                      ugbutt,UG_INCREASE_OFFS_HZ,24);
493 
494 make_button(ug.xleft+27.5*text_width+2,ug.ybottom-3*text_height/2-1,
495                                          ugbutt,UG_DECREASE_OFFS_KHZ,25);
496 make_button(ug.xleft+29*text_width+2,ug.ybottom-3*text_height/2-1,
497                                      ugbutt,UG_INCREASE_OFFS_KHZ,24);
498 
499 make_button(ug.xleft+27.5*text_width+2,ug.ybottom-5*text_height/2-1,
500                                          ugbutt,UG_DECREASE_SERPORT_NMBR,25);
501 make_button(ug.xleft+29*text_width+2,ug.ybottom-5*text_height/2-1,
502                                      ugbutt,UG_INCREASE_SERPORT_NMBR,24);
503 
504 make_button(ug.xleft+57.5*text_width+2,ug.ytop+1.5*text_height/2-1,
505                                          ugbutt,UG_DECREASE_TRANSCEIVER_NMBR,25);
506 make_button(ug.xleft+59*text_width+2,ug.ytop+1.5*text_height/2-1,
507                                      ugbutt,UG_INCREASE_TRANSCEIVER_NMBR,24);
508 show_user_parms();
509 //draw separatorlines in usergraph
510 //vertical
511 lir_line(ug.xleft+30.5*text_width,ug.ytop+1.3*text_height,ug.xleft+30.5*text_width,ug.ybottom,7);
512 lir_line(ug.xleft+10*text_width,ug.ytop+0*text_height,ug.xleft+10*text_width,ug.ytop+1.3*text_height,7);
513 //horizontal
514 lir_line(ug.xleft,ug.ytop+1.3*text_height,ug.xright,ug.ytop+1.3*text_height,7);
515 //
516 resume_thread(THREAD_SCREEN);
517 }
518 
mouse_continue_users_graph(void)519 void mouse_continue_users_graph(void)
520 {
521 int i, j;      // required for move graph
522 switch (mouse_active_flag-1)
523   {
524 // Move border lines immediately.
525 // for other functions, wait until button is released.
526 // Move fixed size window  based on coding in freq_control.c
527 case UG_TOP:
528   if(ug.ytop!=mouse_y)goto ugm;
529   break;
530 
531   case UG_BOTTOM:
532   if(ug.ybottom!=mouse_y)goto ugm;
533   break;
534 
535   case UG_LEFT:
536   if(ug.xleft!=mouse_x)goto ugm;
537   break;
538 
539   case UG_RIGHT:
540   if(ug.xright==mouse_x)break;
541 ugm:;
542   pause_screen_and_hide_mouse();
543   graph_borders((void*)&ug,0);
544   if(ug_oldx==-10000)
545     {
546     ug_oldx=mouse_x;
547     ug_oldy=mouse_y;
548     }
549   else
550     {
551     i=mouse_x-ug_oldx;
552     j=mouse_y-ug_oldy;
553     ug_oldx=mouse_x;
554     ug_oldy=mouse_y;
555     ug.ytop+=j;
556     ug.ybottom+=j;
557     ug.xleft+=i;
558     ug.xright+=i;
559     check_ug_borders();
560     ug.yborder=(ug.ytop+ug.ybottom)>>1;
561     }
562   graph_borders((void*)&ug,15);
563   resume_thread(THREAD_SCREEN);
564   break;
565 
566   default:
567   goto await_release;
568   }
569 if(leftpressed == BUTTON_RELEASED)goto finish;
570 return;
571 await_release:;
572 if(leftpressed != BUTTON_RELEASED) return;
573 // Assuming the user wants to control hardware we
574 // allow commands only when data is not over the network.
575 if((ui.network_flag&NET_RX_INPUT) == 0) //for linrad02.23
576   {
577   switch (mouse_active_flag-1)
578     {
579     case UG_INCREASE_OFFS_HZ:
580     hwaredriver.offs_hz[ug_band_no]++;
581     set_press_q_key_new_freq_msg();
582     show_user_parms();
583     break;
584 
585     case UG_DECREASE_OFFS_HZ:
586     hwaredriver.offs_hz[ug_band_no]--;
587     set_press_q_key_new_freq_msg();
588     show_user_parms();
589     break;
590 
591     case UG_INCREASE_OFFS_KHZ:
592     hwaredriver.offs_khz[ug_band_no]++;
593     set_press_q_key_new_freq_msg();
594     show_user_parms();
595     break;
596 
597     case UG_DECREASE_OFFS_KHZ:
598     hwaredriver.offs_khz[ug_band_no]--;
599     set_press_q_key_new_freq_msg();
600     show_user_parms();
601     break;
602 
603     case UG_INCREASE_SERPORT_NMBR:
604     serport_number++;
605     if (serport_number >= 8) serport_number =8;
606     set_press_q_key_chnge_port_msg();
607     show_user_parms();
608     break;
609 
610     case UG_DECREASE_SERPORT_NMBR:
611     serport_number--;
612     if (serport_number <= 1) serport_number =1;
613     set_press_q_key_chnge_port_msg();
614     show_user_parms();
615     break;
616 
617     case UG_INCREASE_TRANSCEIVER_NMBR:
618     transceiver_number++;
619     if  ((strcmp(list[transceiver_number].name,"END LIST   ")==0))
620          transceiver_number--;
621     set_press_q_key_new_freq_msg();
622     show_user_parms();
623     break;
624 
625     case UG_DECREASE_TRANSCEIVER_NMBR:
626     transceiver_number--;
627     if (transceiver_number <= 0) transceiver_number =0;
628     set_press_q_key_new_freq_msg();
629     show_user_parms();
630     break;
631 
632     default:
633 // This should never happen.
634     lirerr(211053);
635     break;
636     }
637   }
638 finish:;
639 hide_mouse(ug_old_x1,ug_old_x2,ug_old_y1,ug_old_y2);
640 leftpressed=BUTTON_IDLE;
641 mouse_active_flag=0;
642 graph_borders((void*)&ug,0);
643 lir_fillbox(ug_old_x1,ug_old_y1,ug_old_x2-ug_old_x1,ug_old_y2-ug_old_y1,0);
644 make_users_control_graph();
645 ug_oldx=-10000;
646 }
647 
new_user_offs_hz(void)648 void new_user_offs_hz(void)
649 {
650 hwaredriver.offs_hz[ug_band_no]=numinput_int_data;
651 pause_thread(THREAD_SCREEN);
652 set_press_q_key_new_freq_msg();
653 show_user_parms();
654 resume_thread(THREAD_SCREEN);
655 }
656 
users_new_user_offs_khz(void)657 void users_new_user_offs_khz(void)
658 {
659 hwaredriver.offs_khz[ug_band_no]=numinput_float_data;
660 pause_thread(THREAD_SCREEN);
661 set_press_q_key_new_freq_msg();
662 show_user_parms();
663 resume_thread(THREAD_SCREEN);
664 }
665 
mouse_on_users_graph(void)666 void mouse_on_users_graph(void)
667 {
668 int event_no;
669 // First find out if we are on a button or border line.
670 for(event_no=0; event_no<MAX_UGBUTT; event_no++)
671   {
672   if( ugbutt[event_no].x1 <= mouse_x &&
673       ugbutt[event_no].x2 >= mouse_x &&
674       ugbutt[event_no].y1 <= mouse_y &&
675       ugbutt[event_no].y2 >= mouse_y)
676     {
677     ug_old_y1=ug.ytop;
678     ug_old_y2=ug.ybottom;
679     ug_old_x1=ug.xleft;
680     ug_old_x2=ug.xright;
681     mouse_active_flag=1+event_no;
682     current_mouse_activity=mouse_continue_users_graph;
683     return;
684     }
685   }
686 // Not button or border.
687 // Prompt the user for offs_hz or offs_khz depending on whether the mouse is
688 // in the upper or the lower part of the window.
689 mouse_active_flag=1;
690 numinput_xpix=ug.xleft+18.5*text_width;
691 if(mouse_x > ug.xleft && mouse_x < ug.xleft+10*text_width)
692 {
693 if(mouse_y > ug.ytop && mouse_y < (ug.ytop+1.3*text_height))
694   {
695   ug_msg_color=11;
696   strcpy(ug_msg0,"PRESS Q-KEY TO CALIBRATE");
697   ug_msg1[0]=0;
698   ug_msg2[0]=0;
699   chnge_calibr_switch=1;
700   show_user_parms();
701   }
702 }
703 if(mouse_x > ug.xleft+18.5*text_width && mouse_x < ug.xleft+25*text_width)
704   {
705 if(mouse_y > (ug.ytop+3.8*text_height))
706     {
707     numinput_ypix=ug.ytop+3.6*text_height;
708     numinput_chars=4;
709     erase_numinput_txt();
710     numinput_flag=FIXED_INT_PARM;
711     par_from_keyboard_routine=new_user_offs_hz; //offset-fine
712 
713     }
714   else
715     {
716     numinput_ypix=ug.ytop+(2.4*text_height)+1;
717     numinput_chars=7;
718     erase_numinput_txt();
719     numinput_flag=FIXED_FLOAT_PARM;
720     par_from_keyboard_routine=users_new_user_offs_khz; //offset-raw
721     }
722   }
723 else
724   {
725 // If we did not select a numeric input by setting numinput_flag
726 // we have to set mouse_active flag.
727 // Set the routine to mouse_nothing, we just want to
728 // set flags when the mouse button is released.
729   current_mouse_activity=mouse_nothing;
730   mouse_active_flag=1;
731   }
732 }
733 
init_users_control_window(void)734 void init_users_control_window(void)
735 {
736 int i;
737 // Get values from parameterfile
738 int errcod;
739 char hwaredriver_parfil_name[20];
740 sprintf(hwaredriver_parfil_name,"%s_hwd_ug",rxpar_filenames[rx_mode]);
741 errcod=read_sdrpar(hwaredriver_parfil_name, MAX_HWAREDRIVER_PARM,
742                                      users_hwaredriver_parm_text, (int*)((void*)&hwaredriver));
743 if (errcod != 0)
744   {
745   FILE *hwaredriver_file;
746   int *sdr_pi;
747   hwaredriver_file=fopen(hwaredriver_parfil_name,"w");
748 //set_default_parameter values
749   hwaredriver.ug_xleft=60*text_width;
750   hwaredriver.ug_ytop=(screen_last_line-4)*text_height;
751   hwaredriver.serport_number=1;
752   hwaredriver.transceiver_number=0;
753   for(i=0; i<NO_OF_BANDS; i++)
754    {
755    hwaredriver.offs_hz[i]=0;
756    hwaredriver.offs_khz[i]=0;
757    }
758   sdr_pi=(int*)(&hwaredriver);
759   for(i=0; i<MAX_HWAREDRIVER_PARM; i++)
760    {
761    fprintf(hwaredriver_file,"%s [%d]\n",users_hwaredriver_parm_text[i],sdr_pi[i]);
762    }
763   parfile_end(hwaredriver_file);
764   }
765 ug.xleft=hwaredriver.ug_xleft;
766 ug.ytop=hwaredriver.ug_ytop;
767 serport_number=hwaredriver.serport_number;
768 transceiver_number=hwaredriver.transceiver_number;
769 
770 //trace
771 //printf("\n serport_number %i\n",serport_number);
772 lir_close_serport();
773 // 1=COM1 or /dev/ttyS0 , 2=COM2....
774 // baudrate 110 to 57600
775 // 1=two stopbits, 0=one stopbit
776 serport_open_status=lir_open_serport(serport_number,
777      list[transceiver_number].serport_baudrate,
778      list[transceiver_number].serport_stopbits,
779      list[transceiver_number].serport_rts_mode);
780 set_press_q_key_new_freq_msg();
781 ug_hsiz=(30+MAX_MSGSIZE)*text_width;                  //  WIDTH OF USERGRAPH
782 ug_vsiz=(4.8*text_height);                            //  HEIGHT OF USERGRAPH
783 ug.xright=ug.xleft+ug_hsiz;
784 ug.ybottom= ug.ytop+ug_vsiz;
785 if(rx_mode < MODE_TXTEST)
786   {
787   users_graph_scro=no_of_scro;
788   make_users_control_graph();
789   no_of_scro++;
790   if(no_of_scro >= MAX_SCRO)lirerr(89);
791   }
792 }
793 
users_init_mode(void)794 void users_init_mode(void)
795 {
796 // A switch statement can be used to do different things depending on
797 // the processing mode.
798 //switch (rx_mode)
799 //  {
800 //  case MODE_WCW:
801 //  case MODE_HSMS:
802 //  case MODE_QRSS:
803 //  break;
804 //  case MODE_NCW:
805 //  case MODE_SSB:
806 // Open a window to allow mouse control of your own things
807   init_users_control_window();
808 //  break;
809 //  case MODE_FM:
810 //  case MODE_AM:
811 //  case MODE_TXTEST:
812 //  case MODE_RX_ADTEST:
813 //  case MODE_TUNE:
814 //  break;
815 //  }
816 }
817 // ***************************************************************************
818 // END ROUTINES FOR THE PROCESSING OF A 'MOVABLE' FIXED SIZE USERGRAPH
819 // ***************************************************************************
820 
users_eme(void)821 void users_eme(void)
822 {
823 }
824 
userdefined_u(void)825 void userdefined_u(void)
826 {
827 }
828 
edit_ugmsg(char * s,double fq)829 void edit_ugmsg(char *s, double fq)
830 {
831 //edit frequency information
832 double t1;
833 int i, j, k, l,m;
834 // We are called with a frequency in Hz and already something written
835 // in the msg string. Find out how many characters we have at our disposal.
836 j=strlen(s);
837 i=MAX_MSGSIZE-j-3;
838 // We will insert separators for each group of 3 digits so we loose i/3
839 // positions.
840 i-=i/3;
841 // Find out the largest fq we can write in Hz.
842 // Write in kHz if fq is above the limit.
843 t1=i;
844 t1=pow(10.0,t1)-1;
845 if(fabs(fq) < t1)
846   {
847   sprintf (&s[j],"%.0f Hz",fq);
848   }
849 else
850   {
851   sprintf(&s[j],"%.0f kHz",fq/1000);
852   }
853 // Locate the blank in front of Hz or kHz.
854 i=strlen(s);
855 k=i;
856 while(s[i] != ' ')i--;
857 // Insert a separator for every 3 digits.
858 i--;
859 j=0;
860 while(s[i-1] != ' ' && s[i-1] != '-')
861   {
862   j++;
863   if(j==3)
864     {
865     k++;
866     m=k;
867     while(m > i)
868       {
869       s[m]=s[m-1];
870       m--;
871       }
872     s[i]=39;
873     j=0;
874     }
875   i--;
876   }
877 // Align frequency information  to the right
878 j=MAX_MSGSIZE-1;
879 i=strlen(s);
880 for (l=i; l<=j;l++) s[l]='\x0';
881 k=j;
882 while(s[k] != 'z')k--;
883 if (k!=j-1){
884 m=j;
885 while(s[m] != '=')m--;
886 j--;
887 for (i=k; i > m; i--) {
888    s[j] = s[i];
889    s[i] = 32;
890    j--;
891    }
892 for (i=j; i > m; i--) {
893    s[i] = 32;
894    j--;
895    }
896  }
897 }
898 
users_close_devices(void)899 void users_close_devices(void)
900 {
901 lir_close_serport();
902 //trace
903 //printf("\n serport closed\n");
904 }
905 
users_open_devices(void)906 void users_open_devices(void)
907 {
908 // open selected serial port with the parameters defined in transceiver list
909 // 1=COM1 or /dev/ttyS0 , 2=COM2..,4=COM4 or /dev/ttyUSB0...
910 // baudrate 110 to 57600
911 // 1=two stopbits, 0=one stopbit
912 serport_open_status=lir_open_serport(serport_number ,
913      list[transceiver_number].serport_baudrate,
914      list[transceiver_number].serport_stopbits,
915      list[transceiver_number].serport_rts_mode);
916 //trace to screen
917 //printf("\n serport open:stat%i,nbr%i,baud%i,stopb%i\n",serport_open_status,serport_number,list
918 //[transceiver_number].serport_baudrate,
919 //     list[transceiver_number].serport_stopbits );
920 }
921 
userdefined_q(void)922 void userdefined_q(void)
923 {
924 // ****************************************************************************
925 // ****************************************************************************
926 // THIS ROUTINE IS CALLED EACH TIME THE 'Q' KEY IS PRESSED
927 // The processing is selected based on the following switch-values:
928 //   if(chnge_serport_switch==1)
929 //       then the new name of the serial port is displayed on the usergraph
930 //       and the port is opened
931 //   if(chnge_calibr_switch==1)
932 //       then a "CALIBRATION REQUEST" is processed
933 //   else a "SET VFO" request is processed
934 // ****************************************************************************
935 // ****************************************************************************
936 double transceiver_freq;
937 double offset_hwfreq;
938 unsigned long freq;
939 double transverter_offset_raw;  //raw offset in Khz (for tranverter)
940 double transverter_offset_fine; //fine offset in Hz (for transverter)
941 extern char serport_name[14];
942 unsigned char a;
943 int n=-1;
944 int i, j;
945 double kxx;
946 char s[80];
947 
948 void analyze_serport_error (void)
949 {
950   ug_msg_color=12;
951   sprintf (ug_msg0,"SERIAL PORT  ERROR :");
952   switch (serport_open_status )
953  {
954   case 1244:
955   sprintf (ug_msg1,"OPEN FAILED (%i)",serport_open_status);
956   break;
957   case 1277:
958   sprintf (ug_msg1,"GET OPTIONS FAILED (%i)",serport_open_status);
959   break;
960   case 1278:
961   sprintf (ug_msg1,"SET OPTIONS FAILED (%i)",serport_open_status);
962   break;
963   case 1279:
964   sprintf (ug_msg1,"ILLEGAL PORT NUMBER (%i)",serport_open_status);
965   break;
966   case 1280:
967   sprintf (ug_msg1,"ILLEGAL BAUDRATE (%i)",serport_open_status);
968   break;
969   default:
970   sprintf (ug_msg1,"UNKNOWN ERR CODE (%i)",serport_open_status);
971   }
972 }
973 
974 if(chnge_serport_switch==1)
975 // ****************************************************************************
976 // ****************************************************************************
977 // ROUTINE FOR THE PROCESSING OF A CHANGE REQUEST FOR THE SERIAL PORT
978 // ****************************************************************************
979 // ****************************************************************************
980 {
981 chnge_serport_switch=0;
982 sprintf(s," SERIAL PORT:%s ",serport_name);
983 lir_pixwrite(ug.xleft+.5*text_width,ug.ytop+1.5*text_height,s);
984 users_close_devices();
985 users_open_devices();
986 //check status serial port
987 if ( serport_open_status!=0)
988  {
989  analyze_serport_error ();
990  }
991 else
992  {
993  ug_msg_color=15;
994  sprintf (ug_msg0,"SERIAL PORT OPEN OK");
995  sprintf (ug_msg1,"PRESS Q-KEY TO SET TRX FREQ.");
996  }
997 goto userdefined_q_exit_1;
998 }
999 
1000 // ****************************************************************************
1001 // ****************************************************************************
1002 // ROUTINES FOR THE PROCESSING OF A "CALIBRATION REQUEST":
1003 //   -validate and initialize
1004 //  - select and execute the transceiver-dependent routine:
1005 //    - create the CAT command message strings for reading the VFO
1006 //    - write/read the message strings to/from serial port
1007 //    - calculate the offset between VFO frequency and Linrad freq
1008 //    - display this offset on the usergraph
1009 // ****************************************************************************
1010 // ****************************************************************************
1011 // generic routines for calibration:
1012 void calculate_offset(void)
1013 {
1014 transceiver_freq=kxx;
1015 offset_hwfreq=transceiver_freq-(hwfreq*1000);
1016 transverter_offset_raw=floor(offset_hwfreq/1000);
1017 transverter_offset_fine=ceil(offset_hwfreq-transverter_offset_raw*1000);
1018 hwaredriver.offs_khz[ug_band_no]=transverter_offset_raw;
1019 hwaredriver.offs_hz[ug_band_no]=transverter_offset_fine;
1020 ug_msg_color=11;
1021 sprintf (ug_msg0,"TRX VFO FREQ:%.0f",kxx);
1022 sprintf (ug_msg1,"NEW OFFSET VALUES LOADED");
1023 sprintf (ug_msg2,"PRESS Q-KEY TO SET TRX FREQ.");
1024 }
1025 
1026 void fail_message_1(void)
1027 {ug_msg_color=12;
1028 sprintf (ug_msg0,"CALIBRATION FAILED:");
1029 sprintf (ug_msg1,"WRITE TO SERIAL PORT FAILED");
1030 sprintf (ug_msg2,"PRESS Q-KEY TO SET TRX FREQ.");
1031 }
1032 
1033 void fail_message_2(void)
1034 {ug_msg_color=12;
1035 sprintf (ug_msg0,"CALIBRATION FAILED:");
1036 sprintf (ug_msg1,"READ FROM SERIAL PORT FAILED");
1037 sprintf (ug_msg2,"PRESS Q-KEY TO SET TRX FREQ.");
1038 }
1039 
1040 void fail_message_3(void)
1041 {ug_msg_color=12;
1042 sprintf (ug_msg0,"CALIBRATION FAILED:");
1043 sprintf (ug_msg1,"TRX VFO FREQ = 0");
1044 sprintf (ug_msg2,"PRESS Q-KEY TO SET TRX FREQ.");
1045 }
1046 
1047 //check the calibration-request switch
1048 if(chnge_calibr_switch==1)
1049   {
1050   chnge_calibr_switch=0;
1051 
1052 //VALIDATE and INITIALIZE:
1053 // exit if no linrad-frequency selected
1054   if(mix1_selfreq[0] < 0)
1055     {
1056     ug_msg_color=12;
1057     sprintf (ug_msg0,"NO FREQ. SELECT. ON W/F GRAPH");
1058     goto userdefined_q_exit_1;
1059     }
1060 // flush buffers
1061    users_close_devices();
1062    users_open_devices();
1063 
1064 // SELECT and execute transceiver-dependent routines for calibration:
1065 
1066 // ************************ CAL FT-817 and FT-897 ***********************************
1067 if (((strcmp(list[transceiver_number].name,"FT-817     ")==0))
1068    |((strcmp(list[transceiver_number].name,"FT-897     ")==0)))
1069 {
1070 // write delay in msec between two bytes
1071 int   write_delay =10;
1072 // CAT command for getting the vfo freq:
1073 unsigned char getfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x00, 0x03};
1074 // WRITE CAT command to the serial port
1075 unsigned char cat_cmnd[5];
1076 int write_cat_cmnd(void)
1077 {
1078 int r;
1079 for (i=0;i<5;i=i+1)
1080  {
1081   r=lir_write_serport((char*)&cat_cmnd[i],1);
1082   if (r<0) return -1;
1083 // printf("\n %#4.2x ",cat_cmnd[i]);  //trace output to screen
1084   lir_sleep(write_delay*1000);
1085  }
1086 return 0;
1087 }
1088 memcpy(cat_cmnd,getfreq_cmnd, 5);
1089 n=write_cat_cmnd();
1090 if (n<0)
1091   {
1092 // write to serial port failed
1093   fail_message_1();
1094   goto userdefined_q_exit_1;
1095   }
1096 // READ the vfo freq
1097 unsigned char ft897_zero[5]= {0x0000000000};
1098 memcpy(s,ft897_zero, 5);
1099 n=lir_read_serport(s,5);
1100 // ANALYSE and process returned values
1101 if (n==5)
1102   {
1103 // s holds now the vfo frequency encoded as
1104 // 0x43 0x97 0x00 0x00 0xNN for a frequency of 439.700.000,00 MHz
1105 // last byte, xNN, is the mode (usb,lsb,..) and will be  discarded
1106 // convert now  pos 0 to 3 in s, from packed bcd to double kxx
1107   kxx=0;
1108   j=10;
1109   for (i=3; i >-1; i--)
1110     {
1111     a=(s[i]%16 & 0x0f);
1112     kxx= kxx+a*j;
1113     j=j*10;
1114     a= ((s[i]>>4)%16) & 0x0f;
1115     kxx= kxx+a*j;
1116     j=j*10;
1117     }
1118   if (kxx==0)
1119    {
1120 // failure: trx vfo freq = 0
1121    fail_message_3();
1122    goto userdefined_q_exit_1;
1123    }
1124   else
1125    {
1126 // success
1127    calculate_offset();
1128    goto userdefined_q_exit_1;
1129    }
1130   }
1131 else
1132   {
1133 // failure: read from serial port failed
1134   fail_message_2();
1135   goto userdefined_q_exit_1;
1136   }
1137 }
1138 // ************************CAL FT-920 ****************************************
1139 if ((strcmp(list[transceiver_number].name,"FT-920     ")==0))
1140 {
1141 // CAT command definition for getting the frequency of VFO A & B
1142 // (it returns 2 x 16 bytes):
1143 unsigned char getfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x03, 0x10};
1144 // WRITE CAT_cmnd to the serial port
1145 for (i=0;i<5;i=i+1)
1146  {
1147   n=lir_write_serport((char*)&getfreq_cmnd[i],1);
1148   if (n<0)
1149     {
1150 // write to serial port failed
1151     fail_message_1();
1152     goto userdefined_q_exit_1;
1153     }
1154 // wait 5msec between each write
1155   lir_sleep(5000);
1156  }
1157 // READ the vfo freq
1158 // wait 60msec to allow the CAT system to settle
1159 lir_sleep(60000);
1160 unsigned char ft920_zero[14]= {0x0000000000000000000000000000};
1161 memcpy(s,ft920_zero, 14);
1162 n=lir_read_serport(s,28);
1163 // ANALYSE and process returned values
1164 if (n==28)
1165   {
1166 // s holds now the vfo frequencies of VFO A & B in 28 bytes
1167 // VFO A is in bytes 1-4 (1 MSB -> 4 LSB) in hex format
1168 // convert pos 1 to 4 from the ascii string s, to the double kxx
1169   kxx=0;
1170   j=1;
1171   for (i=4; i >0; i--)
1172     {
1173     a=(s[i]%16 & 0x0f);
1174     kxx= kxx+a*j;
1175     j=j*16;
1176     a= ((s[i]>>4)%16) & 0x0f;
1177     kxx= kxx+a*j;
1178     j=j*16;
1179     }
1180   if (kxx==0)
1181     {
1182 // failure: trx vfo freq = 0
1183     fail_message_3();
1184     goto userdefined_q_exit_1;
1185     }
1186   else
1187     {
1188 // success
1189     calculate_offset();
1190     goto userdefined_q_exit_1;
1191     }
1192   }
1193 else
1194   {
1195 // failure: read from serial port failed
1196   fail_message_2();
1197   goto userdefined_q_exit_1;
1198   }
1199 }
1200 // ************************CAL FT-1000 ****************************************
1201 if ((strcmp(list[transceiver_number].name,"FT-1000    ")==0))
1202 {
1203 // write delay in msec between two bytes
1204 int   write_delay = 5;
1205 // CAT command definition for getting the frequency of VFO A & B
1206 // (it returns 2 x 16 bytes):
1207 unsigned char getfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x03, 0x10};
1208 // WRITE CAT_cmnd to the serial port
1209 for (i=0;i<5;i=i+1)
1210  {
1211   n=lir_write_serport((char*)&getfreq_cmnd[i],1);
1212   if (n<0)
1213     {
1214 // write to serial port failed
1215     fail_message_1();
1216     goto userdefined_q_exit_1;
1217     }
1218   lir_sleep(write_delay*1000);
1219  }
1220 // READ the vfo freq
1221 // wait 60msec to allow the CAT system to settle
1222 lir_sleep(60000);
1223 unsigned char ft1000_zero[16]= {0x00000000000000000000000000000000};
1224 memcpy(s,ft1000_zero, 16);
1225 n=lir_read_serport(s,32);
1226 // ANALYSE and process returned values
1227 if (n==32)
1228   {
1229 // s holds now the vfo frequencies of VFO A & B in 32 bytes:
1230 // convert pos 8 to 15 from the ascii string s, to the double kxx
1231   kxx=0;
1232   j=1;
1233   for (i=15; i > 7 ; i--) {
1234     kxx=kxx+(s[i] & 0x0f)*j;
1235     j=j*10;
1236     }
1237   if (kxx==0)
1238     {
1239 // failure: trx vfo freq = 0
1240     fail_message_3();
1241     goto userdefined_q_exit_1;
1242     }
1243   else
1244     {
1245 // success
1246     calculate_offset();
1247     goto userdefined_q_exit_1;
1248     }
1249   }
1250 else
1251   {
1252 // failure: read from serial port failed
1253   fail_message_2();
1254   goto userdefined_q_exit_1;
1255   }
1256 }
1257 
1258 // *********************** CAL TS-850/TS-2000/K3 *********************************
1259 if (((strcmp(list[transceiver_number].name,"K3         ")==0))
1260    |((strcmp(list[transceiver_number].name,"TS-850     ")==0))
1261    |((strcmp(list[transceiver_number].name,"TS-2000    ")==0)))
1262 {
1263 // CAT command definition for getting the vfo freq:
1264 sprintf (s,"FA;");
1265 // WRITE CAT command to serial port
1266 n=lir_write_serport(s,3);
1267 if (n<0)
1268   {
1269 // write to serial port failed
1270   fail_message_1();
1271   goto userdefined_q_exit_1;
1272   }
1273 // READ the vfo freq
1274 sprintf (s,"0000000000000;");
1275 n=lir_read_serport(s,14);
1276 // ANALYSE and process returned values
1277 if (n==14)
1278   {
1279 // s holds now the vfo frequency encoded p.e. as
1280 // FA00014250000; for the frequency 14.250.000 Hz:
1281 // convert pos 2 to 12 of s to the double kxx
1282   kxx=0;
1283   for (i=2; i<=12;i++)
1284     {
1285     j=s[i]-'0';
1286     kxx=kxx*10+j;
1287     }
1288   if (kxx==0)
1289     {
1290 // failure: trx vfo freq = 0
1291     fail_message_3();
1292     goto userdefined_q_exit_1;
1293     }
1294   else
1295     {
1296 // success
1297     calculate_offset();
1298     goto userdefined_q_exit_1;
1299     }
1300   }
1301 else
1302   {
1303 // failure: read from serial port failed
1304   fail_message_2();
1305   goto userdefined_q_exit_1;
1306   }
1307 }
1308 
1309 // *******************CAL FT-450 and FT-950 and FT-2000********************************
1310 if   (((strcmp(list[transceiver_number].name,"FT-450     ")==0))
1311      |((strcmp(list[transceiver_number].name,"FT-950     ")==0))
1312      |((strcmp(list[transceiver_number].name,"FT-2000    ")==0)))
1313 {
1314 // CAT command to request the vfo freq:
1315 sprintf (s,"FA;");
1316 // WRITE to serial port
1317 n=lir_write_serport(s,3);
1318 //traces
1319 //printf("\n %s",s); //trace output to screen
1320 //printf("\n");      //'next line' to display last trace entry
1321 if (n<0)
1322   {
1323 // write to serial port failed
1324   fail_message_1();
1325   goto userdefined_q_exit_1;
1326   }
1327 // READ requested vfo freq
1328 sprintf (s,"0000000000;");
1329 n=lir_read_serport(s,11);
1330 //printf("\n s=%s n=%i",s,n); //trace output to screen
1331 //printf("\n");      //'next line' to display last trace entry
1332 if (n==11)
1333   {
1334 // s holds the vfo frequency encoded as FA14250000; for the frequency
1335 // 14.250.000 Hz
1336 // convert position 2 to 9 of s to double kxx
1337   kxx=0;
1338   for (i=2; i<=9;i++)
1339     {
1340     j=s[i]-'0';
1341     kxx=kxx*10+j;
1342     }
1343   if (kxx==0)
1344     {
1345 //failure: trx vfo freq = 0
1346     fail_message_3();
1347     goto userdefined_q_exit_1;
1348     }
1349   else
1350     {
1351 //success
1352     calculate_offset();
1353     goto userdefined_q_exit_1;
1354     }
1355   }
1356 else
1357   {
1358 //failure: read from serial port failed
1359   fail_message_2();
1360   goto userdefined_q_exit_1;
1361   }
1362 }
1363 
1364 // ***************************** CAL CATCH ALL *******************************
1365 
1366 else{
1367     ug_msg_color=12;
1368     sprintf (ug_msg0,"NO CALIBRATION AVAILABLE");
1369     sprintf (ug_msg1,"FOR THIS TRX");
1370     sprintf (ug_msg2,"PRESS Q-KEY TO SET TRX FREQ.");
1371     }
1372 goto userdefined_q_exit_1;
1373 }
1374 // ***************************************************************************
1375 // ***************************************************************************
1376 // ROUTINES FOR THE PROCESSING OF A "SET VFO " REQUEST
1377 //  - do some validations and initialize usergraph
1378 //  - select and execute the transceiver-dependent routines for setting the
1379 //    VFO frequency
1380 //      input:  desired frequency stored in the variables freq (unsigned long)
1381 //              or transceiver_freq (double)
1382 //      proces: create the transceiver-dependent CAT commands for setting the
1383 //              VFO frequency
1384 //              write/read the message strings to/from the serial port
1385 //      output: updated  messages in the usergraph
1386 // ***************************************************************************
1387 // ***************************************************************************
1388 // VALIDATE and INITIALIZE:
1389 // check status of serial port
1390 if ( serport_open_status!=0)
1391   {
1392   analyze_serport_error ();
1393   goto userdefined_q_exit_1;
1394   }
1395 // check if linrad frequency is selected
1396 if(mix1_selfreq[0] < 0)
1397   {
1398   ug_msg_color=12;
1399   sprintf (ug_msg0,"NO FREQ. SELECT. ON W/F GRAPH");
1400   goto userdefined_q_exit_1;
1401   }
1402 // check whether the desired frequency is within the valid range for the
1403 // selected transceiver
1404 //raw offset in Khz for transverter :
1405 transverter_offset_raw=hwaredriver.offs_khz[ug_band_no];
1406 //fine offset in Hz for transverter :
1407 transverter_offset_fine=hwaredriver.offs_hz[ug_band_no];
1408 //Freq in KHz :
1409 offset_hwfreq= transverter_offset_raw +(transverter_offset_fine*.001) ;
1410 //Freq in Hz
1411 transceiver_freq= (hwfreq+offset_hwfreq)*1000;
1412 transceiver_freq=floor(transceiver_freq);
1413 freq= transceiver_freq;
1414 if ((transceiver_freq < list[transceiver_number].min_transceiver_freq )
1415      ||(transceiver_freq > list[transceiver_number].max_transceiver_freq))
1416   {
1417   ug_msg_color=12;
1418   sprintf (ug_msg0,"INVALID FREQ.FOR %s",list[transceiver_number].name);
1419   goto userdefined_q_exit_2;
1420   }
1421 // initialize message-area in usergraph:
1422 ug_msg_color=12;
1423 strcpy(ug_msg0,"FREQUENCY SETTING IN PROGRESS");
1424 ug_msg1[0]=0;
1425 ug_msg2[0]=0;
1426 show_user_parms();
1427 
1428 // SELECT and execute transceiver dependent routines for setting the VFO
1429 // frequency:
1430 
1431 // *********************** SET VFO IC-275 and IC-706 *****************************
1432 if  (((strcmp(list[transceiver_number].name,"IC-275     ")==0))
1433     |((strcmp(list[transceiver_number].name,"ICOM-all   ")==0))
1434     |((strcmp(list[transceiver_number].name,"IC-706     ")==0))
1435     |((strcmp(list[transceiver_number].name,"IC-706MKII ")==0))
1436     |((strcmp(list[transceiver_number].name,"IC-706MKIIG")==0)))
1437 {
1438 // CAT command definition.
1439 // 'Set Frequency command' for IC-275/IC-706:
1440 struct {
1441    char prefix[2];
1442    char radio_addr;
1443    char computer_addr;
1444    char cmd_nr;
1445    unsigned char freq[5];
1446    char suffix;
1447    } msg0 = {{0xFE, 0xFE},               // preamble code x 2
1448              0x10,                       // receive address for IC-275
1449              0xE0,                       // transmit address of controller
1450              0x05,                       // 'set freq' cmnd code
1451              {0x00,0x00,0x00,0x00,0x00}, // freq
1452              // 145.678.900 Hz  is encoded as x00 x89 x67 x45 x01
1453              0xFD};                    // end of message code
1454 
1455 if  ((strcmp(list[transceiver_number].name,"ICOM-all   ")==0))
1456    msg0.radio_addr='\x00';   // receive address for any icom-radio broadcasting
1457 if  ((strcmp(list[transceiver_number].name,"IC-706     ")==0))
1458    msg0.radio_addr='\x48';   // receive address for IC-706
1459 if  ((strcmp(list[transceiver_number].name,"IC-706MKII ")==0))
1460    msg0.radio_addr='\x4e';   // receive address for IC-706MKII
1461 if  ((strcmp(list[transceiver_number].name,"IC-706MKIIG")==0))
1462    msg0.radio_addr='\x58';   // receive address for IC-706MKIIG
1463 // CONVERT freq to the CAT command format;
1464 //   convert 10 digits of freq to packed bcd and store in msg0.freq,
1465 //   put first digit-pair in FIRST output byte
1466 for (i=0; i < 5; i++) {
1467    a = freq%10;
1468    freq /= 10;
1469    a |= (freq%10)<<4;
1470    freq /= 10;
1471    msg0.freq[i]= a;
1472 //printf("\n %#4.2x ",msg0.freq[i]); //trace output to screen
1473    }
1474 //printf("\n");      //'next line' to display last trace entry
1475 // WRITE CAT command to serial port
1476 n=lir_write_serport((char *) &msg0, sizeof(msg0));
1477 goto display_messages_in_usersgraph;
1478 }
1479 
1480 // ******************* SET VFO TS-850, TS-2000 and K3 *********************
1481 if (((strcmp(list[transceiver_number].name,"K3         ")==0))
1482    |((strcmp(list[transceiver_number].name,"TS-850     ")==0))
1483    |((strcmp(list[transceiver_number].name,"TS-2000    ")==0)))
1484 {
1485 // CAT command definition for setting the VFO freq:
1486 //   FA is the "set VFO-A frequency" command code
1487 //   Freq in Hz; 11 digits, leading zeros, no decimal point, trailing semicolon.
1488 // CONVERT transceiver_freq to the CAT command format
1489 sprintf (s,"FA%011.0f;",transceiver_freq);
1490 // WRITE CAT command to serial port
1491 n=lir_write_serport(s,14);
1492 //printf("\n %s",s);    //trace output to screen
1493 //printf("\n");         //add 'next line' to trace output
1494 goto display_messages_in_usersgraph;
1495 }
1496 
1497 // ************************ SET VFO FT-736 ************************************
1498 
1499 if ((strcmp(list[transceiver_number].name,"FT-736     ")==0))
1500 {
1501 // write delay in msec between two bytes
1502 int   write_delay =50;
1503 // CAT command definitions for setting the VFO freq:
1504 //   Setting the VFO frequency to 145.678.900 HZ is encoded as
1505 //   0x14 0x56 0x78 0x90 0x01
1506 //   the last byte 0x01 is the "set freq" command code
1507 unsigned char setfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x00, 0x01};
1508 unsigned char open_cmnd[5] =  { 0x00, 0x00, 0x00, 0x00, 0x00};
1509 unsigned char close_cmnd[5] = { 0x80, 0x80, 0x80, 0x80, 0x80};
1510 // WRITE CAT commands to serial port
1511 unsigned char cat_cmnd[5];
1512 int write_cat_cmnd(void)
1513 {
1514 int r=0;
1515 for (i=0;i<5;i=i+1)
1516  {
1517   r=lir_write_serport((char*)&cat_cmnd[i],1);
1518   if (r<0) return -1;
1519 // printf("\n %#4.2x ",cat_cmnd[i]);  //trace output to screen
1520   lir_sleep(write_delay*1000);
1521  }
1522 return 0;
1523 }
1524 // 1. open CAT system
1525 memcpy(cat_cmnd,open_cmnd, 5);
1526 n=write_cat_cmnd();
1527 if (n<0) goto ft736_exit;
1528 // 2. CONVERT the content of "freq" variable to the setfreq_cmd format:
1529 //   discard least significant digit of freq
1530 //   convert next 8 digits of freq to packed bcd and store in setfreq_cmd
1531 //   put first digit-pair in LAST  output byte
1532 freq /= 10;
1533 for (i=0; i < 4; i++) {
1534    a = freq%10;
1535    freq /= 10;
1536    a |= (freq%10)<<4;
1537    freq /= 10;
1538    setfreq_cmnd[3-i]= a;
1539    }
1540 // 3. write setfreq_cmd to the serial port
1541 memcpy(cat_cmnd,setfreq_cmnd, 5);
1542 n=write_cat_cmnd();
1543 if (n<0) goto ft736_exit;
1544 // 4. close CAT system
1545 memcpy(cat_cmnd,close_cmnd, 5);
1546 n=write_cat_cmnd();
1547 ft736_exit:;
1548 //printf("\n");  //'next line' to display last trace entry
1549 goto display_messages_in_usersgraph;
1550 }
1551 // ************* SET VFO FT-1000 and FT-920  ********************************
1552 if (((strcmp(list[transceiver_number].name,"FT-1000    ")==0))
1553    |((strcmp(list[transceiver_number].name,"FT-920     ")==0)))
1554 {
1555 // write delay in msec between two bytes
1556 int   write_delay =5;
1557 // CAT command definition for setting the VFO freq:
1558 //  the command to set the VFO to p.e. 014.250.000 Hz is encoded as
1559 //  0x00 0x50 0x42 0x01 0x0a
1560 //  the last byte 0x0a is the "set freq" command code
1561 unsigned char setfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x00, 0x0a};
1562 // CONVERT the content of "freq" variable to the CAT command format:
1563 //  discard the least significant digit of "freq"
1564 //  convert the next 8 digits of "freq" to packed bcd and store them in
1565 //  setfreq_cmd,
1566 //  put the first digit-pair in first output byte
1567 freq /= 10;
1568 for (i=0; i < 4; i++) {
1569    a = freq%10;
1570    freq /= 10;
1571    a |= (freq%10)<<4;
1572    freq /= 10;
1573    setfreq_cmnd[i]= a;
1574    }
1575 // WRITE CAT command to the serial port
1576 for (i=0;i<5;i=i+1)
1577  {
1578   n=lir_write_serport((char*)&setfreq_cmnd[i],1);
1579   if (n<0)  goto ft1000_exit;             //an error occured
1580 // printf("\n %#4.2x ",setfreq_cmnd[i]);  //trace each character to screen
1581   lir_sleep(write_delay*1000);
1582  }
1583 ft1000_exit:;
1584 //printf("\n");                          //trace last character
1585 goto display_messages_in_usersgraph;
1586 }
1587 
1588 // ********************* SET VFO FT-450 and FT-950 and FT-2000 *************************
1589 if   (((strcmp(list[transceiver_number].name,"FT-450     ")==0))
1590      |((strcmp(list[transceiver_number].name,"FT-950     ")==0))
1591      |((strcmp(list[transceiver_number].name,"FT-2000    ")==0)))
1592 {
1593 // CAT command definition for setting the VFO freq:
1594 //   To set the VFO frequency to 14.250.000 Hz the command is encoded as
1595 //   FA14250000; (ASCII values)
1596 //   "FA" is the "SET VFO A "command code
1597 //   freq in Hz; 8 digits, leading zeros, no decimal point,
1598 //   ";" is a delimiter
1599 // CONVERT the content of "transceiver_freq" variable to the CAT command format:
1600 sprintf (s,"FA%08.0f;",transceiver_freq);
1601 // WRITE the CAT command to the serial port
1602 n=lir_write_serport(s,11);
1603 //printf("\n %s",s); //trace output to screen
1604 //printf("\n");      //'next line' to display last trace entry
1605 goto display_messages_in_usersgraph;
1606 }
1607 
1608 // *************************** SET VFO FT-817 and FT-897 *********************************
1609 if (((strcmp(list[transceiver_number].name,"FT-817     ")==0))
1610    |((strcmp(list[transceiver_number].name,"FT-897     ")==0)))
1611 
1612 {
1613 // write delay in msec between two bytes
1614 int   write_delay = 10;
1615 // CAT command definition:
1616 //  setting the  VFO frequency to 439.70 MHz is encoded as
1617 //  0x43 0x97 0x00 0x00 0x01 (hex values)
1618 //  last byte 0x01 is the "SET FREQUENCY" command code.
1619 unsigned char setfreq_cmnd[5]= { 0x00, 0x00, 0x00, 0x00, 0x01};
1620 // CONVERT the content of "freq" variable to the setfreq_cmd format:
1621 //  discard least significant digit of freq
1622 //  convert next 8 digits of freq to packed bcd and store in setfreq_cmd
1623 //  put first digit-pair in last output byte
1624 freq /= 10;
1625 for (i=0; i < 4; i++) {
1626    a = freq%10;
1627    freq /= 10;
1628    a |= (freq%10)<<4;
1629    freq /= 10;
1630    setfreq_cmnd[3-i]= a;
1631    }
1632 // WRITE setfreq_cmd to the serial port
1633 unsigned char cat_cmnd[5];
1634 int write_cat_cmnd(void)
1635 {
1636   int r;
1637   for (i=0;i<5;i=i+1)
1638    {
1639     r=lir_write_serport((char*)&cat_cmnd[i],1);
1640     if (r<0) return -1;
1641 // printf("\n %#4.2x ",cat_cmnd[i]);  //trace output to screen
1642     lir_sleep(write_delay*1000);
1643    }
1644   return 0;
1645 }
1646 memcpy(cat_cmnd,setfreq_cmnd, 5);
1647 n=write_cat_cmnd();
1648 //printf("\n");  //add 'next line' to display last trace entry
1649 goto display_messages_in_usersgraph;
1650 }
1651 
1652 // ************************ SET VFO CATCH_ALL**********************************
1653 ug_msg_color=12;
1654 sprintf (ug_msg0,"INTERNAL ERROR ");
1655 goto userdefined_q_exit_1;
1656 
1657 // ***********************END 'SET VFO' ROUTINES ******************************
1658 
1659 // display messages in usergraph
1660 display_messages_in_usersgraph:;
1661 if (n<0)
1662   {
1663   ug_msg_color=12;
1664   sprintf (ug_msg0,"WRITE TO %s FAILED",serport_name);
1665   goto userdefined_q_exit_1;
1666   }
1667 ug_msg_color=14;
1668 sprintf (ug_msg0,"LINRAD FREQ = ");
1669 edit_ugmsg(ug_msg0,floor(hwfreq*1000));
1670 userdefined_q_exit_2:;
1671 sprintf (ug_msg1,"TOTAL OFFSET= ");
1672 edit_ugmsg(ug_msg1,offset_hwfreq*1000);
1673 sprintf (ug_msg2,"TRX FREQ= ");
1674 edit_ugmsg(ug_msg2, transceiver_freq);
1675 //main  exit for userdefined_q
1676 userdefined_q_exit_1:;
1677 show_user_parms();
1678 // ****************************************************************************
1679 // END void userdefined_q(void) routine
1680 // ****************************************************************************
1681 }
1682 
update_users_rx_frequency(void)1683 void update_users_rx_frequency(void)
1684 {
1685 // This routine is called from the screen thread.
1686 if(fabs(hwfreq-old_hwfreq) > 0.001)
1687   {
1688   ug_msg_color=10;
1689   sprintf (ug_msg0,"LINRAD FREQ= ");
1690   edit_ugmsg(ug_msg0,floor(hwfreq*1000));
1691   hide_mouse(ug.xleft, ug.xright,ug.ytop,ug.ybottom);
1692   sprintf (ug_msg1,"PRESS Q-KEY TO SET TRX FREQ");
1693   sprintf (ug_msg2," ");
1694   show_user_parms();
1695   settextcolor(7);
1696   }
1697 }
1698 // ****************************************************************************
1699 // WSE Rx and Tx and SDR-14/SDR-IQ Rx routines
1700 // ****************************************************************************
1701 #if (RX_HARDWARE == 0)
1702 #include "wse_sdrxx.c"
1703 #endif
1704 // ****************************************************************************
1705 // Dummy routines to support converters and other hardwares
1706 // ****************************************************************************
1707 #if (RX_HARDWARE == 1)
control_hware(void)1708 void control_hware(void){};
set_hardware_tx_frequency(void)1709 void set_hardware_tx_frequency(void){};
1710 
set_hardware_rx_frequency(void)1711 void set_hardware_rx_frequency(void)
1712 {
1713 fg.passband_increment=0.01;
1714 fg.passband_direction = 1;
1715 fft1_direction = fg.passband_direction;
1716 }
1717 
set_hardware_rx_gain(void)1718 void set_hardware_rx_gain(void){};
hware_interface_test(void)1719 void hware_interface_test(void){};
hware_set_rxtx(int state)1720 void hware_set_rxtx(int state)
1721   {
1722   int i;
1723   i=state;
1724   };
hware_hand_key(void)1725 void hware_hand_key(void){};
clear_hware_data(void)1726 void clear_hware_data(void){};
1727 #endif
1728 
1729 
1730