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 { 78 u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, 79 FI}; 80 int temp; 81 int rc; 82 83 cmd[3] = (char)ident; 84 if (ident == IC735) 85 temp = 4; 86 else 87 temp = 5; 88 doublefreq(freq * 1e6, &cmd[6], temp); 89 rc = write(fd, cmd, temp + 7); 90 if (rc == -1) { 91 msyslog(LOG_ERR, "icom_freq: write() failed: %m"); 92 return -1; 93 } else if (rc != temp + 7) { 94 msyslog(LOG_ERR, "icom_freq: only wrote %d of %d bytes.", 95 rc, temp+7); 96 return 1; 97 } 98 99 return 0; 100 } 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 { 113 int i; 114 char s1[16]; 115 char *y; 116 117 snprintf(s1, sizeof(s1), " %10.0f", freq); 118 y = s1 + 10; 119 i = 0; 120 while (*y != ' ') { 121 x[i] = *y-- & 0x0f; 122 x[i] = x[i] | ((*y-- & 0x0f) << 4); 123 i++; 124 } 125 for ( ; i < len; i++) 126 x[i] = 0; 127 x[i] = FI; 128 } 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 { 144 TTY ttyb; 145 int fd; 146 int rc; 147 int saved_errno; 148 149 fd = tty_open(device, O_RDWR, 0777); 150 if (fd < 0) 151 return -1; 152 153 rc = tcgetattr(fd, &ttyb); 154 if (rc < 0) { 155 saved_errno = errno; 156 close(fd); 157 errno = saved_errno; 158 return -1; 159 } 160 ttyb.c_iflag = 0; /* input modes */ 161 ttyb.c_oflag = 0; /* output modes */ 162 ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ 163 ttyb.c_lflag = 0; /* local modes */ 164 ttyb.c_cc[VMIN] = 0; /* min chars */ 165 ttyb.c_cc[VTIME] = 5; /* receive timeout */ 166 cfsetispeed(&ttyb, (u_int)speed); 167 cfsetospeed(&ttyb, (u_int)speed); 168 rc = tcsetattr(fd, TCSANOW, &ttyb); 169 if (rc < 0) { 170 saved_errno = errno; 171 close(fd); 172 errno = saved_errno; 173 return -1; 174 } 175 return (fd); 176 } 177 178 /* end program */ 179