gobot.io/x/gobot@v1.16.0/drivers/i2c/drv2605l_driver.go (about)

     1  package i2c
     2  
     3  import (
     4  	"gobot.io/x/gobot"
     5  )
     6  
     7  // DRV2605Mode - operating mode
     8  type DRV2605Mode uint8
     9  
    10  // Operating modes, for use in SetMode()
    11  const (
    12  	DRV2605ModeIntTrig     DRV2605Mode = 0x00
    13  	DRV2605ModeExtTrigEdge             = 0x01
    14  	DRV2605ModeExtTrigLvl              = 0x02
    15  	DRV2605ModePWMAnalog               = 0x03
    16  	DRV2605ModeAudioVibe               = 0x04
    17  	DRV2605ModeRealtime                = 0x05
    18  	DRV2605ModeDiagnose                = 0x06
    19  	DRV2605ModeAutocal                 = 0x07
    20  )
    21  
    22  const (
    23  	drv2605Address = 0x5A
    24  
    25  	drv2605RegStatus = 0x00
    26  	drv2605RegMode   = 0x01
    27  
    28  	drv2605Standby = 0x40
    29  
    30  	drv2605RegRTPin    = 0x02
    31  	drv2605RegLibrary  = 0x03
    32  	drv2605RegWaveSeq1 = 0x04
    33  	drv2605RegWaveSeq2 = 0x05
    34  	drv2605RegWaveSeq3 = 0x06
    35  	drv2605RegWaveSeq4 = 0x07
    36  	drv2605RegWaveSeq5 = 0x08
    37  	drv2605RegWaveSeq6 = 0x09
    38  	drv2605RegWaveSeq7 = 0x0A
    39  	drv2605RegWaveSeq8 = 0x0B
    40  
    41  	drv2605RegGo            = 0x0C
    42  	drv2605RegOverdrive     = 0x0D
    43  	drv2605RegSustainPos    = 0x0E
    44  	drv2605RegSustainNeg    = 0x0F
    45  	drv2605RegBreak         = 0x10
    46  	drv2605RegAudioCtrl     = 0x11
    47  	drv2605RegAudioMinLevel = 0x12
    48  	drv2605RegAudioMaxLevel = 0x13
    49  	drv2605RegAudioMinDrive = 0x14
    50  	drv2605RegAudioMaxDrive = 0x15
    51  	drv2605RegRatedV        = 0x16
    52  	drv2605RegClampV        = 0x17
    53  	drv2605RegAutocalComp   = 0x18
    54  	drv2605RegAutocalEmp    = 0x19
    55  	drv2605RegFeedback      = 0x1A
    56  	drv2605RegControl1      = 0x1B
    57  	drv2605RegControl2      = 0x1C
    58  	drv2605RegControl3      = 0x1D
    59  	drv2605RegControl4      = 0x1E
    60  	drv2605RegVBat          = 0x21
    61  	drv2605RegLRAResoPeriod = 0x22
    62  )
    63  
    64  // DRV2605LDriver is the gobot driver for the TI/Adafruit DRV2605L Haptic Controller
    65  //
    66  // Device datasheet: http://www.ti.com/lit/ds/symlink/drv2605l.pdf
    67  //
    68  // Inspired by the Adafruit Python driver by Sean Mealin.
    69  //
    70  // Basic use:
    71  //
    72  //  haptic := i2c.NewDRV2605Driver(adaptor)
    73  //  haptic.SetSequence([]byte{1, 13})
    74  //  haptic.Go()
    75  //
    76  type DRV2605LDriver struct {
    77  	name       string
    78  	connector  Connector
    79  	connection Connection
    80  	Config
    81  }
    82  
    83  // NewDRV2605LDriver creates a new driver for the DRV2605L device.
    84  //
    85  // Params:
    86  //		conn Connector - the Adaptor to use with this Driver
    87  //
    88  // Optional params:
    89  //		i2c.WithBus(int):	bus to use with this driver
    90  //		i2c.WithAddress(int):	address to use with this driver
    91  //
    92  func NewDRV2605LDriver(conn Connector, options ...func(Config)) *DRV2605LDriver {
    93  	driver := &DRV2605LDriver{
    94  		name:      gobot.DefaultName("DRV2605L"),
    95  		connector: conn,
    96  		Config:    NewConfig(),
    97  	}
    98  
    99  	for _, option := range options {
   100  		option(driver)
   101  	}
   102  
   103  	return driver
   104  }
   105  
   106  // Name returns the name of the device.
   107  func (d *DRV2605LDriver) Name() string {
   108  	return d.name
   109  }
   110  
   111  // SetName sets the name of the device.
   112  func (d *DRV2605LDriver) SetName(name string) {
   113  	d.name = name
   114  }
   115  
   116  // Connection returns the connection of the device.
   117  func (d *DRV2605LDriver) Connection() gobot.Connection {
   118  	return d.connector.(gobot.Connection)
   119  }
   120  
   121  // Start initializes the device.
   122  func (d *DRV2605LDriver) Start() (err error) {
   123  	if err := d.initialize(); err != nil {
   124  		return err
   125  	}
   126  	return nil
   127  }
   128  
   129  func (d *DRV2605LDriver) writeByteRegisters(regValPairs []struct{ reg, val uint8 }) (err error) {
   130  	for _, rv := range regValPairs {
   131  		if err = d.connection.WriteByteData(rv.reg, rv.val); err != nil {
   132  			break
   133  		}
   134  	}
   135  	return err
   136  }
   137  
   138  func (d *DRV2605LDriver) initialize() (err error) {
   139  	bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
   140  	address := d.GetAddressOrDefault(drv2605Address)
   141  
   142  	d.connection, err = d.connector.GetConnection(address, bus)
   143  	if err != nil {
   144  		return
   145  	}
   146  
   147  	feedback, err := d.connection.ReadByteData(drv2605RegFeedback)
   148  	if err != nil {
   149  		return
   150  	}
   151  
   152  	control, err := d.connection.ReadByteData(drv2605RegControl3)
   153  	if err != nil {
   154  		return
   155  	}
   156  
   157  	err = d.writeByteRegisters([]struct{ reg, val uint8 }{
   158  		// leave standby, enter "internal trig" mode
   159  		{drv2605RegMode, 0},
   160  		// turn off real-time play
   161  		{drv2605RegRTPin, 0},
   162  		// init wave sequencer with "strong click"
   163  		{drv2605RegWaveSeq1, 1},
   164  		{drv2605RegWaveSeq1, 0},
   165  		// no physical parameter tweaks
   166  		{drv2605RegSustainPos, 0},
   167  		{drv2605RegSustainNeg, 0},
   168  		{drv2605RegBreak, 0},
   169  		// set up ERM open loop
   170  		{drv2605RegFeedback, feedback & 0x7f},
   171  		{drv2605RegControl3, control | 0x20},
   172  	})
   173  
   174  	return
   175  }
   176  
   177  // SetMode sets the device in one of the eight modes as described in the
   178  // datasheet. Defaults to mode 0, internal trig.
   179  func (d *DRV2605LDriver) SetMode(newMode DRV2605Mode) (err error) {
   180  	mode, err := d.connection.ReadByteData(drv2605RegMode)
   181  	if err != nil {
   182  		return err
   183  	}
   184  
   185  	// clear mode bits (lower three bits)
   186  	mode &= 0xf8
   187  	// set new mode bits
   188  	mode |= uint8(newMode)
   189  
   190  	err = d.connection.WriteByteData(drv2605RegMode, mode)
   191  
   192  	return err
   193  }
   194  
   195  // SetStandbyMode controls device low power mode
   196  func (d *DRV2605LDriver) SetStandbyMode(standby bool) (err error) {
   197  	modeVal, err := d.connection.ReadByteData(drv2605RegMode)
   198  	if err != nil {
   199  		return err
   200  	}
   201  	if standby {
   202  		modeVal |= drv2605Standby
   203  	} else {
   204  		modeVal &= 0xFF ^ drv2605Standby
   205  	}
   206  
   207  	err = d.connection.WriteByteData(drv2605RegMode, modeVal)
   208  
   209  	return err
   210  }
   211  
   212  // SelectLibrary selects which waveform library to play from, 1-7.
   213  // See datasheet for more info.
   214  func (d *DRV2605LDriver) SelectLibrary(library uint8) (err error) {
   215  	err = d.connection.WriteByteData(drv2605RegLibrary, library&0x7)
   216  	return err
   217  }
   218  
   219  // GetPauseWaveform returns a special waveform ID used in SetSequence() to encode
   220  // pauses between waveforms. Time is specified in tens of milliseconds
   221  // ranging from 0ms (delayTime10MS = 0) to 1270ms (delayTime10MS = 127).
   222  // Times out of range are clipped to fit.
   223  func (d *DRV2605LDriver) GetPauseWaveform(delayTime10MS uint8) (pauseID uint8) {
   224  	if delayTime10MS > 127 {
   225  		delayTime10MS = 127
   226  	}
   227  
   228  	return delayTime10MS | 0x80
   229  }
   230  
   231  // SetSequence sets the sequence of waveforms to be played by the sequencer,
   232  // specified by waveform id as described in the datasheet.
   233  // The sequencer can play at most 8 waveforms in sequence, longer
   234  // sequences will be truncated.
   235  // A waveform id of zero marks the end of the sequence.
   236  // Pauses can be encoded using GetPauseWaveform().
   237  func (d *DRV2605LDriver) SetSequence(waveforms []uint8) (err error) {
   238  	if len(waveforms) < 8 {
   239  		waveforms = append(waveforms, 0)
   240  	}
   241  	if len(waveforms) > 8 {
   242  		waveforms = waveforms[0:8]
   243  	}
   244  	for i, w := range waveforms {
   245  		if err = d.connection.WriteByteData(uint8(drv2605RegWaveSeq1+i), w); err != nil {
   246  			return err
   247  		}
   248  	}
   249  	return nil
   250  }
   251  
   252  // Go plays the current sequence of waveforms.
   253  func (d *DRV2605LDriver) Go() (err error) {
   254  	err = d.connection.WriteByteData(drv2605RegGo, 1)
   255  	return err
   256  }
   257  
   258  // Halt halts the device.
   259  func (d *DRV2605LDriver) Halt() (err error) {
   260  	if d.connection != nil {
   261  		// stop playback
   262  		if err = d.connection.WriteByteData(drv2605RegGo, 0); err != nil {
   263  			return err
   264  		}
   265  
   266  		// enter standby
   267  		return d.SetStandbyMode(true)
   268  	}
   269  	return
   270  }