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