Interrupts & Notifications

Meadow has two complementary approaches to notifications when interrupts (changes) happen on inputs. The first is the classic .Net Eventing pattern, in which an event is raised on change, and the second is an IObservable pattern, which is a more powerful and flexible reactive-style approach.

Classic Events

The event pattern is a familiar and simple pattern for subscribing to change notifications; interrupts (changes) on inputs such as digital or analog inputs can raise a Changed notification, that can be subscribed to via a classic handler (delegate):

public class ButtonEventsApp : App<F7Micro, ButtonEventsApp>
    IDigitalInputPort input;

    public ButtonEventsApp()
        input = Device.CreateDigitalInputPort(Device.Pins.D02, debounceDuration: 20);
        input.Changed += Input_Changed;

    private void Input_Changed(object sender, DigitalInputPortEventArgs e)
        Console.WriteLine("Changed: " + e.Value.ToString() + ", Time: " + e.Time.ToString());

IObservable/Reactive Pattern

However, for more advanced filtering we’ve exposed System.IObservable support, along with a FilterableObserver<T> that allows you to subscribe to an observable, with an optional predicate to filter on the events, as well as a handler shortcut. Consider the following code:

public class InputObservableApp : App<F7Micro, InputObservableApp>
    IDigitalInputPort _input;

    public InputObservableApp()
        // create an input port on D02. 
        _input = Device.CreateDigitalInputPort(Device.Pins.D02);

        // Note that the filter is an optional parameter. If you're
        // interested in all notifications, don't pass a filter/predicate.
        _input.Subscribe(new FilterableObserver<DigitalInputPortEventArgs>(
            e => {
                Console.WriteLine($"Observer Observing the Observable, Observably speaking, Time: {e.Time.Millisecond}, Value: {e.Value}");
            f => {
                return (f.Time - f.PreviousTime > new TimeSpan(0, 0, 0, 0, 1000));

A filter expression, or predicate, that tests for a particular condition is passed in to the FilterableObservable constructor, which is used to test whether the change satisfies a particular condition. Any expression that evaluates to a boolean (true/false), can be used.

In the above code, it filters out events that occur less than a second after the last notification:

return (f.Time - f.PreviousTime > new TimeSpan(0, 0, 0, 0, 1000));

General Use

However, the Subscribe method will take any IObservable, so you can also use whatever Reactive pattern and framework you choose.

Advantages of FilterableObserver

The FilterableObservable pattern has the distinct advantage of handling event filtering internally, meaning that consuming code will only be notified with the notifications satisfy the filter expression passed in.


These docs are open source. If you find an issue, please file a bug, or send us a pull request. And if you want to contribute, we'd love that too!