ts-7000
[Top] [All Lists]

[ts-7000] TIOCMIWAIT Test Program (Was: Re: GPSD with PPS on COM1 DCD)

To:
Subject: [ts-7000] TIOCMIWAIT Test Program (Was: Re: GPSD with PPS on COM1 DCD)
From: "jywmpg" <>
Date: Sat, 18 Aug 2007 17:17:28 -0000
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/
 

<Prev in Thread] Current Thread [Next in Thread>
  • [ts-7000] TIOCMIWAIT Test Program (Was: Re: GPSD with PPS on COM1 DCD), jywmpg <=
Admin

Disclaimer: Neither Andrew Taylor nor the University of NSW School of Computer and Engineering take any responsibility for the contents of this archive. It is purely a compilation of material sent by many people to the birding-aus mailing list. It has not been checked for accuracy nor its content verified in any way. If you wish to get material removed from the archive or have other queries about the archive e-mail Andrew Taylor at this address: andrewt@cse.unsw.EDU.AU