diff -r bdc123ae7b49 -r bb72d448e282 main/task_apds9930.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/task_apds9930.c Mon Apr 03 16:07:34 2023 +0200 @@ -0,0 +1,186 @@ +/** + * @file task_apds9930.c + * @brief The FreeRTOS task to query the APDS9930 sensor. + */ + + +#include "config.h" + + +static const char *TAG = "task_apds9930"; + +SemaphoreHandle_t xSemaphoreAPDS9930 = NULL; ///< Semaphore APDS9930 task +EventGroupHandle_t xEventGroupAPDS9930; ///< Events APDS9930 task +APDS9930_State *apds9930_state; ///< Public state for other tasks + +float ambient_light; +uint16_t ch0 = 0; +uint16_t ch1 = 1; +uint16_t ALS_maxcount; ///< Maximum ADC value +uint16_t ALS_mincount; ///< Threshold to increase gain + + +extern apds9930_t apds9930_dev; + +const int TASK_APDS9930_REQUEST_DONE = BIT0; ///< All requests are done. +const int TASK_APDS9930_REQUEST_LIGHT = BIT1; ///< Request Ambient Light + + + +void request_apds9930(void) +{ + xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); + xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); +} + + + +bool ready_apds9930(void) +{ + if (xEventGroupGetBits(xEventGroupAPDS9930) & TASK_APDS9930_REQUEST_DONE) + return true; + return false; +} + + + +/* + * Task to read APDS9930 sensor on request. + */ +void task_apds9930(void *pvParameter) +{ + int tries; + esp_err_t err = ESP_OK; + uint8_t l_gain = 0, l_aglbit = 0; + + ESP_LOGI(TAG, "Starting task APDS9930 sda=%d scl=%d", CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL); + apds9930_state = malloc(sizeof(APDS9930_State)); + + apds9930_state->valid = false; + apds9930_state->fake = (apds9930_dev.i2c_dev.addr == 0) ? true:false; + apds9930_state->address = apds9930_dev.i2c_dev.addr; + apds9930_state->error = APDS9930_ERR_NONE; + + /* event handler and event group for this task */ + xEventGroupAPDS9930 = xEventGroupCreate(); + EventBits_t uxBits; + + /* + * Task loop forever. + */ + ESP_LOGI(TAG, "Starting loop APDS9930 sensor 0x%02x %d", apds9930_state->address, apds9930_state->fake); + while (1) { + + uxBits = xEventGroupWaitBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT, pdFALSE, pdFALSE, portMAX_DELAY ); + + if (uxBits & TASK_APDS9930_REQUEST_LIGHT) { + + if (! apds9930_state->fake) { + /* Real sensor is present */ + apds9930_enablePower(&apds9930_dev); + apds9930_enableLightSensor(&apds9930_dev, false); + apds9930_disableProximitySensor(&apds9930_dev); + if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { + l_gain = apds9930_state->gain; + l_aglbit = apds9930_state->aglbit; + xSemaphoreGive(xSemaphoreAPDS9930); + } + if (l_gain > 3) + l_gain = 0; + apds9930_setAmbientLightGain(&apds9930_dev, l_gain); + apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); + vTaskDelay(200 / portTICK_PERIOD_MS); + tries = 6; + err = ESP_OK; + + while (tries) { + err = apds9930_readAmbientLightLux(&apds9930_dev, &ambient_light); + if (err == ESP_OK) { + err = apds9930_readCh0Light(&apds9930_dev, &ch0); + if (err == ESP_OK) { + err = apds9930_readCh1Light(&apds9930_dev, &ch1); + } + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "read APDS-9930 values error '%s'", esp_err_to_name(err)); + break; + } + + /* + * Check ranges + */ + if (((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) && ((l_gain > 0) || (l_aglbit == 0))) { + /* Looks like an internal overflow */ + if (l_gain > 0) { + l_gain--; + } else { + l_aglbit = 1; + } + apds9930_setAmbientLightGain(&apds9930_dev, l_gain); + apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); + vTaskDelay(200 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Gain decreased to %d AGL: %d", l_gain, l_aglbit); + } else if ((ch0 < ALS_mincount) && (ch1 < ALS_mincount) && (l_gain < 3)) { + /* Looks like low resolution of the ADC. */ + if ((l_gain == 0) && l_aglbit) { + l_aglbit = 0; + } else { + l_gain++; + } + apds9930_setAmbientLightGain(&apds9930_dev, l_gain); + apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); + vTaskDelay(200 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Gain increased to %d AGL: %d", l_gain, l_aglbit); + } else { + if ((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) { + ambient_light = -1; + } else if (l_aglbit) { + ambient_light = ambient_light / 0.1666; + } + ESP_LOGI(TAG, "Ambient: %.3f Ch0: %d Ch1: %d Gain: %d AGL: %d", ambient_light, ch0, ch1, l_gain, l_aglbit); + break; + } + tries--; + } + if (tries == 0) { + ESP_LOGW(TAG, "tries = 0"); + } + apds9930_disableLightSensor(&apds9930_dev); + apds9930_disablePower(&apds9930_dev); + + if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { + if (err == ESP_OK) { + apds9930_state->error = APDS9930_ERR_NONE; + apds9930_state->valid = true; + apds9930_state->ambient_light = ambient_light; + apds9930_state->gain = l_gain; + apds9930_state->aglbit = l_aglbit; + } else { + apds9930_state->error = APDS9930_ERR_READ; + apds9930_state->valid = false; + apds9930_state->ambient_light = 12.34; + apds9930_state->gain = 2; + apds9930_state->aglbit = 0; + } + xSemaphoreGive(xSemaphoreAPDS9930); + } + } else { + /* Use fake values */ + if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { + apds9930_state->error = APDS9930_ERR_NONE; + apds9930_state->valid = true; + apds9930_state->ambient_light = 12.34; + apds9930_state->gain = 2; + apds9930_state->aglbit = 0; + xSemaphoreGive(xSemaphoreAPDS9930); + } + } + + xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); + xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); +#if 1 + ESP_LOGI(TAG, " Light: %.2f, gain: %d, error: %d", apds9930_state->ambient_light, apds9930_state->gain, apds9930_state->error); +#endif + } + } +}