//Cleaned up 3/26 CMH #ifdef __cplusplus extern "C" { #endif /*================================================================================================== INCLUDE FILES ==================================================================================================*/ #include "te9_tf9_hybrid_driver.h" #include "i2c-dev.h" /*================================================================================================== LOCAL VARIABLES ==================================================================================================*/ #ifdef KX_PLATFORM_LINUX static int fd = 0; //local file descriptor for the /dev/i2c interface static int block = 0; //flag for block read functionality (1=block, 0=no block) #endif static int device = 0; //flag to indicate device KXTE9=0, KXTF9=1 #ifdef KX_PLATFORM_REX LOCAL rex_crit_sect_type tf9_crit_sect; #else int tf9_crit_sect; #endif unsigned char gpio_int_type; /*================================================================================================== COMMON FUNCTIONS ==================================================================================================*/ // TODO: #ifdef KX_PLATFORM_REX extern sky_accel_mode_type sky_accel_current_mode; extern i2c_status_type accel_i2c_write(unsigned char dev_addr, unsigned char addr, unsigned char *data, unsigned char length); extern i2c_status_type accel_i2c_read(unsigned char dev_addr, unsigned char addr, unsigned char *data, unsigned char length); extern void accel_process_landscape(unsigned char tilt_pos_pre, unsigned char tilt_pos_cur); extern void accel_process_updown(unsigned char tilt_pos_pre, unsigned char tilt_pos_cur); extern void accel_process_tap(unsigned char tap_mode, unsigned char tap_direction); #elif defined(KX_PLATFORM_FIRMWARE) void Wr24C080(U32 slvAddr,U32 addr,U8 data); void Rd24C080(U32 slvAddr,U32 addr,U8 *data); void _Wr24C080(U32 slvAddr,U32 addr,U8 data); void _Rd24C080(U32 slvAddr,U32 addr,U8 *data); #endif /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_bytes DESCRIPTION: This function reads data from the Kionix accelerometer in bytes. ARGUMENTS PASSED: register address, data pointer, length in number of bytes RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None IMPORTANT NOTES: Using the i2c_smbus functions requires the inclusion of the i2c-dev.h file available in the lm-sensors package. ==================================================================================================*/ int KIONIX_ACCEL_read_bytes(int reg, char* data, int length) { int status = 0; int ret = 0; int i; KIONIX_EnterCriticalSection(&tf9_crit_sect); #ifdef KX_PLATFORM_LINUX if (block == 1){ status = i2c_smbus_read_i2c_block_data(fd, reg, length, (__u8*)data); if(status < 0){ //status will be number of bytes read, negative if read failed //printf("Read failed on register 0x%02x\n", reg); KIONIX_LeaveCriticalSection(&tf9_crit_sect); return 1; } } else if (block == 0){ for (i = 0; i < length; i++){ ret = i2c_smbus_read_byte_data(fd, reg + i); if (ret < 0){ //status will be the data retrieved in the byte read //printf("Read failed on register 0x%02x\n", (reg + i)); return 1; } else data[i] = (char)ret; } } else { KIONIX_LeaveCriticalSection(&tf9_crit_sect); return 1; } #elif defined(KX_PLATFORM_WIN32) || defined(KX_PLATFORM_WINCE) #elif defined(KX_PLATFORM_REX) status = accel_i2c_read(KIONIX_ACCEL_I2C_SLV_ADDR, reg, &data[0], length); #elif defined(KX_PLATFORM_FIRMWARE) #ifdef USE_I2C_GPIO { unsigned char wb[2], rb[2]; wb[0] = reg; i2c_read(KIONIX_ACCEL_I2C_SLV_ADDR, &wb[0], 1, &data[0], length); } #elif defined(USE_I2C_INT) for(i=0; i>2); KIONIX_ACCEL_process_directional_tap(tap_mode, int_src_reg1); // tap_mode(single/dobule), tap_direction } if(int_src_reg2 & BIT(0) ) { // TPS KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_TILT_POS_CUR, &tilt_pos_cur, 1); KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_TILT_POS_PRE, &tilt_pos_pre, 1); KIONIX_ACCEL_process_screen_rotation(tilt_pos_pre, tilt_pos_cur); } if(int_src_reg2 & BIT(1)) { // WUFS KIONIX_ACCEL_process_motion_detection(int_src_reg1, int_src_reg2); } break; case 2: // KXSD9 break; } RELEASE_INT: KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_INT_REL, &int_rel, 1); // enable accelerometer interrupt again KIONIX_ACCEL_enable_interrupt(); KX_INTFREE( ); #if 0 int return_status = 1; char dummy = 0; if (device == 0){ //KXTE9 // read the interrupt source register if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_SRC_REG2, (char *)source_of_interrupt, 1) == 0){ // clear the interrupt source information along with interrupt pin if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_INT_REL, &dummy, 1) == 0){ return_status = 0; } else return_status = 1; } else return_status = 1; } else if (device == 1){ //KXTF9 // read the interrupt source register if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG2, (char *)source_of_interrupt, 1) == 0){ // clear the interrupt source information along with interrupt pin if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_INT_REL, &dummy, 1) == 0){ return_status = 0; } else return_status = 1; } else return_status = 1; } else return_status = 1; return return_status; #endif // end of #if 0 } /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_LPF_cnt DESCRIPTION: This function reads the number of counts on the X, Y, and Z axes. ARGUMENTS PASSED: x, y, and z pointers RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: x, y, and z are assigned ==================================================================================================*/ int KIONIX_ACCEL_read_LPF_cnt(int* x, int* y, int* z) { int status, x_sign, y_sign, z_sign; char Res, x_char; char ret[3] = {0, 0, 0}; char xyz[6] = {0, 0, 0, 0, 0, 0}; if (device == 0){ //KXTE9 status = KIONIX_ACCEL_read_bytes(KXTE9_I2C_XOUT, ret, 3); if(status == 0){ *x = (int)(ret[0]) >> 2; *y = (int)(ret[1]) >> 2; *z = (int)(ret[2]) >> 2; } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &Res, 1) == 0){ Res = Res & 0x40; switch(Res){ case 0x00: //low-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_L, xyz, 6)) == 0){ *x = ((int)xyz[1]); x_sign = *x >> 7; //1 = negative; 0 = positive if (x_sign == 1){ *x = ((~(*x) + 0x01) & 0x0FF); *x = -(*x); } *y = ((int)xyz[3]); y_sign = *y >> 7; //1 = negative; 0 = positive if (y_sign == 1){ *y = ((~(*y) + 0x01) & 0x0FF); //2's complement *y = -(*y); } *z = ((int)xyz[5]); z_sign = *z >> 7; //1 = negative; 0 = positive if (z_sign == 1){ *z = ((~(*z) + 0x01) & 0x0FF); //2's complement *z = -(*z); } } break; case 0x40: //high-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_L, xyz, 6)) == 0){ *x = ((int)xyz[0]) >> 4; *x = *x + (((int)xyz[1]) << 4); x_sign = *x >> 11; //1 = negative; 0 = positive if (x_sign == 1){ *x = ((~(*x) + 0x01) & 0x0FFF); //2's complement *x = -(*x); } *y = ((int)xyz[2]) >> 4; *y = *y + (((int)xyz[3]) << 4); y_sign = *y >> 11; //1 = negative; 0 = positive if (y_sign == 1){ *y = ((~(*y) + 0x01) & 0x0FFF); //2's complement *y = -(*y); } *z = ((int)xyz[4]) >> 4; *z = *z + (((int)xyz[5]) << 4); z_sign = *z >> 11; //1 = negative; 0 = positive if (z_sign == 1){ *z = ((~(*z) + 0x01) & 0x0FFF); //2's complement *z = -(*z); } } break; } } } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_LPF_g DESCRIPTION: This function reads the G(gravity force) values on the X, Y, and Z axes. The units used are milli-g's, or 1/1000*G. ARGUMENTS PASSED: gx, gy, and gz pointers RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: gx, gy, and gz are assigned ==================================================================================================*/ int KIONIX_ACCEL_read_LPF_g(int* gx, int* gy, int* gz) { int status, sensitivity; int x = 0; int y = 0; int z = 0; int x_sign, y_sign, z_sign; char xyz[6] = {0, 0, 0, 0, 0, 0}; char Res = 0; char G_range = 0; int range = 0; if (device == 0){ //KXTE9 sensitivity = BIT_SENSITIVITY_2_G; if ((status = KIONIX_ACCEL_read_LPF_cnt(&x, &y, &z)) == 0){ /* calculate milli-G's */ *gx = 1000 * (x - ZERO_G_OFFSET) / sensitivity; *gy = 1000 * (y - ZERO_G_OFFSET) / sensitivity; *gz = 1000 * (z - ZERO_G_OFFSET) / sensitivity; } else status = 1; } else if (device == 1){ //KXTF9 //determine if in the low resolution or high resolution state if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &Res, 1) == 0){ if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &G_range, 1) == 0){ G_range = G_range & 0x18; G_range = G_range >> 3; switch(G_range){ case 0: range = 2; break; case 1: range = 4; break; case 2: range = 8; break; default: break; } Res = Res & 0x40; switch(Res){ case 0x00: //low-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_L, xyz, 6)) == 0){ x = ((int)xyz[1]); x_sign = x >> 7; //1 = negative; 0 = positive if (x_sign == 1){ x = ((~(x) + 0x01) & 0x0FF); x = -(x); } y = ((int)xyz[3]); y_sign = y >> 7; //1 = negative; 0 = positive if (y_sign == 1){ y = ((~(y) + 0x01) & 0x0FF); //2's complement y = -(y); } z = ((int)xyz[5]); z_sign = z >> 7; //1 = negative; 0 = positive if (z_sign == 1){ z = ((~(z) + 0x01) & 0x0FF); //2's complement z = -(z); } sensitivity = (256)/(2*range); /* calculate milli-G's */ *gx = 1000 * (x) / sensitivity; *gy = 1000 * (y) / sensitivity; *gz = 1000 * (z) / sensitivity; } break; case 0x40: //high-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_L, xyz, 6)) == 0){ x = ((int)xyz[0]) >> 4; x = x + (((int)xyz[1]) << 4); x_sign = x >> 11; //1 = negative; 0 = positive if (x_sign == 1){ x = ((~(x) + 0x01) & 0x0FFF); //2's complement x = -(x); } y = ((int)xyz[2]) >> 4; y = y + (((int)xyz[3]) << 4); y_sign = y >> 11; //1 = negative; 0 = positive if (y_sign == 1){ y = ((~(y) + 0x01) & 0x0FFF); //2's complement y = -(y); } z = ((int)xyz[4]) >> 4; z = z + (((int)xyz[5]) << 4); z_sign = z >> 11; //1 = negative; 0 = positive if (z_sign == 1){ z = ((~(z) + 0x01) & 0x0FFF); //2's complement z = -(z); } sensitivity = (4096)/(2*range); /* calculate milli-G's */ *gx = 1000 * (x) / sensitivity; *gy = 1000 * (y) / sensitivity; *gz = 1000 * (z) / sensitivity; } break; default: break; } } else status = 1; } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_current_odr_motion DESCRIPTION: This function reads the current ODR of the general motion function. ARGUMENTS PASSED: ODR_rate_motion pointer RETURN VALUE: 0 = ODR set correctly; 1 = ODR invalid PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: ODR_rate_motion is assigned ==================================================================================================*/ int KIONIX_ACCEL_read_current_odr_motion(double* ODR_rate_motion) { int status; char status_reg, ctrl_reg; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_STATUS_REG, &status_reg, 1) == 0){ status_reg &= 0x0C; status_reg >>= 2; switch (status_reg){ case 0: *ODR_rate_motion = 1; status = 0; break; case 1: *ODR_rate_motion = 3; status = 0; break; case 2: *ODR_rate_motion = 10; status = 0; break; case 3: *ODR_rate_motion = 40; status = 0; break; default: status = 1; break; } } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG3, &ctrl_reg, 1) == 0){ ctrl_reg &= 0x03; ctrl_reg >>= 2; switch (ctrl_reg){ case 0: *ODR_rate_motion = 25; status = 0; break; case 1: *ODR_rate_motion = 50; status = 0; break; case 2: *ODR_rate_motion = 100; status = 0; break; case 3: *ODR_rate_motion = 200; status = 0; break; default: status = 1; break; } } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_position_status DESCRIPTION: This function reads INT_SRC_REG to determine if there was a change in tilt. ARGUMENTS PASSED: None RETURN VALUE: 0 = tilt occurred; 1 = no tilt occurred PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None ==================================================================================================*/ int KIONIX_ACCEL_read_position_status(void) { int position_status; char src_reg1, src_reg2; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_SRC_REG1, &src_reg1, 1) == 0){ if((src_reg1 & 0x01) == 1){ position_status = 0; } else position_status = 1; } else position_status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG2, &src_reg2, 1) == 0){ if((src_reg2 & 0x01) == 1){ position_status = 0; } else position_status = 1; } else position_status = 1; } else position_status = 1; return position_status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_read_wuf_status DESCRIPTION: This function reads INT_SRC_REG1 to determine if wake up occurred. ARGUMENTS PASSED: None RETURN VALUE: 0 = wake up occurred; 1 = no wake up occurred PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None ==================================================================================================*/ int KIONIX_ACCEL_read_wuf_status(void) { int wuf_status; char src_reg1, src_reg2; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_SRC_REG1, &src_reg1, 1) == 0){ if((src_reg1 & 0x02) == 0x02){ wuf_status = 0; } else wuf_status = 1; } else wuf_status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG2, &src_reg2, 1) == 0){ if((src_reg2 & 0x02) == 0x02){ wuf_status = 0; } else wuf_status = 1; } else wuf_status = 1; } else wuf_status = 1; return wuf_status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_enable_int DESCRIPTION: This function enables the physical interrupt. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt enabled ==================================================================================================*/ int KIONIX_ACCEL_enable_int(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEN); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEN); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_disable_int DESCRIPTION: This function disables the physical interrupt. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt disabled ==================================================================================================*/ int KIONIX_ACCEL_disable_int(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEN); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEN); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_int_activeh DESCRIPTION: This function sets the polarity of physical interrupt pin to active high. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt set to active high ==================================================================================================*/ int KIONIX_ACCEL_int_activeh(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEA); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEA); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_int_activel DESCRIPTION: This function sets the polarity of physical interrupt pin to active low. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt set to active low ==================================================================================================*/ int KIONIX_ACCEL_int_activel(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEA); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEA); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_int_latch DESCRIPTION: This function sets the physical interrupt to a latch state. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt set to latched response ==================================================================================================*/ int KIONIX_ACCEL_int_latch(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEL); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEL); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_int_pulse DESCRIPTION: This function sets the physical interrupt to a pulse state. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Physical interrupt set to pulse response ==================================================================================================*/ int KIONIX_ACCEL_int_pulse(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTE9_INT_CTRL_REG1_IEL); KIONIX_ACCEL_write_byte(KXTE9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else if (device == 1){ //KXTF9 if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_IEL); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; } else status = 1; return status; } /*================================================================================================== KXTE9-SPECIFIC FUNCTIONS ==================================================================================================*/ /*================================================================================================== FUNCTION: KIONIX_ACCEL_enable_back_to_sleep DESCRIPTION: This function enables the back to sleep function. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Back to sleep is enabled ==================================================================================================*/ int KIONIX_ACCEL_enable_back_to_sleep(void) { char ctlreg_1 = 0; int status = 0; if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctlreg_1, 1) == 0){ SET_REG_BIT(ctlreg_1, CTRL_REG1_B2SE); /* set the B2SE bit to enable back to sleep function */ KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG1, ctlreg_1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KIONIX_ACCEL_disable_back_to_sleep DESCRIPTION: This function disables the back to sleep function. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Back to sleep is disabled ==================================================================================================*/ int KIONIX_ACCEL_disable_back_to_sleep(void) { char ctlreg_1 = 0; int status = 0; if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctlreg_1, 1) == 0){ UNSET_REG_BIT(ctlreg_1, CTRL_REG1_B2SE); /* unset the B2SE bit to disable back to sleep function */ KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG1, ctlreg_1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTE9_read_b2s_status DESCRIPTION: This function reads INT_SRC_REG1 to determine if back to sleep occurred. ARGUMENTS PASSED: None RETURN VALUE: 0 = back to sleep occurred; 1 = back to sleep did not occur PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None ==================================================================================================*/ int KXTE9_read_b2s_status(void) { int wuf_status; char src_reg1; if (device == 1){ //KXTF9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTE9_I2C_INT_SRC_REG1, &src_reg1, 1) == 0){ if((src_reg1 & 0x04) == 0x04){ wuf_status = 0; } else wuf_status = 1; } else wuf_status = 1; return wuf_status; } /*================================================================================================== FUNCTION: KXTE9_b2s_timer DESCRIPTION: This function sets the number of back-to-sleep debounce samples. ARGUMENTS PASSED: b2s_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Back-to-sleep debounce set according to b2s_timer ==================================================================================================*/ int KXTE9_b2s_timer(int b2s_timer) { int status; if (device == 1){ //KXTF9 return 1; } if (KIONIX_ACCEL_write_byte(KXTE9_I2C_B2S_TIMER, b2s_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTE9_b2s_thresh DESCRIPTION: This function defines the threshold for back-to-sleep detection. ARGUMENTS PASSED: b2s_thresh ; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Back-to-sleep function threshold set according to b2s_thresh IMPORTANT NOTES: Default: 1.5g (0x60h) ==================================================================================================*/ int KXTE9_b2s_thresh(int b2s_thresh) { int status; if (device == 1){ //KXTF9 return 1; } if (KIONIX_ACCEL_write_byte(KXTE9_I2C_B2S_THRESH, b2s_thresh) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== KXTF9-SPECIFIC FUNCTIONS ==================================================================================================*/ /*================================================================================================== FUNCTION: KXTF9_enable_tap_detection DESCRIPTION: This function enables the tap detection function. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Tap detection is enabled ==================================================================================================*/ int KXTF9_enable_tap_detection(void) { char ctlreg_1 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctlreg_1, 1) == 0){ SET_REG_BIT(ctlreg_1, CTRL_REG1_TDTE); /* set TDTE bit to enable tap function */ KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG1, ctlreg_1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_disable_tap_detection DESCRIPTION: This function disables the tap detection function. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Tap detection is disabled ==================================================================================================*/ int KXTF9_disable_tap_detection(void) { char ctlreg_1 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctlreg_1, 1) == 0){ UNSET_REG_BIT(ctlreg_1, CTRL_REG1_TDTE); /* unset the TDTE bit to disable tap function */ KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG1, ctlreg_1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_read_single_tap_status DESCRIPTION: This function reads INT_SRC_REG2 to determine whether a single tap event occurred. ARGUMENTS PASSED: None RETURN VALUE: 0 = single tap occurred; 1 = single tap did not occur PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None ==================================================================================================*/ int KXTF9_read_single_tap_status(void) { int single_tap; char src_reg2; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG2, &src_reg2, 1) == 0){ if((src_reg2 & 0x0C) == 0x04){ single_tap = 0; } else single_tap = 1; } else single_tap = 1; return single_tap; } /*================================================================================================== FUNCTION: KXTF9_read_double_tap_status DESCRIPTION: This function reads INT_SRC_REG2 to determine whether a double tap event occurred. ARGUMENTS PASSED: None RETURN VALUE: 0 = double tap occurred; 1 = double tap did not occur PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: None ==================================================================================================*/ int KXTF9_read_double_tap_status(void) { int double_tap; char src_reg2; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG2, &src_reg2, 1) == 0){ if((src_reg2 & 0x0C) == 0x08){ double_tap = 0; } else double_tap = 1; } else double_tap = 1; return double_tap; } /*================================================================================================== FUNCTION: KXTF9_set_odr_tilt DESCRIPTION: This function sets the ODR frequency for the tilt position function. ARGUMENTS PASSED: frequency variable; 1, 6, 12, or 50 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: ODR is set for tilt function according to frequency ==================================================================================================*/ int KXTF9_set_odr_tilt(int frequency) { char ctlreg_3 = 0; if (device == 0){ //KXTE9 // CTRL_REG1's initial output data rate ??? return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG3, &ctlreg_3, 1) != 0){ return 1; } switch (frequency){ case 1: /* set all ODR's to 1.6Hz */ UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTPA); UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTPB); break; case 6: /* set all ODR's to 6.3Hz */ UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTPA); SET_REG_BIT(ctlreg_3, CTRL_REG3_OTPB); break; case 12: /* set all ODR's to 12.5Hz */ SET_REG_BIT(ctlreg_3, CTRL_REG3_OTPA); UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTPB); break; case 50: /* set all ODR's to 50Hz */ SET_REG_BIT(ctlreg_3, CTRL_REG3_OTPA); SET_REG_BIT(ctlreg_3, CTRL_REG3_OTPB); break; default: return 1; } KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG3, ctlreg_3); return 0; } /*================================================================================================== FUNCTION: KXTF9_set_G_range DESCRIPTION: This function sets the accelerometer G range. ARGUMENTS PASSED: range variable; 2, 4, or 8 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: G range is set according to range ==================================================================================================*/ int KXTF9_set_G_range(int range) { char ctlreg_1 = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctlreg_1, 1) != 0){ return 1; } switch (range){ case 2: /* set G-range to 2g */ UNSET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL1); UNSET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL0); break; case 4: /* set G-range to 4g */ UNSET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL1); SET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL0); break; case 8: /* set G-range to 8g */ SET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL1); UNSET_REG_BIT(ctlreg_1, CTRL_REG1_GSEL0); break; default: return 1; } KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG1, ctlreg_1); return 0; } /*================================================================================================== FUNCTION: KXTF9_read_HPF_cnt DESCRIPTION: This function reads the high pass filtered number of counts on the X, Y, and Z axes. ARGUMENTS PASSED: x, y, and z pointers RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: x, y, and z are assigned ==================================================================================================*/ int KXTF9_read_HPF_cnt(int* x, int* y, int* z) { int status, x_sign, y_sign, z_sign; char Res = 0; char xyz[6] = {0, 0, 0, 0, 0, 0}; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &Res, 1) == 0){ Res = Res & 0x40; switch(Res){ case 0x00: //low-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_HPF_L, xyz, 6)) == 0){ *x = ((int)xyz[1]); x_sign = *x >> 7; //1 = negative; 0 = positive if (x_sign == 1){ *x = ((~(*x) + 0x01) & 0x0FF); *x = -(*x); } *y = ((int)xyz[3]); y_sign = *y >> 7; //1 = negative; 0 = positive if (y_sign == 1){ *y = ((~(*y) + 0x01) & 0x0FF); //2's complement *y = -(*y); } *z = ((int)xyz[5]); z_sign = *z >> 7; //1 = negative; 0 = positive if (z_sign == 1){ *z = ((~(*z) + 0x01) & 0x0FF); //2's complement *z = -(*z); } } break; case 0x40: //high-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_HPF_L, xyz, 6)) == 0){ *x = ((int)xyz[0]) >> 4; *x = *x + (((int)xyz[1]) << 4); x_sign = *x >> 11; //1 = negative; 0 = positive if (x_sign == 1){ *x = ((~(*x) + 0x01) & 0x0FFF); //2's complement *x = -(*x); } *y = ((int)xyz[2]) >> 4; *y = *y + (((int)xyz[3]) << 4); y_sign = *y >> 11; //1 = negative; 0 = positive if (y_sign == 1){ *y = ((~(*y) + 0x01) & 0x0FFF); //2's complement *y = -(*y); } *z = ((int)xyz[4]) >> 4; *z = *z + (((int)xyz[5]) << 4); z_sign = *z >> 11; //1 = negative; 0 = positive if (z_sign == 1){ *z = ((~(*z) + 0x01) & 0x0FFF); //2's complement *z = -(*z); } } break; } } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_read_HPF_g DESCRIPTION: This function reads the G(gravity force) values on the X, Y, and Z axes. The units used are milli-g's, or 1/1000*G. ARGUMENTS PASSED: gx, gy, and gz pointers RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: gx, gy, and gz are assigned ==================================================================================================*/ int KXTF9_read_HPF_g(int* gx, int* gy, int* gz) { int status; int x,y,z; int x_sign, y_sign, z_sign; int sensitivity; char xyz[6] = {0, 0, 0, 0, 0, 0}; char Res = 0; char G_range = 0; int range = 0; if (device == 0){ //KXTE9 return 1; } //determine if in the low resolution or high resolution state if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &Res, 1) == 0){ if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &G_range, 1) == 0){ G_range = G_range & 0x18; G_range = G_range >> 3; switch(G_range){ case 0: range = 2; break; case 1: range = 4; break; case 2: range = 8; break; default: break; } Res = Res & 0x40; switch(Res){ case 0x00: //low-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_HPF_L, xyz, 6)) == 0){ x = ((int)xyz[1]); x_sign = x >> 7; //1 = negative; 0 = positive if (x_sign == 1){ x = ((~(x) + 0x01) & 0x0FF); x = -(x); } y = ((int)xyz[3]); y_sign = y >> 7; //1 = negative; 0 = positive if (y_sign == 1){ y = ((~(y) + 0x01) & 0x0FF); //2's complement y = -(y); } z = ((int)xyz[5]); z_sign = z >> 7; //1 = negative; 0 = positive if (z_sign == 1){ z = ((~(z) + 0x01) & 0x0FF); //2's complement z = -(z); } sensitivity = (256)/(2*range); /* calculate milli-G's */ *gx = 1000 * (x) / sensitivity; *gy = 1000 * (y) / sensitivity; *gz = 1000 * (z) / sensitivity; } break; case 0x40: //high-resolution state if ((status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_XOUT_HPF_L, xyz, 6)) == 0){ x = ((int)xyz[0]) >> 4; x = x + (((int)xyz[1]) << 4); x_sign = x >> 11; //1 = negative; 0 = positive if (x_sign == 1){ x = ((~(x) + 0x01) & 0x0FFF); //2's complement x = -(x); } y = ((int)xyz[2]) >> 4; y = y + (((int)xyz[3]) << 4); y_sign = y >> 11; //1 = negative; 0 = positive if (y_sign == 1){ y = ((~(y) + 0x01) & 0x0FFF); //2's complement y = -(y); } z = ((int)xyz[4]) >> 4; z = z + (((int)xyz[5]) << 4); z_sign = z >> 11; //1 = negative; 0 = positive if (z_sign == 1){ z = ((~(z) + 0x01) & 0x0FFF); //2's complement z = -(z); } sensitivity = (4096)/(2*range); /* calculate milli-G's */ *gx = 1000 * (x) / sensitivity; *gy = 1000 * (y) / sensitivity; *gz = 1000 * (z) / sensitivity; } break; default: break; } } else status = 1; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_read_current_odr_tilt DESCRIPTION: This function reads the current ODR of the tilt function. ARGUMENTS PASSED: ODR_rate_tilt pointer RETURN VALUE: 0 = ODR set correctly; 1 = ODR invalid PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: ODR_rate_tilt is assigned ==================================================================================================*/ int KXTF9_read_current_odr_tilt(double* ODR_rate_tilt) { int status; char ctrl_reg; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG3, &ctrl_reg, 1) == 0){ ctrl_reg &= 0x60; ctrl_reg >>= 5; switch (ctrl_reg){ case 0: *ODR_rate_tilt = 1.6; status = 0; break; case 1: *ODR_rate_tilt = 6.3; status = 0; break; case 2: *ODR_rate_tilt = 12.5; status = 0; break; case 3: *ODR_rate_tilt = 50; status = 0; break; default: status = 1; break; } } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_read_current_odr_tap DESCRIPTION: This function reads the current ODR of the tap double tap function. ARGUMENTS PASSED: ODR_rate_tap pointer RETURN VALUE: 0 = ODR set correctly; 1 = ODR invalid PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: ODR_rate_tap is assigned ==================================================================================================*/ int KXTF9_read_current_odr_tap(double* ODR_rate_tap) { int status; char ctrl_reg; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG3, &ctrl_reg, 1) == 0){ ctrl_reg &= 0x0C; ctrl_reg >>= 2; switch (ctrl_reg){ case 0: *ODR_rate_tap = 50; status = 0; break; case 1: *ODR_rate_tap = 100; status = 0; break; case 2: *ODR_rate_tap = 200; status = 0; break; case 3: *ODR_rate_tap = 400; status = 0; break; default: status = 1; break; } } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_read_tap_direction DESCRIPTION: This function reads INT_SRC_REG1 to determine which axis and in which direction a tap or double tap event occurred. ARGUMENTS PASSED: int_src_reg1 pointer RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: int_src_reg1 is assigned ==================================================================================================*/ int KXTF9_read_tap_direction(char* int_src_reg1) { int status; if (device == 0){ //KXTE9 return 1; } status = KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_SRC_REG1, int_src_reg1, 1); return status; } /*================================================================================================== FUNCTION: KXTF9_int_alt_disable DESCRIPTION: This function disables the alternate unlatched response for the physical interrupt pin. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Alternate unlatched response for physical interrupt disabled ==================================================================================================*/ int KXTF9_int_alt_disable(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ UNSET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_ULMB); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_int_alt_enable DESCRIPTION: This function enables the alternate unlatched response for the physical interrupt pin. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Alternate unlatched response for physical interrupt enabled ==================================================================================================*/ int KXTF9_int_alt_enable(void) { char int_ctrl_reg1 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG1, &int_ctrl_reg1, 1) == 0){ SET_REG_BIT(int_ctrl_reg1, KXTF9_INT_CTRL_REG1_ULMB); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG1, int_ctrl_reg1); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_timer DESCRIPTION: This function defines the minimum separation between the first and second taps in a double tap event. ARGUMENTS PASSED: tdt_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Double tap minimum separation set according to tdt_timer IMPORTANT NOTES: Default: 0.3s (0x78h) ==================================================================================================*/ int KXTF9_tdt_timer(int tdt_timer) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_TIMER, tdt_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_h_thresh DESCRIPTION: This function defines the upper limit for the jerk threshold. ARGUMENTS PASSED: tdt_h_thresh; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Upper tap threshold set according to tdt_h_thresh IMPORTANT NOTES: Default: 14j (0xB6h) ==================================================================================================*/ int KXTF9_tdt_h_thresh(int tdt_h_thresh) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_H_THRESH, tdt_h_thresh) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_l_thresh DESCRIPTION: This function defines the lower limit for the jerk threshold. ARGUMENTS PASSED: tdt_l_thresh; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Lower tap threshold set according to tdt_l_thresh IMPORTANT NOTES: Default: 1j (0x1Ah) ==================================================================================================*/ int KXTF9_tdt_l_thresh(int tdt_l_thresh) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_L_THRESH, tdt_l_thresh) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_tap_timer DESCRIPTION: This function defines the minimum and maximum pulse width for the tap event. ARGUMENTS PASSED: tdt_tap_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Tap timer set according to tdt_tap_timer IMPORTANT NOTES: Default: 0.005s lower limit, 0.05s upper limit (0xA2h) ==================================================================================================*/ int KXTF9_tdt_tap_timer(int tdt_tap_timer) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_TAP_TIMER, tdt_tap_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_total_timer DESCRIPTION: This function defines the amount of time that two taps in a double tap event can be avove the PI threshold. ARGUMENTS PASSED: tdt_total_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Total timer set according to tdt_total_timer IMPORTANT NOTES: Default: 0.09s (0x24h) ==================================================================================================*/ int KXTF9_tdt_total_timer(int tdt_total_timer) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_TOTAL_TIMER, tdt_total_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_latency_timer DESCRIPTION: This function defines the total amount of time that the tap algorithm will count samples that are above the PI threshold. ARGUMENTS PASSED: tdt_latency_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Latency timer set according to tdt_latency_timer IMPORTANT NOTES: Default: 0.1s (0x28h) ==================================================================================================*/ int KXTF9_tdt_latency_timer(int tdt_latency_timer) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_LATENCY_TIMER, tdt_latency_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tdt_window_timer DESCRIPTION: This function defines the time window for the entire tap event, single or double, to occur. ARGUMENTS PASSED: tdt_window_timer; 0-255 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Window timer set according to tdt_window_timer IMPORTANT NOTES: Default: 0.4s (0xA0h) ==================================================================================================*/ int KXTF9_tdt_window_timer(int tdt_window_timer) { int status; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_write_byte(KXTF9_I2C_TDT_WINDOW_TIMER, tdt_window_timer) == 0){ status = 0; } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TFU DESCRIPTION: This function masks Z+ (face up) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Z+ tap masked ==================================================================================================*/ int KXTF9_tap_mask_TFU(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TFUM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TFU DESCRIPTION: This function unmasks Z+ (face up) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Z+ tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TFU(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TFUM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TFD DESCRIPTION: This function masks Z- (face down) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Z- tap masked ==================================================================================================*/ int KXTF9_tap_mask_TFD(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TFDM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TFD DESCRIPTION: This function unmasks Z- (face down) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Z- tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TFD(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TFDM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TUP DESCRIPTION: This function masks Y+ (up) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Y+ tap masked ==================================================================================================*/ int KXTF9_tap_mask_TUP(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TUPM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TUP DESCRIPTION: This function unmasks Y+ (up) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Y+ tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TUP(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TUPM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TDO DESCRIPTION: This function masks Y- (down) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Y- tap masked ==================================================================================================*/ int KXTF9_tap_mask_TDO(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TDOM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TDO DESCRIPTION: This function unmasks Y- (down) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Y- tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TDO(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TDOM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TRI DESCRIPTION: This function masks X+ (right) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: X+ tap masked ==================================================================================================*/ int KXTF9_tap_mask_TRI(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TRIM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TRI DESCRIPTION: This function unmasks X+ (right) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: X+ tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TRI(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TRIM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_TLE DESCRIPTION: This function masks X- (left) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: X- tap masked ==================================================================================================*/ int KXTF9_tap_mask_TLE(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ SET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TLEM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_TLE DESCRIPTION: This function unmasks X- (left) tap. ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: X- tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_TLE(void) { char ctrl_reg3 = 0; int status = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_INT_CTRL_REG3, &ctrl_reg3, 1) == 0){ UNSET_REG_BIT(ctrl_reg3, INT_CTRL_REG3_TLEM); KIONIX_ACCEL_write_byte(KXTF9_I2C_INT_CTRL_REG3, ctrl_reg3); } else status = 1; return status; } /*================================================================================================== FUNCTION: KXTF9_tap_mask_all_direction DESCRIPTION: ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: All direction tap masked ==================================================================================================*/ int KXTF9_tap_mask_all_direction(void) { int res=0; res |= KXTF9_tap_mask_TFU(); // Z+ res |= KXTF9_tap_mask_TFD(); // Z- res |= KXTF9_tap_mask_TUP(); // Y+ res |= KXTF9_tap_mask_TDO(); // Y- res |= KXTF9_tap_mask_TRI(); // X+ res |= KXTF9_tap_mask_TLE(); // X- return res; } /*================================================================================================== FUNCTION: KXTF9_tap_unmask_all_direction DESCRIPTION: ARGUMENTS PASSED: None RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: All direction tap unmasked ==================================================================================================*/ int KXTF9_tap_unmask_all_direction(void) { int res=0; res |= KXTF9_tap_unmask_TFU(); // Z+ res |= KXTF9_tap_unmask_TFD(); // Z- res |= KXTF9_tap_unmask_TUP(); // Y+ res |= KXTF9_tap_unmask_TDO(); // Y- res |= KXTF9_tap_unmask_TRI(); // X+ res |= KXTF9_tap_unmask_TLE(); // X- return res; } /*================================================================================================== FUNCTION: KXTF9_set_odr_tap DESCRIPTION: This function sets the ODR frequency for the Direction Tap function. ARGUMENTS PASSED: frequency variable; 50, 100, 200 or 400 RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: ODR is set for Direction Tap function according to frequency ==================================================================================================*/ int KXTF9_set_odr_tap(int frequency) { char ctlreg_3 = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG3, &ctlreg_3, 1) != 0){ return 1; } switch (frequency){ case 50: /* set all ODR's to 50Hz */ UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTA); UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTB); break; case 100: /* set all ODR's to 100Hz */ UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTA); SET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTB); break; case 200: /* set all ODR's to 200Hz */ SET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTA); UNSET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTB); break; case 400: /* set all ODR's to 400Hz */ SET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTA); SET_REG_BIT(ctlreg_3, CTRL_REG3_OTDTB); break; default: return 1; } KIONIX_ACCEL_write_byte(KIONIX_ACCEL_I2C_CTRL_REG3, ctlreg_3); return 0; } /*================================================================================================== FUNCTION: KXTF9_set_hpf_odr DESCRIPTION: This function sets the high pass filter roll off frequency for the accelerometer outputs. ARGUMENTS PASSED: frequency, where roll_off_frequency = ODR/alpha; alpha = (50, 100, 200, 400) RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: High pass filter roll off is set according to frequency ==================================================================================================*/ int KXTF9_set_hpf_odr(int frequency) { char data_ctrl_reg = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_DATA_CTRL_REG, &data_ctrl_reg, 1) != 0){ return 1; } switch (frequency){ case 50: /* set tap ODR to 50Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROB); break; case 100: /* set tap ODR to 100 Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROA); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROB); break; case 200: /* set tap ODR to 200 Hz */ SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROB); break; case 400: /* set tap ODR to 400 Hz */ SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROA); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_HPFROB); break; default: return 1; } KIONIX_ACCEL_write_byte(KXTF9_I2C_DATA_CTRL_REG, data_ctrl_reg); return 0; } /*================================================================================================== FUNCTION: KXTF9_set_lpf_odr DESCRIPTION: This function sets the low pass filter roll off for the accelerometer outputs. ARGUMENTS PASSED: roll off frequency (6, 12, 25, 50, 100, 200, 400) RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Low pass filter roll off is set according to frequency ==================================================================================================*/ int KXTF9_set_lpf_odr(int frequency) { char data_ctrl_reg = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KXTF9_I2C_DATA_CTRL_REG, &data_ctrl_reg, 1) != 0){ return 1; } switch (frequency){ case 6: /* set LPF rolloff to 6.25Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 12: /* set LPF rolloff to 12.5Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 25: /* set LPF rolloff to 25Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 50: /* set LPF rolloff to 50Hz */ UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 100: /* set LPF rolloff to 100Hz */ SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 200: /* set LPF rolloff to 200 Hz */ SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; case 400: /* set LPF rolloff to 400 Hz */ SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAA); SET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAB); UNSET_REG_BIT(data_ctrl_reg, DATA_CTRL_REG_OSAC); break; default: return 1; } KIONIX_ACCEL_write_byte(KXTF9_I2C_DATA_CTRL_REG, data_ctrl_reg); return 0; } /*================================================================================================== FUNCTION: KXTF9_set_resolution DESCRIPTION: This function sets the resolution of the accelerometer outputs. ARGUMENTS PASSED: resolution (8-bit or 12-bit) RETURN VALUE: 0 = pass; 1 = fail PRE-CONDITIONS: KIONIX_ACCEL_init() has been called POST-CONDITIONS: Accelerometer resolution is set according to resolution ==================================================================================================*/ int KXTF9_set_resolution(int resolution) { char ctrl_reg1 = 0; if (device == 0){ //KXTE9 return 1; } if (KIONIX_ACCEL_read_bytes(KIONIX_ACCEL_I2C_CTRL_REG1, &ctrl_reg1, 1) != 0){ return 1; } switch (resolution){ case 8: /* set resolution to 8 bits */ UNSET_REG_BIT(ctrl_reg1, CTRL_REG1_RES); break; case 12: /* set resolution to 12 bits */ SET_REG_BIT(ctrl_reg1, CTRL_REG1_RES); break; default: return 1; } return 0; } //************************************************************* // KIONIX_SHAKE_Init // - initializes the shake detection engine // params // - shake_data* data = engine data // return // - none //************************************************************* void KIONIX_SHAKE_Init(shake_data* data) { // init thresholds (convert ms to counts) data->maxDuration = CONFIG_DURATION / (1000 / CONFIG_RATE); data->maxDelay = CONFIG_DELAY / (1000 / CONFIG_RATE); data->maxTimeout = CONFIG_TIMEOUT / (1000 / CONFIG_RATE); // init timers data->cntDuration = 0; data->cntDelay = 0; data->cntTimeout = 0; // init counters data->cntShake = 0; data->cntInvalid = 0; } //************************************************************* // KIONIX_SHAKE_Update // - updates the shake detection engine // - maintains current shake count // - NOTE: must be called at a fixed interval // params // - shake_data* data = engine data // - long val = (x^2 + y^2 + z^2) / 1000 // return // - long = current shake count //************************************************************* long KIONIX_SHAKE_Update(shake_data* data, long val) { // possible shake... if (val > CONFIG_THRESHOLD) { // if the delay timer has started & // not yet expired -> flag invalid if (data->cntDelay > 0) data->cntInvalid = 1; // inc duration data->cntDuration += 1; // reset delay & timeout data->cntDelay = data->maxDelay; data->cntTimeout = data->maxTimeout; return 0; } // shake detected... if ((data->cntDuration >= 2) && (data->cntDuration <= data->maxDuration)) { // add valid shakes to the count if (data->cntInvalid == 0) data->cntShake += 1; } // flag valid & reset duration data->cntInvalid = 0; data->cntDuration = 0; // dec delay & timeout (if necessary) data->cntDelay -= (data->cntDelay > 0 ? 1 : 0); data->cntTimeout -= (data->cntTimeout > 0 ? 1 : 0); // reset shake count after timeout if (data->cntTimeout <= 0) { data->cntShake = 0; data->cntDelay = 0; data->cntTimeout = 0; } return data->cntShake; } #ifdef __cplusplus } #endif