vcnl36825t: additional delay after wakeup on "force"-mode
There is an (undocumented) additional delay necessary if the device woke up and a measurement is triggered via the "force"-mode. The additional sleep time was determined empirically on different devices. Signed-off-by: Juliane Schulze <juliane.schulze@deveritec.com>
This commit is contained in:
parent
3978693d47
commit
38ee9aa17b
2 changed files with 70 additions and 16 deletions
|
@ -65,6 +65,8 @@ static int vcnl36825t_update(const struct i2c_dt_spec *spec, uint8_t reg_addr, u
|
|||
static int vcnl36825t_pm_action(const struct device *dev, enum pm_device_action action)
|
||||
{
|
||||
const struct vcnl36825t_config *config = dev->config;
|
||||
struct vcnl36825t_data *data = dev->data;
|
||||
|
||||
int rc;
|
||||
|
||||
switch (action) {
|
||||
|
@ -98,6 +100,9 @@ static int vcnl36825t_pm_action(const struct device *dev, enum pm_device_action
|
|||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
data->meas_timeout_us = data->meas_timeout_wakeup_us;
|
||||
|
||||
break;
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
rc = vcnl36825t_update(&config->i2c, VCNL36825T_REG_PS_CONF2, VCNL36825T_PS_ST_MSK,
|
||||
|
@ -166,6 +171,10 @@ static int vcnl36825t_sample_fetch(const struct device *dev, enum sensor_channel
|
|||
}
|
||||
|
||||
k_usleep(data->meas_timeout_us);
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
data->meas_timeout_us = data->meas_timeout_running_us;
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = vcnl36825t_read(&config->i2c, VCNL36825T_REG_PS_DATA, &data->proximity);
|
||||
|
@ -201,6 +210,22 @@ static int vcnl36825t_channel_get(const struct device *dev, enum sensor_channel
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculate measurement timeout in us
|
||||
*
|
||||
* @param meas_duration base duration of a measurement in us*VCNL36825T_FORCED_FACTOR_SCALE
|
||||
* @param meas_factor factor which needs to be multiplied to cope with additional delays (multiplied
|
||||
* by VCNL36825T_FORCED_FACTOR_SCALE)
|
||||
*
|
||||
* @note
|
||||
* Always add 1 to prevent corner case losses due to precision.
|
||||
*/
|
||||
static inline unsigned int vcn36825t_measurement_timeout_us(unsigned int meas_duration,
|
||||
unsigned int forced_factor)
|
||||
{
|
||||
return ((meas_duration * forced_factor) / VCNL36825T_FORCED_FACTOR_SCALE) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper function to configure the registers
|
||||
*
|
||||
|
@ -214,6 +239,8 @@ static int vcnl36825t_init_registers(const struct device *dev)
|
|||
int rc;
|
||||
uint16_t reg_value;
|
||||
|
||||
unsigned int meas_duration = 1;
|
||||
|
||||
/* reset registers as defined by the datasheet */
|
||||
const uint16_t resetValues[][2] = {
|
||||
{VCNL36825T_REG_PS_CONF1, VCNL36825T_CONF1_DEFAULT},
|
||||
|
@ -229,8 +256,6 @@ static int vcnl36825t_init_registers(const struct device *dev)
|
|||
vcnl36825t_write(&config->i2c, resetValues[i][0], resetValues[i][1]);
|
||||
}
|
||||
|
||||
data->meas_timeout_us = 1;
|
||||
|
||||
/* PS_CONF1 */
|
||||
reg_value = 0x01; /* must be set according to datasheet */
|
||||
reg_value |= VCNL36825T_PS_ON;
|
||||
|
@ -277,21 +302,21 @@ static int vcnl36825t_init_registers(const struct device *dev)
|
|||
switch (config->proximity_it) {
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_1T:
|
||||
reg_value |= VCNL36825T_PS_IT_1T;
|
||||
data->meas_timeout_us *= 1;
|
||||
meas_duration *= 1;
|
||||
break;
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_2T:
|
||||
reg_value |= VCNL36825T_PS_IT_2T;
|
||||
data->meas_timeout_us *= 2;
|
||||
meas_duration *= 2;
|
||||
break;
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_4T:
|
||||
reg_value |= VCNL36825T_PS_IT_4T;
|
||||
data->meas_timeout_us *= 4;
|
||||
meas_duration *= 4;
|
||||
break;
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_8T:
|
||||
__fallthrough;
|
||||
default:
|
||||
reg_value |= VCNL36825T_PS_IT_8T;
|
||||
data->meas_timeout_us *= 8;
|
||||
meas_duration *= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -315,13 +340,13 @@ static int vcnl36825t_init_registers(const struct device *dev)
|
|||
switch (config->proximity_itb) {
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_DURATION_25us:
|
||||
reg_value |= VCNL36825T_PS_ITB_25us;
|
||||
data->meas_timeout_us *= 25;
|
||||
meas_duration *= 25;
|
||||
break;
|
||||
case VCNL36825T_PROXIMITY_INTEGRATION_DURATION_50us:
|
||||
__fallthrough;
|
||||
default:
|
||||
reg_value |= VCNL36825T_PS_ITB_50us;
|
||||
data->meas_timeout_us *= 50;
|
||||
meas_duration *= 50;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -409,13 +434,22 @@ static int vcnl36825t_init_registers(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* calculate measurement timeout
|
||||
* Note: always add 1 to prevent corner case losses due to precision.
|
||||
*/
|
||||
data->meas_timeout_us =
|
||||
(data->meas_timeout_us * VCNL36825T_FORCED_FACTOR_SUM) /
|
||||
(VCNL36825T_FORCED_FACTOR_SCALE) +
|
||||
1;
|
||||
vcn36825t_measurement_timeout_us(meas_duration, VCNL36825T_FORCED_FACTOR_SUM);
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
data->meas_timeout_running_us = data->meas_timeout_us;
|
||||
data->meas_timeout_wakeup_us = vcn36825t_measurement_timeout_us(
|
||||
meas_duration, VCNL36825T_FORCED_FACTOR_WAKEUP_SUM);
|
||||
|
||||
/* ensure that the time is roughly around VCNL36825T_FORCED_WAKEUP_DELAY_MAX_US if the
|
||||
* wakeup time is bigger but "normal" measurement time is less
|
||||
*/
|
||||
if (data->meas_timeout_wakeup_us > VCNL36825T_FORCED_WAKEUP_DELAY_MAX_US) {
|
||||
data->meas_timeout_wakeup_us =
|
||||
MAX(data->meas_timeout_running_us, VCNL36825T_FORCED_WAKEUP_DELAY_MAX_US);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -424,6 +458,7 @@ static int vcnl36825t_init(const struct device *dev)
|
|||
{
|
||||
const struct vcnl36825t_config *config = dev->config;
|
||||
int rc;
|
||||
|
||||
uint16_t reg_value;
|
||||
|
||||
if (!i2c_is_ready_dt(&config->i2c)) {
|
||||
|
|
|
@ -219,12 +219,26 @@
|
|||
#define VCNL36825T_FORCED_FACTOR_DC_KILL_AMBIENT 3
|
||||
#define VCNL36825T_FORCED_FACTOR_MEASUREMENT 1
|
||||
#define VCNL36825T_FORCED_FACTOR_SHUTDOWN 1
|
||||
#define VCNL36825T_FORCED_FACTOR_SCALE 10
|
||||
#define VCNL36825T_FORCED_FACTOR_SCALE 10
|
||||
|
||||
/* necessary time to wait before data of a "forced" measurement is available */
|
||||
#define VCNL36825T_FORCED_FACTOR_SUM \
|
||||
((VCNL36825T_FORCED_FACTOR_TIME_TO_TRIGGER + VCNL36825T_FORCED_FACTOR_DC_KILL_AMBIENT + \
|
||||
VCNL36825T_FORCED_FACTOR_MEASUREMENT + VCNL36825T_FORCED_FACTOR_SHUTDOWN) * \
|
||||
VCNL36825T_FORCED_FACTOR_SCALE)
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
|
||||
#define VCNL36825T_FORCED_WAKEUP_DELAY_MAX_US 1000
|
||||
#define VCNL36825T_FORCED_FACTOR_WAKEUP_DELAY 10
|
||||
|
||||
/* necessary wait time before data for a "forced" measurement is available AFTER the device slept */
|
||||
#define VCNL36825T_FORCED_FACTOR_WAKEUP_SUM \
|
||||
(VCNL36825T_FORCED_FACTOR_SUM + \
|
||||
(VCNL36825T_FORCED_FACTOR_WAKEUP_DELAY * VCNL36825T_FORCED_FACTOR_SCALE))
|
||||
|
||||
#endif
|
||||
|
||||
enum vcnl36825t_operation_mode {
|
||||
VCNL36825T_OPERATION_MODE_AUTO,
|
||||
VCNL36825T_OPERATION_MODE_FORCE,
|
||||
|
@ -288,7 +302,12 @@ struct vcnl36825t_config {
|
|||
struct vcnl36825t_data {
|
||||
uint16_t proximity;
|
||||
|
||||
int meas_timeout_us; /** wait time for finished measurement for "forced" operation mode */
|
||||
unsigned int meas_timeout_us; /** wait time for finished measurement in "forced"-mode */
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
unsigned int meas_timeout_running_us;
|
||||
unsigned int meas_timeout_wakeup_us;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue