How to get precise interrupt timing? (reading RC PPM signal)

How to get precise interrupt timing? (reading RC PPM signal)

Post by Itai Nahsho » Tue, 13 Aug 1996 04:00:00



I try to write a device driver that will get the PPM signal
from a Radio Control transmitter and return the joystick
positions. I use the trainer cord output from a transmitter
connected to the ACK signal on a parallel port.
If you heard of jrcsim, I try to use the same type of connection.

The signal to the port is:
1. A start pulse.
2. N pulses for N channels. The delay between pulses
   is 1-2 ms, relative to stick position.
3. Long delay to the begining of the next start pulse.
   A new frame starts in every 20 msec, so this delay if we have
   4 channels is about 12-16 msec.

It is important to accurately time the delay between pulses.
The thing which I have working is using interrupt on the
port. In each interrupt read the time (do_gettimeval) and
subtract it from the last time. The driver returns 4 values
in the range of 1000-2000 (time in usec for 4 channels) as
well as other junk which I needed for debugging.

The problem is that I cannot get precise timing. I tried to
interface this driver with a flight simulator and that thing
has too much jitter. I guess that rather than using interrupts
I could use polling (like the joystick driver) but that means
hogging the CPU for average of 30% of the time.

I thought I could try to put the driver in tight loop only
for the predicted time that I need it (assuming that
the controls are moved slowly I can predict the timing of the
next pulse and allow a small mitake (start polling earlier).
If I do not allow enough mistake the original interrupt handler
can take over and give the base for the measurement in the
next frame. It will still give a monotonic movement and
stabilize when the sticks are not moved.

I tried to look at the "timer" code but it does not
have enough resulution. I need a source for a timer interrupt
which can be programmed in the up to 10ms range and has
a resolution of about 10usec or better.

Is there a "free" system timer that can do that?
Which interrupt can I use with it?
Where can I find programming info (eihter free or is anyone can
recommend a good book).

The other approach may be to build a special hardware to time
these events. It would be much easier, I know. I would like
to explore the software approch first.


also to this newsgroup.

Itai
--

 
 
 

How to get precise interrupt timing? (reading RC PPM signal)

Post by Theodore Y. Ts' » Tue, 13 Aug 1996 04:00:00



   Date: Mon, 12 Aug 1996 01:42:32 -0700

   I try to write a device driver that will get the PPM signal
   It is important to accurately time the delay between pulses.
   The thing which I have working is using interrupt on the
   port. In each interrupt read the time (do_gettimeval) and
   subtract it from the last time. The driver returns 4 values
   in the range of 1000-2000 (time in usec for 4 channels) as
   well as other junk which I needed for debugging.

Have you looked at the code for do_gettimeofday?  It is actually quite
accurate, as it at the RTC timer or the pentium clock register to adjust
the usec field.  Note that if you can count on using a pentium, using
the cycle counter is the quikest way to time the pulses.

                                                - Ted

 
 
 

How to get precise interrupt timing? (reading RC PPM signal)

Post by Itai Nahsho » Tue, 13 Aug 1996 04:00:00




>    Date: Mon, 12 Aug 1996 01:42:32 -0700

>    I try to write a device driver that will get the PPM signal
>    It is important to accurately time the delay between pulses.
>    The thing which I have working is using interrupt on the
>    port. In each interrupt read the time (do_gettimeval) and
>    subtract it from the last time. The driver returns 4 values
>    in the range of 1000-2000 (time in usec for 4 channels) as
>    well as other junk which I needed for debugging.

> Have you looked at the code for do_gettimeofday?  It is actually quite
> accurate, as it at the RTC timer or the pentium clock register to adjust
> the usec field.  Note that if you can count on using a pentium, using
> the cycle counter is the quikest way to time the pulses.

>                                                 - Ted

I tried to look at it but it would be much easier if I learn
more about the hardware architecture. In the second part of my
posting I asked for recommendations for a good book on this
subject (off course, online free documentation of PC hardware
is more than welcome).

However getting the time by calling do_gettimeval is probably
not the problem. The problem (as I see it) is inconsistent
response time to interrupts. I would like to try polling
(with interrupts disabled). In pure polling I will lose
too much CPU cycles. I want to set a timer interrupt handler
that will start short time before the expected input pulse and
poll the input signal. The "real" signal will be polled
in a small time "window" when I expect it.  If I lose it I
will use the existing interrupt handler and fix the table
by which I calculate the time of the next timer interrupt.

I estimate that a 100 usec polling window (5 times in 20 msec)
can give me good results and also let the CPU do real work for
most of the time.

If I were to build special hardware for the job it would be
a 16 bit counter, free running at 2 MHZ and a latch. At
the pulse the count is held and the PC interrupted to read
the value. (yes - It works great with a 68HC11). The point is
that (like any EE graduate?) I want to do it in software
(or in fact use existing standard PC hardware).

Itai
--

 
 
 

How to get precise interrupt timing? (reading RC PPM signal)

Post by Ingo Moln » Wed, 14 Aug 1996 04:00:00


: However getting the time by calling do_gettimeval is probably
: not the problem. The problem (as I see it) is inconsistent
: response time to interrupts. I would like to try polling
: (with interrupts disabled). In pure polling I will lose
: too much CPU cycles. I want to set a timer interrupt handler
: that will start short time before the expected input pulse and
: poll the input signal. The "real" signal will be polled
: in a small time "window" when I expect it.  If I lose it I
: will use the existing interrupt handler and fix the table
: by which I calculate the time of the next timer interrupt.
:
: I estimate that a 100 usec polling window (5 times in 20 msec)
: can give me good results and also let the CPU do real work for
: most of the time.

Timer interrupts happen only every 10 msecs. I presume that you need
better accuracy than this. So you wont have 'high precision timer
interrupts', with the current kernel timers.

Maybe it's a good idea to check out the RTC device, you can
program it to up to 8192 Hz interrupts, thus you can do 500 usec
timings with no problem. (the concept is still polling, but in
a more moderate manner). This is a user-space solution.

: If I were to build special hardware for the job it would be
: a 16 bit counter, free running at 2 MHZ and a latch. At
: the pulse the count is held and the PC interrupted to read
: the value. (yes - It works great with a 68HC11). The point is
: that (like any EE graduate?) I want to do it in software
: (or in fact use existing standard PC hardware).

The main problem that the PC timer is not extended towards high
precision sofware timers, yet. There are lots of problems even
with the current (simple) usage of the PC timer: lost timer
ticks are hard to detect, you need ISA cycles to set the registers
up -> quite of an overhead, and other problems. IMHO, it's not
robust enough.

The Pentium has it's own 32 bit, high precision hardware timers,
which are worth checking out IMHO. They generate mega-fast IPI
interrupts i think, but i havent seen any code using them, yet.

-- mingo

 
 
 

1. : Getting signal value from interrupted (slow) system call

Does POSIX generally, and Linux specifically specify how a process can obtain
the value of a signal delivered while blocked in a slow system call? For
example, suppose a process, blocked in select(), sustains a SIGINT.  Assuming
SA_RESART is not set, how can the process detect that it returned from the
select() because SIGINT was delivered and not, say, SIGTERM?

        while( select(...) < 0 )
        {
                if( errno == EINTR )
                {
                        ??? Do something to determine what signal interrupted
                        ??? the system call.

                        if( time remains )
                                continue;
                }

                -- Handle other error conditions --
        }

One thought that occurred to me was that the interrupting signal might have
been put in the set of the processes pending signals.

/mtp
--
   +-----------------------------------------------------------------------+
   |   Michael T. Peterson     |         For latest PD DCE Info see        |

   +-----------------------------------------------------------------------+

2. mklinux installation w/ 3rd party SCSI card

3. Alarm signal doesn't interrupt read() on SunOS

4. NLS : where ?

5. SA_RESTART signal handler, but read() still interrupted

6. $$ EASY AND LEGAL $$

7. Floating-Point signal handler: imprecise vs. precise

8. [PATCH] linux-2.4.20-pre5_bad-tsc_A0

9. Getting accurate timing via interrupt?

10. Ethernet interrupts getting processed as timer interrupts

11. if your GCC (or binutils) gets signal 11, READ THIS!

12. precise timing

13. Precise time on SYSVR4