gobot.io/x/gobot/v2@v2.1.0/drivers/i2c/drv2605l_driver.go (about)

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