1 /*!
2 * @file tsc_ecs.c
3 *
4 * @brief This file contains all functions to manage the ECS
5 *
6 * @version V1.0.1
7 *
8 * @date 2022-09-20
9 *
10 * @attention
11 *
12 * Copyright (C) 2020-2022 Geehy Semiconductor
13 *
14 * You may not use this file except in compliance with the
15 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16 *
17 * The program is only for reference, which is distributed in the hope
18 * that it will be useful and instructional for customers to develop
19 * their software. Unless required by applicable law or agreed to in
20 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23 * and limitations under the License.
24 */
25
26 /* Includes */
27 #include "tsc.h"
28 #include "tsc_ecs.h"
29
30 /** @addtogroup TSC_Driver_Library TSC Driver Library
31 @{
32 */
33
34 /** @addtogroup TSC_ECS_Driver TSC ECS Driver
35 @{
36 */
37
38 /** @defgroup TSC_ECS_Macros Macros
39 @{
40 */
41
42 /**@} end of group TSC_ECS_Macros */
43
44 /** @defgroup TSC_ECS_Enumerations Enumerations
45 @{
46 */
47
48 /**@} end of group TSC_ECS_Enumerations */
49
50 /** @defgroup TSC_ECS_Structures Structures
51 @{
52 */
53
54 /**@} end of group TSC_ECS_Structures */
55
56 /** @defgroup TSC_ECS_Variables Variables
57 @{
58 */
59
60 /**@} end of group TSC_ECS_Variables */
61
62 /** @defgroup TSC_ECS_Functions Functions
63 @{
64 */
65
66 /*!
67 * @brief Calculate the K coefficient
68 *
69 * @param kDiffer: K coefficient when objects have different delta variation
70 *
71 * @param kSame: K coefficient when objects have the same delta variation
72 *
73 * @retval K coefficient (differ or same)
74 */
TSC_Ecs_CalculateK(TSC_ObjectGroup_T * objgrp,TSC_tKCoeff_T kDiffer,TSC_tKCoeff_T kSame)75 TSC_tKCoeff_T TSC_Ecs_CalculateK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kDiffer, TSC_tKCoeff_T kSame)
76 {
77 TSC_tIndex_T idxObj;
78 TSC_tIndex_T idxChannel;
79 TSC_tDelta_T value = 0;
80 TSC_tDelta_T Cmd = 1;
81 TSC_tDelta_T Dir = 0;
82 TSC_tNum_T numChannel = 0;
83 TSC_tKCoeff_T retval = kDiffer;
84 TSC_Channel_Data_T* p_Ch = 0;
85 CONST TSC_Object_T* pObj;
86
87 pObj = objgrp->p_Obj;
88
89 /* Process all objects */
90 for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++)
91 {
92 TSC_Obj_ConfigGlobalObj(pObj);
93
94 switch (FOR_OBJ_TYPE)
95 {
96 #if TOUCH_TOTAL_KEYS > 0
97 case TSC_OBJ_TOUCHKEY:
98 case TSC_OBJ_TOUCHKEYB:
99 if (FOR_KEY_STATEID != TSC_STATEID_RELEASE)
100 {
101 pObj++;
102 continue;
103 }
104 numChannel = 1;
105 p_Ch = TSC_Globals.For_Key->p_ChD;
106 break;
107 #endif
108
109 #if TOUCH_TOTAL_LNRTS > 0
110 case TSC_OBJ_LINEAR:
111 case TSC_OBJ_LINEARB:
112 case TSC_OBJ_ROTARY:
113 case TSC_OBJ_ROTARYB:
114 if (FOR_LINROT_STATEID != TSC_STATEID_RELEASE)
115 {
116 pObj++;
117 continue;
118 }
119 numChannel = FOR_LINROT_NB_CHANNELS;
120 p_Ch = TSC_Globals.For_LinRot->p_ChD;
121 break;
122 #endif
123 default:
124 break;
125 }
126
127 /* Check all channels of current object */
128 for (idxChannel = 0; idxChannel < numChannel; idxChannel++)
129 {
130 value = p_Ch->Delta;
131
132 if (value)
133 {
134 if (value >= 0)
135 {
136 if (Dir > 0)
137 {
138 Dir = 1;
139 }
140 else
141 {
142 Cmd = 0;
143 }
144 }
145 else
146 {
147 if (Dir < 0)
148 {
149 Dir = -1;
150 }
151 else
152 {
153 Cmd = 0;
154 }
155 }
156 }
157 else
158 {
159 Cmd = 0;
160 }
161 p_Ch++;
162 }
163 pObj++;
164 }
165
166 if (Cmd)
167 {
168 retval = kSame;
169 }
170 return retval;
171 }
172
173 /*!
174 * @brief Calculate the new Reference on a group of objects
175 *
176 * @param objgrp: Pointer to the objects group to process
177 *
178 * @param kCoeff: K coefficient to apply
179 *
180 * @retval None
181 */
TSC_Ecs_ProcessK(TSC_ObjectGroup_T * objgrp,TSC_tKCoeff_T kCoeff)182 void TSC_Ecs_ProcessK(TSC_ObjectGroup_T* objgrp, TSC_tKCoeff_T kCoeff)
183 {
184 TSC_tIndex_T idxObj;
185 TSC_tIndex_T idxChannel;
186 CONST TSC_Object_T* pObj;
187 TSC_tKCoeff_T kCoeffComp;
188 uint32_t meas, refer;
189 TSC_tNum_T numChannel = 0;
190 TSC_Channel_Data_T* p_Ch = 0;
191 void(*pFunc_SetStateCalibration)(TSC_tCounter_T delay) = 0;
192
193 pObj = objgrp->p_Obj;
194
195 /* Calculate the K coefficient complement */
196 kCoeffComp = (0xFF ^ kCoeff) + 1;
197
198 /* Process all objects */
199 for (idxObj = 0; idxObj < objgrp->NbObjects; idxObj++)
200 {
201 TSC_Obj_ConfigGlobalObj(pObj);
202
203 switch (FOR_OBJ_TYPE)
204 {
205 #if TOUCH_TOTAL_KEYS > 0
206 case TSC_OBJ_TOUCHKEY:
207 case TSC_OBJ_TOUCHKEYB:
208 if (FOR_KEY_STATEID != TSC_STATEID_RELEASE)
209 {
210 pObj++;
211 continue;
212 }
213 numChannel = 1;
214 p_Ch = TSC_Globals.For_Key->p_ChD;
215 pFunc_SetStateCalibration = &TSC_TouchKey_ConfigCalibrationState;
216 break;
217 #endif
218
219 #if TOUCH_TOTAL_LNRTS > 0
220 case TSC_OBJ_LINEAR:
221 case TSC_OBJ_LINEARB:
222 case TSC_OBJ_ROTARY:
223 case TSC_OBJ_ROTARYB:
224 if (FOR_LINROT_STATEID != TSC_STATEID_RELEASE)
225 {
226 pObj++;
227 continue;
228 }
229 numChannel = FOR_LINROT_NB_CHANNELS;
230 p_Ch = TSC_Globals.For_LinRot->p_ChD;
231 pFunc_SetStateCalibration = &TSC_Linrot_ConfigCalibrationState;
232 break;
233 #endif
234 default:
235 break;
236 }
237
238 /* Calculate the new reference + rest for all channels */
239 for (idxChannel = 0; idxChannel < numChannel; idxChannel++)
240 {
241 meas = TSC_Acq_ComputeMeas(p_Ch->Refer, p_Ch->Delta);
242 meas <<= 8;
243
244 refer = (uint32_t)(p_Ch->Refer);
245 refer <<= 8;
246 refer += p_Ch->RefRest;
247 refer *= kCoeffComp;
248 refer += (kCoeff * meas);
249
250 p_Ch->RefRest = (TSC_tRefRest_T)((refer >> 8) & 0xFF);
251 p_Ch->Refer = (TSC_tRefer_T)(refer >> 16);
252
253 /* Go in Calibration state in the Reference is out of Range */
254 if (TSC_Acq_TestReferenceRange(p_Ch) == TSC_TRUE)
255 {
256 pFunc_SetStateCalibration(0);
257 }
258 p_Ch++;
259 }
260 pObj++;
261 }
262 }
263
264 /*!
265 * @brief ECS algorithm on a group of objects
266 * The ECS is only performed if at least an object is in Release state and
267 * if no objects are in active states (Prox, Detect or Touch)
268 * An optional delay is added after the ECS condition (all sensors in Release state) is reached.
269 *
270 * @param objgrp: Pointer to the objects group to process
271 *
272 * @retval Status
273 */
TSC_Ecs_Process(TSC_ObjectGroup_T * objgrp)274 TSC_STATUS_T TSC_Ecs_Process(TSC_ObjectGroup_T* objgrp)
275 {
276 TSC_tKCoeff_T myKcoeff;
277 TSC_STATUS_T retval;
278
279 if ((objgrp->StateMask & TSC_STATE_RELEASE_BIT_MASK) && !(objgrp->StateMask & TSC_STATEMASK_ACTIVE))
280 {
281 #if TOUCH_ECS_DELAY > 0
282 if (!objgrp->wait)
283 {
284 disableInterrupts();
285 objgrp->time = TSC_Globals.Tick_ms;
286 enableInterrupts();
287 objgrp->wait = 1;
288 objgrp->execution = 0;
289 }
290 #else
291 objgrp->execution = 1;
292 #endif
293 }
294 else
295 {
296 #if TOUCH_ECS_DELAY > 0
297 objgrp->wait = 0;
298 #endif
299 objgrp->execution = 0;
300 }
301
302 #if TOUCH_ECS_DELAY > 0
303 if (objgrp->wait && (!objgrp->execution))
304 {
305 if (TSC_Time_Delay_ms(TOUCH_ECS_DELAY, &objgrp->time) == TSC_STATUS_OK)
306 {
307 objgrp->execution = 1;
308 }
309 }
310 #endif
311
312 if (objgrp->execution == 0)
313 {
314 retval = TSC_STATUS_BUSY;
315 }
316 else
317 {
318 /* Calculate the K coefficient */
319 myKcoeff = TSC_Ecs_CalculateK(objgrp, TOUCH_ECS_K_DIFFER, TOUCH_ECS_K_SAME);
320 /* Process the objects */
321 TSC_Ecs_ProcessK(objgrp, myKcoeff);
322 retval = TSC_STATUS_OK;
323 }
324 return retval;
325 }
326
327 /**@} end of group TSC_ECS_Functions */
328 /**@} end of group TSC_ECS_Driver */
329 /**@} end of group TSC_Driver_Library */
330