Design of instructions for Counter/Timer subdevices...

We are working on a device driver to integrate the NI 6602
counter/timer card into Comedi.
Our priority is to use the card as an encoder, but we also
want to do the effort to use a "correct" interface which is more general
than just encoders. So, below are my suggestions for integrating
General Purpose Counter/Timer (GPCT) cards into the _EXISTING_
instruction/command infrastructure.  

Herman Bruyninckx

==================================
David has written a design document in
  Documentation/comedi/counter-spec
which calls for an new data structure. In fact, I am in favor of such
a change because it is a much "cleaner" solution, but it's up to David
to decide which way to follow: a new GPCT data structure, or new
INSN_CONFIG flags and arguments. Anyway, I attach some comments on
that counter-spec document at the end of this message.

There exists already one driver that has a GPCT subdevice: the
ni_mio_common.c (Other drivers have defined a COMEDI_SUBD_COUNTER
subdevice, but do not really implement much functionality...)
The counter subdevice of the ni_mio_common doesn't have all the GPCT
functionalities that the 6602 has, _and_ it doesn't follow the clean
and generic Comedi approach of instruction/command, so it has
some superfluous things:
- GPCT_RESET
  What is the generic meaning of a reset???? I think this should not
  be a Comedi function.
- this driver has a configuration flag for outputting one single pulse
  (GPCT_SINGLE_PULSE_OUT), and another one for a continuous stream of
  pulses (GPCT_CONT_PULSE_OUT). I think this distinction is not
  appropriate in Comedi, because Comedi already has "instructions"
  (single execution) and "commands" (continuous execution).

My suggestion below consists of:
- reusing what is already there from the ni_mio_common.c driver,
- extending it with some more GPCT functionality, and
- incorporating all functionality in the instruction/command model of
  Comedi.
The result does probably not cover all possible counter card
functionalities...

The full documentation of a COMEDI_SUBD_COUNTER is as follows. I use
the name "counter" both for input GPCT (counter) as output GPCT
(timer).

1. General operations:
- comedi_data_read: read current value of the counter.
- comedi_data_read_n: read n times the counter value.
- comedi_data_read_delayed: read the counter value after a delay of a
    given number of nanoseconds.
- comedi_data_write: fill in a given value ("latch" value in counter)
    (this function will have no effect in some counter configurations)
- insn_read: read current value of the counter
- insn_write: fill in given value ("latch" value in counter)
- insn_bits: not applicable
- insn_config: see next paragraph

2. Configuration
The "insn" flag of the instruction data structure is INSN_CONFIG;
the "data" field contains the configuration arguments.

- Pulse counter (alias: "event counter")

  Configuration arguments:
  - data[0]: indicates which signal serves as the pulse train
  - data[1]: GPCT_UP (counter counts up at each pulse), GPCT_DOWN
  - data[2]: indicate the GATE source, i.e., the counter only counts
             when the signal on the GATE source is high.
  - data[3]: specification of which edge of the pulse triggers the
             counter (still to be defined how this is encoded).
  - data[4]: delay in nanoseconds before counter starts counting

  Constraints:
  - channel has type SDF_READABLE

  Notes:
  - the "signal" above is NOT a Comedi channel, but a hardware signal
    on the interface card. These numbers will be card-specific.

- Pulse generator

  Configuration arguments:
  - data[0]: indicates which signal serves as the pulse train
  - data[1]: pulse shape = time during which pulse is high
  - data[2]: delay in nanoseconds before pulse is generated
  - data[3]: indicate the GATE source, i.e., the counter only
             generates pulses when the signal on the GATE source is
             high.

  Constraints:
  - channel has type SDF_WRITEABLE

  Notes:
  - the configuration of the frequency of a continous pulse train
    should be programmed by means of a Comedi command

- Pulse width counter
  (counter counts the number of internal clock ticks that a pulse is high)

  Configuration arguments:
  - data[0]: indicates which signal serves as the clock
  - data[1]: indicates which signal serves as the pulse train
  - data[2]: delay in nanoseconds before counter starts
  - data[3]: indicate the GATE source, i.e., the counter only
	     counts the clock pulses when the signal on the GATE
             source is high.

    Constraints:
    - channel has type SDF_READABLE?

- Frequency/Period counter
  (counter returns the number of clock ticks between two same
   edges of a pulse train)

  Configuration arguments:
  - data[0]: indicates which signal serves as the clock
  - data[1]: indicates which signal serves as the pulse train
  - data[2]: delay in nanoseconds before counter starts
  - data[3]: indicate the GATE source, i.e., the counter only
             counts the clocj pulses when the signal on the GATE source 
             is high.

- Two-signal separation counter
  (counts the number of clock ticks between the active edges on two
   signals)

  Configuration arguments:
  - data[0]: indicates which signal serves as the clock
  - data[1]: indicates which signal serves as the first signal
  - data[2]: indicates which signal serves as the second signal
  - data[3]: indicates what is active edge: RISING_EDGE or FALLING_EDGE
  - data[4]: delay in nanoseconds before counter starts
  - data[5]: indicate the GATE source, i.e., the counter only
             generates pulses when the signal on the GATE source is
             high.

- Incremental ("AB") encoder

  Configuration arguments:
  - data[0]:
    GPCT_X1: count on one of the four edges in the A or B pulse trains
             (which edge is taken is device dependent)
    GPCT_X2: count on two of the edges
    GPCT_X4: count on all four edges
  - data[1]: delay in nanoseconds before counter starts

- Two-pulse encoder
  (the counter counts up when a pulse on signal "A" is received, and
   down when a pulse on signal "B" is received)

  Configuration arguments:
  - data[0]: indicates which signal serves as the A signal
  - data[1]: indicates which signal serves as the B signal
  - data[2]: indicates what is active edge: RISING_EDGE or FALLING_EDGE
  - data[3]: delay in nanoseconds before counter starts
  - data[4]: indicate the GATE source, i.e., the counter only
             counts pulses when the signal on the GATE source is
             high.

- Arm/disarm
  (only an armed counter counts/generates pulses)

  Configuration arguments:
  - data[0]: GPCT_ARM, GPCT_DISARM
  - data[1]: delay in nanoseconds before action is performed

  Constraints:
  - delay > 0
  - counter must already have been configured as a counter

  Notes:
  - Arm/Disarm is a _software_ enabling/disabling. It's complementary
    to the _hardware_ enabling/disabling done through the GATE
    signals.

Comments on the counter-spec document:
- the "Interval timing" example uses "event_src", "event_arg" and
  "flags" fields that are not part of the data structure given in the
  beginning of the document.
- quadrature encoding needs X1, X2 and X3 flags. Or can this be
  specified with an OR of FALLING_EDGE and RISING_EDGE on the src_arg
  field?
- this design introduces a new data structure, but doesn't this impose
  the need to extend the instruction/command API to include a counter
  data structure argument?
- the second half of the document (about the "000->010" like
  transitions) is not too clear :-)

Received on 2003-04-11Z07:36:59