📄 tsip_utl.c
字号:
/*
* *************************************************************************
*
* Trimble Navigation, Ltd.
* OEM Products Development Group
* P.O. Box 3642
* 645 North Mary Avenue
* Sunnyvale, California 94088-3642
*
* Corporate Headquarter:
* Telephone: (408) 481-8000
* Fax: (408) 481-6005
*
* Technical Support Center:
* Telephone: (800) 767-4822 (U.S. and Canada)
* (408) 481-6940 (outside U.S. and Canada)
* Fax: (408) 481-6020
* BBS: (408) 481-7800
* e-mail: trimble_support@trimble.com
*
* *************************************************************************
*
* Vers Date Changes Author
* ---- --------- ---------------------------------------- ----------
* 1.1 16 Jun 93 Initial version pvwl
* 1.12 14 Feb 94 Revisions pvwl
* 1.12a 31 Mar 94 Added cts display window pvwl
* 1.20 5 Jun 95 Revisions: timezone ahl
* 26 Jul 95 Communications above 9600 bps
* 28 Aug 95 Revision: ask_byte() for maxage
*
* *************************************************************************
*
* TSIP_UTL.C contains five types of functions:
*
* 1) Borland-compatible window control functions: The Borland version of
* TSIPCHAT supports two windows: a command and report window and an auto
* window. The command and report window displays the command list, command
* entries and parameters, and display of requested packets. The auto window
* scrolls through unrequested reports, which are generated according to the
* I/O options specified.
*
* The following are Borland C++ functions used to create text windows. If
* suitable functions can be found in the Microsoft Visual C++ Compiler, the
* windowing feaures may be recreated. (Creating TSIPCHAT without BORLAND
* defined results in all commands, both auto and requested, scrolling up the
* screen.)
*
* ;; create a window
* void window (short left, short top, short right, short bottom)
*
* ;; set backgrounf and foreground colors
* void textattr (char attr)
*
* ;; go to row x, colw y w.r.t window origin
* void gotoxy (short x, short y)
*
* ;; report row relative to window origin
* short wherex (void)
*
* ;; report column relative to window origin
* short wherey (void)
*
* ;; clear window to the end of the line
* void clrscr (void), clreol (void)
*
* ;; get text attributes
* void gettextinfo (struct *textinfo)
*
* 2) User interface functions: Specifically, these are functions that query
* integer, double, or YES/NO inputs. There is also a function for toggling
* file storage on and off.
*
* 3) Storage file functions: These functions open and close binary
* storage files.
*
* 4) DOS-specific time functions: These functions synchronize the receiver
* and PC clocks.
*
* 5) Serial port functions: These functions send, receive, and set
* parameters. They are DOS-specific.
*
* *************************************************************************
*
*/
#define END_STRING '\0'
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <time.h>
#include "tsip_ifc.h"
#include "tsipincl.h"
const short days_in_year[32] =
{
361, 365, 365, 365, 366, 365, 365, 365, /* 1980-1987 */
366, 365, 365, 365, 366, 365, 365, 365, /* 1988-1995 */
366, 365, 365, 365, 366, 365, 365, 365, /* 1996-2003 */
366, 365, 365, 365, 366, 365, 365, 365 /* 2004-2011 */
};
/*
Note: 1980 is short because GPS time starts midnight 1/6/1980.
2000 IS a leap year.
*/
const unsigned char leap_year[32] =
{
1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0
};
const char days_in_month[2][12] =
{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
/**/
/* ******************* 1. CONSOLE WINDOW CONTROL ****************** */
/*
* The following routines set up two windows: one which prints only
* commands and requested reports, the other only unrequested reports.
* The routines are set up for Borland compilers. Similar functions can
* be found with Microsoft compilers. Generic versions are included
* for non-Borland compilers.
*/
/* backspace, enter, printable characters except control characters */
#include <conio.h>
#define MENUWIN 2
/* text attributes for different screen functions */
static short
auto_y,
text_color[3];
static struct text_info
t_info,
w_info[2];
/* current window = command or requested reply, or auto report */
/* TRUE if current window is command window */
static short
curr_win = AUTOWIN;
void show_crlf (void)
{
clreol ();
xprintf ("\r\n");
clreol ();
}
short which_window (void)
{
return (curr_win);
}
void switch_window (short new_win)
{
struct text_info *old_info, *new_info;
old_info = &w_info[curr_win];
gettextinfo (old_info);
if (new_win == curr_win) {
return;
}
curr_win = new_win;
new_info = &w_info[curr_win];
switch (new_win) {
case AUTOWIN:
/* auto window is the bottom of the screen; unrequested reports */
/* are printed here in scrolled mode */
window (1, old_info->cury + 1, 80, 24);
textattr (text_color[new_win]);
/* start at bottom of auto window and scroll */
gotoxy (80, auto_y - (old_info->cury + 1));
break;
case CMDWIN:
/* cmd window is the top of the screen; commands and requested */
/* reports are printed in scrolled mode in blue or reverse text */
/* autowin absolute line coordinate */
auto_y = old_info->cury + old_info->wintop;
window (1, 1, 80, 24);
textattr (text_color[new_win]);
gotoxy (new_info->curx, new_info->cury);
clreol ();
break;
}
}
void new_cmd_window (void)
{
/* blank out old command window */
if (curr_win == AUTOWIN) {
gettextinfo (&w_info[curr_win]);
auto_y = w_info[curr_win].cury + w_info[curr_win].wintop;
}
textattr (text_color[AUTOWIN]);
if (w_info[CMDWIN].cury > 1) {
window (1, 2, 80, w_info[CMDWIN].cury);
clrscr ();
}
w_info[CMDWIN].cury = 1;
w_info[CMDWIN].curx = 1;
/* perch in the auto window at the last location */
curr_win = AUTOWIN;
window (1, 2, 80, 24);
gotoxy (80, auto_y - 2);
switch_window (CMDWIN);
clreol ();
highvideo ();
textbackground (BANNER_BACKGROUND);
textcolor (BANNER_TEXT);
xprintf (
" TSIPCHAT %s(%s) Use <Esc> to Exit; Use '?' for Help Screen",
TSIPCHAT_VERNUM, TSIP_VERNUM);
clreol ();
normvideo ();
textcolor (LIGHTGRAY);
textbackground (BLUE);
gotoxy (1, 1);
}
void clr_cmd_window (short mode)
{
short
i;
static short
endline;
switch_window (CMDWIN);
if (mode) {
for (i = w_info[CMDWIN].cury + 1; i <= endline; i++) {
gotoxy (1, i);
clreol ();
}
} else {
endline = w_info[CMDWIN].cury;
for (i = 1; i <= endline; i++) {
gotoxy (1,i);
clreol ();
}
gotoxy (1, 1);
highvideo ();
textbackground (BANNER_BACKGROUND);
textcolor (BANNER_TEXT);
xprintf (
" TSIPCHAT %s:%s Use <CR> to Return to Normal Mode",
TSIPCHAT_VERNUM, TSIP_VERNUM);
clreol (); show_crlf ();
normvideo ();
textcolor (LIGHTGRAY);
textbackground (BLUE);
}
switch_window (AUTOWIN);
}
void start_menu_window (void)
{
textattr (text_color[MENUWIN]);
}
void end_menu_window (void)
{
textattr (text_color[CMDWIN]);
}
void initialize_screen (void)
{
/* get initial text attributes and save for restore before exit. */
gettextinfo (&t_info);
clrscr();
text_color[AUTOWIN] = LIGHTGRAY + (BLACK << 4);
text_color[CMDWIN] = LIGHTGRAY + (BLUE << 4);
text_color[MENUWIN] = LIGHTGRAY + (BLUE << 4);
w_info[CMDWIN].cury = 1;
w_info[CMDWIN].curx = 1;
/* start in auto window */
textattr (text_color[AUTOWIN]);
clrscr ();
gotoxy (1, 25);
}
void reset_screen (void)
{
window (1,1,80,25);
/* return text to original */
textattr (t_info.normattr);
gotoxy (80, 25);
show_crlf ();
clrscr();
}
/**/
/* ****************** 2. USER INPUT PROMPTS ********************* */
/*
* Prompt functions: allows user to supply a character string in response
* to a prompt.
*/
/* These routines are to set cmdesc (TRUE = abort command).
* Used in TSIP_CMD.C.
*/
static short cmd_abort = FALSE;
short cmd_esc (void)
{
return cmd_abort;
}
void set_cmd_esc (short x)
{
cmd_abort = x;
}
/* Common prompt escape sequence. */
static short esc_out (char c) {
short cmdesc;
/* backspace, <CR>, printable characters except control characters */
cmdesc = (c != 0x08) && (c != 0x0D) && (!isprint (c) || iscntrl (c));
set_cmd_esc (cmdesc);
return cmdesc;
}
static short get_prompt_string (char kbbuf[], short maxi)
{
char kbch;
short i;
i = 0;
for (i = 0; i < maxi; ) {
kbch = read_rpts_wait_for_kbhit ();
if (kbch == 0x08) { /* backspace */
xprintf ("%c", kbch);
if (i) i--;
} else if (kbch == 0x0D) { /* <CR> */
break;
} else if (esc_out(kbch)) {
i = 0;
break;
} else {
xprintf ("%c", kbch);
kbbuf[i] = kbch;
i++;
}
}
/* terminate string */
kbbuf[i] = END_STRING;
show_crlf();
set_cmd_esc (!i);
return i;
}
/* prompt for an integer from user */
short ask_byte (char *prompt)
{
short n;
char kbbuf[30];
n = 0;
clreol ();
xprintf (prompt);
if (get_prompt_string (kbbuf, 30)) {
set_cmd_esc (sscanf (kbbuf, "%d", &n) < 1);
}
return n;
}
/* prompt for a choice from among nine or fewer */
short pick_one (char *prompt, char *code_txt[], short nopts)
{
short i, j, kbch;
set_cmd_esc (FALSE);
/* cycle through a series of choices & allow user to choose one. */
/* Routine returns numerical value corresponding to choice. */
xprintf ("%s(<Space> cycle, <CR> select, ^Z abort)", prompt);
kbch = read_rpts_wait_for_kbhit ();
clreol ();
if (esc_out(kbch)) {
return 0;
}
/* direct choice by digit (0..9) */
j = (kbch - '0');
i = 0;
if ((j < nopts) && (j >= 0)) {
if (code_txt[j][0] != END_STRING) {
i = j;
}
}
xprintf ("\r%s ", prompt);
for ( ; ; i++) {
xprintf ("\r%s", prompt);
if (i >= nopts) i -= nopts;
/* skip choices with null character string */
if (code_txt[i][0] == END_STRING) continue;
highvideo ();
xprintf ("%s (%d)", code_txt[i], i);
lowvideo ();
clreol ();
for ( ; ; ) { /* wait for <CR> or <space> or digit selection */
kbch = read_rpts_wait_for_kbhit ();
if (kbch == 0x0D) { /* <CR>: choice is made */
show_crlf ();
return i;
} else if (kbch == 0x20) { /* <Space>: drops out to new choice */
break;
} else if (esc_out(kbch)) {
show_crlf();
return 0;
} else {
j = (kbch - '0');
if ((j < nopts) && (j >= 0)) {
if (code_txt[j][0] != END_STRING) {
/* direct choice by digit (0..9); offset at top of loop */
i = j - 1;
break;
}
}
}
}
}
}
/* prompt user to enter an double */
double ask_dbl (char *prompt)
{
double d = 0.0;
char kbbuf[30];
clreol ();
xprintf (prompt);
if (get_prompt_string (kbbuf, 30)) {
set_cmd_esc (sscanf (kbbuf, "%lf", &d) < 1);
}
return d;
}
/* ask user for up to 4 hex codes */
unsigned char ask_hex_string (char *prompt, unsigned char *h)
{
char kbbuf [30];
clreol ();
xprintf (prompt);
if (get_prompt_string (kbbuf, 30)) {
if (6==sscanf(kbbuf,"%2x %2x %2x %2x %2x %2x",
&h[0],&h[1],&h[2],&h[3],&h[4],&h[5])) return 6;
if (5==sscanf(kbbuf,"%2x %2x %2x %2x %2x",
&h[0],&h[1],&h[2],&h[3],&h[4])) return 5;
if (4==sscanf(kbbuf,"%2x %2x %2x %2x",
&h[0],&h[1],&h[2],&h[3])) return 4;
if (3==sscanf(kbbuf,"%2x %2x %2x",
&h[0],&h[1],&h[2])) return 3;
if (2==sscanf(kbbuf,"%2x %2x",
&h[0],&h[1])) return 2;
if (1==sscanf(kbbuf,"%2x",&h[0])) return 1;
set_cmd_esc (TRUE);
}
return 0;
}
/* prompt user to verify choice with a 'Y' or 'y' */
short ask_verify (void)
{
unsigned char kbch;
short affirm;
xprintf (" (Y/N) ");
kbch = read_rpts_wait_for_kbhit ();
if (esc_out(kbch)) return FALSE;
affirm = ((kbch == 'Y') || (kbch == 'y'));
xprintf (affirm ? "YES" : "NO");
show_crlf ();
return affirm;
}
short ask_verify_nocmdcrlf (void)
{
unsigned char kbch;
short affirm;
xprintf (" (Y/N) ");
kbch = read_rpts_wait_for_kbhit ();
if (esc_out(kbch)) return FALSE;
affirm = ((kbch == 'Y') || (kbch == 'y'));
xprintf (affirm ? "YES" : "NO");
return affirm;
}
/**/
/* ******************** 3. TIMING ROUTINES *********************** */
/* logical indicating desire to set time */
static double
timezone_hrs = -24.0; /* timezone offset, hours; nonsense value to start */
static short
timezone_set = FALSE;
const short days_of_month [12] = {
0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
double raw_PC_time (void)
{
/*
** Note: Borland routines have a timezone implicit in them, most often
** -5 hours. We use DOS access directly so this does not screw us up.
*/
union REGS
regs;
double
day, year,
gpsday,
hour, minute, second;
short
month;
regs.h.ah = 0x2A; /* get date from DOS */
intdos (®s, ®s);
year = regs.x.cx; /* year */
month = regs.h.dh; /* month */
day = regs.h.dl; /* day */
gpsday = day + days_of_month[month - 1] + (year - 1980) * 365 - 6;
/* leap years - add one for every fourth previous February */
gpsday += (short)(12*(year-1976)+month-3)/48;
regs.h.ah = 0x2C; /* get time from DOS */
intdos (®s, ®s);
hour = regs.h.ch; /* hours */
minute = regs.h.cl; /* minutes */
second = regs.h.dh; /* seconds */
return (second + 60. * (minute + 60. * (hour + 24. * gpsday)));
}
short set_raw_PC_time (double gpstime)
{
long days;
short days_this_month, years, months;
union REGS
regs;
short
hour, minute, second,
year, month, day;
//=========================
days = (long)(gpstime / 86400.);
/* determine elapsed years since start of GPS */
years = 0;
while(TRUE)
{
if(days < days_in_year[years])
break;
days -= days_in_year[years];
years++;
}
year = 1980 + years;
/* determine elapsed months since start of year */
months = 0;
while (TRUE)
{
if (leap_year[years])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -