2 * FILE: $Header: /home/egg/src/RCS/reg_orion.c,v 1.1 1998/12/31 22:04:39 ghn Exp $
3 * PURPOSE: PEAR (Bradish box/micro-REG) hardware interface
7 * REVISED: $Log: reg_orion.c,v $
8 * REVISED: Revision 1.1 1998/12/31 22:04:39 ghn
9 * REVISED: Initial revision
11 * REVISED: Revision 1.3 1998/08/01 18:50:39 ghn
12 * REVISED: Added John's byte-order-independence changes and PSEUDO support.
14 * REVISED: Revision 1.2 1998/08/01 17:13:51 ghn
15 * REVISED: Added John's Solaris support and DUMPREG option.
17 * REVISED: Revision 1.1 1998/07/21 11:37:41 ghn
18 * REVISED: Initial revision
20 * Copyright 1998 - Greg Nelson
21 * Redistributable under the terms of the GNU Public Licence (GPL)
24 /* Define this to dump samples from the REG which we actually use into
25 a file named dumpreg.dat. This can be used to debug serial port
26 mode problems (for example, setting the character frame to 7 bits,
27 or telling it to ignore breaks, which will lose all zero bytes. */
49 /* The Orion REG is powered by the serial port into which
50 it is plugged. If the port is not providing power to
51 the REG before we initialise it, the REG may deliver
52 garbage data as the power comes up. To guard against
53 this we take two precautions. First of all, we sleep
54 REG_INIT seconds after initialising the serial port to
55 let the REG start up and stabilise after power is
56 turned on, and we further discard REG_DISCARD initial
57 samples which may have been queued as the REG was
58 powering up. If either of these symbols is not defined
59 or zero, the corresponding start-up action will not
62 #define REG_INIT 10 /* REG power on delay */
63 #define REG_DISCARD 1024 /* Bytes to discard at start-up */
65 static int32 oldbits[MAXDEV], bitsleft[MAXDEV];
68 static FILE *dumpfile; /* REG dump file handle */
69 static unsigned char dumpbuf[1024]; /* REG dump buffer */
70 static int dumpptr = 0; /* Pointer into dump buffer */
74 extern int flush_fd; /* File descriptor for auto-flush */
77 static int32 OpenDev(DevOpts *opts) {
84 dumpfile = fopen("dumpreg.dat", "w");
85 setbuf(dumpfile, NULL);
90 /* Serial ports (at least built-in ones) have names of
91 /dev/term/a, /dev/term/b, etc. Map the port numbers
92 from the RC file into this nomenclature, with "1"
93 designating /dev/term/a. */
95 sprintf(ttydev, "/dev/ttyd%d", opts->port);
97 sprintf(ttydev, "/dev/term/%c", 'a' + (opts->port - 1));
100 sprintf(ttydev, "/dev/ttyS%d", opts->port);
104 case 1200: baudcon = B1200; break;
105 case 2400: baudcon = B2400; break;
106 case 4800: baudcon = B4800; break;
107 case 9600: baudcon = B9600; break;
108 case 19200: baudcon = B19200; break;
109 case 38400: baudcon = B38400; break;
111 case 115200: baudcon = B115200; break;
114 printf("%s: Baud rate %ld not supported.\n", pgmname, opts->baud);
118 fprintf(stderr, "Opening %s at %ld\n", ttydev, opts->baud);
119 if ((TTY_fd = open(ttydev, O_RDONLY
125 fprintf(stderr, "Error in open(%s)\n", ttydev);
129 if (TTY_fd >= MAXDEV) {
130 fprintf(stderr, "%s: Too many devices open.\n", pgmname);
135 res = tcgetattr(TTY_fd, &tt);
140 tt.c_cflag = baudcon | CS8 | CLOCAL;
142 tt.c_cflag = baudcon | CS8 | CREAD | CLOCAL;
145 tt.c_cc[VMIN] = 1; /* This many chars satisfies reads */
146 tt.c_cc[VTIME] = 0; /* or in this many tenths of seconds */
148 res = cfsetospeed(&tt, baudcon);
150 tt.c_oflag &= (~(TABDLY | ONLCR));
152 res = tcsetattr(TTY_fd, TCSANOW, &tt);
154 oldbits[TTY_fd] = bitsleft[TTY_fd] = 0;
156 /* Perform start-up power on delay and data flush. */
165 if (REG_DISCARD > 0) {
169 for (d = 0; d < REG_DISCARD; d++) {
171 n1 = read(TTY_fd, &c1, 1);
172 } while (n1 == 0 || (n1 == -1 && errno == EAGAIN));
184 static int32 Sample(int32 dd, uint16 bits) {
194 tcsetattr(dd, TCSANOW, &tt);
198 if (dd < 0) return -1;
203 sum += (oldbits[dd] & 0x01);
209 n1 = read(dd, &c1, 1);
210 } while (n1 == 0 || (n1 == -1 && errno == EAGAIN));
212 /* Fatal error occurred, die now? */
216 /* Orion REG does not compensate for first order bias. XOR
217 each sample with 01010101b to invert the sense of
218 alternate bits in the samples. */
222 dumpbuf[dumpptr++] = c1;
223 if (dumpptr >= sizeof(dumpbuf)) {
224 fwrite(dumpbuf, sizeof(dumpbuf), 1, dumpfile);
236 tt.c_cflag &= ~CREAD;
237 tcsetattr(dd, TCSANOW, &tt);
243 #define SAMP_PERIOD 1000 /* msec */
244 #define MARGIN .95 /* how much to headroom to allow in
247 static int32 EvalSpeed(int32 dd) {
248 struct timeval start, end;
251 if (dd < 0) return -1;
253 gettimeofday(&start, NULL);
256 gettimeofday(&end, NULL);
257 if (deltams(&end, &start) >= SAMP_PERIOD) break;
258 samp = Sample(dd, 1);
262 return (int32)(bitct * MARGIN);
265 static int32 Discard(int32 dd) {
272 if (dd < 0) return -1;
279 n1 = read(dd, &c1, 1);
283 tcflush(dd, TCIFLUSH);
289 static int32 CloseDev(int32 dd) {
290 if (dd < 0) return -1;
296 /* Driver description table. */
298 REG_driver REG_orion = {