-
-
Notifications
You must be signed in to change notification settings - Fork 146
/
GpioButtonInputProvider.cs
126 lines (103 loc) · 3.71 KB
/
GpioButtonInputProvider.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections;
using System.Device.Gpio;
using nanoFramework.UI;
using nanoFramework.UI.Input;
using nanoFramework.UI.Threading;
using nanoFramework.Presentation;
namespace Tetris
{
/// <summary>
/// Uses the hardware provider to get the pins for handling button input.
/// </summary>
public sealed class GPIOButtonInputProvider
{
public readonly Dispatcher Dispatcher;
//private ButtonPad[] buttons;
private readonly ArrayList buttons;
private readonly DispatcherOperationCallback callback;
private readonly InputProviderSite site;
private readonly PresentationSource source;
private readonly GpioController Gpio = new GpioController();
/// <summary>
/// Maps GPIOs to Buttons that can be processed by
/// nanoFramework.Presentation.
/// </summary>
/// <param name="source"></param>
public GPIOButtonInputProvider(PresentationSource source)
{
// Set the input source.
this.source = source;
// Register our object as an input source with the input manager and
// get back an InputProviderSite object which forwards the input
// report to the input manager, which then places the input in the
// staging area.
site = InputManager.CurrentInputManager.RegisterInputProvider(this);
// Create a delegate that refers to the InputProviderSite object's
// ReportInput method.
callback = new DispatcherOperationCallback(delegate (object report)
{
InputReportArgs args = (InputReportArgs)report;
return site.ReportInput(args.Device, args.Report);
});
Dispatcher = Dispatcher.CurrentDispatcher;
this.buttons = new ArrayList();
}
/// <summary>
/// Add a GPIO pin as a specific Button
/// </summary>
/// <param name="gpioPinNumber">GPIO pin number</param>
/// <param name="button">Button that this pin represents</param>
/// <param name="internalPullup">If true will enable the internal pull up on pin ( SetDriveMode = InputPullUp )
public void AddButton(int gpioPinNumber, Button button, bool internalPullup)
{
GpioPin pin = Gpio.OpenPin(gpioPinNumber);
pin.SetPinMode(internalPullup ? PinMode.InputPullUp : PinMode.Input);
pin.DebounceTimeout = new TimeSpan(0, 0, 0, 0, 50);
this.buttons.Add(new ButtonPad(this, button, pin));
}
/// <summary>
/// Represents a button pad on the emulated device, containing five
/// buttons for user input.
/// </summary>
internal class ButtonPad : IDisposable
{
private readonly Button button;
private readonly GPIOButtonInputProvider sink;
private readonly ButtonDevice buttonDevice = InputManager.CurrentInputManager.ButtonDevice;
/// <summary>
/// Constructs a ButtonPad object that handles the
/// hardware's button interrupts.
/// </summary>
/// <param name="sink"></param>
/// <param name="button"></param>
/// <param name="pin"></param>
public ButtonPad(GPIOButtonInputProvider sink, Button button, GpioPin pin)
{
this.sink = sink;
this.button = button;
pin.ValueChanged += Pin_ValueChanged;
}
private void Pin_ValueChanged(object sender, PinValueChangedEventArgs e)
{
RawButtonActions action = (e.ChangeType == PinEventTypes.Falling) ? RawButtonActions.ButtonUp : RawButtonActions.ButtonDown;
// Create a time, should be from the pin_ValueChanged event.
DateTime time = DateTime.UtcNow;
RawButtonInputReport report = new RawButtonInputReport(sink.source, time, button, action);
// Queue the button press to the input provider site.
sink.Dispatcher.BeginInvoke(sink.callback, new InputReportArgs(buttonDevice, report));
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
}