33open System
44open System.Threading .Tasks
55open FSharp.Control .Tasks .ContextInsensitive
6+ open System.Device .Gpio
67
7- open Unosquare.RaspberryIO
8- open Unosquare.WiringPi
9- open Unosquare.RaspberryIO .Abstractions
10-
11-
12- let init () =
13- Pi.Init< BootstrapWiringPi>()
14-
15- type LED ( pin : IGpioPin ) =
8+ type LED ( controller : GpioController , log : log4net.ILog , pin : int ) =
169 let mutable active = false
10+ let mutable blinking = false
1711 do
18- pin.PinMode <- GpioPinDriveMode .Output
19- pin .Write false
12+ controller.OpenPin ( pin , PinMode .Output)
13+ controller .Write( pin , PinValue.Low )
2014
2115 with
2216 member __.IsActive = active
2317
2418 member __.Activate () =
25- pin.Write true
19+ controller.Write( pin, PinValue.High)
20+ blinking <- false
2621 active <- true
2722
2823 member __.Deactivate () =
29- pin.Write false
24+ controller.Write( pin, PinValue.Low)
25+ blinking <- false
3026 active <- false
3127
3228 member this.Blink ( times : int ) = task {
29+ blinking <- false
3330 for _ in 0 .. times-1 do
3431 this.Activate()
3532 do ! Task.Delay( 300 )
3633 this.Deactivate()
3734 do ! Task.Delay( 300 )
3835 }
3936
40- type Button ( pin : IGpioPin , onPress ) =
41- let mutable lastChangedState = DateTime.MinValue
42- let bounceTimeSpan = TimeSpan.FromMilliseconds 30.
43- let mutable lastState = false
37+ member this.StartBlinking () = task {
38+ blinking <- true
39+ while blinking do
40+ this.Activate()
41+ do ! Task.Delay( 300 )
42+ this.Deactivate()
43+ do ! Task.Delay( 300 )
44+ }
45+
46+ member this.StopBlinking () = this.Deactivate()
47+
48+ type CableConnection ( controller : GpioController , log : log4net.ILog , pin : int ) =
49+ let mutable onConnected = None
50+ let mutable onDisconnected = None
51+ let mutable lastState = None
52+
53+ let execute expectedState f =
54+ match lastState with
55+ | Some s ->
56+ let state = controller.Read( pin) = PinValue.High
57+ if state = expectedState && s <> state then
58+ f()
59+ lastState <- Some state
60+ | None ->
61+ let state = controller.Read( pin) = PinValue.High
62+ if state = expectedState then
63+ f()
64+ lastState <- Some state
65+
4466 do
45- pin.PinMode <- GpioPinDriveMode.Input
46- pin.InputPullMode <- GpioPinResistorPullMode.PullUp
47- lastState <- pin.Read()
48- pin.RegisterInterruptCallback(
49- EdgeDetection.FallingAndRisingEdge,
50- fun () ->
51- let state = pin.Read()
52- let time = DateTime.UtcNow
53- let bounceTimeReached = lastChangedState.Add bounceTimeSpan < time
54- if bounceTimeReached && ( not state) && lastState then
55- ()
56- if bounceTimeReached && state && not lastState then
57- onPress()
58- if lastState <> state then
59- lastChangedState <- time
60- lastState <- state)
61-
62- let d =
63- { new IDisposable with
64- member __.Dispose () = () }
65-
66- interface IDisposable with
67- member __.Dispose () = d.Dispose()
68-
69- let waitForButtonPress ( pin : IGpioPin ) = task {
70- let pressed = ref false
71- use _button = new Button( pin,( fun _ -> pressed := true ))
72- while not ! pressed do
73- do ! Task.Delay( 100 )
74- }
67+ controller.OpenPin( pin, PinMode.InputPullUp)
68+
69+ let rising ( _sender : obj ) ( _e : PinValueChangedEventArgs ) =
70+ log.InfoFormat( " Rising - unconnected" )
71+ match onDisconnected with
72+ | None -> ()
73+ | Some f -> execute true f
74+
75+ let falling ( _sender : obj ) ( _e : PinValueChangedEventArgs ) =
76+ log.InfoFormat( " Falling - connected" )
77+ match onConnected with
78+ | None -> ()
79+ | Some f -> execute false f
80+
81+ controller.RegisterCallbackForPinValueChangedEvent(
82+ pin,
83+ PinEventTypes.Rising,
84+ PinChangeEventHandler rising)
85+
86+ controller.RegisterCallbackForPinValueChangedEvent(
87+ pin,
88+ PinEventTypes.Falling,
89+ PinChangeEventHandler falling)
90+
91+ member __.SetOnConnected f =
92+ onConnected <- Some f
93+ execute false f
94+
95+ member __.SetOnDisConnected f =
96+ onDisconnected <- Some f
97+ execute true f
98+
99+ type Button ( controller : GpioController , log : log4net.ILog , pin : int , onPress ) =
100+ let mutable lastState = None
101+
102+ let execute () =
103+ match lastState with
104+ | Some s ->
105+ let state = controller.Read( pin) = PinValue.High
106+ if not state && s <> state then
107+ lastState <- Some state
108+ | None ->
109+ let state = controller.Read( pin) = PinValue.High
110+ if not state then
111+ onPress()
112+ lastState <- Some state
113+
114+ do
115+ controller.OpenPin( pin, PinMode.InputPullUp)
116+
117+ let falling ( _sender : obj ) ( _e : PinValueChangedEventArgs ) =
118+ log.InfoFormat( " Falling - pressed" )
119+ execute ()
120+
121+ controller.RegisterCallbackForPinValueChangedEvent(
122+ pin,
123+ PinEventTypes.Falling,
124+ PinChangeEventHandler falling)
125+
126+
127+ type Controller ( log : log4net.ILog ) =
128+ let controller = new GpioController( PinNumberingScheme.Logical)
129+
130+ with
131+ member __.NewLED ( pin ) =
132+ LED( controller, log, pin)
133+
134+ member __.NewCableConnection ( pin : int ) =
135+ CableConnection( controller, log, pin)
136+
137+ member __.NewButton ( pin : int , onPress ) =
138+ Button( controller, log, pin, onPress)
139+
140+ interface IDisposable with
141+ member __.Dispose () = controller.Dispose()
0 commit comments