/** * Sets the gain increment used when sampling light values. * * @param The sensor interface * @param gain The gain increment which can be one of: * - 0x00: 1x (no gain) * - 0x10: 16x gain * * @return 0 on success, non-zero on failure */ int tsl2561_set_gain(struct sensor_itf *itf, uint8_t gain) { int rc; uint8_t int_time; if ((gain != TSL2561_LIGHT_GAIN_1X) && (gain != TSL2561_LIGHT_GAIN_16X)) { TSL2561_LOG(ERROR, "Invalid gain value\n"); rc = SYS_EINVAL; goto err; } rc = tsl2561_get_integration_time(itf, &int_time); if (rc) { goto err; } rc = tsl2561_write8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, int_time | gain); if (rc) { goto err; } return 0; err: return rc; }
/** * Enables or disables the HW interrupt on the device * * @param The sensor interface * @param enable0 to disable the interrupt, 1 to enablee it * * @return 0 on success, non-zero on failure */ int tsl2561_enable_interrupt(struct sensor_itf *itf, uint8_t enable) { int rc; uint8_t persist_val; if (enable > 1) { TSL2561_LOG(ERROR, "Invalid value 0x%02X in tsl2561_enable_interrupt\n", enable); rc = SYS_EINVAL; goto err; } /* Read the current value to maintain PERSIST state */ rc = tsl2561_read8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &persist_val); if (rc) { goto err; } /* Enable (1) or disable (0) level interrupts */ rc = tsl2561_write8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, ((enable & 0x01) << 4) | (persist_val & 0x0F) ); if (rc) { goto err; } return 0; err: return rc; }
// turn TSL2561 into power saving mode static inline int TSL2561_OFF(TSL2561 *sensor) { int rc; if(sensor->adapter_fd == -1) { // not opened // TODO: choose a valid errno error sensor->lasterr = -1; return -1; } rc = tsl2561_write8(sensor, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); return rc; }
// This function both clears any pending interrupts, as well as configures the next interrupt int TSL2561_INTR_SETCLEAR(TSL2561 *sensor, tsl2561InterruptControl_t mode, uint8_t persistence) { int rc; uint8_t value; value = persistence; value |= mode << 4; rc = tsl2561_write8(sensor, TSL2561_COMMAND_BIT | TSL2561_CLEAR_BIT | TSL2561_REGISTER_INTERRUPT, value); if (rc != 0) // invalid read or sensor error return -1; else return 0; }
/** * Sets the upper and lower interrupt thresholds * * @param The sensor interface * @param rate Sets the rate of interrupts to the host processor: * - 0 Every ADC cycle generates interrupt * - 1 Any value outside of threshold range * - 2 2 integration time periods out of range * - 3 3 integration time periods out of range * - 4 4 integration time periods out of range * - 5 5 integration time periods out of range * - 6 6 integration time periods out of range * - 7 7 integration time periods out of range * - 8 8 integration time periods out of range * - 9 9 integration time periods out of range * - 10 10 integration time periods out of range * - 11 11 integration time periods out of range * - 12 12 integration time periods out of range * - 13 13 integration time periods out of range * - 14 14 integration time periods out of range * - 15 15 integration time periods out of range * @param lower The lower threshold * @param upper The upper threshold * * @return 0 on success, non-zero on failure */ int tsl2561_setup_interrupt(struct sensor_itf *itf, uint8_t rate, uint16_t lower, uint16_t upper) { int rc; uint8_t intval; /* Set lower threshold */ rc = tsl2561_write16(itf, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDL_LOW, lower); if (rc) { goto err; } /* Set upper threshold */ rc = tsl2561_write16(itf, TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_THRESHHOLDH_LOW, upper); if (rc) { goto err; } /* Set rate */ rc = tsl2561_read8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, &intval); if (rc) { goto err; } /* Maintain the INTR Control Select bits */ rate = (intval & 0xF0) | (rate & 0xF); rc = tsl2561_write8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_INTERRUPT, rate); if (rc) { goto err; } return 0; err: return rc; }
int TSL2561_SETGAIN(TSL2561 *sensor, tsl2561Gain_t gain) { int rc; if(sensor->adapter_fd == -1) { // not opened // TODO: choose a valid errno error sensor->lasterr = -1; return -1; } TSL2561_ON(sensor); rc = tsl2561_write8(sensor, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, sensor->integration_time | gain); TSL2561_OFF(sensor); if(rc == 0) { sensor->gain = gain; //fprintf(stderr, "setting gain: 0x%02x to 0x%02x\n", TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, sensor->integration_time | gain); return 0; } else { //fprintf(stderr, "Error setting gain: 0x%02x to 0x%02x\n", TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, sensor->integration_time | gain); return -1; } return -1; }
int TSL2561_SETINTEGRATIONTIME(TSL2561 *sensor, tsl2561IntegrationTime_t time) { int rc; if(sensor->adapter_fd == -1) { // not opened // TODO: choose a valid errno error sensor->lasterr = -1; return -1; } TSL2561_ON(sensor); rc = tsl2561_write8(sensor, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | sensor->gain); TSL2561_OFF(sensor); if(rc == 0) { sensor->integration_time = time; //fprintf(stderr, "setting integration time: 0x%02x to 0x%02x\n", TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | sensor->gain); return 0; } else { //fprintf(stderr, "Error setting integration time: 0x%02x to 0x%02x\n", TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | sensor->gain); return -1; } return -1; }
int tsl2561_set_gain(uint8_t gain) { int rc; if ((gain != TSL2561_LIGHT_GAIN_1X) && (gain != TSL2561_LIGHT_GAIN_16X)) { TSL2561_ERR("Invalid gain value\n"); rc = SYS_EINVAL; goto err; } rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, g_tsl2561_integration_time | gain); if (rc) { goto err; } g_tsl2561_gain = gain; err: return rc; }
int tsl2561_write8(struct sensor_itf *itf, uint8_t reg, uint32_t value) { int rc; uint8_t payload[2] = { reg, value & 0xFF }; struct hal_i2c_master_data data_struct = { .address = itf->si_addr, .len = 2, .buffer = payload }; rc = sensor_itf_lock(itf, MYNEWT_VAL(TSL2561_ITF_LOCK_TMO)); if (rc) { return rc; } rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_LOG(ERROR, "Failed to write 0x%02X:0x%02X with value 0x%02lX\n", data_struct.address, reg, value); STATS_INC(g_tsl2561stats, errors); } sensor_itf_unlock(itf); return rc; } int tsl2561_write16(struct sensor_itf *itf, uint8_t reg, uint16_t value) { int rc; uint8_t payload[3] = { reg, value & 0xFF, (value >> 8) & 0xFF }; struct hal_i2c_master_data data_struct = { .address = itf->si_addr, .len = 3, .buffer = payload }; rc = sensor_itf_lock(itf, MYNEWT_VAL(TSL2561_ITF_LOCK_TMO)); if (rc) { return rc; } rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_LOG(ERROR, "Failed to write @0x%02X with value 0x%02X 0x%02X\n", reg, payload[0], payload[1]); } sensor_itf_unlock(itf); return rc; } int tsl2561_read8(struct sensor_itf *itf, uint8_t reg, uint8_t *value) { int rc; uint8_t payload; struct hal_i2c_master_data data_struct = { .address = itf->si_addr, .len = 1, .buffer = &payload }; rc = sensor_itf_lock(itf, MYNEWT_VAL(TSL2561_ITF_LOCK_TMO)); if (rc) { return rc; } /* Register write */ payload = reg; rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_LOG(ERROR, "Failed to address sensor\n"); goto err; } /* Read one byte back */ payload = 0; rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); *value = payload; if (rc) { TSL2561_LOG(ERROR, "Failed to read @0x%02X\n", reg); } err: sensor_itf_unlock(itf); return rc; } int tsl2561_read16(struct sensor_itf *itf, uint8_t reg, uint16_t *value) { int rc; uint8_t payload[2] = { reg, 0 }; struct hal_i2c_master_data data_struct = { .address = itf->si_addr, .len = 1, .buffer = payload }; rc = sensor_itf_lock(itf, MYNEWT_VAL(TSL2561_ITF_LOCK_TMO)); if (rc) { return rc; } /* Register write */ rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_LOG(ERROR, "Failed to address sensor\n"); goto err; } /* Read two bytes back */ memset(payload, 0, 2); data_struct.len = 2; rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1); *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8); if (rc) { TSL2561_LOG(ERROR, "Failed to read @0x%02X\n", reg); goto err; } err: sensor_itf_unlock(itf); return rc; } /** * Enable or disables the sensor to save power * * @param The sensor interface * @param state 1 to enable the sensor, 0 to disable it * * @return 0 on success, non-zero on failure */ int tsl2561_enable(struct sensor_itf *itf, uint8_t state) { /* Enable the device by setting the control bit to 0x03 */ return tsl2561_write8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, state ? TSL2561_CONTROL_POWERON : TSL2561_CONTROL_POWEROFF); } /** * Checks if the sensor in enabled or not * * @param The sensor interface * @param ptr to enabled * * @return 0 on success, non-zero on fialure */ int tsl2561_get_enable(struct sensor_itf *itf, uint8_t *enabled) { int rc; uint8_t reg; /* Enable the device by setting the control bit to 0x03 */ rc = tsl2561_read8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, ®); if (rc) { goto err; } *enabled = reg & 0x03 ? 1 : 0; return 0; err: return rc; } /** * Sets the integration time used when sampling light values. * * @param The sensor interface * @param int_time The integration time which can be one of: * - 0x00: 13ms * - 0x01: 101ms * - 0x02: 402ms * * @return 0 on success, non-zero on failure */ int tsl2561_set_integration_time(struct sensor_itf *itf, uint8_t int_time) { int rc; uint8_t gain; rc = tsl2561_get_gain(itf, &gain); if (rc) { goto err; } rc = tsl2561_write8(itf, TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, int_time | gain); if (rc) { goto err; } return 0; err: return rc; }
int tsl2561_write8(uint8_t reg, uint32_t value) { int rc; uint8_t payload[2] = { reg, value & 0xFF }; struct hal_i2c_master_data data_struct = { .address = MYNEWT_VAL(TSL2561_I2CADDR), .len = 2, .buffer = payload }; rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to write 0x%02X:0x%02X with value 0x%02X\n", data_struct.address, reg, value); #if MYNEWT_VAL(TSL2561_STATS) STATS_INC(g_tsl2561stats, errors); #endif } return rc; } int tsl2561_write16(uint8_t reg, uint16_t value) { int rc; uint8_t payload[3] = { reg, value & 0xFF, (value >> 8) & 0xFF }; struct hal_i2c_master_data data_struct = { .address = MYNEWT_VAL(TSL2561_I2CADDR), .len = 3, .buffer = payload }; rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to write @0x%02X with value 0x%02X 0x%02X\n", reg, payload[0], payload[1]); } return rc; } int tsl2561_read8(uint8_t reg, uint8_t *value) { int rc; uint8_t payload; struct hal_i2c_master_data data_struct = { .address = MYNEWT_VAL(TSL2561_I2CADDR), .len = 1, .buffer = &payload }; /* Register write */ payload = reg; rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to address sensor\n"); goto err; } /* Read one byte back */ payload = 0; rc = hal_i2c_master_read(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); *value = payload; if (rc) { TSL2561_ERR("Failed to read @0x%02X\n", reg); } err: return rc; } int tsl2561_read16(uint8_t reg, uint16_t *value) { int rc; uint8_t payload[2] = { reg, 0 }; struct hal_i2c_master_data data_struct = { .address = MYNEWT_VAL(TSL2561_I2CADDR), .len = 1, .buffer = payload }; /* Register write */ rc = hal_i2c_master_write(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); if (rc) { TSL2561_ERR("Failed to address sensor\n"); goto err; } /* Read two bytes back */ memset(payload, 0, 2); data_struct.len = 2; rc = hal_i2c_master_read(MYNEWT_VAL(TSL2561_I2CBUS), &data_struct, OS_TICKS_PER_SEC / 10, 1); *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8); if (rc) { TSL2561_ERR("Failed to read @0x%02X\n", reg); goto err; } err: return rc; } int tsl2561_enable(uint8_t state) { int rc; /* Enable the device by setting the control bit to 0x03 */ rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, state ? TSL2561_CONTROL_POWERON : TSL2561_CONTROL_POWEROFF); if (!rc) { g_tsl2561_enabled = state ? 1 : 0; } return rc; } uint8_t tsl2561_get_enable (void) { return g_tsl2561_enabled; } int tsl2561_set_integration_time(uint8_t int_time) { int rc; rc = tsl2561_write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, int_time | g_tsl2561_gain); if (rc) { goto err; } g_tsl2561_integration_time = int_time; err: return rc; }