icom.c revision 285612
10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * Program to control ICOM radios 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * This is a ripoff of the utility routines in the ICOM software 50Sstevel@tonic-gate * distribution. The only function provided is to load the radio 60Sstevel@tonic-gate * frequency. All other parameters must be manually set before use. 70Sstevel@tonic-gate */ 80Sstevel@tonic-gate#include <config.h> 90Sstevel@tonic-gate#include "icom.h" 100Sstevel@tonic-gate#include <unistd.h> 110Sstevel@tonic-gate#include <stdio.h> 120Sstevel@tonic-gate#include <fcntl.h> 130Sstevel@tonic-gate#include <errno.h> 140Sstevel@tonic-gate 150Sstevel@tonic-gate#include "ntp_tty.h" 160Sstevel@tonic-gate#include "l_stdlib.h" 170Sstevel@tonic-gate 180Sstevel@tonic-gate#ifdef SYS_WINNT 190Sstevel@tonic-gate#undef write /* ports/winnt/include/config.h: #define write _write */ 200Sstevel@tonic-gateextern int async_write(int, const void *, unsigned int); 210Sstevel@tonic-gate#define write(fd, data, octets) async_write(fd, data, octets) 220Sstevel@tonic-gate#endif 230Sstevel@tonic-gate 240Sstevel@tonic-gate/* 250Sstevel@tonic-gate * Packet routines 260Sstevel@tonic-gate * 270Sstevel@tonic-gate * These routines send a packet and receive the response. If an error 280Sstevel@tonic-gate * (collision) occurs on transmit, the packet is resent. If an error 290Sstevel@tonic-gate * occurs on receive (timeout), all input to the terminating FI is 300Sstevel@tonic-gate * discarded and the packet is resent. If the maximum number of retries 310Sstevel@tonic-gate * is not exceeded, the program returns the number of octets in the user 320Sstevel@tonic-gate * buffer; otherwise, it returns zero. 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * ICOM frame format 350Sstevel@tonic-gate * 360Sstevel@tonic-gate * Frames begin with a two-octet preamble PR-PR followyd by the 370Sstevel@tonic-gate * transceiver address RE, controller address TX, control code CN, zero 380Sstevel@tonic-gate * or more data octets DA (depending on command), and terminator FI. 390Sstevel@tonic-gate * Since the bus is bidirectional, every octet output is echoed on 400Sstevel@tonic-gate * input. Every valid frame sent is answered with a frame in the same 410Sstevel@tonic-gate * format, but with the RE and TX fields interchanged. The CN field is 420Sstevel@tonic-gate * set to NAK if an error has occurred. Otherwise, the data are returned 430Sstevel@tonic-gate * in this and following DA octets. If no data are returned, the CN 440Sstevel@tonic-gate * octet is set to ACK. 450Sstevel@tonic-gate * 460Sstevel@tonic-gate * +------+------+------+------+------+--//--+------+ 470Sstevel@tonic-gate * | PR | PR | RE | TX | CN | DA | FI | 480Sstevel@tonic-gate * +------+------+------+------+------+--//--+------+ 490Sstevel@tonic-gate */ 500Sstevel@tonic-gate/* 510Sstevel@tonic-gate * Scraps 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate#define DICOM /dev/icom/ /* ICOM port link */ 540Sstevel@tonic-gate 550Sstevel@tonic-gate/* 560Sstevel@tonic-gate * Local function prototypes 570Sstevel@tonic-gate */ 580Sstevel@tonic-gatestatic void doublefreq (double, u_char *, int); 592139Sjp161948 602139Sjp161948 612139Sjp161948/* 622139Sjp161948 * icom_freq(fd, ident, freq) - load radio frequency 632139Sjp161948 */ 642139Sjp161948int 652139Sjp161948icom_freq( /* returns 0 (ok), EIO (error) */ 662139Sjp161948 int fd, /* file descriptor */ 670Sstevel@tonic-gate int ident, /* ICOM radio identifier */ 682139Sjp161948 double freq /* frequency (MHz) */ 690Sstevel@tonic-gate ) 700Sstevel@tonic-gate{ 710Sstevel@tonic-gate u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI, 720Sstevel@tonic-gate FI}; 730Sstevel@tonic-gate int temp; 740Sstevel@tonic-gate 750Sstevel@tonic-gate cmd[3] = (char)ident; 760Sstevel@tonic-gate if (ident == IC735) 770Sstevel@tonic-gate temp = 4; 780Sstevel@tonic-gate else 790Sstevel@tonic-gate temp = 5; 800Sstevel@tonic-gate doublefreq(freq * 1e6, &cmd[6], temp); 810Sstevel@tonic-gate temp = write(fd, cmd, temp + 7); 820Sstevel@tonic-gate 830Sstevel@tonic-gate return (0); 840Sstevel@tonic-gate} 850Sstevel@tonic-gate 860Sstevel@tonic-gate 870Sstevel@tonic-gate/* 880Sstevel@tonic-gate * doublefreq(freq, y, len) - double to ICOM frequency with padding 890Sstevel@tonic-gate */ 900Sstevel@tonic-gatestatic void 910Sstevel@tonic-gatedoublefreq( /* returns void */ 920Sstevel@tonic-gate double freq, /* frequency */ 930Sstevel@tonic-gate u_char *x, /* radio frequency */ 940Sstevel@tonic-gate int len /* length (octets) */ 950Sstevel@tonic-gate ) 960Sstevel@tonic-gate{ 970Sstevel@tonic-gate int i; 980Sstevel@tonic-gate char s1[16]; 990Sstevel@tonic-gate char *y; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate snprintf(s1, sizeof(s1), " %10.0f", freq); 1020Sstevel@tonic-gate y = s1 + 10; 1030Sstevel@tonic-gate i = 0; 1040Sstevel@tonic-gate while (*y != ' ') { 1050Sstevel@tonic-gate x[i] = *y-- & 0x0f; 1060Sstevel@tonic-gate x[i] = x[i] | ((*y-- & 0x0f) << 4); 1070Sstevel@tonic-gate i++; 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate for ( ; i < len; i++) 1100Sstevel@tonic-gate x[i] = 0; 1110Sstevel@tonic-gate x[i] = FI; 1120Sstevel@tonic-gate} 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate/* 1150Sstevel@tonic-gate * icom_init() - open and initialize serial interface 1162139Sjp161948 * 1170Sstevel@tonic-gate * This routine opens the serial interface for raw transmission; that 1180Sstevel@tonic-gate * is, character-at-a-time, no stripping, checking or monkeying with the 1190Sstevel@tonic-gate * bits. For Unix, an input operation ends either with the receipt of a 1200Sstevel@tonic-gate * character or a 0.5-s timeout. 1210Sstevel@tonic-gate */ 122871Scasperint 123871Scaspericom_init( 1240Sstevel@tonic-gate const char *device, /* device name/link */ 1250Sstevel@tonic-gate int speed, /* line speed */ 1260Sstevel@tonic-gate int trace /* trace flags */ ) 1270Sstevel@tonic-gate{ 1280Sstevel@tonic-gate TTY ttyb; 1290Sstevel@tonic-gate int fd; 1300Sstevel@tonic-gate int rc; 1310Sstevel@tonic-gate int saved_errno; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate fd = tty_open(device, O_RDWR, 0777); 1340Sstevel@tonic-gate if (fd < 0) 1350Sstevel@tonic-gate return -1; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate rc = tcgetattr(fd, &ttyb); 1380Sstevel@tonic-gate if (rc < 0) { 1390Sstevel@tonic-gate saved_errno = errno; 1400Sstevel@tonic-gate close(fd); 1412139Sjp161948 errno = saved_errno; 1420Sstevel@tonic-gate return -1; 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate ttyb.c_iflag = 0; /* input modes */ 1450Sstevel@tonic-gate ttyb.c_oflag = 0; /* output modes */ 1460Sstevel@tonic-gate ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */ 1470Sstevel@tonic-gate ttyb.c_lflag = 0; /* local modes */ 1480Sstevel@tonic-gate ttyb.c_cc[VMIN] = 0; /* min chars */ 1490Sstevel@tonic-gate ttyb.c_cc[VTIME] = 5; /* receive timeout */ 1500Sstevel@tonic-gate cfsetispeed(&ttyb, (u_int)speed); 1510Sstevel@tonic-gate cfsetospeed(&ttyb, (u_int)speed); 1520Sstevel@tonic-gate rc = tcsetattr(fd, TCSANOW, &ttyb); 1530Sstevel@tonic-gate if (rc < 0) { 1540Sstevel@tonic-gate saved_errno = errno; 1550Sstevel@tonic-gate close(fd); 1560Sstevel@tonic-gate errno = saved_errno; 1570Sstevel@tonic-gate return -1; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate return (fd); 1600Sstevel@tonic-gate} 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate/* end program */ 1630Sstevel@tonic-gate