1a151a66cSOllivier Robert /* 2a151a66cSOllivier Robert * Program to control ICOM radios 3a151a66cSOllivier Robert * 4a151a66cSOllivier Robert * This is a ripoff of the utility routines in the ICOM software 5a151a66cSOllivier Robert * distribution. The only function provided is to load the radio 6a151a66cSOllivier Robert * frequency. All other parameters must be manually set before use. 7a151a66cSOllivier Robert */ 82b15cb3dSCy Schubert #include <config.h> 9*9034852cSGleb Smirnoff #include <ntp_stdlib.h> 10*9034852cSGleb Smirnoff #include <ntp_tty.h> 11*9034852cSGleb Smirnoff #include <l_stdlib.h> 12*9034852cSGleb Smirnoff #include <icom.h> 13*9034852cSGleb Smirnoff 14a151a66cSOllivier Robert #include <unistd.h> 15a151a66cSOllivier Robert #include <stdio.h> 16a151a66cSOllivier Robert #include <fcntl.h> 17a151a66cSOllivier Robert #include <errno.h> 18a151a66cSOllivier Robert 19224ba2bdSOllivier Robert 202b15cb3dSCy Schubert #ifdef SYS_WINNT 212b15cb3dSCy Schubert #undef write /* ports/winnt/include/config.h: #define write _write */ 222b15cb3dSCy Schubert extern int async_write(int, const void *, unsigned int); 232b15cb3dSCy Schubert #define write(fd, data, octets) async_write(fd, data, octets) 242b15cb3dSCy Schubert #endif 25a151a66cSOllivier Robert 26a151a66cSOllivier Robert /* 27a151a66cSOllivier Robert * Packet routines 28a151a66cSOllivier Robert * 29a151a66cSOllivier Robert * These routines send a packet and receive the response. If an error 30a151a66cSOllivier Robert * (collision) occurs on transmit, the packet is resent. If an error 31a151a66cSOllivier Robert * occurs on receive (timeout), all input to the terminating FI is 32a151a66cSOllivier Robert * discarded and the packet is resent. If the maximum number of retries 33a151a66cSOllivier Robert * is not exceeded, the program returns the number of octets in the user 34a151a66cSOllivier Robert * buffer; otherwise, it returns zero. 35a151a66cSOllivier Robert * 36a151a66cSOllivier Robert * ICOM frame format 37a151a66cSOllivier Robert * 38a151a66cSOllivier Robert * Frames begin with a two-octet preamble PR-PR followyd by the 39a151a66cSOllivier Robert * transceiver address RE, controller address TX, control code CN, zero 40a151a66cSOllivier Robert * or more data octets DA (depending on command), and terminator FI. 41a151a66cSOllivier Robert * Since the bus is bidirectional, every octet output is echoed on 42a151a66cSOllivier Robert * input. Every valid frame sent is answered with a frame in the same 43a151a66cSOllivier Robert * format, but with the RE and TX fields interchanged. The CN field is 44a151a66cSOllivier Robert * set to NAK if an error has occurred. Otherwise, the data are returned 45a151a66cSOllivier Robert * in this and following DA octets. If no data are returned, the CN 46a151a66cSOllivier Robert * octet is set to ACK. 47a151a66cSOllivier Robert * 48a151a66cSOllivier Robert * +------+------+------+------+------+--//--+------+ 49a151a66cSOllivier Robert * | PR | PR | RE | TX | CN | DA | FI | 50a151a66cSOllivier Robert * +------+------+------+------+------+--//--+------+ 51a151a66cSOllivier Robert */ 52a151a66cSOllivier Robert /* 532b15cb3dSCy Schubert * Scraps 542b15cb3dSCy Schubert */ 552b15cb3dSCy Schubert #define DICOM /dev/icom/ /* ICOM port link */ 562b15cb3dSCy Schubert 572b15cb3dSCy Schubert /* 582b15cb3dSCy Schubert * Local function prototypes 592b15cb3dSCy Schubert */ 602b15cb3dSCy Schubert static void doublefreq (double, u_char *, int); 612b15cb3dSCy Schubert 622b15cb3dSCy Schubert 632b15cb3dSCy Schubert /* 642b15cb3dSCy Schubert * icom_freq(fd, ident, freq) - load radio frequency 65*9034852cSGleb Smirnoff * 66*9034852cSGleb Smirnoff * returns: 67*9034852cSGleb Smirnoff * 0 (ok) 68*9034852cSGleb Smirnoff * -1 (error) 69*9034852cSGleb Smirnoff * 1 (short write to device) 702b15cb3dSCy Schubert */ 712b15cb3dSCy Schubert int 72*9034852cSGleb Smirnoff icom_freq( 732b15cb3dSCy Schubert int fd, /* file descriptor */ 742b15cb3dSCy Schubert int ident, /* ICOM radio identifier */ 752b15cb3dSCy Schubert double freq /* frequency (MHz) */ 762b15cb3dSCy Schubert ) 772b15cb3dSCy Schubert { 782b15cb3dSCy Schubert u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, 792b15cb3dSCy Schubert FI}; 802b15cb3dSCy Schubert int temp; 81*9034852cSGleb Smirnoff int rc; 822b15cb3dSCy Schubert 832b15cb3dSCy Schubert cmd[3] = (char)ident; 842b15cb3dSCy Schubert if (ident == IC735) 852b15cb3dSCy Schubert temp = 4; 862b15cb3dSCy Schubert else 872b15cb3dSCy Schubert temp = 5; 882b15cb3dSCy Schubert doublefreq(freq * 1e6, &cmd[6], temp); 89*9034852cSGleb Smirnoff rc = write(fd, cmd, temp + 7); 90*9034852cSGleb Smirnoff if (rc == -1) { 91*9034852cSGleb Smirnoff msyslog(LOG_ERR, "icom_freq: write() failed: %m"); 92*9034852cSGleb Smirnoff return -1; 93*9034852cSGleb Smirnoff } else if (rc != temp + 7) { 94*9034852cSGleb Smirnoff msyslog(LOG_ERR, "icom_freq: only wrote %d of %d bytes.", 95*9034852cSGleb Smirnoff rc, temp+7); 96*9034852cSGleb Smirnoff return 1; 97*9034852cSGleb Smirnoff } 982b15cb3dSCy Schubert 99*9034852cSGleb Smirnoff return 0; 1002b15cb3dSCy Schubert } 1012b15cb3dSCy Schubert 1022b15cb3dSCy Schubert 1032b15cb3dSCy Schubert /* 1042b15cb3dSCy Schubert * doublefreq(freq, y, len) - double to ICOM frequency with padding 1052b15cb3dSCy Schubert */ 1062b15cb3dSCy Schubert static void 1072b15cb3dSCy Schubert doublefreq( /* returns void */ 1082b15cb3dSCy Schubert double freq, /* frequency */ 1092b15cb3dSCy Schubert u_char *x, /* radio frequency */ 1102b15cb3dSCy Schubert int len /* length (octets) */ 1112b15cb3dSCy Schubert ) 1122b15cb3dSCy Schubert { 1132b15cb3dSCy Schubert int i; 1142b15cb3dSCy Schubert char s1[16]; 1152b15cb3dSCy Schubert char *y; 1162b15cb3dSCy Schubert 1172b15cb3dSCy Schubert snprintf(s1, sizeof(s1), " %10.0f", freq); 1182b15cb3dSCy Schubert y = s1 + 10; 1192b15cb3dSCy Schubert i = 0; 1202b15cb3dSCy Schubert while (*y != ' ') { 1212b15cb3dSCy Schubert x[i] = *y-- & 0x0f; 1222b15cb3dSCy Schubert x[i] = x[i] | ((*y-- & 0x0f) << 4); 1232b15cb3dSCy Schubert i++; 1242b15cb3dSCy Schubert } 1252b15cb3dSCy Schubert for ( ; i < len; i++) 1262b15cb3dSCy Schubert x[i] = 0; 1272b15cb3dSCy Schubert x[i] = FI; 1282b15cb3dSCy Schubert } 1292b15cb3dSCy Schubert 1302b15cb3dSCy Schubert /* 1312b15cb3dSCy Schubert * icom_init() - open and initialize serial interface 132a151a66cSOllivier Robert * 133a151a66cSOllivier Robert * This routine opens the serial interface for raw transmission; that 134a151a66cSOllivier Robert * is, character-at-a-time, no stripping, checking or monkeying with the 135a151a66cSOllivier Robert * bits. For Unix, an input operation ends either with the receipt of a 136a151a66cSOllivier Robert * character or a 0.5-s timeout. 137a151a66cSOllivier Robert */ 138a151a66cSOllivier Robert int 139a151a66cSOllivier Robert icom_init( 1402b15cb3dSCy Schubert const char *device, /* device name/link */ 141a151a66cSOllivier Robert int speed, /* line speed */ 142a151a66cSOllivier Robert int trace /* trace flags */ ) 143a151a66cSOllivier Robert { 144224ba2bdSOllivier Robert TTY ttyb; 145a151a66cSOllivier Robert int fd; 1462b15cb3dSCy Schubert int rc; 1472b15cb3dSCy Schubert int saved_errno; 148a151a66cSOllivier Robert 1492b15cb3dSCy Schubert fd = tty_open(device, O_RDWR, 0777); 150a151a66cSOllivier Robert if (fd < 0) 1512b15cb3dSCy Schubert return -1; 152ea906c41SOllivier Robert 1532b15cb3dSCy Schubert rc = tcgetattr(fd, &ttyb); 1542b15cb3dSCy Schubert if (rc < 0) { 1552b15cb3dSCy Schubert saved_errno = errno; 1562b15cb3dSCy Schubert close(fd); 1572b15cb3dSCy Schubert errno = saved_errno; 1582b15cb3dSCy Schubert return -1; 1592b15cb3dSCy Schubert } 160a151a66cSOllivier Robert ttyb.c_iflag = 0; /* input modes */ 161a151a66cSOllivier Robert ttyb.c_oflag = 0; /* output modes */ 1622b15cb3dSCy Schubert ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ 163a151a66cSOllivier Robert ttyb.c_lflag = 0; /* local modes */ 164a151a66cSOllivier Robert ttyb.c_cc[VMIN] = 0; /* min chars */ 165a151a66cSOllivier Robert ttyb.c_cc[VTIME] = 5; /* receive timeout */ 166a151a66cSOllivier Robert cfsetispeed(&ttyb, (u_int)speed); 167a151a66cSOllivier Robert cfsetospeed(&ttyb, (u_int)speed); 1682b15cb3dSCy Schubert rc = tcsetattr(fd, TCSANOW, &ttyb); 1692b15cb3dSCy Schubert if (rc < 0) { 1702b15cb3dSCy Schubert saved_errno = errno; 1712b15cb3dSCy Schubert close(fd); 1722b15cb3dSCy Schubert errno = saved_errno; 1732b15cb3dSCy Schubert return -1; 1742b15cb3dSCy Schubert } 175a151a66cSOllivier Robert return (fd); 176a151a66cSOllivier Robert } 177a151a66cSOllivier Robert 178a151a66cSOllivier Robert /* end program */ 179