gobot.io/x/gobot/v2@v2.1.0/platforms/dragonboard/dragonboard_adaptor.go (about)

     1  package dragonboard
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	multierror "github.com/hashicorp/go-multierror"
     8  	"gobot.io/x/gobot/v2"
     9  	"gobot.io/x/gobot/v2/platforms/adaptors"
    10  	"gobot.io/x/gobot/v2/system"
    11  )
    12  
    13  const defaultI2cBusNumber = 0
    14  
    15  // Adaptor represents a Gobot Adaptor for a DragonBoard 410c
    16  type Adaptor struct {
    17  	name   string
    18  	sys    *system.Accesser
    19  	mutex  sync.Mutex
    20  	pinMap map[string]int
    21  	*adaptors.DigitalPinsAdaptor
    22  	*adaptors.I2cBusAdaptor
    23  }
    24  
    25  // Valid pins are the GPIO_A through GPIO_L pins from the
    26  // extender (pins 23-34 on header J8), as well as the SoC pins
    27  // aka all the other pins, APQ GPIO_0-GPIO_122 and PM_MPP_0-4.
    28  var fixedPins = map[string]int{
    29  	"GPIO_A": 36,
    30  	"GPIO_B": 12,
    31  	"GPIO_C": 13,
    32  	"GPIO_D": 69,
    33  	"GPIO_E": 115,
    34  	"GPIO_F": 507,
    35  	"GPIO_G": 24,
    36  	"GPIO_H": 25,
    37  	"GPIO_I": 35,
    38  	"GPIO_J": 34,
    39  	"GPIO_K": 28,
    40  	"GPIO_L": 33,
    41  
    42  	"LED_1": 21,
    43  	"LED_2": 120,
    44  }
    45  
    46  // NewAdaptor creates a DragonBoard 410c Adaptor
    47  //
    48  // Optional parameters:
    49  //
    50  //	adaptors.WithGpiodAccess():	use character device gpiod driver instead of sysfs
    51  //	adaptors.WithSpiGpioAccess(sclk, nss, mosi, miso):	use GPIO's instead of /dev/spidev#.#
    52  func NewAdaptor(opts ...func(adaptors.Optioner)) *Adaptor {
    53  	sys := system.NewAccesser()
    54  	c := &Adaptor{
    55  		name: gobot.DefaultName("DragonBoard"),
    56  		sys:  sys,
    57  	}
    58  	c.DigitalPinsAdaptor = adaptors.NewDigitalPinsAdaptor(sys, c.translateDigitalPin, opts...)
    59  	c.I2cBusAdaptor = adaptors.NewI2cBusAdaptor(sys, c.validateI2cBusNumber, defaultI2cBusNumber)
    60  	c.pinMap = fixedPins
    61  	for i := 0; i < 122; i++ {
    62  		pin := fmt.Sprintf("GPIO_%d", i)
    63  		c.pinMap[pin] = i
    64  	}
    65  	return c
    66  }
    67  
    68  // Name returns the name of the Adaptor
    69  func (c *Adaptor) Name() string { return c.name }
    70  
    71  // SetName sets the name of the Adaptor
    72  func (c *Adaptor) SetName(n string) { c.name = n }
    73  
    74  // Connect create new connection to board and pins.
    75  func (c *Adaptor) Connect() error {
    76  	c.mutex.Lock()
    77  	defer c.mutex.Unlock()
    78  
    79  	if err := c.I2cBusAdaptor.Connect(); err != nil {
    80  		return err
    81  	}
    82  
    83  	return c.DigitalPinsAdaptor.Connect()
    84  }
    85  
    86  // Finalize closes connection to board and pins
    87  func (c *Adaptor) Finalize() error {
    88  	c.mutex.Lock()
    89  	defer c.mutex.Unlock()
    90  
    91  	err := c.DigitalPinsAdaptor.Finalize()
    92  
    93  	if e := c.I2cBusAdaptor.Finalize(); e != nil {
    94  		err = multierror.Append(err, e)
    95  	}
    96  
    97  	return err
    98  }
    99  
   100  func (c *Adaptor) validateI2cBusNumber(busNr int) error {
   101  	// Valid bus number is [0..1] which corresponds to /dev/i2c-0 through /dev/i2c-1.
   102  	if (busNr < 0) || (busNr > 1) {
   103  		return fmt.Errorf("Bus number %d out of range", busNr)
   104  	}
   105  	return nil
   106  }
   107  
   108  func (c *Adaptor) translateDigitalPin(id string) (string, int, error) {
   109  	if line, ok := c.pinMap[id]; ok {
   110  		return "", line, nil
   111  	}
   112  	return "", -1, fmt.Errorf("'%s' is not a valid id for a digital pin", id)
   113  }