|
1 /** |
|
2 * @file task_apds9930.c |
|
3 * @brief The FreeRTOS task to query the APDS9930 sensor. |
|
4 */ |
|
5 |
|
6 |
|
7 #include "config.h" |
|
8 |
|
9 |
|
10 static const char *TAG = "task_apds9930"; |
|
11 |
|
12 SemaphoreHandle_t xSemaphoreAPDS9930 = NULL; ///< Semaphore APDS9930 task |
|
13 EventGroupHandle_t xEventGroupAPDS9930; ///< Events APDS9930 task |
|
14 APDS9930_State *apds9930_state; ///< Public state for other tasks |
|
15 |
|
16 float ambient_light; |
|
17 uint16_t ch0 = 0; |
|
18 uint16_t ch1 = 1; |
|
19 uint16_t ALS_maxcount; ///< Maximum ADC value |
|
20 uint16_t ALS_mincount; ///< Threshold to increase gain |
|
21 |
|
22 |
|
23 extern apds9930_t apds9930_dev; |
|
24 |
|
25 const int TASK_APDS9930_REQUEST_DONE = BIT0; ///< All requests are done. |
|
26 const int TASK_APDS9930_REQUEST_LIGHT = BIT1; ///< Request Ambient Light |
|
27 |
|
28 |
|
29 |
|
30 void request_apds9930(void) |
|
31 { |
|
32 xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); |
|
33 xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); |
|
34 } |
|
35 |
|
36 |
|
37 |
|
38 bool ready_apds9930(void) |
|
39 { |
|
40 if (xEventGroupGetBits(xEventGroupAPDS9930) & TASK_APDS9930_REQUEST_DONE) |
|
41 return true; |
|
42 return false; |
|
43 } |
|
44 |
|
45 |
|
46 |
|
47 /* |
|
48 * Task to read APDS9930 sensor on request. |
|
49 */ |
|
50 void task_apds9930(void *pvParameter) |
|
51 { |
|
52 int tries; |
|
53 esp_err_t err = ESP_OK; |
|
54 uint8_t l_gain = 0, l_aglbit = 0; |
|
55 |
|
56 ESP_LOGI(TAG, "Starting task APDS9930 sda=%d scl=%d", CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL); |
|
57 apds9930_state = malloc(sizeof(APDS9930_State)); |
|
58 |
|
59 apds9930_state->valid = false; |
|
60 apds9930_state->fake = (apds9930_dev.i2c_dev.addr == 0) ? true:false; |
|
61 apds9930_state->address = apds9930_dev.i2c_dev.addr; |
|
62 apds9930_state->error = APDS9930_ERR_NONE; |
|
63 |
|
64 /* event handler and event group for this task */ |
|
65 xEventGroupAPDS9930 = xEventGroupCreate(); |
|
66 EventBits_t uxBits; |
|
67 |
|
68 /* |
|
69 * Task loop forever. |
|
70 */ |
|
71 ESP_LOGI(TAG, "Starting loop APDS9930 sensor 0x%02x %d", apds9930_state->address, apds9930_state->fake); |
|
72 while (1) { |
|
73 |
|
74 uxBits = xEventGroupWaitBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT, pdFALSE, pdFALSE, portMAX_DELAY ); |
|
75 |
|
76 if (uxBits & TASK_APDS9930_REQUEST_LIGHT) { |
|
77 |
|
78 if (! apds9930_state->fake) { |
|
79 /* Real sensor is present */ |
|
80 apds9930_enablePower(&apds9930_dev); |
|
81 apds9930_enableLightSensor(&apds9930_dev, false); |
|
82 apds9930_disableProximitySensor(&apds9930_dev); |
|
83 if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { |
|
84 l_gain = apds9930_state->gain; |
|
85 l_aglbit = apds9930_state->aglbit; |
|
86 xSemaphoreGive(xSemaphoreAPDS9930); |
|
87 } |
|
88 if (l_gain > 3) |
|
89 l_gain = 0; |
|
90 apds9930_setAmbientLightGain(&apds9930_dev, l_gain); |
|
91 apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); |
|
92 vTaskDelay(200 / portTICK_PERIOD_MS); |
|
93 tries = 6; |
|
94 err = ESP_OK; |
|
95 |
|
96 while (tries) { |
|
97 err = apds9930_readAmbientLightLux(&apds9930_dev, &ambient_light); |
|
98 if (err == ESP_OK) { |
|
99 err = apds9930_readCh0Light(&apds9930_dev, &ch0); |
|
100 if (err == ESP_OK) { |
|
101 err = apds9930_readCh1Light(&apds9930_dev, &ch1); |
|
102 } |
|
103 } |
|
104 if (err != ESP_OK) { |
|
105 ESP_LOGE(TAG, "read APDS-9930 values error '%s'", esp_err_to_name(err)); |
|
106 break; |
|
107 } |
|
108 |
|
109 /* |
|
110 * Check ranges |
|
111 */ |
|
112 if (((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) && ((l_gain > 0) || (l_aglbit == 0))) { |
|
113 /* Looks like an internal overflow */ |
|
114 if (l_gain > 0) { |
|
115 l_gain--; |
|
116 } else { |
|
117 l_aglbit = 1; |
|
118 } |
|
119 apds9930_setAmbientLightGain(&apds9930_dev, l_gain); |
|
120 apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); |
|
121 vTaskDelay(200 / portTICK_PERIOD_MS); |
|
122 ESP_LOGI(TAG, "Gain decreased to %d AGL: %d", l_gain, l_aglbit); |
|
123 } else if ((ch0 < ALS_mincount) && (ch1 < ALS_mincount) && (l_gain < 3)) { |
|
124 /* Looks like low resolution of the ADC. */ |
|
125 if ((l_gain == 0) && l_aglbit) { |
|
126 l_aglbit = 0; |
|
127 } else { |
|
128 l_gain++; |
|
129 } |
|
130 apds9930_setAmbientLightGain(&apds9930_dev, l_gain); |
|
131 apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); |
|
132 vTaskDelay(200 / portTICK_PERIOD_MS); |
|
133 ESP_LOGI(TAG, "Gain increased to %d AGL: %d", l_gain, l_aglbit); |
|
134 } else { |
|
135 if ((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) { |
|
136 ambient_light = -1; |
|
137 } else if (l_aglbit) { |
|
138 ambient_light = ambient_light / 0.1666; |
|
139 } |
|
140 ESP_LOGI(TAG, "Ambient: %.3f Ch0: %d Ch1: %d Gain: %d AGL: %d", ambient_light, ch0, ch1, l_gain, l_aglbit); |
|
141 break; |
|
142 } |
|
143 tries--; |
|
144 } |
|
145 if (tries == 0) { |
|
146 ESP_LOGW(TAG, "tries = 0"); |
|
147 } |
|
148 apds9930_disableLightSensor(&apds9930_dev); |
|
149 apds9930_disablePower(&apds9930_dev); |
|
150 |
|
151 if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { |
|
152 if (err == ESP_OK) { |
|
153 apds9930_state->error = APDS9930_ERR_NONE; |
|
154 apds9930_state->valid = true; |
|
155 apds9930_state->ambient_light = ambient_light; |
|
156 apds9930_state->gain = l_gain; |
|
157 apds9930_state->aglbit = l_aglbit; |
|
158 } else { |
|
159 apds9930_state->error = APDS9930_ERR_READ; |
|
160 apds9930_state->valid = false; |
|
161 apds9930_state->ambient_light = 12.34; |
|
162 apds9930_state->gain = 2; |
|
163 apds9930_state->aglbit = 0; |
|
164 } |
|
165 xSemaphoreGive(xSemaphoreAPDS9930); |
|
166 } |
|
167 } else { |
|
168 /* Use fake values */ |
|
169 if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { |
|
170 apds9930_state->error = APDS9930_ERR_NONE; |
|
171 apds9930_state->valid = true; |
|
172 apds9930_state->ambient_light = 12.34; |
|
173 apds9930_state->gain = 2; |
|
174 apds9930_state->aglbit = 0; |
|
175 xSemaphoreGive(xSemaphoreAPDS9930); |
|
176 } |
|
177 } |
|
178 |
|
179 xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); |
|
180 xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); |
|
181 #if 1 |
|
182 ESP_LOGI(TAG, " Light: %.2f, gain: %d, error: %d", apds9930_state->ambient_light, apds9930_state->gain, apds9930_state->error); |
|
183 #endif |
|
184 } |
|
185 } |
|
186 } |