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  }