@@ -20,8 +20,8 @@ public abstract class Tca955x : GpioDriver
2020 private readonly int _interrupt ;
2121 private readonly Dictionary < int , PinValue > _pinValues = new Dictionary < int , PinValue > ( ) ;
2222 private readonly ConcurrentDictionary < int , PinChangeEventHandler > _eventHandlers = new ConcurrentDictionary < int , PinChangeEventHandler > ( ) ;
23- private readonly Dictionary < int , PinEventTypes > _interruptPins = new Dictionary < int , PinEventTypes > ( ) ;
24- private Dictionary < int , PinValue > _interruptLastInputValues = new Dictionary < int , PinValue > ( ) ;
23+ private readonly Dictionary < int , PinEventTypes > _interruptPinsSubscribedEvents = new Dictionary < int , PinEventTypes > ( ) ;
24+ private readonly ConcurrentDictionary < int , PinValue > _interruptLastInputValues = new ConcurrentDictionary < int , PinValue > ( ) ;
2525
2626 private GpioController ? _controller ;
2727
@@ -89,7 +89,15 @@ protected Tca955x(I2cDevice device, int interrupt = -1, GpioController? gpioCont
8989 }
9090
9191 if ( _interrupt != - 1 )
92- {
92+ {
93+ // Initialise the interrupt handling state because ints may start coming from the INT pin
94+ // on the expander as soon as we register the interrupt handler.
95+ for ( int i = 0 ; i < PinCount ; i ++ )
96+ {
97+ _interruptPinsSubscribedEvents . Add ( i , PinEventTypes . None ) ;
98+ _interruptLastInputValues . TryAdd ( i , PinValue . Low ) ;
99+ }
100+
93101 _shouldDispose = shouldDispose || gpioController is null ;
94102 _controller = gpioController ?? new GpioController ( ) ;
95103 if ( ! _controller . IsPinOpen ( _interrupt ) )
@@ -456,7 +464,7 @@ private Task ProcessInterruptInTask()
456464 {
457465 // Take a snapshot of the current interrupt pin configuration and last known input values
458466 // so we can safely process them outside the lock in a background task.
459- var interruptPinsSnapshot = new Dictionary < int , PinEventTypes > ( _interruptPins ) ;
467+ var interruptPinsSnapshot = new Dictionary < int , PinEventTypes > ( _interruptPinsSubscribedEvents ) ;
460468 var interruptLastInputValuesSnapshot = new Dictionary < int , PinValue > ( _interruptLastInputValues ) ;
461469
462470 Task processingTask = new Task ( ( ) =>
@@ -494,9 +502,9 @@ private Task ProcessInterruptInTask()
494502 interruptLastInputValuesSnapshot [ pin ] = newValue ;
495503 }
496504
497- lock ( _interruptHandlerLock )
498- {
499- _interruptLastInputValues = interruptLastInputValuesSnapshot ;
505+ foreach ( var pin in interruptLastInputValuesSnapshot . Keys )
506+ {
507+ _interruptLastInputValues . TryUpdate ( pin , interruptLastInputValuesSnapshot [ pin ] , ! interruptLastInputValuesSnapshot [ pin ] ) ;
500508 }
501509 }
502510 } ) ;
@@ -557,16 +565,13 @@ protected override void AddCallbackForPinValueChangedEvent(int pinNumber, PinEve
557565
558566 lock ( _interruptHandlerLock )
559567 {
560- if ( _interruptPins . ContainsKey ( pinNumber ) )
561- {
562- throw new InvalidOperationException ( $ "A callback is already registered for pin { pinNumber } ") ;
563- }
564- else
568+ _interruptPinsSubscribedEvents [ pinNumber ] = eventType ;
569+ var currentValue = Read ( pinNumber ) ;
570+ _interruptLastInputValues . TryUpdate ( pinNumber , currentValue , ! currentValue ) ;
571+ if ( ! _eventHandlers . TryAdd ( pinNumber , callback ) )
565572 {
566- _interruptPins . Add ( pinNumber , eventType ) ;
567- _interruptLastInputValues . Add ( pinNumber , Read ( pinNumber ) ) ;
568- _eventHandlers [ pinNumber ] = callback ;
569- }
573+ throw new InvalidOperationException ( $ "An event handler is already registered for pin { pinNumber } ") ;
574+ }
570575 }
571576 }
572577
@@ -575,11 +580,8 @@ protected override void RemoveCallbackForPinValueChangedEvent(int pinNumber, Pin
575580 {
576581 lock ( _interruptHandlerLock )
577582 {
578- if ( _eventHandlers . TryRemove ( pinNumber , out _ ) )
579- {
580- _interruptPins . Remove ( pinNumber ) ;
581- _interruptLastInputValues . Remove ( pinNumber ) ;
582- }
583+ _eventHandlers . TryRemove ( pinNumber , out _ ) ;
584+ _interruptPinsSubscribedEvents [ pinNumber ] = PinEventTypes . None ;
583585 }
584586 }
585587
0 commit comments