gobot.io/x/gobot@v1.16.0/platforms/dragonboard/dragonboard_adaptor.go (about)

     1  package dragonboard
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sync"
     7  
     8  	multierror "github.com/hashicorp/go-multierror"
     9  	"gobot.io/x/gobot"
    10  	"gobot.io/x/gobot/drivers/i2c"
    11  	"gobot.io/x/gobot/sysfs"
    12  )
    13  
    14  // Adaptor represents a Gobot Adaptor for a DragonBoard 410c
    15  type Adaptor struct {
    16  	name        string
    17  	digitalPins map[int]*sysfs.DigitalPin
    18  	pinMap      map[string]int
    19  	i2cBuses    [3]i2c.I2cDevice
    20  	mutex       *sync.Mutex
    21  }
    22  
    23  var fixedPins = map[string]int{
    24  	"GPIO_A": 36,
    25  	"GPIO_B": 12,
    26  	"GPIO_C": 13,
    27  	"GPIO_D": 69,
    28  	"GPIO_E": 115,
    29  	"GPIO_F": 507,
    30  	"GPIO_G": 24,
    31  	"GPIO_H": 25,
    32  	"GPIO_I": 35,
    33  	"GPIO_J": 34,
    34  	"GPIO_K": 28,
    35  	"GPIO_L": 33,
    36  
    37  	"LED_1": 21,
    38  	"LED_2": 120,
    39  }
    40  
    41  // NewAdaptor creates a DragonBoard 410c Adaptor
    42  func NewAdaptor() *Adaptor {
    43  	c := &Adaptor{
    44  		name:  gobot.DefaultName("DragonBoard"),
    45  		mutex: &sync.Mutex{},
    46  	}
    47  
    48  	c.setPins()
    49  	return c
    50  }
    51  
    52  // Name returns the name of the Adaptor
    53  func (c *Adaptor) Name() string { return c.name }
    54  
    55  // SetName sets the name of the Adaptor
    56  func (c *Adaptor) SetName(n string) { c.name = n }
    57  
    58  // Connect initializes the board
    59  func (c *Adaptor) Connect() (err error) {
    60  	return
    61  }
    62  
    63  // Finalize closes connection to board and pins
    64  func (c *Adaptor) Finalize() (err error) {
    65  	c.mutex.Lock()
    66  	defer c.mutex.Unlock()
    67  
    68  	for _, pin := range c.digitalPins {
    69  		if pin != nil {
    70  			if e := pin.Unexport(); e != nil {
    71  				err = multierror.Append(err, e)
    72  			}
    73  		}
    74  	}
    75  	for _, bus := range c.i2cBuses {
    76  		if bus != nil {
    77  			if e := bus.Close(); e != nil {
    78  				err = multierror.Append(err, e)
    79  			}
    80  		}
    81  	}
    82  	return
    83  }
    84  
    85  // DigitalPin returns matched digitalPin for specified values
    86  func (c *Adaptor) DigitalPin(pin string, dir string) (sysfsPin *sysfs.DigitalPin, err error) {
    87  	c.mutex.Lock()
    88  	defer c.mutex.Unlock()
    89  
    90  	i, err := c.translatePin(pin)
    91  
    92  	if err != nil {
    93  		return
    94  	}
    95  
    96  	if c.digitalPins[i] == nil {
    97  		c.digitalPins[i] = sysfs.NewDigitalPin(i)
    98  		if err = c.digitalPins[i].Export(); err != nil {
    99  			return
   100  		}
   101  	}
   102  
   103  	if err = c.digitalPins[i].Direction(dir); err != nil {
   104  		return
   105  	}
   106  
   107  	return c.digitalPins[i], nil
   108  }
   109  
   110  // DigitalRead reads digital value to the specified pin.
   111  // Valids pins are the GPIO_A through GPIO_L pins from the
   112  // extender (pins 23-34 on header J8), as well as the SoC pins
   113  // aka all the other pins, APQ GPIO_0-GPIO_122 and PM_MPP_0-4.
   114  func (c *Adaptor) DigitalRead(pin string) (val int, err error) {
   115  	sysfsPin, err := c.DigitalPin(pin, sysfs.IN)
   116  	if err != nil {
   117  		return
   118  	}
   119  	return sysfsPin.Read()
   120  }
   121  
   122  // DigitalWrite writes digital value to the specified pin.
   123  // Valids pins are the GPIO_A through GPIO_L pins from the
   124  // extender (pins 23-34 on header J8), as well as the SoC pins
   125  // aka all the other pins, APQ GPIO_0-GPIO_122 and PM_MPP_0-4.
   126  func (c *Adaptor) DigitalWrite(pin string, val byte) (err error) {
   127  	sysfsPin, err := c.DigitalPin(pin, sysfs.OUT)
   128  	if err != nil {
   129  		return err
   130  	}
   131  	return sysfsPin.Write(int(val))
   132  }
   133  
   134  // GetConnection returns a connection to a device on a specified bus.
   135  // Valid bus number is [0..1] which corresponds to /dev/i2c-0 through /dev/i2c-1.
   136  func (c *Adaptor) GetConnection(address int, bus int) (connection i2c.Connection, err error) {
   137  	c.mutex.Lock()
   138  	defer c.mutex.Unlock()
   139  
   140  	if (bus < 0) || (bus > 1) {
   141  		return nil, fmt.Errorf("Bus number %d out of range", bus)
   142  	}
   143  	if c.i2cBuses[bus] == nil {
   144  		c.i2cBuses[bus], err = sysfs.NewI2cDevice(fmt.Sprintf("/dev/i2c-%d", bus))
   145  	}
   146  	return i2c.NewConnection(c.i2cBuses[bus], address), err
   147  }
   148  
   149  // GetDefaultBus returns the default i2c bus for this platform
   150  func (c *Adaptor) GetDefaultBus() int {
   151  	return 0
   152  }
   153  
   154  func (c *Adaptor) setPins() {
   155  	c.digitalPins = make(map[int]*sysfs.DigitalPin)
   156  	c.pinMap = fixedPins
   157  	for i := 0; i < 122; i++ {
   158  		pin := fmt.Sprintf("GPIO_%d", i)
   159  		c.pinMap[pin] = i
   160  	}
   161  }
   162  
   163  func (c *Adaptor) translatePin(pin string) (i int, err error) {
   164  	if val, ok := c.pinMap[pin]; ok {
   165  		i = val
   166  	} else {
   167  		err = errors.New("Not a valid pin")
   168  	}
   169  	return
   170  }