Welcome to mirror list, hosted at ThFree Co, Russian Federation.

tsl_ecs.c « src « STM32_TouchSensing_Library « ST « Middlewares - github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 718dafdcceb9e6e3a82be405a32e27ba6349adb4 (plain)
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
/**
  ******************************************************************************
  * @file    tsl_ecs.c
  * @author  MCD Application Team
  * @brief   This file contains all functions to manage the ECS.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 20020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tsl_ecs.h"
#include "tsl_globals.h"

/* Private typedefs ----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/

#define THIS_OBJ_TYPE      TSL_Globals.This_Obj->Type
#define THIS_TKEY_REF      TSL_Globals.This_TKey->p_ChD->Ref
#define THIS_TKEY_REFREST  TSL_Globals.This_TKey->p_ChD->RefRest
#define THIS_TKEY_DELTA    TSL_Globals.This_TKey->p_ChD->Delta
#define THIS_TKEY_STATEID  TSL_Globals.This_TKey->p_Data->StateId

#define THIS_LINROT_STATEID      TSL_Globals.This_LinRot->p_Data->StateId
#define THIS_LINROT_NB_CHANNELS  TSL_Globals.This_LinRot->NbChannels

/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private functions prototype -----------------------------------------------*/

/**
  * @brief Calculate the K coefficient
  * @param[in] objgrp Pointer to the objects group to process
  * @param[in] k_slow  K coefficient when objects have different delta variation
  * @param[in] k_fast  K coefficient when objects have the same delta variation
  * @retval    K coefficient (slow or fast)
  */
TSL_tKCoeff_T TSL_ecs_CalcK(TSL_ObjectGroup_T *objgrp, TSL_tKCoeff_T k_slow, TSL_tKCoeff_T k_fast)
{
  TSL_tIndex_T idx_obj; // Index of current object
  TSL_tIndex_T idx_ch; // Index of current channel
  TSL_tDelta_T ldelta = 0; // Temporary delta
  TSL_tDelta_T ECS_Fast_Enable = 1;
  TSL_tDelta_T ECS_Fast_Direction = 0;
  CONST TSL_Object_T *pobj;
  TSL_tKCoeff_T retval = k_slow;
  TSL_tNb_T nb_channels = 0; // Number of channels inside current object
  TSL_ChannelData_T *p_Ch = 0;

  // Check parameters
  if (k_slow > 255) k_slow = 255;
  if (k_fast > 255) k_fast = 255;

  pobj = objgrp->p_Obj; // First object in the group

  // Process all objects
  for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
  {

    // Assign global object
    TSL_obj_SetGlobalObj(pobj);

#if TSLPRM_TOTAL_TKEYS > 0
    if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
    {
      // Ignore object if not in Release state (OFF or Error in this case)
      if (THIS_TKEY_STATEID != TSL_STATEID_RELEASE)
      {
        pobj++; // Next object
        continue; // Stop processing of current object
      }
      nb_channels = 1;
      p_Ch = TSL_Globals.This_TKey->p_ChD;
    }
#endif

#if TSLPRM_TOTAL_LNRTS > 0
    if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
        (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
    {
      // Ignore object if not in Release state (OFF or Error in this case)
      if (THIS_LINROT_STATEID != TSL_STATEID_RELEASE)
      {
        pobj++; // Next object
        continue; // Stop processing of current object
      }
      nb_channels = THIS_LINROT_NB_CHANNELS;
      p_Ch = TSL_Globals.This_LinRot->p_ChD;
    }
#endif

    // Check channel pointer variable
    if (p_Ch == 0) return 0;

    // Check all channels of current object
    for (idx_ch = 0; idx_ch < nb_channels; idx_ch++)
    {

      ldelta = p_Ch->Delta;

      // Check delta
      if (ldelta == 0) // No Fast ECS !
      {
        ECS_Fast_Enable = 0;
      }
      else
      {
        if (ldelta < 0)
        {
          if (ECS_Fast_Direction > 0) // No Fast ECS !
          {
            ECS_Fast_Enable = 0;
          }
          else
          {
            ECS_Fast_Direction = -1;
          }
        }
        else
        {
          if (ECS_Fast_Direction < 0) // No Fast ECS !
          {
            ECS_Fast_Enable = 0;
          }
          else
          {
            ECS_Fast_Direction = 1;
          }
        }
      }

      p_Ch++; // Next channel

    } // for all channels of current object

    pobj++; // Next object

  } // for all objects

  // Assign K fast following Delta variations
  if (ECS_Fast_Enable)
  {
    retval = k_fast;
  }

  return retval;
}


/**
  * @brief Calculate the new Reference on a group of objects
  * @param[in] objgrp Pointer to the objects group to process
  * @param[in] Kcoeff K coefficient to apply
  * @retval None
  */
void TSL_ecs_ProcessK(TSL_ObjectGroup_T *objgrp, TSL_tKCoeff_T Kcoeff)
{
  TSL_tIndex_T idx_obj; // Index of current object
  TSL_tIndex_T idx_ch; // Index of current channel
  CONST TSL_Object_T *pobj;
  TSL_tKCoeff_T Kcoeff_comp;
  uint32_t ECS_meas;
  uint32_t ECS_ref;
  TSL_tNb_T nb_channels = 0; // Number of channels inside current object
  TSL_ChannelData_T *p_Ch = 0;
  void(*pFunc_SetStateCalibration)(TSL_tCounter_T delay) = 0;

  // Check parameter
  if (Kcoeff > 255) Kcoeff = 255;

  pobj = objgrp->p_Obj; // First object in the group

  // Calculate the K coefficient complement
  Kcoeff_comp = (0xFF ^ Kcoeff) + 1;

  // Process all objects
  for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
  {

    // Assign global object
    TSL_obj_SetGlobalObj(pobj);

#if TSLPRM_TOTAL_TKEYS > 0
    if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
    {
      // Ignore object if not in Release state (OFF or Error in this case)
      if (THIS_TKEY_STATEID != TSL_STATEID_RELEASE)
      {
        pobj++; // Next object
        continue; // Stop processing of current object
      }
      nb_channels = 1;
      p_Ch = TSL_Globals.This_TKey->p_ChD;
      pFunc_SetStateCalibration = &TSL_tkey_SetStateCalibration;
    }
#endif

#if TSLPRM_TOTAL_LNRTS > 0
    if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
        (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
    {
      // Ignore object if not in Release state (OFF or Error in this case)
      if (THIS_LINROT_STATEID != TSL_STATEID_RELEASE)
      {
        pobj++; // Next object
        continue; // Stop processing of current object
      }
      nb_channels = THIS_LINROT_NB_CHANNELS;
      p_Ch = TSL_Globals.This_LinRot->p_ChD;
      pFunc_SetStateCalibration = &TSL_linrot_SetStateCalibration;
    }
#endif

    // Check channel pointer variable
    if (p_Ch == 0) return;

    // Calculate the new reference + rest for all channels
    for (idx_ch = 0; idx_ch < nb_channels; idx_ch++)
    {
      ECS_meas = TSL_acq_ComputeMeas(p_Ch->Ref, p_Ch->Delta);
      ECS_meas <<= 8;

      ECS_ref = (uint32_t)(p_Ch->Ref);
      ECS_ref <<= 8;
      ECS_ref += p_Ch->RefRest;
      ECS_ref *= Kcoeff_comp;
      ECS_ref += (Kcoeff * ECS_meas);

      p_Ch->RefRest = (TSL_tRefRest_T)((ECS_ref >> 8) & 0xFF);
      p_Ch->Ref = (TSL_tRef_T)(ECS_ref >> 16);

      // Go in Calibration state in the Reference is out of Range
      if (TSL_acq_TestReferenceOutOfRange(p_Ch) == TSL_TRUE)
      {
        pFunc_SetStateCalibration(0);
      }

      p_Ch++; // Next channel
    }

    pobj++; // Next object

  } // for all objects

}


/**
  * @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[in] objgrp Pointer to the objects group to process
  * @retval Status
  */
TSL_Status_enum_T TSL_ecs_Process(TSL_ObjectGroup_T *objgrp)
{
  TSL_tKCoeff_T MyKcoeff;
  TSL_Status_enum_T retval;

  if ((objgrp->StateMask & TSL_STATE_RELEASE_BIT_MASK) && !(objgrp->StateMask & TSL_STATEMASK_ACTIVE))
  {
#if TSLPRM_ECS_DELAY > 0
    if (!objgrp->ECS_wait)
    {
      disableInterrupts();
      objgrp->ECS_start_time = TSL_Globals.Tick_ms; // Save the current time
      enableInterrupts();
      objgrp->ECS_wait = 1;
      objgrp->ECS_exec = 0;
    }
#else
    objgrp->ECS_exec = 1;
#endif
  }
  else
  {
#if TSLPRM_ECS_DELAY > 0
    objgrp->ECS_wait = 0;
#endif
    objgrp->ECS_exec = 0;
  }

#if TSLPRM_ECS_DELAY > 0
  if (objgrp->ECS_wait && (!objgrp->ECS_exec))
  {
    // Execute the ECS only when the delay has elapsed
    if (TSL_tim_CheckDelay_ms(TSLPRM_ECS_DELAY, &objgrp->ECS_start_time) == TSL_STATUS_OK)
    {
      objgrp->ECS_exec = 1;
    }
  }
#endif

  if (objgrp->ECS_exec)
  {
    // Calculate the K coefficient
    MyKcoeff = TSL_ecs_CalcK(objgrp, TSLPRM_ECS_K_SLOW, TSLPRM_ECS_K_FAST);
    // Process the objects
    TSL_ecs_ProcessK(objgrp, MyKcoeff);
    retval = TSL_STATUS_OK;
  }
  else
  {
    retval = TSL_STATUS_BUSY;
  }

  return retval;
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/