/**
 * 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;
}
Exemple #3
0
// 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;
}
Exemple #4
0
// 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;
}
Exemple #6
0
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;
}
Exemple #7
0
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,
                        &reg);
    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;
}