summaryrefslogtreecommitdiff
path: root/libntp/icom.c
blob: 80700114255ef2347f950c65437b6e09dcc6a6c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * Program to control ICOM radios
 *
 * This is a ripoff of the utility routines in the ICOM software
 * distribution. The only function provided is to load the radio
 * frequency. All other parameters must be manually set before use.
 */
#include <config.h>
#include "icom.h"
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

#include "ntp_tty.h"
#include "l_stdlib.h"

#ifdef SYS_WINNT
#undef write	/* ports/winnt/include/config.h: #define write _write */
extern int async_write(int, const void *, unsigned int);
#define write(fd, data, octets)	async_write(fd, data, octets)
#endif

/*
 * Packet routines
 *
 * These routines send a packet and receive the response. If an error
 * (collision) occurs on transmit, the packet is resent. If an error
 * occurs on receive (timeout), all input to the terminating FI is
 * discarded and the packet is resent. If the maximum number of retries
 * is not exceeded, the program returns the number of octets in the user
 * buffer; otherwise, it returns zero.
 *
 * ICOM frame format
 *
 * Frames begin with a two-octet preamble PR-PR followyd by the
 * transceiver address RE, controller address TX, control code CN, zero
 * or more data octets DA (depending on command), and terminator FI.
 * Since the bus is bidirectional, every octet output is echoed on
 * input. Every valid frame sent is answered with a frame in the same
 * format, but with the RE and TX fields interchanged. The CN field is
 * set to NAK if an error has occurred. Otherwise, the data are returned
 * in this and following DA octets. If no data are returned, the CN
 * octet is set to ACK.
 *
 *	+------+------+------+------+------+--//--+------+
 *	|  PR  |  PR  |  RE  |  TX  |  CN  |  DA  |  FI  |
 *	+------+------+------+------+------+--//--+------+
 */
/*
 * Scraps
 */
#define DICOM /dev/icom/	/* ICOM port link */

/*
 * Local function prototypes
 */
static void doublefreq		(double, u_char *, int);


/*
 * icom_freq(fd, ident, freq) - load radio frequency
 */
int
icom_freq(			/* returns 0 (ok), EIO (error) */
	int fd,			/* file descriptor */
	int ident,		/* ICOM radio identifier */
	double freq		/* frequency (MHz) */
	)
{
	u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI,
	    FI};
	int temp;

	cmd[3] = (char)ident;
	if (ident == IC735)
		temp = 4;
	else
		temp = 5;
	doublefreq(freq * 1e6, &cmd[6], temp);
	temp = write(fd, cmd, temp + 7);

	return (0);
}


/*
 * doublefreq(freq, y, len) - double to ICOM frequency with padding
 */
static void
doublefreq(			/* returns void */
	double freq,		/* frequency */
	u_char *x,		/* radio frequency */
	int len			/* length (octets) */
	)
{
	int i;
	char s1[16];
	char *y;

	snprintf(s1, sizeof(s1), " %10.0f", freq);
	y = s1 + 10;
	i = 0;
	while (*y != ' ') {
		x[i] = *y-- & 0x0f;
		x[i] = x[i] | ((*y-- & 0x0f) << 4);
		i++;
	}
	for ( ; i < len; i++)
		x[i] = 0;
	x[i] = FI;
}

/*
 * icom_init() - open and initialize serial interface
 *
 * This routine opens the serial interface for raw transmission; that
 * is, character-at-a-time, no stripping, checking or monkeying with the
 * bits. For Unix, an input operation ends either with the receipt of a
 * character or a 0.5-s timeout.
 */
int
icom_init(
	const char *device,	/* device name/link */
	int speed,		/* line speed */
	int trace		/* trace flags */	)
{
	TTY ttyb;
	int fd;
	int rc;
	int saved_errno;

	fd = tty_open(device, O_RDWR, 0777);
	if (fd < 0)
		return -1;

	rc = tcgetattr(fd, &ttyb);
	if (rc < 0) {
		saved_errno = errno;
		close(fd);
		errno = saved_errno;
		return -1;
	}
	ttyb.c_iflag = 0;	/* input modes */
	ttyb.c_oflag = 0;	/* output modes */
	ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes  (no read) */
	ttyb.c_lflag = 0;	/* local modes */
	ttyb.c_cc[VMIN] = 0;	/* min chars */
	ttyb.c_cc[VTIME] = 5;	/* receive timeout */
	cfsetispeed(&ttyb, (u_int)speed);
	cfsetospeed(&ttyb, (u_int)speed);
	rc = tcsetattr(fd, TCSANOW, &ttyb);
	if (rc < 0) {
		saved_errno = errno;
		close(fd);
		errno = saved_errno;
		return -1;
	}
	return (fd);
}

/* end program */