Home | History | Annotate | Line # | Download | only in libntp
icom.c revision 1.3.16.1
      1 /*	$NetBSD: icom.c,v 1.3.16.1 2014/12/25 02:13:05 snj Exp $	*/
      2 
      3 /*
      4  * Program to control ICOM radios
      5  *
      6  * This is a ripoff of the utility routines in the ICOM software
      7  * distribution. The only function provided is to load the radio
      8  * frequency. All other parameters must be manually set before use.
      9  */
     10 #include <config.h>
     11 #include "icom.h"
     12 #include <unistd.h>
     13 #include <stdio.h>
     14 #include <fcntl.h>
     15 #include <errno.h>
     16 
     17 #include "ntp_tty.h"
     18 #include "l_stdlib.h"
     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 int
     67 icom_freq(			/* returns 0 (ok), EIO (error) */
     68 	int fd,			/* file descriptor */
     69 	int ident,		/* ICOM radio identifier */
     70 	double freq		/* frequency (MHz) */
     71 	)
     72 {
     73 	u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI,
     74 	    FI};
     75 	int temp;
     76 
     77 	cmd[3] = (char)ident;
     78 	if (ident == IC735)
     79 		temp = 4;
     80 	else
     81 		temp = 5;
     82 	doublefreq(freq * 1e6, &cmd[6], temp);
     83 	temp = write(fd, cmd, temp + 7);
     84 
     85 	return (0);
     86 }
     87 
     88 
     89 /*
     90  * doublefreq(freq, y, len) - double to ICOM frequency with padding
     91  */
     92 static void
     93 doublefreq(			/* returns void */
     94 	double freq,		/* frequency */
     95 	u_char *x,		/* radio frequency */
     96 	int len			/* length (octets) */
     97 	)
     98 {
     99 	int i;
    100 	char s1[16];
    101 	char *y;
    102 
    103 	snprintf(s1, sizeof(s1), " %10.0f", freq);
    104 	y = s1 + 10;
    105 	i = 0;
    106 	while (*y != ' ') {
    107 		x[i] = *y-- & 0x0f;
    108 		x[i] = x[i] | ((*y-- & 0x0f) << 4);
    109 		i++;
    110 	}
    111 	for ( ; i < len; i++)
    112 		x[i] = 0;
    113 	x[i] = FI;
    114 }
    115 
    116 /*
    117  * icom_init() - open and initialize serial interface
    118  *
    119  * This routine opens the serial interface for raw transmission; that
    120  * is, character-at-a-time, no stripping, checking or monkeying with the
    121  * bits. For Unix, an input operation ends either with the receipt of a
    122  * character or a 0.5-s timeout.
    123  */
    124 int
    125 icom_init(
    126 	const char *device,	/* device name/link */
    127 	int speed,		/* line speed */
    128 	int trace		/* trace flags */	)
    129 {
    130 	TTY ttyb;
    131 	int fd;
    132 	int rc;
    133 	int saved_errno;
    134 
    135 	fd = tty_open(device, O_RDWR, 0777);
    136 	if (fd < 0)
    137 		return -1;
    138 
    139 	rc = tcgetattr(fd, &ttyb);
    140 	if (rc < 0) {
    141 		saved_errno = errno;
    142 		close(fd);
    143 		errno = saved_errno;
    144 		return -1;
    145 	}
    146 	ttyb.c_iflag = 0;	/* input modes */
    147 	ttyb.c_oflag = 0;	/* output modes */
    148 	ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes  (no read) */
    149 	ttyb.c_lflag = 0;	/* local modes */
    150 	ttyb.c_cc[VMIN] = 0;	/* min chars */
    151 	ttyb.c_cc[VTIME] = 5;	/* receive timeout */
    152 	cfsetispeed(&ttyb, (u_int)speed);
    153 	cfsetospeed(&ttyb, (u_int)speed);
    154 	rc = tcsetattr(fd, TCSANOW, &ttyb);
    155 	if (rc < 0) {
    156 		saved_errno = errno;
    157 		close(fd);
    158 		errno = saved_errno;
    159 		return -1;
    160 	}
    161 	return (fd);
    162 }
    163 
    164 /* end program */
    165