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