I2C Piezo Haptic Driver with Integrated Boost Converter and Digital Front End

Committer:
akashvibhute
Date:
Mon May 30 06:59:36 2016 +0000
Revision:
1:e2c726c628dc
Parent:
0:b85fd3fdfcfa
working library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akashvibhute 0:b85fd3fdfcfa 1 /**
akashvibhute 0:b85fd3fdfcfa 2 * DRV2665 library
akashvibhute 0:b85fd3fdfcfa 3 *
akashvibhute 0:b85fd3fdfcfa 4 * @author Akash Vibhute
akashvibhute 0:b85fd3fdfcfa 5 * @author < akash . roboticist [at] gmail . com >
akashvibhute 0:b85fd3fdfcfa 6 * @version 0.1
akashvibhute 0:b85fd3fdfcfa 7 * @date May/24/2016
akashvibhute 0:b85fd3fdfcfa 8 */
akashvibhute 0:b85fd3fdfcfa 9
akashvibhute 0:b85fd3fdfcfa 10 #include "drv2665.h"
akashvibhute 0:b85fd3fdfcfa 11 #define M_PI 3.14159265358979
akashvibhute 0:b85fd3fdfcfa 12
akashvibhute 1:e2c726c628dc 13 static const uint8_t drv2665_sine_wave_form[] = {
akashvibhute 1:e2c726c628dc 14 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66,
akashvibhute 1:e2c726c628dc 15 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10,
akashvibhute 1:e2c726c628dc 16 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a,
akashvibhute 1:e2c726c628dc 17 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
akashvibhute 1:e2c726c628dc 18 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66,
akashvibhute 1:e2c726c628dc 19 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10,
akashvibhute 1:e2c726c628dc 20 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a,
akashvibhute 1:e2c726c628dc 21 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
akashvibhute 1:e2c726c628dc 22 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66,
akashvibhute 1:e2c726c628dc 23 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10,
akashvibhute 1:e2c726c628dc 24 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a,
akashvibhute 1:e2c726c628dc 25 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
akashvibhute 1:e2c726c628dc 26 };
akashvibhute 1:e2c726c628dc 27
akashvibhute 0:b85fd3fdfcfa 28 DRV2665_DIGITAL::DRV2665_DIGITAL( PinName sda, PinName scl ):i2c_(sda, scl)
akashvibhute 0:b85fd3fdfcfa 29 {
akashvibhute 1:e2c726c628dc 30 i2c_.frequency(100000);
akashvibhute 0:b85fd3fdfcfa 31 i2c_addr = DRV2665_I2C_ADDRESS << 1;
akashvibhute 0:b85fd3fdfcfa 32 wait_ms(2); //wait 2ms for i2c bus
akashvibhute 0:b85fd3fdfcfa 33 }
akashvibhute 0:b85fd3fdfcfa 34
akashvibhute 0:b85fd3fdfcfa 35 void DRV2665_DIGITAL::init(uint8_t output_gain, uint8_t idle_timeout)
akashvibhute 0:b85fd3fdfcfa 36 {
akashvibhute 1:e2c726c628dc 37 write(DRV2665_CTRL_2, DRV2665_DEV_RST); //reset
akashvibhute 0:b85fd3fdfcfa 38 write(DRV2665_CTRL_2, 0); //clear standby
akashvibhute 1:e2c726c628dc 39 //write(DRV2665_CTRL_1, (DRV2665_DIGITAL_IN | output_gain)); //set mode digital, set gain
akashvibhute 1:e2c726c628dc 40 write(DRV2665_CTRL_1, DRV2665_DIGITAL_IN); //set mode digital, set gain
akashvibhute 1:e2c726c628dc 41 write(DRV2665_CTRL_1, DRV2665_100_VPP_GAIN); //set mode digital, set gain
akashvibhute 0:b85fd3fdfcfa 42 write(DRV2665_CTRL_2, idle_timeout); //set timeout period
akashvibhute 0:b85fd3fdfcfa 43 }
akashvibhute 0:b85fd3fdfcfa 44
akashvibhute 0:b85fd3fdfcfa 45 void DRV2665_DIGITAL::reset()
akashvibhute 0:b85fd3fdfcfa 46 {
akashvibhute 0:b85fd3fdfcfa 47 write(DRV2665_CTRL_2, DRV2665_DEV_RST);
akashvibhute 0:b85fd3fdfcfa 48 }
akashvibhute 0:b85fd3fdfcfa 49
akashvibhute 0:b85fd3fdfcfa 50 void DRV2665_DIGITAL::outputWave(int8_t waveform[], uint8_t length)
akashvibhute 0:b85fd3fdfcfa 51 {
akashvibhute 1:e2c726c628dc 52 char reg;
akashvibhute 1:e2c726c628dc 53 char buff[100];
akashvibhute 1:e2c726c628dc 54
akashvibhute 1:e2c726c628dc 55 buff[0] = DRV2665_FIFO;
akashvibhute 1:e2c726c628dc 56 length = 81;
akashvibhute 1:e2c726c628dc 57
akashvibhute 1:e2c726c628dc 58 /*
akashvibhute 1:e2c726c628dc 59 for(int i=0; i<length; i++)
akashvibhute 1:e2c726c628dc 60 buff[i+1] = drv2665_sine_wave_form[i];
akashvibhute 1:e2c726c628dc 61
akashvibhute 1:e2c726c628dc 62 //while(!fifo_check());
akashvibhute 1:e2c726c628dc 63
akashvibhute 1:e2c726c628dc 64 i2c_.write(i2c_addr, buff, 42);
akashvibhute 1:e2c726c628dc 65 */
akashvibhute 1:e2c726c628dc 66
akashvibhute 0:b85fd3fdfcfa 67 if(fifo_check()) {
akashvibhute 1:e2c726c628dc 68 //i2c_.write(i2c_addr, buff, 42);
akashvibhute 1:e2c726c628dc 69
akashvibhute 0:b85fd3fdfcfa 70 for(int i=0; i<length; i++) {
akashvibhute 1:e2c726c628dc 71 write(DRV2665_FIFO, drv2665_sine_wave_form[i]);
akashvibhute 1:e2c726c628dc 72 wait_us(20);
akashvibhute 0:b85fd3fdfcfa 73 }
akashvibhute 1:e2c726c628dc 74
akashvibhute 0:b85fd3fdfcfa 75 } else
akashvibhute 0:b85fd3fdfcfa 76 return;
akashvibhute 1:e2c726c628dc 77
akashvibhute 0:b85fd3fdfcfa 78 }
akashvibhute 0:b85fd3fdfcfa 79
akashvibhute 0:b85fd3fdfcfa 80 void DRV2665_DIGITAL::outputSine(uint16_t hz)
akashvibhute 0:b85fd3fdfcfa 81 {
akashvibhute 0:b85fd3fdfcfa 82 int8_t waveform_byte;
akashvibhute 0:b85fd3fdfcfa 83 uint16_t length;
akashvibhute 1:e2c726c628dc 84 uint8_t repeat = 1;
akashvibhute 0:b85fd3fdfcfa 85
akashvibhute 0:b85fd3fdfcfa 86 //in the linux driver example, a 41 byte waveform plays back at 8kHz
akashvibhute 0:b85fd3fdfcfa 87 //wavelength 41 -> wave time 125us -> frequency 8kHz
akashvibhute 0:b85fd3fdfcfa 88 //hence per byte sampling time = 125us / 41 = 3.04878049
akashvibhute 0:b85fd3fdfcfa 89 //ie 41 bytes :: 8kHz -> 328 bytes :: 1000Hz
akashvibhute 0:b85fd3fdfcfa 90 //calculations done here are from this factor
akashvibhute 0:b85fd3fdfcfa 91
akashvibhute 1:e2c726c628dc 92 //length = (1000 * 328) / hz;
akashvibhute 0:b85fd3fdfcfa 93
akashvibhute 1:e2c726c628dc 94
akashvibhute 0:b85fd3fdfcfa 95 //If the above assumption is incorrect, it could be that the DRV plays
akashvibhute 0:b85fd3fdfcfa 96 //anything in its FIFO at a fix rate of 8ksps in that case, it would mean
akashvibhute 0:b85fd3fdfcfa 97 //a per byte play time of 125us, ie for a 100byte wavelength -> a playback
akashvibhute 1:e2c726c628dc 98 //time of 12.5ms (80Hz)
akashvibhute 1:e2c726c628dc 99 //So, 100B :: 80Hz -> 100*80B :: 1Hz
akashvibhute 1:e2c726c628dc 100 //For 'n' Hz :: (100*80/n) B
akashvibhute 0:b85fd3fdfcfa 101
akashvibhute 1:e2c726c628dc 102 length = (100 * 80) / hz;
akashvibhute 0:b85fd3fdfcfa 103
akashvibhute 0:b85fd3fdfcfa 104
akashvibhute 1:e2c726c628dc 105 for(int j=0; j<repeat; j++) {
akashvibhute 0:b85fd3fdfcfa 106
akashvibhute 1:e2c726c628dc 107 for(int i=0; i<length; i++) {
akashvibhute 1:e2c726c628dc 108 waveform_byte = 100.0 * sin( 2*M_PI * i/(length-1) ); //102 is the max +ve / -ve value, typecasting in uint8 turns -ve values into 2's complement required by the driver
akashvibhute 1:e2c726c628dc 109
akashvibhute 1:e2c726c628dc 110 write(DRV2665_FIFO, (uint8_t)waveform_byte);
akashvibhute 1:e2c726c628dc 111 wait_us(20);
akashvibhute 1:e2c726c628dc 112 }
akashvibhute 0:b85fd3fdfcfa 113 }
akashvibhute 0:b85fd3fdfcfa 114 }
akashvibhute 0:b85fd3fdfcfa 115
akashvibhute 0:b85fd3fdfcfa 116 bool DRV2665_DIGITAL::fifo_check()
akashvibhute 0:b85fd3fdfcfa 117 {
akashvibhute 0:b85fd3fdfcfa 118 uint8_t reply;
akashvibhute 0:b85fd3fdfcfa 119 reply = read(DRV2665_STATUS);
akashvibhute 0:b85fd3fdfcfa 120
akashvibhute 0:b85fd3fdfcfa 121 if((reply & 0x01) == 0)
akashvibhute 0:b85fd3fdfcfa 122 return(true);
akashvibhute 0:b85fd3fdfcfa 123 else
akashvibhute 0:b85fd3fdfcfa 124 return(false);
akashvibhute 0:b85fd3fdfcfa 125 }
akashvibhute 0:b85fd3fdfcfa 126
akashvibhute 1:e2c726c628dc 127 void DRV2665_DIGITAL::en_override(uint8_t en)
akashvibhute 0:b85fd3fdfcfa 128 {
akashvibhute 1:e2c726c628dc 129 char buff[2];
akashvibhute 1:e2c726c628dc 130
akashvibhute 1:e2c726c628dc 131 buff[0] = DRV2665_BOOST_EN;
akashvibhute 1:e2c726c628dc 132 buff[1] = en;
akashvibhute 1:e2c726c628dc 133
akashvibhute 0:b85fd3fdfcfa 134 write(DRV2665_CTRL_2, DRV2665_BOOST_EN);
akashvibhute 0:b85fd3fdfcfa 135 }
akashvibhute 0:b85fd3fdfcfa 136
akashvibhute 0:b85fd3fdfcfa 137 uint8_t DRV2665_DIGITAL::read(char reg)
akashvibhute 0:b85fd3fdfcfa 138 {
akashvibhute 0:b85fd3fdfcfa 139 //Create a temporary buffer
akashvibhute 0:b85fd3fdfcfa 140 char buff[2];
akashvibhute 0:b85fd3fdfcfa 141
akashvibhute 0:b85fd3fdfcfa 142 //Select the register
akashvibhute 0:b85fd3fdfcfa 143 i2c_.write(i2c_addr, &reg, 1, true);
akashvibhute 0:b85fd3fdfcfa 144
akashvibhute 0:b85fd3fdfcfa 145 //Read the 16-bit register
akashvibhute 0:b85fd3fdfcfa 146 i2c_.read(i2c_addr, buff, 2);
akashvibhute 0:b85fd3fdfcfa 147
akashvibhute 0:b85fd3fdfcfa 148 //Return the combined 16-bit value
akashvibhute 0:b85fd3fdfcfa 149 return (buff[0] << 8) | buff[1];
akashvibhute 0:b85fd3fdfcfa 150 }
akashvibhute 0:b85fd3fdfcfa 151
akashvibhute 0:b85fd3fdfcfa 152 void DRV2665_DIGITAL::write(char reg, uint8_t data)
akashvibhute 0:b85fd3fdfcfa 153 {
akashvibhute 0:b85fd3fdfcfa 154 //Create a temporary buffer
akashvibhute 0:b85fd3fdfcfa 155 char buff[2];
akashvibhute 0:b85fd3fdfcfa 156
akashvibhute 0:b85fd3fdfcfa 157 //Load the register address and 16-bit data
akashvibhute 0:b85fd3fdfcfa 158 buff[0] = reg;
akashvibhute 0:b85fd3fdfcfa 159 buff[1] = data;
akashvibhute 0:b85fd3fdfcfa 160
akashvibhute 0:b85fd3fdfcfa 161 //Write the data
akashvibhute 0:b85fd3fdfcfa 162 i2c_.write(i2c_addr, buff, 2);
akashvibhute 0:b85fd3fdfcfa 163 }