I2C Piezo Haptic Driver with Integrated Boost Converter and Digital Front End
drv2665.cpp@1:e2c726c628dc, 2016-05-30 (annotated)
- 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?
User | Revision | Line number | New 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, ®, 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 | } |