-
Couldn't load subscription status.
- Fork 606
Tca955x - Fixed bug with interrupt state monitoring #2427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,8 +20,8 @@ public abstract class Tca955x : GpioDriver | |||||
| private readonly int _interrupt; | ||||||
| private readonly Dictionary<int, PinValue> _pinValues = new Dictionary<int, PinValue>(); | ||||||
| private readonly ConcurrentDictionary<int, PinChangeEventHandler> _eventHandlers = new ConcurrentDictionary<int, PinChangeEventHandler>(); | ||||||
| private readonly Dictionary<int, PinEventTypes> _interruptPins = new Dictionary<int, PinEventTypes>(); | ||||||
| private Dictionary<int, PinValue> _interruptLastInputValues = new Dictionary<int, PinValue>(); | ||||||
| private readonly Dictionary<int, PinEventTypes> _interruptPinsSubscribedEvents = new Dictionary<int, PinEventTypes>(); | ||||||
| private readonly ConcurrentDictionary<int, PinValue> _interruptLastInputValues = new ConcurrentDictionary<int, PinValue>(); | ||||||
|
|
||||||
| private GpioController? _controller; | ||||||
|
|
||||||
|
|
@@ -89,7 +89,15 @@ protected Tca955x(I2cDevice device, int interrupt = -1, GpioController? gpioCont | |||||
| } | ||||||
|
|
||||||
| if (_interrupt != -1) | ||||||
| { | ||||||
| { | ||||||
| // Initialise the interrupt handling state because ints may start coming from the INT pin | ||||||
| // on the expander as soon as we register the interrupt handler. | ||||||
| for (int i = 0; i < PinCount; i++) | ||||||
| { | ||||||
| _interruptPinsSubscribedEvents.Add(i, PinEventTypes.None); | ||||||
| _interruptLastInputValues.TryAdd(i, PinValue.Low); | ||||||
| } | ||||||
|
|
||||||
| _shouldDispose = shouldDispose || gpioController is null; | ||||||
| _controller = gpioController ?? new GpioController(); | ||||||
| if (!_controller.IsPinOpen(_interrupt)) | ||||||
|
|
@@ -456,7 +464,7 @@ private Task ProcessInterruptInTask() | |||||
| { | ||||||
| // Take a snapshot of the current interrupt pin configuration and last known input values | ||||||
| // so we can safely process them outside the lock in a background task. | ||||||
| var interruptPinsSnapshot = new Dictionary<int, PinEventTypes>(_interruptPins); | ||||||
| var interruptPinsSnapshot = new Dictionary<int, PinEventTypes>(_interruptPinsSubscribedEvents); | ||||||
| var interruptLastInputValuesSnapshot = new Dictionary<int, PinValue>(_interruptLastInputValues); | ||||||
|
|
||||||
| Task processingTask = new Task(() => | ||||||
|
|
@@ -494,9 +502,9 @@ private Task ProcessInterruptInTask() | |||||
| interruptLastInputValuesSnapshot[pin] = newValue; | ||||||
| } | ||||||
|
|
||||||
| lock (_interruptHandlerLock) | ||||||
| { | ||||||
| _interruptLastInputValues = interruptLastInputValuesSnapshot; | ||||||
| foreach (var pin in interruptLastInputValuesSnapshot.Keys) | ||||||
| { | ||||||
| _interruptLastInputValues.TryUpdate(pin, interruptLastInputValuesSnapshot[pin], !interruptLastInputValuesSnapshot[pin]); | ||||||
| } | ||||||
| } | ||||||
| }); | ||||||
|
|
@@ -557,16 +565,13 @@ protected override void AddCallbackForPinValueChangedEvent(int pinNumber, PinEve | |||||
|
|
||||||
| lock (_interruptHandlerLock) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why you prefer the lock instead of the ConcurrentDictionary for this as well? |
||||||
| { | ||||||
| if (_interruptPins.ContainsKey(pinNumber)) | ||||||
| { | ||||||
| throw new InvalidOperationException($"A callback is already registered for pin {pinNumber}"); | ||||||
| } | ||||||
| else | ||||||
| _interruptPinsSubscribedEvents[pinNumber] = eventType; | ||||||
| var currentValue = Read(pinNumber); | ||||||
| _interruptLastInputValues.TryUpdate(pinNumber, currentValue, !currentValue); | ||||||
|
||||||
| _interruptLastInputValues.TryUpdate(pinNumber, currentValue, !currentValue); | |
| _interruptLastInputValues.TryUpdate(pinNumber, currentValue, currentValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TryUpdate call uses
!interruptLastInputValuesSnapshot[pin]as the comparison value, which appears incorrect. TryUpdate expects the current value to compare against, not the inverse of the new value. This should likely be the actual current value from the ConcurrentDictionary or use TryAdd/AddOrUpdate instead.