static int lis3dh_start_dev(struct i2c_client *client, char rate) { int liRet = 0; int liRate = 0; char lcTmp = 0x0; struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client); if((int)rate == 5) { liRate = 3; } else if((int)rate == 6) { liRate = 2; } else { liRate = 4; } lcTmp = liRate<<4 | LIS3DH_ACC_ENABLE_ALL_AXES; liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG1, lcTmp); if (liRet < 0) { printk(KERN_ERR "lis3dh_start_dev err\n"); } else { stprintkf("lis3dh_start_dev\n"); } lis3dh_active(client,1); enable_irq(client->irq); return liRet; }
upm_result_t lis3dh_enable_interrupt_latching(const lis3dh_context dev, bool int1_latch, bool int2_latch) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG5); if (int1_latch) { reg |= LIS3DH_CTRL_REG5_LIR_INT1; } else { reg &= ~LIS3DH_CTRL_REG5_LIR_INT1; } if (int2_latch) { reg |= LIS3DH_CTRL_REG5_LIR_INT2; } else { reg &= ~LIS3DH_CTRL_REG5_LIR_INT2; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG5, reg)) { printf("%s: failed to set interrupt latching mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
int lis3dh_init(lis3dh_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int1_pin, gpio_t int2_pin, lis3dh_scale_t scale) { uint8_t in; dev->spi = spi; dev->cs = cs_pin; dev->int1 = int1_pin; dev->int2 = int2_pin; dev->scale = 0; /* CS */ gpio_init(dev->cs, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(dev->cs); if (lis3dh_read_regs(dev, LIS3DH_REG_WHO_AM_I, 1, &in) < 0) { /* Communication error */ return -1; } if (in != LIS3DH_WHO_AM_I_RESPONSE) { /* Chip is not responding correctly */ return -1; } /* Set block data update and little endian mode. */ lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG4, (LIS3DH_CTRL_REG4_BDU_ENABLE | LIS3DH_CTRL_REG4_BLE_LITTLE_ENDIAN)); lis3dh_set_scale(dev, scale); return 0; }
upm_result_t lis3dh_enable_temperature(const lis3dh_context dev, bool temperature_enable) { assert(dev != NULL); // ADC must be enabled for temperature readings to work if (temperature_enable && lis3dh_enable_adc(dev, true)) { printf("%s: failed to enable ADC - a prerequisite for enabling temperature sensor\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_TEMP_CFG_REG); if (temperature_enable) { reg |= LIS3DH_TEMP_CFG_REG_TEMP_EN; } else { reg &= ~LIS3DH_TEMP_CFG_REG_TEMP_EN; } if (lis3dh_write_reg(dev, LIS3DH_REG_TEMP_CFG_REG, reg)) { printf("%s: failed to set temperature sensor mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_set_odr(const lis3dh_context dev, LIS3DH_ODR_T odr) { assert(dev != NULL); bool lp_mode = false; uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG1); // Zero out ODR bits reg &= ~_SHIFTMASK(CTRL_REG1_ODR); // We encoded an extra bit in LIS3DH_ODR_T indicating an LP mode. Check for it here. if ((int) odr > (int) _MASK(CTRL_REG1_ODR)) { lp_mode = true; } // Mask it off and set it odr &= _MASK(CTRL_REG1_ODR); reg |= (odr << _SHIFT(CTRL_REG1_ODR)); // Set the LPEN bit appropriately lis3dh_enable_lp_mode(dev, lp_mode); // Commit our changes if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG1, reg)) { printf("%s: failed to set ODR configuration\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_enable_hr_mode(const lis3dh_context dev, bool hr_enable) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG4); if (hr_enable) { // Check whether low power mode is enabled - enabling both LP and HR is not allowed uint8_t tmp_reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG1); if (tmp_reg & LIS3DH_CTRL_REG1_LPEN) { printf("%s: can't enable high resolution mode, low power mode is already enabled\n", __FUNCTION__); return UPM_ERROR_INVALID_PARAMETER; } else { // We are good - enable high resolution mode reg |= LIS3DH_CTRL_REG4_HR; } } else { reg &= ~LIS3DH_CTRL_REG4_HR; } // Set the temperature sensor scaling factor appropriately. // Its max is 10 bit for both normal and HR modes. dev->temperatureFactor = 64; if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG4, reg)) { printf("%s: failed to set high resolution mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_enable_adc(const lis3dh_context dev, bool adc_enable) { assert(dev != NULL); // BDU mode is a prerequisite if (adc_enable && lis3dh_enable_bdu_mode(dev, true)) { printf("%s: failed to enable BDU mode - a prerequisite for enabling ADC\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_TEMP_CFG_REG); if (adc_enable) { reg |= LIS3DH_TEMP_CFG_REG_ADC_EN; } else { reg &= ~LIS3DH_TEMP_CFG_REG_ADC_EN; } if (lis3dh_write_reg(dev, LIS3DH_REG_TEMP_CFG_REG, reg)) { printf("%s: failed to set ADC mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_set_int2_config(const lis3dh_context dev, uint8_t cfg) { assert(dev != NULL); if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG6, cfg)) { printf("%s: failed to set interrupt 2 configuration\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
static int lis3dh_active(struct i2c_client *client,int enable) { int liTmp = 0; int liRet = 0; liTmp =lis3dh_read_reg(client, CTRL_REG1); if(enable) { liTmp |= LIS3DH_ACC_ENABLE_ALL_AXES; } else { liTmp = 0x08; } liRet =lis3dh_write_reg(client, CTRL_REG1, liTmp); return liRet; }
upm_result_t lis3dh_set_interrupt_active_high(const lis3dh_context dev, bool high) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG6); if (high) { reg &= ~LIS3DH_CTRL_REG6_INT_POLARITY; } else { reg |= LIS3DH_CTRL_REG6_INT_POLARITY; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG6, reg)) { printf("%s: failed to set interrupt polarity mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_enable_hp_filtering(const lis3dh_context dev, bool filter) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG2); if (filter) { reg |= LIS3DH_CTRL_REG2_FDS; } else { reg &= ~LIS3DH_CTRL_REG2_FDS; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG2, reg)) { printf("%s: failed to set HP filter mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_enable_bdu_mode(const lis3dh_context dev, bool bdu_enable) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG4); if (bdu_enable) { reg |= LIS3DH_CTRL_REG4_BDU; } else { reg &= ~LIS3DH_CTRL_REG4_BDU; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG4, reg)) { printf("%s: failed to set BDU mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_set_full_scale(const lis3dh_context dev, LIS3DH_FS_T fs) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG4); // Mask out FS bits, add our own reg &= ~_SHIFTMASK(CTRL_REG4_FS); reg |= (fs << _SHIFT(CTRL_REG4_FS)); if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG4, reg)) { printf("%s: failed to set FS configuration\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } // Basic sensitivity in g/LSB, calculated for a full 16b resolution. switch (fs) { case LIS3DH_FS_2G: // (2*2) / 2^16 dev->accScale = 0.000061; break; case LIS3DH_FS_4G: // (4*2) / 2^16 dev->accScale = 0.000122; break; case LIS3DH_FS_8G: // (8*2) / 2^16 dev->accScale = 0.000244; break; case LIS3DH_FS_16G: // (16*2) / 2^16 dev->accScale = 0.000488; break; } return UPM_SUCCESS; }
/** * @brief Write (both set and clear) bits of an 8-bit register on the LIS3DH. * * @param[in] addr Register address on the LIS3DH. * @param[in] mask Bitmask for the bits to modify. * @param[in] values The values to write to the masked bits. * * @return 0 on success * @return -1 on error */ static inline int lis3dh_write_bits(const lis3dh_t *dev, const lis3dh_reg_t reg, const uint8_t mask, const uint8_t values) { uint8_t tmp; if (lis3dh_read_regs(dev, reg, 1, &tmp) < 0) { /* Communication error */ return -1; } tmp &= ~mask; tmp |= (values & mask); if (lis3dh_write_reg(dev, reg, tmp) < 0) { /* Communication error */ return -1; } return 0; }
upm_result_t lis3dh_enable_axes(const lis3dh_context dev, bool x_axis_enable, bool y_axis_enable, bool z_axis_enable) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG1); // X axis if (x_axis_enable) { reg |= LIS3DH_CTRL_REG1_XEN; } else { reg &= ~LIS3DH_CTRL_REG1_XEN; } // Y axis if (y_axis_enable) { reg |= LIS3DH_CTRL_REG1_YEN; } else { reg &= ~LIS3DH_CTRL_REG1_YEN; } // Z axis if (z_axis_enable) { reg |= LIS3DH_CTRL_REG1_ZEN; } else { reg &= ~LIS3DH_CTRL_REG1_ZEN; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG1, reg)) { printf("%s: failed to enable axes\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
upm_result_t lis3dh_enable_lp_mode(const lis3dh_context dev, bool lp_enable) { assert(dev != NULL); uint8_t reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG1); if (lp_enable) { // Check whether high resolution mode is enabled - enabling both LP and HR is not allowed uint8_t tmp_reg = lis3dh_read_reg(dev, LIS3DH_REG_CTRL_REG4); if (tmp_reg & LIS3DH_CTRL_REG4_HR) { printf("%s: can't enable low power mode, high resolution mode is already enabled\n", __FUNCTION__); return UPM_ERROR_INVALID_PARAMETER; } else { // We are good - enable low power mode reg |= LIS3DH_CTRL_REG1_LPEN; // Set temperatureFactor according to LP mode bit width (8b). // This is needed to account for left alignment of the temperature data. // We have to shift the data right (== divide by a factor in case of float) // to eliminate "dead" bits. dev->temperatureFactor = 256; } } else { reg &= ~LIS3DH_CTRL_REG1_LPEN; // Set temperatureFactor according to Normal mode bit width (10b) dev->temperatureFactor = 64; } if (lis3dh_write_reg(dev, LIS3DH_REG_CTRL_REG1, reg)) { printf("%s: failed to set low power mode\n", __FUNCTION__); return UPM_ERROR_OPERATION_FAILED; } return UPM_SUCCESS; }
static int lis3dh_init_device(struct lis3dh_data *lis3dh) { int liRet =-1; memset(lis3dh->resume_state, 0, ARRAY_SIZE(lis3dh->resume_state)); lis3dh->resume_state[RES_CTRL_REG1] = LIS3DH_ACC_ENABLE_ALL_AXES; lis3dh->resume_state[RES_CTRL_REG2] = 0x00; lis3dh->resume_state[RES_CTRL_REG3] = 0x40; lis3dh->resume_state[RES_CTRL_REG4] = 0x08; lis3dh->resume_state[RES_CTRL_REG5] = 0x08; lis3dh->resume_state[RES_CTRL_REG6] = 0x40; lis3dh->resume_state[RES_TEMP_CFG_REG] = 0x00; lis3dh->resume_state[RES_FIFO_CTRL_REG] = 0x00; lis3dh->resume_state[RES_INT_CFG1] = 0xFF; lis3dh->resume_state[RES_INT_THS1] = 0x7F; lis3dh->resume_state[RES_INT_DUR1] = 0x7F; //0x00->ox7f lis3dh->resume_state[RES_TT_CFG] = 0x00; lis3dh->resume_state[RES_TT_THS] = 0x00; lis3dh->resume_state[RES_TT_LIM] = 0x00; lis3dh->resume_state[RES_TT_TLAT] = 0x00; lis3dh->resume_state[RES_TT_TW] = 0x00; liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG1, lis3dh->resume_state[RES_CTRL_REG1]); if (liRet < 0) { printk("RES_CTRL_REG1 err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, TEMP_CFG_REG, lis3dh->resume_state[RES_TEMP_CFG_REG]); if (liRet < 0) { printk("TEMP_CFG_REG err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, FIFO_CTRL_REG, lis3dh->resume_state[RES_FIFO_CTRL_REG]); if(liRet < 0) { printk("FIFO_CTRL_REG err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, TT_THS, lis3dh->resume_state[RES_TT_THS]); liRet =lis3dh_write_reg(lis3dh->client, TT_LIM, lis3dh->resume_state[RES_TT_LIM]); liRet =lis3dh_write_reg(lis3dh->client, TT_TLAT, lis3dh->resume_state[RES_TT_TLAT]); liRet =lis3dh_write_reg(lis3dh->client, TT_TW, lis3dh->resume_state[RES_TT_TW]); if(liRet < 0) { printk("I2C_AUTO_INCREMENT err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, TT_CFG, lis3dh->resume_state[RES_TT_CFG]); if(liRet < 0) { printk("TT_CFG err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, INT_THS1, lis3dh->resume_state[RES_INT_THS1]); liRet =lis3dh_write_reg(lis3dh->client, INT_DUR1, lis3dh->resume_state[RES_INT_DUR1]); if(liRet < 0) { printk("I2C_AUTO_INCREMENT err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, INT_CFG1, lis3dh->resume_state[RES_INT_CFG1]); if(liRet < 0) { printk("INT_CFG1 err\n"); return 0; } else { //nothing } liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG2, lis3dh->resume_state[RES_CTRL_REG2]); liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG3, lis3dh->resume_state[RES_CTRL_REG3]); liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG4, lis3dh->resume_state[RES_CTRL_REG4]); liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG5, lis3dh->resume_state[RES_CTRL_REG5]); liRet =lis3dh_write_reg(lis3dh->client, CTRL_REG6, lis3dh->resume_state[RES_CTRL_REG6]); if(liRet < 0) { printk("I2C_AUTO_INCREMENT err\n"); return 0; } else { //nothing } return liRet; }