⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icom.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
字号:
/* * Program to control ICOM radios * * This is a ripoff of the utility routines in the ICOM software * distribution. The only function provided is to load the radio * frequency. All other parameters must be manually set before use. */#include "icom.h"#include <unistd.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>#include "ntp_tty.h"#include "l_stdlib.h"/* * Scraps */#define BMAX 50			/* max command length */#define DICOM /dev/icom/	/* ICOM port link *//* * FSA definitions */#define S_IDLE	0		/* idle */#define S_HDR	1		/* header */#define S_TX	2		/* address */#define S_DATA	3		/* data */#define S_ERROR	4		/* error *//* * Local function prototypes */static void doublefreq		P((double, u_char *, int));static int sndpkt		P((int, int, u_char *, u_char *));static int sndoctet		P((int, int));static int rcvoctet		P((int));/* * Local variables */static int flags;		/* trace flags */static int state;		/* fsa state *//* * icom_freq(fd, ident, freq) - load radio frequency */inticom_freq(			/* returns 0 (ok), EIO (error) */	int fd,			/* file descriptor */	int ident,		/* ICOM radio identifier */	double freq		/* frequency (MHz) */	){	u_char cmd[BMAX], rsp[BMAX];	int temp;	cmd[0] = V_SFREQ;	if (ident == IC735)		temp = 4;	else		temp = 5;	doublefreq(freq * 1e6, &cmd[1], temp);	temp = sndpkt(fd, ident, cmd, rsp);	if (temp < 1 || rsp[0] != ACK)		return (EIO);	return (0);}/* * doublefreq(freq, y, len) - double to ICOM frequency with padding */static voiddoublefreq(			/* returns void */	double freq,		/* frequency */	u_char *x,		/* radio frequency */	int len			/* length (octets) */	){	int i;	char s1[11];	char *y;	sprintf(s1, " %10.0f", freq);	y = s1 + 10;	i = 0;	while (*y != ' ') {		x[i] = *y-- & 0x0f;		x[i] = x[i] | ((*y-- & 0x0f) << 4);		i++;	}	for (; i < len; i++)		x[i] = 0;	x[i] = FI;}/* * Packet routines * * These routines send a packet and receive the response. If an error * (collision) occurs on transmit, the packet is resent. If an error * occurs on receive (timeout), all input to the terminating FI is * discarded and the packet is resent. If the maximum number of retries * is not exceeded, the program returns the number of octets in the user * buffer; otherwise, it returns zero. * * ICOM frame format * * Frames begin with a two-octet preamble PR-PR followyd by the * transceiver address RE, controller address TX, control code CN, zero * or more data octets DA (depending on command), and terminator FI. * Since the bus is bidirectional, every octet output is echoed on * input. Every valid frame sent is answered with a frame in the same * format, but with the RE and TX fields interchanged. The CN field is * set to NAK if an error has occurred. Otherwise, the data are returned * in this and following DA octets. If no data are returned, the CN * octet is set to ACK. * *	+------+------+------+------+------+--//--+------+ *	|  PR  |  PR  |  RE  |  TX  |  CN  |  DA  |  FI  | *	+------+------+------+------+------+--//--+------+ *//* * icom_open() - open and initialize serial interface * * This routine opens the serial interface for raw transmission; that * is, character-at-a-time, no stripping, checking or monkeying with the * bits. For Unix, an input operation ends either with the receipt of a * character or a 0.5-s timeout. */inticom_init(	char *device,		/* device name/link */	int speed,		/* line speed */	int trace		/* trace flags */	){	TTY ttyb;	int fd;	flags = trace;	fd = open(device, O_RDWR, 0777);	if (fd < 0)		return (fd);	tcgetattr(fd, &ttyb);	ttyb.c_iflag = 0;	/* input modes */	ttyb.c_oflag = 0;	/* output modes */	ttyb.c_cflag = IBAUD|CS8|CREAD|CLOCAL;	/* control modes */	ttyb.c_lflag = 0;	/* local modes */	ttyb.c_cc[VMIN] = 0;	/* min chars */	ttyb.c_cc[VTIME] = 5;	/* receive timeout */	cfsetispeed(&ttyb, (u_int)speed);	cfsetospeed(&ttyb, (u_int)speed);	tcsetattr(fd, TCSANOW, &ttyb);	return (fd);}/* * sndpkt(r, x, y) - send packet and receive response * * This routine sends a command frame, which consists of all except the * preamble octets PR-PR. It then listens for the response frame and * returns the payload to the caller. The routine checks for correct * response header format; that is, the length of the response vector * returned to the caller must be at least 2 and the RE and TX octets * must be interchanged; otherwise, the operation is retried up to * the number of times specified in a global variable. * * The trace function, which is enabled by the P_TRACE bit of the global * flags variable, prints all characters received or echoed on the bus * preceded by a T (transmit) or R (receive). The P_ERMSG bit of the * flags variable enables printing of bus error messages. * * Note that the first octet sent is a PAD in order to allow time for * the radio to flush its receive buffer after sending the previous * response. Even with this precaution, some of the older radios * occasionally fail to receive a command and it has to be sent again. */static intsndpkt(				/* returns octet count */	int fd,			/* file descriptor */	int r,			/* radio address */	u_char *cmd,		/* command vector */	u_char *rsp		/* response vector */	){	int i, j, temp;	(void)tcflush(fd, TCIOFLUSH);	for (i = 0; i < RETRY; i++) {		state = S_IDLE;		/*		 * Transmit packet.		 */		if (flags & P_TRACE)			printf("icom T:");		sndoctet(fd, PAD);	/* send header */		sndoctet(fd, PR);		sndoctet(fd, PR);		sndoctet(fd, r);		sndoctet(fd, TX);		for (j = 0; j < BMAX; j++) { /* send body */			if (sndoctet(fd, cmd[j]) == FI)				break;		}		while (rcvoctet(fd) != FI); /* purge echos */		if (cmd[0] == V_FREQT || cmd[0] == V_MODET)			return (0);	/* shortcut for broadcast */		/*		 * Receive packet. First, delete all characters		 * preceeding a PR, then discard all PRs. Check that the		 * RE and TX fields are correctly interchanged, then		 * copy the remaining data and FI to the user buffer.		 */		if (flags & P_TRACE)			printf("\nicom R:");		j = 0;		while ((temp = rcvoctet(fd)) != FI) {			switch (state) {			case S_IDLE:				if (temp != PR)					continue;				state = S_HDR;				break;			case S_HDR:				if (temp == PR) {					continue;				} else if (temp != TX) {					if (flags & P_ERMSG)						printf(						    "icom: TX error\n");					state = S_ERROR;				}				state = S_TX;				break;			case S_TX:				if (temp != r) {					if (flags & P_ERMSG)						printf(						    "icom: RE error\n");					state = S_ERROR;				}				state = S_DATA;				break;			case S_DATA:				if (j >= BMAX ) {					if (flags & P_ERMSG)						printf(					    "icom: buffer overrun\n");					state = S_ERROR;					j = 0;				}				rsp[j++] = (u_char)temp;				break;			case S_ERROR:				break;			}		}		if (flags & P_TRACE)			printf("\n");		if (j > 0) {			rsp[j++] = FI;			return (j);		}	}	if (flags & P_ERMSG)		printf("icom: retries exceeded\n");	return (0);}/* * Interface routines * * These routines read and write octets on the bus. In case of receive * timeout a FI code is returned. In case of output collision (echo * does not match octet sent), the remainder of the collision frame * (including the trailing FI) is discarded. *//* * sndoctet(fd, x) - send octet */static intsndoctet(			/* returns octet */	int fd,			/* file descriptor */	int x			/* octet */	){	u_char y;	y = (u_char)x;	write(fd, &y, 1);	return (x);}/* * rcvoctet(fd) - receive octet */static intrcvoctet(			/* returns octet */	int fd			/* file descriptor */	){	u_char y;	if (read(fd, &y, 1) < 1)		y = FI;		/* come here if timeout */	if (flags & P_TRACE && y != PAD)		printf(" %02x", y);	return (y);}/* end program */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -