gobot.io/x/gobot/v2@v2.1.0/system/digitalpin_config.go (about) 1 package system 2 3 import ( 4 "time" 5 6 "gobot.io/x/gobot/v2" 7 ) 8 9 const ( 10 // IN gpio direction 11 IN = "in" 12 // OUT gpio direction 13 OUT = "out" 14 // HIGH gpio level 15 HIGH = 1 16 // LOW gpio level 17 LOW = 0 18 ) 19 20 const ( 21 digitalPinBiasDefault = 0 // GPIO uses the hardware default 22 digitalPinBiasDisable = 1 // GPIO has pull disabled 23 digitalPinBiasPullDown = 2 // GPIO has pull up enabled 24 digitalPinBiasPullUp = 3 // GPIO has pull down enabled 25 26 // open drain and open source allows the connection of output ports with the same mode (OR logic) 27 // * for open drain/collector pull up the ports with an external resistor/load 28 // * for open source/emitter pull down the ports with an external resistor/load 29 digitalPinDrivePushPull = 0 // the pin will be driven actively high and low (default) 30 digitalPinDriveOpenDrain = 1 // the pin will be driven active to low only 31 digitalPinDriveOpenSource = 2 // the pin will be driven active to high only 32 33 digitalPinEventNone = 0 // no event will be triggered on any pin change (default) 34 digitalPinEventOnFallingEdge = 1 // an event will be triggered on changes from high to low state 35 digitalPinEventOnRisingEdge = 2 // an event will be triggered on changes from low to high state 36 digitalPinEventOnBothEdges = 3 // an event will be triggered on all changes 37 ) 38 39 const ( 40 // DigitalPinEventRisingEdge indicates an inactive to active event. 41 DigitalPinEventRisingEdge = "rising edge" 42 // DigitalPinEventFallingEdge indicates an active to inactive event. 43 DigitalPinEventFallingEdge = "falling edge" 44 ) 45 46 type digitalPinConfig struct { 47 label string 48 direction string 49 outInitialState int 50 activeLow bool 51 bias int 52 drive int 53 debouncePeriod time.Duration 54 edge int 55 edgeEventHandler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32) 56 } 57 58 func newDigitalPinConfig(label string, options ...func(gobot.DigitalPinOptioner) bool) *digitalPinConfig { 59 cfg := &digitalPinConfig{ 60 label: label, 61 direction: IN, 62 } 63 for _, option := range options { 64 option(cfg) 65 } 66 return cfg 67 } 68 69 // WithPinLabel use a pin label, which will replace the default label "gobotio#". 70 func WithPinLabel(label string) func(gobot.DigitalPinOptioner) bool { 71 return func(d gobot.DigitalPinOptioner) bool { return d.SetLabel(label) } 72 } 73 74 // WithPinDirectionOutput initializes the pin as output instead of the default "input". 75 func WithPinDirectionOutput(initial int) func(gobot.DigitalPinOptioner) bool { 76 return func(d gobot.DigitalPinOptioner) bool { return d.SetDirectionOutput(initial) } 77 } 78 79 // WithPinDirectionInput initializes the pin as input. 80 func WithPinDirectionInput() func(gobot.DigitalPinOptioner) bool { 81 return func(d gobot.DigitalPinOptioner) bool { return d.SetDirectionInput() } 82 } 83 84 // WithPinActiveLow initializes the pin with inverse reaction (applies on input and output). 85 func WithPinActiveLow() func(gobot.DigitalPinOptioner) bool { 86 return func(d gobot.DigitalPinOptioner) bool { return d.SetActiveLow() } 87 } 88 89 // WithPinPullDown initializes the pin to be pulled down (high impedance to GND, applies on input and output). 90 // This is working since Kernel 5.5. 91 func WithPinPullDown() func(gobot.DigitalPinOptioner) bool { 92 return func(d gobot.DigitalPinOptioner) bool { return d.SetBias(digitalPinBiasPullDown) } 93 } 94 95 // WithPinPullUp initializes the pin to be pulled up (high impedance to VDD, applies on input and output). 96 // This is working since Kernel 5.5. 97 func WithPinPullUp() func(gobot.DigitalPinOptioner) bool { 98 return func(d gobot.DigitalPinOptioner) bool { return d.SetBias(digitalPinBiasPullUp) } 99 } 100 101 // WithPinOpenDrain initializes the output pin to be driven with open drain/collector. 102 func WithPinOpenDrain() func(gobot.DigitalPinOptioner) bool { 103 return func(d gobot.DigitalPinOptioner) bool { return d.SetDrive(digitalPinDriveOpenDrain) } 104 } 105 106 // WithPinOpenSource initializes the output pin to be driven with open source/emitter. 107 func WithPinOpenSource() func(gobot.DigitalPinOptioner) bool { 108 return func(d gobot.DigitalPinOptioner) bool { return d.SetDrive(digitalPinDriveOpenSource) } 109 } 110 111 // WithPinDebounce initializes the input pin to be debounced. 112 func WithPinDebounce(period time.Duration) func(gobot.DigitalPinOptioner) bool { 113 return func(d gobot.DigitalPinOptioner) bool { return d.SetDebounce(period) } 114 } 115 116 // WithPinEventOnFallingEdge initializes the input pin for edge detection and call the event handler on falling edges. 117 func WithPinEventOnFallingEdge(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, 118 lseqno uint32)) func(gobot.DigitalPinOptioner) bool { 119 return func(d gobot.DigitalPinOptioner) bool { 120 return d.SetEventHandlerForEdge(handler, digitalPinEventOnFallingEdge) 121 } 122 } 123 124 // WithPinEventOnRisingEdge initializes the input pin for edge detection and call the event handler on rising edges. 125 func WithPinEventOnRisingEdge(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, 126 lseqno uint32)) func(gobot.DigitalPinOptioner) bool { 127 return func(d gobot.DigitalPinOptioner) bool { 128 return d.SetEventHandlerForEdge(handler, digitalPinEventOnRisingEdge) 129 } 130 } 131 132 // WithPinEventOnBothEdges initializes the input pin for edge detection and call the event handler on all edges. 133 func WithPinEventOnBothEdges(handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, 134 lseqno uint32)) func(gobot.DigitalPinOptioner) bool { 135 return func(d gobot.DigitalPinOptioner) bool { 136 return d.SetEventHandlerForEdge(handler, digitalPinEventOnBothEdges) 137 } 138 } 139 140 // SetLabel sets the label to use for next reconfigure. The function is intended to use by WithPinLabel(). 141 func (d *digitalPinConfig) SetLabel(label string) bool { 142 if d.label == label { 143 return false 144 } 145 d.label = label 146 return true 147 } 148 149 // SetDirectionOutput sets the direction to output for next reconfigure. The function is intended to use 150 // by WithPinDirectionOutput(). 151 func (d *digitalPinConfig) SetDirectionOutput(initial int) bool { 152 if d.direction == OUT { 153 // in this case also the initial value will not be written 154 return false 155 } 156 d.direction = OUT 157 d.outInitialState = initial 158 return true 159 } 160 161 // SetDirectionInput sets the direction to input for next reconfigure. The function is intended to use 162 // by WithPinDirectionInput(). 163 func (d *digitalPinConfig) SetDirectionInput() bool { 164 if d.direction == IN { 165 return false 166 } 167 d.direction = IN 168 return true 169 } 170 171 // SetActiveLow sets the pin with inverse reaction (applies on input and output) for next reconfigure. The function 172 // is intended to use by WithPinActiveLow(). 173 func (d *digitalPinConfig) SetActiveLow() bool { 174 if d.activeLow { 175 return false 176 } 177 d.activeLow = true 178 return true 179 } 180 181 // SetBias sets the pin bias (applies on input and output) for next reconfigure. The function 182 // is intended to use by WithPinPullUp() and WithPinPullDown(). 183 func (d *digitalPinConfig) SetBias(bias int) bool { 184 if d.bias == bias { 185 return false 186 } 187 d.bias = bias 188 return true 189 } 190 191 // SetDrive sets the pin drive mode (applies on output only) for next reconfigure. The function 192 // is intended to use by WithPinOpenDrain(), WithPinOpenSource() and WithPinPushPull(). 193 func (d *digitalPinConfig) SetDrive(drive int) bool { 194 if d.drive == drive { 195 return false 196 } 197 d.drive = drive 198 return true 199 } 200 201 // SetDebounce sets the input pin with the given debounce period for next reconfigure. The function 202 // is intended to use by WithPinDebounce(). 203 func (d *digitalPinConfig) SetDebounce(period time.Duration) bool { 204 if d.debouncePeriod == period { 205 return false 206 } 207 d.debouncePeriod = period 208 return true 209 } 210 211 // SetEventHandlerForEdge sets the input pin to edge detection and to call the event handler on specified edge. The 212 // function is intended to use by WithPinEventOnFallingEdge(), WithPinEventOnRisingEdge() and WithPinEventOnBothEdges(). 213 func (d *digitalPinConfig) SetEventHandlerForEdge(handler func(int, time.Duration, string, uint32, uint32), edge int) bool { 214 if d.edge == edge { 215 return false 216 } 217 d.edge = edge 218 d.edgeEventHandler = handler 219 return true 220 }