Basic I2C Driver for the TI DRV2605 Haptic Driver. Currently only supports Open-Loop ERM operation using internal Immersion TouchSense 2200 software/library, although user can use the Read/Write Byte methods to manually set registers and control the device.

Dependents:   DRV2605L_Haptic_Driver_Demo IoT_Haptic_Noise_Irritator DuelingTanks

Files at this revision

API Documentation at this revision

Comitter:
electromotivated
Date:
Wed Oct 21 01:02:59 2015 +0000
Commit message:
v1 Upload;

Changed in this revision

DRV2605.cpp Show annotated file Show diff for this revision Revisions of this file
DRV2605.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 3b2b4f34aaca DRV2605.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRV2605.cpp	Wed Oct 21 01:02:59 2015 +0000
@@ -0,0 +1,115 @@
+#include "DRV2605.h"
+
+DRV2605::DRV2605(PinName sda, PinName scl): i2c(sda, scl){
+        wait_us(250);   // Device datasheet specified wait time before I2C
+                        // comms should be used
+}
+
+void DRV2605::i2cWriteByte(char reg, char value){
+    char buff[2] = {reg, value};
+    i2c.write(SLAVE_ADDR_7_BIT<<1, buff, 2);
+}
+
+uint8_t DRV2605::i2cReadByte(char reg){
+    char result;                                    // Temp result storage
+    i2c.write(SLAVE_ADDR_7_BIT<<1, &reg, 1, true);  
+    i2c.read(SLAVE_ADDR_7_BIT<<1, &result, 1);
+    
+    return result;         
+}
+
+void DRV2605::mode(Mode mode){
+    i2cWriteByte(MODE, mode);
+}
+
+int DRV2605::init(float actuator_peak_voltage, Library lib){
+    int result = 
+        auto_cal_open_loop(actuator_peak_voltage); // Perform Open-Loop ERM Cal
+    i2cWriteByte(LIBRARY_SELECTION, lib);     // Select ROM Library
+    mode(STANDBY);                            // Put device into low- power mode
+    return result;                            // Cal/Init Result 0: Pass 1: Fail
+}
+
+uint8_t DRV2605::diagnostics(){
+    mode(DIAG);
+    i2cWriteByte(GO, 1);
+    while(i2cReadByte(GO));     // Wait for GO bit to clear
+    
+    return i2cReadByte(STATUS); // Return Status Reg Value
+}
+
+void DRV2605::play_waveform(int waveform_effect){
+    mode(INTERNAL_TRIG);                                 // Bring device out of standby and set to internal trigger
+    i2cWriteByte(WAVEFORM_SEQUENCER_1, waveform_effect); // Load waveform index to play
+    i2cWriteByte(WAVEFORM_SEQUENCER_2, 0);               // Insert stop condition so we don't play other registers if filled
+    i2cWriteByte(GO, 0x01);                              // Set GO bit to start playback
+}
+
+void DRV2605::load_waveform_sequence(int effect1, int effect2, 
+                                     int effect3, int effect4,
+                                     int effect5, int effect6, 
+                                     int effect7, int effect8){
+    i2cWriteByte(WAVEFORM_SEQUENCER_1, effect1);
+    i2cWriteByte(WAVEFORM_SEQUENCER_2, effect2);
+    i2cWriteByte(WAVEFORM_SEQUENCER_3, effect3);
+    i2cWriteByte(WAVEFORM_SEQUENCER_4, effect4);
+    i2cWriteByte(WAVEFORM_SEQUENCER_5, effect5);
+    i2cWriteByte(WAVEFORM_SEQUENCER_6, effect6);
+    i2cWriteByte(WAVEFORM_SEQUENCER_7, effect7);
+    i2cWriteByte(WAVEFORM_SEQUENCER_8, effect8);                                         
+}
+
+void DRV2605::play(){
+    i2cWriteByte(MODE, INTERNAL_TRIG);      // Internal Trigger Mode
+    i2cWriteByte(GO, 1);
+}
+
+uint8_t DRV2605::auto_cal_open_loop(float actuator_peak_voltage){
+    // Exit Standby Mode; Enter Auto- Cal Mode
+    mode(AUTO_CAL);
+    
+    /* Set the following registers to the appropriate values:
+        • Rated Voltage (0x16)
+        • Overdrive Voltage (0x17)
+        • Feedback Control (0x1A) – Bits [1:0] can be left blank and will be
+          populated by the auto-calibration engine
+        • Control 1 (0x1B), Control 2 (0x1C), and Control 3 (0x1D)
+        • Mode (0x01) – Set mode to Auto-Calibration
+        • Auto-calibration Memory Interface (0x1E) – the auto-calibration time 
+          can be increased to improve calibration, but can be left as default 
+          for the initial calibration
+    */ 
+    // Rated Voltage (0x16) not referenced for open-loop operation, skip calc
+    
+    // Calc and Set Overdrive Voltage Register (0x17)
+    int od_clamp = (int)(((actuator_peak_voltage*255)/5.6)+0.5);
+    i2cWriteByte(OVERDRIVE_CLAMP_VOLTAGE,
+                 i2cReadByte(OVERDRIVE_CLAMP_VOLTAGE) | od_clamp);
+    
+    // Set Feedback Control Register (0x1A), use default values
+    
+    
+    // Set Control 1 Register (0x1B), use default values
+    
+    
+    // Set Control 2 Register (0x1C), use default values
+    
+    // Set Control3 Register (0x1D), Set to ERM Open-Loop Operation 
+    i2cWriteByte(CONTROL3, 0xA0);   
+
+    // Set Control 4 Register (0x1E)                
+    i2cWriteByte(CONTROL4,
+                 i2cReadByte(CONTROL4 | 0x30)); // Max Calibration Time
+    
+    // Device already set to Auto- Cal Mode at top of this code block
+    
+    // Start auto- calibration
+    i2cWriteByte(GO, 0x01);
+    
+    // Wait for calibration to complete
+    while(i2cReadByte(GO));
+    
+    // Read and return DIAG_RESULT in Status Register (0x00)
+    return (i2cReadByte(STATUS)); // Return the Diag_Result Bit Result
+}
+        
diff -r 000000000000 -r 3b2b4f34aaca DRV2605.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRV2605.h	Wed Oct 21 01:02:59 2015 +0000
@@ -0,0 +1,199 @@
+/*
+    Bryce Williams 10/16/2015
+    
+    Library for the TI DRV2605L 2 to 5.2 V Haptic Driver for LRA and ERM
+    With Effect Library and Smart-Loop Architecture
+     
+    References:
+    http://www.ti.com/product/DRV2605L/description&lpos=Middle_Container&lid=Alternative_Devices
+    http://www.ti.com/lit/ds/symlink/drv2605l.pdf (Datasheet) 
+    http://www.ti.com/lit/an/sloa189/sloa189.pdf (Setup Guide; SLOA189)
+*/
+
+#ifndef DRV2605_H
+#define DRV2605_H
+
+#include "mbed.h"
+
+/******************************************************************************
+***** DRV2605 Addresses
+******************************************************************************/
+#define SLAVE_ADDR_7_BIT 0x5A // 7-bit slave address 
+
+/******************************************************************************
+****** DRV2605 REGISTERS ******************************************************
+******************************************************************************/
+#define STATUS                               0x00
+#define MODE                                 0x01
+#define REAL_TIME_PLAYBACK                   0x02
+#define LIBRARY_SELECTION                    0x03
+#define WAVEFORM_SEQUENCER_1                 0x04
+#define WAVEFORM_SEQUENCER_2                 0x05
+#define WAVEFORM_SEQUENCER_3                 0x06
+#define WAVEFORM_SEQUENCER_4                 0x07
+#define WAVEFORM_SEQUENCER_5                 0x08
+#define WAVEFORM_SEQUENCER_6                 0x09
+#define WAVEFORM_SEQUENCER_7                 0x0A
+#define WAVEFORM_SEQUENCER_8                 0x0B
+#define GO                                   0x0C
+#define OVERDRIVE_TIME_OFFSET                0x0D
+#define POSITIVE_SUSTAIN_TIME_OFFSET         0x0E
+#define NEGATIVE_SUSTAIN_TIME_OFFSET         0x0F
+#define BRAKE_TIME_OFFSET                    0x10
+#define AUDIO_TO_VIBE_CONTROL                0x11
+#define AUDIO_TO_VIBE_MINIMUM_INPUT_LEVEL    0x12
+#define AUDIO_TO_VIBE_MAXIMUM_INPUT_LEVEL    0x13
+#define AUDIO_TO_VIBE_MINIMUM_OUPUT_DRIVE    0x14
+#define AUDIO_TO_VIBE_MAXIMUM_OUTPUT_DRIVE   0x15
+#define RATED_VOLTAGE                        0x16
+#define OVERDRIVE_CLAMP_VOLTAGE              0x17
+#define AUTO_CALIBRATION_COMPENSATION_RESULT 0x18
+#define AUTO_CALIBRATION_BACK_EMF_RESULT     0x19
+#define FEEDBACK_CONTROL                     0x1A
+#define CONTROL                              0x1B
+#define CONTROL2                             0x1C
+#define CONTROL3                             0x1D
+#define CONTROL4                             0x1E
+#define CONTROL5                             0x1F
+#define LRA_OPEN_LOOP_PERIOD                 0x20
+#define VBAT_VOLTAGE_MONITOR                 0x21
+#define LRA_RESONANCE_PERIOD                 0x22
+
+class DRV2605{
+    
+    public:
+        //// modes defines the possible modes of the DRV2605L
+        enum Mode{
+            INTERNAL_TRIG,   // 0x00: Waveforms fired by Setting GO bit in Register 0x0C
+            EXTERNAL_EDGE,   // 0x01: Rising Edge on IN/TRIG pin set GO Bit.
+            EXTERNAL_LEVEL,  // 0x02: GO bit follows state of edge on IN/TRIG pin. 
+            PWM_ANALOG,      // 0x03: PWM or Analog Signal accepted at IN/TRIG pin.
+            AUDIO_TO_VIBE,   // 0x04: An AC-coupled audio signal is accepted at the IN/TRIG pin.
+            RTP,             // 0x05: Real- Time Playback
+            DIAG,            // 0x06: Set to perform actuator diagnostics
+            AUTO_CAL,        // 0x07: Set to perform auto calibration of device for actuator 
+            STANDBY = 0x40,  // 0x40: Set Device to Software Standby (Low- Power Mode)
+            RESET = 0x80,    // 0x80: Reset Device (equivalent of power cycling the device)
+         };
+         
+         //// FeedBack_Controls Fields Bitmasks (Register Addr: 0x1A)
+         enum Actuator_Type{ERM = 0, LRA = 0x80}; // bit-7
+         enum Brake_Factor{x1 = 0x00, x2 = 0x10, x3 = 0x20, 
+                           x4 = 0x40, x6 = 0x80, x8 = 0x50, 
+                           x16 = 0x60, DISABLE = 0x70}; // bit-6..4
+         enum Loop_Gain{LOW = 0x00, 
+                        MED = 0x04, 
+                        HIGH = 0x08, 
+                        VERY_HIGH = 0x0C};  // bit-3..2
+                    
+         enum Library{EMPTY, A, B, C, D, E,
+                      LRA_LIB, F};              // ROM Waveform Library Selections
+        
+        /**
+            Constructor for DRV2605 Objects
+        */
+        DRV2605(PinName sda, PinName scl);
+        
+        /**
+            Write value to specified register of device
+            @param reg      The device register to write 
+            @param value    The value to write to the register
+        */
+        void i2cWriteByte(char reg, char value);
+        
+        /**
+            Read value from register of device
+            @param reg  The device register to read
+            @return     The result
+        */
+        uint8_t i2cReadByte(char reg);
+        
+        /**
+            Place device into specified mode
+            @param mode     The mode to place device into
+        */
+        void mode(Mode mode);
+        
+        /**
+            TODO: Expand to allow initialization for LRAs and Closed Loop operation 
+            Initialize the device for Open- Loop ERM mode using specified ROM 
+            Waveform Library as specified in Section 9.3 of Device Datasheet.
+            See also Device Setup Guide 1.6.1 ERM Initialization Example
+            @param actuator_peak_voltage    The Peak Voltage Rating of Actuator
+            @param lib  The ROM Waveform Library to use
+        */
+        int init(float actuator_peak_voltage, Library lib = B);
+        
+        /**
+            Runs diagnostics on the Actuator and Device and returns the results. 
+            The results indicate if an actuator is detected, over- current events, 
+            etc. Refer to STATUS Register (0x00) in device datasheet for more 
+            description register values.
+            
+            Note: This should be run if the user is having trouble getting the actuator 
+            to work.
+            
+            @return The results of the diagnostics (i.e. Status Reg (0x00))
+        */
+        uint8_t diagnostics();
+        
+        /**
+            Play single waveform from ROM Library as outlined in Section 9.3.2.1
+            of Device Datasheet.
+            The library used is the one that is currently written 
+            to the Library_Selection Register (0x03). This library
+            is set in the init(Library lib) method, but can be 
+            changed manually.
+            @param waveform_effect  The Waveform Effect Library Index value to play
+                                    (valid values are 1 to 123)
+        */
+        void play_waveform(int waveform_effect);
+        
+        /**
+            Load Wave Sequence into DRV2605 Sequence Registers
+            @param effect1... effect8   The effect to play. Valid inputs are 
+                                        0 to 123; 0: Stop Condition, 
+                                                  1- 123: Waveform Index
+        */
+        void load_waveform_sequence(int effect1 = 0, int effect2 = 0, 
+                                    int effect3 = 0, int effect4 = 0,
+                                    int effect5 = 0, int effect6 = 0, 
+                                    int effect7 = 0, int effect8 = 0);
+        
+        /**
+            Plays the currently loaded waveform or waveform sequence. 
+            Call this after calling play_waveform() or after calling 
+            load_waveform_sequence()
+            Preconditions: User must have already loaded waveform(s) 
+                           using play_waveform() or load_waveform_sequence()
+        */
+        void play();
+        
+        /**
+            TODO: Add Closed Loop Calibration
+            
+            Run basic DRV2605L Auto- Calibration as detailed in Section 2 of 
+            the Device Setup Guide for OPEN- LOOP ONLY.
+            This must be done before using the device in closed- loop mode 
+            (unless cal has been done before with values stored in non-volatile
+             mem; see datasheet for more info). 
+                
+            NOTE: It is NOT recommended to store cal values into device 
+            non-volatile memory as this can be done only once. Thus do not 
+            use this feature unless the device is being used in a final 
+            project AND values have been confirmed to result in satisfactory 
+            performance).
+                
+            This uses many of the default device register values such as
+            the default DRIVE_TIME .
+
+            @param actuator_peak_voltage The maximum/peak voltage rating of the actuator
+        */
+        uint8_t auto_cal_open_loop(float actuator_peak_voltage);        
+          
+    private:
+    I2C i2c;
+    
+};
+
+#endif
\ No newline at end of file