13.2.9 Interrupt Counter [T-Series Datasheet]
Overview
T4 Capable DIO: DIO4, DIO5, DIO6, DIO7, DIO8, DIO9 (aka FIO4, FIO5, FIO6, FIO7, EIO0, EIO1)
T7 Capable DIO: DIO0, DIO1, DIO2, DIO3, DIO6, DIO7 (aka FIO0, FIO1, FIO2, FIO3, FIO6, FIO7)
T8 Capable DIO: DIO0, DIO1, DIO2, DIO3, DIO4, DIO5, DIO6, DIO7, DIO8, DIO9, DIO10, DIO11, DIO12, DIO13, DIO14, DIO15 (aka FIO0, FIO1, FIO2, FIO3, FIO4, FIO5, FIO6, FIO7, EIO0, EIO1, EIO2, EIO3, EIO4, EIO5, EIO6, EIO7)
Requires Clock Source: No
Index: 8
Streamable: Yes—integer READ registers only.
Interrupt Counter counts the rising edge of pulses on the associated IO line. This interrupt-based digital I/O extended feature (DIO-EF) is not purely implemented in hardware, but rather firmware must service each edge. See the discussion of edge rate limits at the bottom of this page.
Configure
DIO#_EF_ENABLE: 0 = Disable, 1 = Enable
DIO#_EF_INDEX: 8
DIO#_EF_CLOCK_SOURCE: Not used.
DIO#_EF_CONFIG_A: Not used.
DIO#_EF_CONFIG_B: Not used.
DIO#_EF_CONFIG_B: Not used.
DIO#_EF_CONFIG_B: Not used.
There are 3 basic techniques for device configuration:
1. Power-up defaults. Most registers related to I/O configuration are part of the IO Config system where their startup values can be defined by the user. This is easily done with the Power-up Defaults tab in Kipling.
2. Real time software configuration. Software can write any needed configuration values at the beginning of execution, but you might have to consider how to handle if the device later reboots during software execution. An advantage to this method is that a factory device will work out-of-the-box without requiring the user to first configure the device.
3. Startup script. A Lua script can be set to run at startup and can write any values to any registers.
Update
No update operations can be performed on Interrupt Counter.
Read
Results are read from the following register.
DIO#_EF_READ_A: Returns the current Count
Stream Read
All operations discussed in this section are supported in command-response mode. In stream mode, you can read from the integer READ registers (A, B, A_AND_RESET), but as mentioned in the Stream Section those reads only return the lower 16 bits so you need to also use STREAM_DATA_CAPTURE_16 in the scan list to get the upper 16 bits.
Reset
DIO#_EF_READ_A_AND_RESET: Reads the current count then clears the counter. Note that there is a brief period of time between reading and clearing during which edges can be missed. During normal operation this time period is 10-30 µs. If missed edges at this point can not be tolerated then reset should not be used.
Frequency Measurement
Counters are often used to measure frequency by taking change in count over change in time:
Frequency = (CurrentCount - PreviousCount) / (CurrentTimestamp - PreviousTimestamp)
Typically the timestamps are from the host clock (software), but for more accurate timestamps read the CORE_TIMER register in the same Modbus packet as the READ registers. See the System Timing Register section for more information about the CORE_TIMER.
Also note that other digital extended features are available to measure frequency by timing individual pulses rather than counting over time.
Example
Enable a counter on DIO0 (use DIO4 on the T4):
DIO0_EF_ENABLE = 0
DIO0_EF_INDEX = 8
DIO0_EF_ENABLE = 1
Use the Register Matrix in Kipling to write those 2 registers above, and also add DIO0_EF_READ_A so you see its value. Now take a wire connected to a GND terminal and tap that wire to the inside-back of the DIO0 screw-terminal (labeled "FIO0"). DIO0_EF_READ_A should increment by 1 or more counts each time you tap the ground wire in DIO0.
As another test you can set DAC1_FREQUENCY_OUT_ENABLE = 1 to enable the 10 Hz test signal (T7 requires firmware 1.0234+). Jumper DAC1 to DIO0 and you should see DIO0_EF_READ_A increment by about 10 counts per second.
For a more detailed walkthrough, see Configuring & Reading a Counter.
Edge Rate Limits
This interrupt-based digital I/O extended feature (DIO-EF) is not purely implemented in hardware, but rather firmware must service each edge. This makes it substantially slower than other DIO-EF that are purely hardware-based. To avoid missed edges, the aggregate limit for edges seen by all interrupt-based DIO-EF is 70k edges/second. If stream mode is active, the limit is reduced to 20k edges/second. Excessive processor loading (e.g. a busy Lua script) can also reduce these limits. Note that interrupt features must process all edges, rising & falling, even if a given feature is configured to only look at one or the other. Additionally, note that intensive interrupt based features may limit the maximum streaming rates due to processor loading.
The more proper way to think of the edge limit, and understand error that could be introduced when using multiple interrupt-based DIO-EF, is to consider that the interrupt that processes an edge can take up to 14 μs to complete. When a particular channel sees an applicable edge, an IF (interrupt flag) is set for that channel that tells the processor it needs to run an ISR (interrupt service routine) for that channel. Once an ISR is started, it runs to completion and no other ISR can run until it is done (except that stream interrupts are higher priority and will preempt other interrupts). When an ISR completes, it clears the IF for that channel. So it is okay to have edges on multiple channels at the same time, as long as there is not another edge on any of those channels before enough time to process all the initial edges.
Say that channel A & B have an edge occur at the same time and an ISR starts to process the edge on channel A. If channel A has another edge during the first 14 μs, that edge will be lost. If channel B has another edge during the first 14 μs, the initial edge will be lost. If channel B has another edge during the second 14 μs (during the ISR for channel B), the new edge will be lost.