private void OnEventResult(ref PinEventConfiguration config)
        {
            if (config == null || !PinController.IsValidPin(config.GpioPin))
            {
                return;
            }

            if (config.Current.Equals(config.Previous))
            {
                return;
            }

            OnValueChangedEventArgs onValueChangedEventArgs = new OnValueChangedEventArgs(config.GpioPin, (CurrentValue)config.Current, (PreviousValue)config.Previous);

            switch (config.EventState)
            {
            case PinEventState.Activated when config.Current.DigitalValue:
                OnActivatedEventArgs onActivatedEventArgs = new OnActivatedEventArgs(config.GpioPin, (CurrentValue)config.Current);
                ParallelExecuteOnEach(config.EventState, (p) => p.OnActivated(this, onActivatedEventArgs)).RunSynchronously();
                break;

            case PinEventState.Deactivated when !config.Current.DigitalValue:
                OnDeactivatedEventArgs onDeactivatedEventArgs = new OnDeactivatedEventArgs(config.GpioPin, (CurrentValue)config.Current);
                ParallelExecuteOnEach(config.EventState, (p) => p.OnDeactivated(this, onDeactivatedEventArgs)).RunSynchronously();
                break;

            case PinEventState.Both:
                break;
            }

            ParallelExecuteOnEach(config.EventState, (p) => p.OnValueChanged(this, onValueChangedEventArgs)).RunSynchronously();
        }
        // Should be invoked on a different thread
        private void Generate(ref PinEventConfiguration config)
        {
            if (config == null || !PinController.IsValidPin(config.GpioPin))
            {
                return;
            }

            config.IsEventRegistered = true;

            do
            {
                Pin pinConfig = Driver.GetPinConfig(config.GpioPin);
                config.Current = new CurrentValue(pinConfig.PinState, pinConfig.IsPinOn, pinConfig.Mode, config.EventState);
                OnEventResult(ref config);
                Thread.Sleep(POLL_DELAY);
                config.Previous = config.Current;
            } while (!ShutdownEventGenerationToken.IsCancellationRequested || !config.EventToken.IsCancellationRequested);

            config.IsEventRegistered = false;
            Logger.Trace($"Polling for '{config.GpioPin}' has been stopped.");
        }
        internal void InitEventGeneration()
        {
            Core.Config.GpioConfiguration.InputModePins.ForEach((pin) => {
                Pin pinConfig                = Driver.GetPinConfig(pin);
                CurrentValue currentValue    = new CurrentValue(pinConfig.PinState, pinConfig.IsPinOn, pinConfig.Mode, PinEventState.Both);
                PreviousValue previousValue  = new PreviousValue(pinConfig.PinState, pinConfig.IsPinOn, pinConfig.Mode, PinEventState.Both);
                PinEventConfiguration config = new PinEventConfiguration(pin, PinEventState.Both, currentValue, previousValue, new CancellationTokenSource());
                Helpers.InBackgroundThread(() => Generate(ref config), longRunning: true);
                EventConfigurations.Add(config);
            });

            Core.Config.GpioConfiguration.OutputModePins.ForEach((pin) => {
                Pin pinConfig                = Driver.GetPinConfig(pin);
                CurrentValue currentValue    = new CurrentValue(pinConfig.PinState, pinConfig.IsPinOn, pinConfig.Mode, PinEventState.Both);
                PreviousValue previousValue  = new PreviousValue(pinConfig.PinState, pinConfig.IsPinOn, pinConfig.Mode, PinEventState.Both);
                PinEventConfiguration config = new PinEventConfiguration(pin, PinEventState.Both, currentValue, previousValue, new CancellationTokenSource());
                Helpers.InBackgroundThread(() => Generate(ref config), longRunning: true);
                EventConfigurations.Add(config);
            });

            Logger.Info($"'{EventConfigurations.Count}' pin configurations with events initiated.");
        }