All,
I am having trouble getting the TIOCMIWAIT command to work properly on
the console port (/dev/ttyAM0) of my TS-7260. I have a Garmin GPS
18LVC that is wired to provide a 100 millisecond pulse at 1 Hz to the
DCD pin of COM1.
Jumpers JP2 and JP4 are in place so that console output is directed to
COM2 and does not effect this test. In addition, ttyAM0 has been
removed from /etc/inittab, and the machine rebooted.
The TIOCMIWAIT call in question should complete every time there is a
transition on the DCD line, but unfortunately this routine never completes
Attached is a test program that demonstrates the problem. It has
three modes of operation:
0. Dumps out all received serial data. This works and produces the
NMEA sentences generated by the Garmin
1. Waits for TIOCMIWAIT to complete to indicate a transition on the
DCD line. This mode fails because the call does not complete, even
though TIOCMGET (below) reports DCD transitions.
2. Polls the DCD state via TIOCMGET, looking for transitions on the
DCD line. This mode works and reports one length of the second
derived from successive transitions.
Here is the test program, followed by some sample outputs for each mode.
Can anyone see a problem in mode 1 that prevents TIOCMIWAIT from
completing?
Many Thanks,
jw
#include <termios.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
/*
Test to see if TIOCMIWAIT can be made to work
*/
int main(int argc, char **argv) {
int fd;
struct termios newtio;
unsigned char rx[132];
char * ourDev="/dev/ttyAM0";
// try to open the serial port
fd = open(ourDev, O_RDWR | O_NOCTTY | O_NDELAY);
// how'd that go?
if (fd < 0) {
// not so good
perror("Unable to open device /dev/ttyAM0\n");
return 1;
}
fprintf(stderr, "Successfully opened serial device %s\n", ourDev);
/* initialize the serial port */
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = B9600 | CS8 | CREAD | CRTSCTS;
tcflush(fd, TCIOFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
// Figure out which mode we are operating in, based on the command
line argument
//
// Operating Modes:
// mode = 0 - Dump out serial data from port
// mode = 1 - Use TIOCMIWAIT to detect changes on the DCD line -
Currently Fails
// mode = 2 - Use TIOCMGET to detect changes on the DCD line via polling
// Figure out which mode we are in
int mode = 0;
if (argc > 1) mode = atoi(argv[1]);
// Select operation based on mode
switch (mode) {
case 0:
// just dump out any characters arriving on the serial port
fprintf(stderr, "Testing Serial Interface. Dumping data from
%s\n", ourDev);
int readCnt;
while (1) {
while (read(fd, rx, 132) > 0) {
rx[131] = 0;
fprintf(stderr, "%s", rx);
}
sleep(1);
}
break;
case 1:
// wait for DCD transition to be reported via interrupt - fails
fprintf(stderr, "Testing TIOCMIWAIT. Waiting for DCD on %s\n",
ourDev);
while (ioctl(fd, TIOCMIWAIT, TIOCM_CAR) == 0) {
// Problem: The following lines is never executed
fprintf(stderr, "DCD Transition on %s\n", ourDev);
}
fprintf(stderr, "TIOCMIWAIT returns non zero value on %s!\n", ourDev);
break;
case 2:
// poll the DCD line looking for transition; When found, report time
// and various intervals between successive transitions.
fprintf(stderr, "Testing TIOCMGET. Polling DCD on %s\n", ourDev);
struct timeval tv_jw;
int state, lastState;
// get the current state of the DCD line
if (ioctl(fd, TIOCMGET, &lastState) != 0) {
fprintf(stderr, "TIOCMGET fails on %s\n", ourDev);
exit(1);
}
// turn laststate into a boolean indicating presence or absence of DCD
lastState = (int)((lastState & TIOCM_CAR) != 0);
double lastTime = 0;
// for computing average length of a second, as derived from the
// rising edge of the DCD pulse
double total = 0;
int samples = 0;
// loop forever
while (1) {
// get the value of the serial lines
if (ioctl(fd, TIOCMGET, &state) != 0) {
// abort on error
fprintf(stderr, "TIOCMGET fails on %s\n", ourDev);
exit(1);
}
// recover DCD state
state = (int)((state & TIOCM_CAR) != 0);
// Transition?
if (state != lastState) {
// yes. Update the last state
lastState = state;
// Is this a leading (rising) edge?
if (state == 1) {
// yes. let's call this the top of the second
// note the system time
(void)gettimeofday(&tv_jw,NULL);
// turn it into a double
double curTime = tv_jw.tv_sec + tv_jw.tv_usec/1.0e6;
// how long since the last transition?
double diff = curTime - lastTime;
// Update time of 'last' DCD state transition
lastTime = curTime;
// diff should be (really close to) one second
// is diff within reason? (Sometimes transitions appear to be missed)
if (diff < 1.5) {
// update for averaging
total += diff;
samples++;
// report on the times associated with this transition
fprintf(stderr, "DCD transition on %s: %d: %.6f, %6f, %6f\n",
ourDev, state, curTime, diff, total/samples);
}
else {
fprintf(stderr, "DCD transition on %s: %d: %.6f, %6f - wacky
diff\n",
ourDev, state, curTime, diff);
}
}
}
// now sleep for a (very) little while
tv_jw.tv_sec = 0;
tv_jw.tv_usec = 1;
int retval_jw = select(1, NULL, NULL, NULL, &tv_jw);
}
break;
default:
fprintf(stderr, "Unknown mode\n");
}
close(fd);
return 0;
}
Here is some sample output:
Mode 0:
# dcdTest 0
Successfully opened serial device /dev/ttyAM0
Testing Serial Interface. Dumping data from /dev/ttyAM0
$GPRMC,170811,A,4650.0159,N,11400.7510,W,000.0,058.7,180807,015.5,E,A*07
$GPGGA,170811,4650.0159,N,11400.7510,W,1,07,1.7,991.7,M,-7.5,M,,*7A
$GPGSA,A,3,01,04,,,13,16,20,23,,31,,,3.2,1.7,2.7*31
$GPGSV,3,1,11,01,28,091,42,04,15,314,41,06,02,049,00,11,00,214,00*3
$GPGSV,3,2,11,13,28,289,38,16,44,123,52,20,68,220,34,23,56,299,34*74
Mode 1:
# dcdTest 1
Successfully opened serial device /dev/ttyAM0
Testing TIOCMIWAIT. Waiting for DCD on /dev/ttyAM0
<no further output received>
Mode 2:
# dcdTest 2
Successfully opened serial device /dev/ttyAM0
Testing TIOCMGET. Polling DCD on /dev/ttyAM0
DCD transition on /dev/ttyAM0: 1: 1187456948.364524, 1187456948.364524
- wacky diff
DCD transition on /dev/ttyAM0: 1: 1187456949.364630, 1.000106, 1.000106
DCD transition on /dev/ttyAM0: 1: 1187456950.364865, 1.000235, 1.000171
DCD transition on /dev/ttyAM0: 1: 1187456951.365101, 1.000236, 1.000192
DCD transition on /dev/ttyAM0: 1: 1187456952.365335, 1.000234, 1.000203
DCD transition on /dev/ttyAM0: 1: 1187456953.365572, 1.000237, 1.000210
DCD transition on /dev/ttyAM0: 1: 1187456954.365807, 1.000235, 1.000214
DCD transition on /dev/ttyAM0: 1: 1187456955.366041, 1.000234, 1.000217
DCD transition on /dev/ttyAM0: 1: 1187456956.366277, 1.000236, 1.000219
DCD transition on /dev/ttyAM0: 1: 1187456957.366530, 1.000253, 1.000223
DCD transition on /dev/ttyAM0: 1: 1187456958.366748, 1.000218, 1.000222
DCD transition on /dev/ttyAM0: 1: 1187456959.366982, 1.000234, 1.000223
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|