/src/ntp-dev/libntp/icom.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Program to control ICOM radios |
3 | | * |
4 | | * This is a ripoff of the utility routines in the ICOM software |
5 | | * distribution. The only function provided is to load the radio |
6 | | * frequency. All other parameters must be manually set before use. |
7 | | */ |
8 | | #include <config.h> |
9 | | #include <ntp_stdlib.h> |
10 | | #include <ntp_tty.h> |
11 | | #include <l_stdlib.h> |
12 | | #include <icom.h> |
13 | | |
14 | | #include <unistd.h> |
15 | | #include <stdio.h> |
16 | | #include <fcntl.h> |
17 | | #include <errno.h> |
18 | | |
19 | | |
20 | | #ifdef SYS_WINNT |
21 | | #undef write /* ports/winnt/include/config.h: #define write _write */ |
22 | | extern int async_write(int, const void *, unsigned int); |
23 | | #define write(fd, data, octets) async_write(fd, data, octets) |
24 | | #endif |
25 | | |
26 | | /* |
27 | | * Packet routines |
28 | | * |
29 | | * These routines send a packet and receive the response. If an error |
30 | | * (collision) occurs on transmit, the packet is resent. If an error |
31 | | * occurs on receive (timeout), all input to the terminating FI is |
32 | | * discarded and the packet is resent. If the maximum number of retries |
33 | | * is not exceeded, the program returns the number of octets in the user |
34 | | * buffer; otherwise, it returns zero. |
35 | | * |
36 | | * ICOM frame format |
37 | | * |
38 | | * Frames begin with a two-octet preamble PR-PR followyd by the |
39 | | * transceiver address RE, controller address TX, control code CN, zero |
40 | | * or more data octets DA (depending on command), and terminator FI. |
41 | | * Since the bus is bidirectional, every octet output is echoed on |
42 | | * input. Every valid frame sent is answered with a frame in the same |
43 | | * format, but with the RE and TX fields interchanged. The CN field is |
44 | | * set to NAK if an error has occurred. Otherwise, the data are returned |
45 | | * in this and following DA octets. If no data are returned, the CN |
46 | | * octet is set to ACK. |
47 | | * |
48 | | * +------+------+------+------+------+--//--+------+ |
49 | | * | PR | PR | RE | TX | CN | DA | FI | |
50 | | * +------+------+------+------+------+--//--+------+ |
51 | | */ |
52 | | /* |
53 | | * Scraps |
54 | | */ |
55 | | #define DICOM /dev/icom/ /* ICOM port link */ |
56 | | |
57 | | /* |
58 | | * Local function prototypes |
59 | | */ |
60 | | static void doublefreq (double, u_char *, int); |
61 | | |
62 | | |
63 | | /* |
64 | | * icom_freq(fd, ident, freq) - load radio frequency |
65 | | * |
66 | | * returns: |
67 | | * 0 (ok) |
68 | | * -1 (error) |
69 | | * 1 (short write to device) |
70 | | */ |
71 | | int |
72 | | icom_freq( |
73 | | int fd, /* file descriptor */ |
74 | | int ident, /* ICOM radio identifier */ |
75 | | double freq /* frequency (MHz) */ |
76 | | ) |
77 | 0 | { |
78 | 0 | u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, |
79 | 0 | FI}; |
80 | 0 | int temp; |
81 | 0 | int rc; |
82 | |
|
83 | 0 | cmd[3] = (char)ident; |
84 | 0 | if (ident == IC735) |
85 | 0 | temp = 4; |
86 | 0 | else |
87 | 0 | temp = 5; |
88 | 0 | doublefreq(freq * 1e6, &cmd[6], temp); |
89 | 0 | rc = write(fd, cmd, temp + 7); |
90 | 0 | if (rc == -1) { |
91 | 0 | msyslog(LOG_ERR, "icom_freq: write() failed: %m"); |
92 | 0 | return -1; |
93 | 0 | } else if (rc != temp + 7) { |
94 | 0 | msyslog(LOG_ERR, "icom_freq: only wrote %d of %d bytes.", |
95 | 0 | rc, temp+7); |
96 | 0 | return 1; |
97 | 0 | } |
98 | | |
99 | 0 | return 0; |
100 | 0 | } |
101 | | |
102 | | |
103 | | /* |
104 | | * doublefreq(freq, y, len) - double to ICOM frequency with padding |
105 | | */ |
106 | | static void |
107 | | doublefreq( /* returns void */ |
108 | | double freq, /* frequency */ |
109 | | u_char *x, /* radio frequency */ |
110 | | int len /* length (octets) */ |
111 | | ) |
112 | 0 | { |
113 | 0 | int i; |
114 | 0 | char s1[16]; |
115 | 0 | char *y; |
116 | |
|
117 | 0 | snprintf(s1, sizeof(s1), " %10.0f", freq); |
118 | 0 | y = s1 + 10; |
119 | 0 | i = 0; |
120 | 0 | while (*y != ' ') { |
121 | 0 | x[i] = *y-- & 0x0f; |
122 | 0 | x[i] = x[i] | ((*y-- & 0x0f) << 4); |
123 | 0 | i++; |
124 | 0 | } |
125 | 0 | for ( ; i < len; i++) |
126 | 0 | x[i] = 0; |
127 | 0 | x[i] = FI; |
128 | 0 | } |
129 | | |
130 | | /* |
131 | | * icom_init() - open and initialize serial interface |
132 | | * |
133 | | * This routine opens the serial interface for raw transmission; that |
134 | | * is, character-at-a-time, no stripping, checking or monkeying with the |
135 | | * bits. For Unix, an input operation ends either with the receipt of a |
136 | | * character or a 0.5-s timeout. |
137 | | */ |
138 | | int |
139 | | icom_init( |
140 | | const char *device, /* device name/link */ |
141 | | int speed, /* line speed */ |
142 | | int trace /* trace flags */ ) |
143 | 0 | { |
144 | 0 | TTY ttyb; |
145 | 0 | int fd; |
146 | 0 | int rc; |
147 | 0 | int saved_errno; |
148 | |
|
149 | 0 | fd = tty_open(device, O_RDWR, 0777); |
150 | 0 | if (fd < 0) |
151 | 0 | return -1; |
152 | | |
153 | 0 | rc = tcgetattr(fd, &ttyb); |
154 | 0 | if (rc < 0) { |
155 | 0 | saved_errno = errno; |
156 | 0 | close(fd); |
157 | 0 | errno = saved_errno; |
158 | 0 | return -1; |
159 | 0 | } |
160 | 0 | ttyb.c_iflag = 0; /* input modes */ |
161 | 0 | ttyb.c_oflag = 0; /* output modes */ |
162 | 0 | ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ |
163 | 0 | ttyb.c_lflag = 0; /* local modes */ |
164 | 0 | ttyb.c_cc[VMIN] = 0; /* min chars */ |
165 | 0 | ttyb.c_cc[VTIME] = 5; /* receive timeout */ |
166 | 0 | cfsetispeed(&ttyb, (u_int)speed); |
167 | 0 | cfsetospeed(&ttyb, (u_int)speed); |
168 | 0 | rc = tcsetattr(fd, TCSANOW, &ttyb); |
169 | 0 | if (rc < 0) { |
170 | 0 | saved_errno = errno; |
171 | 0 | close(fd); |
172 | 0 | errno = saved_errno; |
173 | 0 | return -1; |
174 | 0 | } |
175 | 0 | return (fd); |
176 | 0 | } |
177 | | |
178 | | /* end program */ |