I2C Piezo Haptic Driver with Integrated Boost Converter and Digital Front End
drv2665.cpp
- Committer:
- akashvibhute
- Date:
- 2016-05-30
- Revision:
- 1:e2c726c628dc
- Parent:
- 0:b85fd3fdfcfa
File content as of revision 1:e2c726c628dc:
/** * DRV2665 library * * @author Akash Vibhute * @author < akash . roboticist [at] gmail . com > * @version 0.1 * @date May/24/2016 */ #include "drv2665.h" #define M_PI 3.14159265358979 static const uint8_t drv2665_sine_wave_form[] = { 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66, 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10, 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a, 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66, 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10, 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a, 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66, 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10, 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a, 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00, }; DRV2665_DIGITAL::DRV2665_DIGITAL( PinName sda, PinName scl ):i2c_(sda, scl) { i2c_.frequency(100000); i2c_addr = DRV2665_I2C_ADDRESS << 1; wait_ms(2); //wait 2ms for i2c bus } void DRV2665_DIGITAL::init(uint8_t output_gain, uint8_t idle_timeout) { write(DRV2665_CTRL_2, DRV2665_DEV_RST); //reset write(DRV2665_CTRL_2, 0); //clear standby //write(DRV2665_CTRL_1, (DRV2665_DIGITAL_IN | output_gain)); //set mode digital, set gain write(DRV2665_CTRL_1, DRV2665_DIGITAL_IN); //set mode digital, set gain write(DRV2665_CTRL_1, DRV2665_100_VPP_GAIN); //set mode digital, set gain write(DRV2665_CTRL_2, idle_timeout); //set timeout period } void DRV2665_DIGITAL::reset() { write(DRV2665_CTRL_2, DRV2665_DEV_RST); } void DRV2665_DIGITAL::outputWave(int8_t waveform[], uint8_t length) { char reg; char buff[100]; buff[0] = DRV2665_FIFO; length = 81; /* for(int i=0; i<length; i++) buff[i+1] = drv2665_sine_wave_form[i]; //while(!fifo_check()); i2c_.write(i2c_addr, buff, 42); */ if(fifo_check()) { //i2c_.write(i2c_addr, buff, 42); for(int i=0; i<length; i++) { write(DRV2665_FIFO, drv2665_sine_wave_form[i]); wait_us(20); } } else return; } void DRV2665_DIGITAL::outputSine(uint16_t hz) { int8_t waveform_byte; uint16_t length; uint8_t repeat = 1; //in the linux driver example, a 41 byte waveform plays back at 8kHz //wavelength 41 -> wave time 125us -> frequency 8kHz //hence per byte sampling time = 125us / 41 = 3.04878049 //ie 41 bytes :: 8kHz -> 328 bytes :: 1000Hz //calculations done here are from this factor //length = (1000 * 328) / hz; //If the above assumption is incorrect, it could be that the DRV plays //anything in its FIFO at a fix rate of 8ksps in that case, it would mean //a per byte play time of 125us, ie for a 100byte wavelength -> a playback //time of 12.5ms (80Hz) //So, 100B :: 80Hz -> 100*80B :: 1Hz //For 'n' Hz :: (100*80/n) B length = (100 * 80) / hz; for(int j=0; j<repeat; j++) { for(int i=0; i<length; i++) { 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 write(DRV2665_FIFO, (uint8_t)waveform_byte); wait_us(20); } } } bool DRV2665_DIGITAL::fifo_check() { uint8_t reply; reply = read(DRV2665_STATUS); if((reply & 0x01) == 0) return(true); else return(false); } void DRV2665_DIGITAL::en_override(uint8_t en) { char buff[2]; buff[0] = DRV2665_BOOST_EN; buff[1] = en; write(DRV2665_CTRL_2, DRV2665_BOOST_EN); } uint8_t DRV2665_DIGITAL::read(char reg) { //Create a temporary buffer char buff[2]; //Select the register i2c_.write(i2c_addr, ®, 1, true); //Read the 16-bit register i2c_.read(i2c_addr, buff, 2); //Return the combined 16-bit value return (buff[0] << 8) | buff[1]; } void DRV2665_DIGITAL::write(char reg, uint8_t data) { //Create a temporary buffer char buff[2]; //Load the register address and 16-bit data buff[0] = reg; buff[1] = data; //Write the data i2c_.write(i2c_addr, buff, 2); }