« Close

Datasheets and User Guides

App Notes

Software & Driver

 

13.1.10 Interrupt Counter with Debounce

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)

Requires Clock Source: No

Index: 9

Streamable: Yes—integer READ registers only.

Interrupt Counter with Debounce will increment its count by 1 when it receives a rising edge, a falling edge, or any edge (2x counting).  After seeing an applicable edge, any further edges will be ignored during the debounce time.

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.

Debounce Modes (DIO#_EF_CONFIG_B)

The exact behavior of the counting/debouncing is controlled by an index value written to DIO#_EF_CONFIG_B.

  • 0:  Count falling, debounce all, self-restarting timeout.
  • 1:  Count rising, debounce all, self-restarting timeout.
  • 2:  Count & debounce all, self-restarting timeout.
  • 3:  Count & debounce falling, fixed timeout.
  • 4:  Count & debounce rising, fixed timeout.
  • 5:  Timeout starts on falling edge.  During timeout, a rising edge cancels and a falling edge restarts the timeout.  After timeout any edge causes a count.
  • 6:  Timeout starts on rising edge.  During timeout, a falling edge cancels and a rising edge restarts the timeout.  After timeout any edge causes a count.

Self-restarting timeout means that during timeout any edge will restart the timeout with the value specified with DIO#_EF_CONFIG_A.

Mode 0 is commonly used with a normally-open push-button switch that is actuated by a person.  We only want to count the push (falling edge), but expect bounce on the push & release (falling & rising edges) so need to debounce both.

Mode 4 might be used with some sort of device that outputs a fixed length positive pulse.  For example, say a device provides a 1000 µs pulse, and there is always at least 5000 µs between pulses.  Set the debounce timeout to 2000 µs so that the timeout period safely covers the entire pulse, but the timeout will for sure be done before another pulse can occur.

Modes 5 & 6 implement a requirement that the state of the line must remain low or high for some amount of time.  For example, if you use mode 5 with a push-button switch and set DIO#_EF_CONFIG_A = 50000, that means that someone must push the switch and hold it down solidly for at least 50ms, and then the count will occur when they release the switch.  An advantage to these modes is that they will ignore brief transient signals.

Configure

DIO#_EF_ENABLE: 0 = Disable, 1 = Enable
DIO#_EF_INDEX: 9
DIO#_EF_OPTIONS: Not used.
DIO#_EF_CONFIG_A: Debounce timeout in microseconds (µs, 0-1000000).
DIO#_EF_CONFIG_B: Debounce mode index. 
DIO#_EF_CONFIG_B: Not used.
DIO#_EF_CONFIG_B: Not used.

Update

No update operations can be performed on Interrupt Counter with Debounce.

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.

Example

Enable a debounce counter on DIO0:

DIO0_EF_ENABLE = 0
DIO0_EF_INDEX = 9
DIO0_EF_CONFIG_A = 20000   // 20 ms debounce time
DIO0_EF_CONFIG_B = 0       // count falling, debounce all, self-restarting timeout
DIO0_EF_ENABLE = 1

Results can be read from the READ registers defined above. 

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.

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.

 

1 comments

Hello !

I need to execute an ISR routine on a FIO rising edge, Do you have an example ??

Where can I link the routine adress ??

Thank you.