]> git.sur5r.net Git - freertos/blob
23774bc6db092cd8835cb5124a5f0826125a7ce7
[freertos] /
1 /**\r
2   ******************************************************************************\r
3   * @file    tsl_acq_stm8tl5x.c\r
4   * @author  MCD Application Team\r
5   * @version V1.3.2\r
6   * @date    22-January-2013\r
7   * @brief   This file contains all functions to manage the PXS acquisition\r
8   *          on STM8TL5x products.\r
9   ******************************************************************************\r
10   * @attention\r
11   *\r
12   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>\r
13   *\r
14   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");\r
15   * You may not use this file except in compliance with the License.\r
16   * You may obtain a copy of the License at:\r
17   *\r
18   *        http://www.st.com/software_license_agreement_liberty_v2\r
19   *\r
20   * Unless required by applicable law or agreed to in writing, software\r
21   * distributed under the License is distributed on an "AS IS" BASIS,\r
22   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
23   * See the License for the specific language governing permissions and\r
24   * limitations under the License.\r
25   *\r
26   ******************************************************************************\r
27   */\r
28 \r
29 /* Includes ------------------------------------------------------------------*/\r
30 #include "tsl_acq_stm8tl5x.h"\r
31 #include "tsl_globals.h"\r
32 #include "stm8tl5x_it.h"\r
33 \r
34 /* Private typedefs ----------------------------------------------------------*/\r
35 \r
36 /* Private defines -----------------------------------------------------------*/\r
37 #define EPCC_INIT_VALUE (0x80)\r
38 #define CS_MIDDLE_VALUE (17)\r
39 #define CS_MAX_VALUE    (32)\r
40 #define MAX_MEASURE     (0xFFFF)\r
41 \r
42 /* Private macros ------------------------------------------------------------*/\r
43 #define IS_BANK_INDEX_OK(INDEX)   (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))\r
44 #define IS_SOURCE_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_CHANNELS)))\r
45 #define IS_EPCC_STATUS_OK(STATUS) ((STATUS & TSL_EPCC_CHANGE_MASK) != 0)\r
46 #define IS_CSSEL_OK(CSSEL)        (((CSSEL) == 0) || (((CSSEL) > 0) && ((CSSEL) < CS_MAX_VALUE)))\r
47 \r
48 /* Private variables ---------------------------------------------------------*/\r
49 TSL_BankConfig_T PXS_BankConfig[TSLPRM_TOTAL_BANKS];\r
50 CONST uint8_t PXS_CSsorting[] = {0, 1, 2, 8, 3, 4, 5, 9, 6, 10, 16, 11, 7, 12, 17, 13, 18, 19, 14, 24, 15, 20, 25, 21, 26, 22, 27, 23, 28, 29, 30, 31};\r
51 \r
52 /* Private functions prototype -----------------------------------------------*/\r
53 void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk);\r
54 int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T bank);\r
55 TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *);\r
56 void SoftDelay(uint32_t val);\r
57 \r
58 /**\r
59   * @brief  Initializes the acquisition module.\r
60   * @param  None\r
61   * @retval Status\r
62   */\r
63 TSL_Status_enum_T TSL_acq_Init(void)\r
64 {\r
65 \r
66   TSL_Status_enum_T retval = TSL_STATUS_OK;\r
67 \r
68   TSL_tIndex_T i;\r
69   TSL_tIndex_T j;\r
70   TSL_tIndex_T idx_bk; // Bank index\r
71   uint16_t TxInUseMask = 0;\r
72   uint16_t RxInUseMask = 0;\r
73   CONST TSL_Bank_T *bank;\r
74   uint8_t *CSArray;\r
75 \r
76   // Enable the PXS IP clock\r
77   CLK->PCKENR1 |= CLK_PCKENR1_PXS;\r
78 \r
79   // Initialization of PXS IP\r
80   PXS->CKCR1 &= (uint8_t)~PXS_CKCR1_PRESC;\r
81 \r
82 #if (TSLPRM_PXS_HSI == 16000)\r
83   PXS->CKCR1 |= PXS_CKCR1_16MHZ;\r
84 #elif (TSLPRM_PXS_HSI == 8000)\r
85   PXS->CKCR1 |= PXS_CKCR1_8MHZ;\r
86 #elif (TSLPRM_PXS_HSI == 4000)\r
87   PXS->CKCR1 |= PXS_CKCR1_4MHZ;\r
88 #elif (TSLPRM_PXS_HSI == 2000)\r
89   PXS->CKCR1 |= PXS_CKCR1_2MHZ;\r
90 #elif (TSLPRM_PXS_HSI == 1000)\r
91   PXS->CKCR1 |= PXS_CKCR1_1MHZ;\r
92 #elif (TSLPRM_PXS_HSI == 500)\r
93   PXS->CKCR1 |= PXS_CKCR1_500KHZ;\r
94 #elif (TSLPRM_PXS_HSI == 250)\r
95   PXS->CKCR1 |= PXS_CKCR1_250KHZ;\r
96 #elif (TSLPRM_PXS_HSI == 125)\r
97   PXS->CKCR1 |= PXS_CKCR1_125KHZ;\r
98 #else\r
99   PXS->CKCR1 |= PXS_CKCR1_16MHZ; // Default\r
100 #endif\r
101 \r
102   PXS->CKCR2 = (uint8_t)(((uint8_t)TSLPRM_PXS_UP_LENGTH & 0x07) << 4) | ((uint8_t)TSLPRM_PXS_PASS_LENGTH & 0x07);\r
103 \r
104 #if TSLPRM_PXS_RF_DETECTION > 0\r
105   enablePXSNoiseDetection();\r
106 #endif\r
107 \r
108   setPXSStab(TSLPRM_PXS_STAB);\r
109   setPXSBias(TSLPRM_PXS_BIAS);\r
110 \r
111   // Initialization of the GPIO shared with the used TX\r
112   for (i = 0; i < TSLPRM_TOTAL_BANKS; i++)\r
113   {\r
114     bank = &(TSL_Globals.Bank_Array[i]);\r
115     CSArray = PXS_BankConfig[i].CSSEL;\r
116     TxInUseMask |= bank->msk_TX;\r
117     // Set the mask with the receivers use as receiver or as transmitter\r
118     RxInUseMask |= bank->msk_RXEN;\r
119     // Set the CS to 0\r
120     for (j = 0; j <= TSLPRM_HIGH_CHANNEL_NB; j++)\r
121     {\r
122       *CSArray = 0;\r
123       CSArray++;\r
124     }\r
125   }\r
126 \r
127   GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));\r
128   // Set the port as output\r
129   GPIOD->DDR |= (uint8_t)(TxInUseMask & 0x00FF);\r
130   // Configure the port as open-drain\r
131   GPIOD->CR1 &= (uint8_t)(~(TxInUseMask & 0x00FF));\r
132 #if TSLPRM_PXS_INACTIVE_TX > 0\r
133   // Configure as floating\r
134   GPIOD->ODR |= (uint8_t)(TxInUseMask & 0x00FF);\r
135 #else\r
136   // Drive them to VSS\r
137   GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));\r
138 #endif\r
139   GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));\r
140   // Set the port as output\r
141   GPIOB->DDR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);\r
142   // Configure the port as open-drain\r
143   GPIOB->CR1 &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));\r
144 #if TSLPRM_PXS_INACTIVE_TX > 0\r
145   // Configure as floating\r
146   GPIOB->ODR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);\r
147 #else\r
148   // Drive it to VSS\r
149   GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));\r
150 #endif\r
151 \r
152   enablePXS();\r
153 \r
154 #if TSLPRM_PXS_INACTIVE_RX > 0\r
155   PXS->RXINSR = 0x3FF;\r
156 #else\r
157   PXS->RXINSR = 0x0000;\r
158 #endif\r
159 \r
160 #if TSLPRM_PXS_RX_COUPLING > 0\r
161   enablePXSCoupling();\r
162 #else\r
163   disablePXSCoupling()\r
164 #endif\r
165 \r
166 #if TSLPRM_PXS_SYNCHRONIZE > 0\r
167   enablePXSSync();\r
168 #if TSLPRM_PXS_SYNCHRO_EDGE > 0\r
169   selectPXSSyncRisingEdge();\r
170 #else\r
171   selectPXSSyncFallingEdge();\r
172 #endif\r
173 #else\r
174   disablePXSSync();\r
175 #endif\r
176 \r
177 #if TSLPRM_USE_ACQ_INTERRUPT > 0\r
178   enablePXSInterrupts(PXS_CR2_EOCITEN);\r
179 #endif\r
180   // Configure the acquisition mode\r
181   PXS->RXCR3 = (uint16_t)RxInUseMask;\r
182   PXS->RXCR2 = (uint16_t)RxInUseMask;\r
183 \r
184 #if TSLPRM_ACQ_MAX > 0\r
185   PXS->MAXR = TSLPRM_ACQ_MAX;\r
186   PXS->MAXENR = 0x03FF;\r
187 #else\r
188   PXS->MAXENR = 0;\r
189 #endif\r
190 \r
191   // Calibrate the CS for all banks\r
192   for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)\r
193   {\r
194     TSL_PXS_CS_CalibrateBank(idx_bk);\r
195   }\r
196 \r
197 \r
198   // Calibrate the EPCC for all banks\r
199   for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)\r
200   {\r
201     if (TSL_PXS_EPCC_CalibrateBank(idx_bk) > 0)\r
202     {\r
203       retval = TSL_STATUS_ERROR;\r
204     }\r
205   }\r
206 #if TSLPRM_PXS_LOW_POWER_MODE > 0\r
207   setPXSLowPower();\r
208 #else\r
209   resetPXSLowPower();\r
210 #endif\r
211 \r
212   return retval;\r
213 \r
214 }\r
215 \r
216 /**\r
217   * @brief Calibrate the CS for a selected acquisition bank\r
218   * @param[in] idx_bk Index of the bank\r
219   * @retval Number of Receivers not correctly calibrated\r
220   */\r
221 void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk)\r
222 {\r
223   TSL_tIndex_T idx_ch;\r
224   uint8_t currentCS = 24;\r
225   uint8_t CS_delta = 4; // Value to add/substract to/from the current CS\r
226   CONST TSL_Bank_T *bank;\r
227   CONST uint16_t targetCount = TSLPRM_KEY_TARGET_REFERENCE / TSLPRM_KEY_TARGET_ATTENUATION;\r
228   CONST uint16_t targetCountError = targetCount >> 3;\r
229   bool CalibrationDone = FALSE;\r
230   uint16_t measSup[TSLPRM_HIGH_CHANNEL_NB+1];\r
231   uint16_t measInf[TSLPRM_HIGH_CHANNEL_NB+1];\r
232   uint8_t CSsup[TSLPRM_HIGH_CHANNEL_NB+1];\r
233   uint8_t CSinf[TSLPRM_HIGH_CHANNEL_NB+1];\r
234 \r
235   // Check parameters (if USE_FULL_ASSERT is defined)\r
236   assert_param(IS_BANK_INDEX_OK(idx_bk));\r
237 #if TSLPRM_USE_ACQ_INTERRUPT == 0\r
238   enablePXSInterrupts(PXS_CR2_EOCITEN);\r
239 #endif\r
240 \r
241   bank = &(TSL_Globals.Bank_Array[idx_bk]);\r
242   resetPXSLowPower();\r
243   TSL_acq_BankConfig(idx_bk);\r
244 \r
245   PXS->MAXR = TSLPRM_KEY_TARGET_REFERENCE;\r
246 \r
247   WFE->CR1 |= WFE_CR1_PXS_EV;\r
248   for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
249   {\r
250     PXS->RXEPCCSELR[idx_ch] = 0;\r
251     PXS->RXCSSELR[idx_ch] = currentCS;\r
252     CSsup[idx_ch] = 0;\r
253     CSinf[idx_ch] = 0;\r
254     measInf[idx_ch] = 0;\r
255     measSup[idx_ch] = 0xFFFF;\r
256 \r
257   }\r
258   do\r
259   {\r
260     startPXSAcquisition();\r
261     wfe();\r
262     clearPXS_ISR_EOCF;\r
263     for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
264     {\r
265       if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))\r
266       {\r
267         if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount - targetCountError))\r
268         {\r
269           PXS->RXCSSELR[idx_ch] -= 8;\r
270         }\r
271       }\r
272     }\r
273     currentCS -= 8;\r
274   }\r
275   while (currentCS);\r
276 \r
277 \r
278   for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
279   {\r
280     PXS->RXCSSELR[idx_ch] += CS_delta;\r
281   }\r
282 \r
283   do\r
284   {\r
285     CS_delta >>= 1;\r
286     if ((CS_delta == 0) && (CalibrationDone == FALSE))\r
287     {\r
288       CalibrationDone = TRUE;\r
289       CS_delta = 1;\r
290     }\r
291 \r
292     startPXSAcquisition();\r
293     wfe();\r
294     clearPXS_ISR_EOCF;\r
295     for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
296     {\r
297       if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))\r
298       {\r
299         if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount))\r
300         {\r
301           measSup[idx_ch] = PXS->RXCNTR[idx_ch];\r
302           CSsup[idx_ch] = PXS->RXCSSELR[idx_ch];\r
303           PXS->RXCSSELR[idx_ch] -= CS_delta;\r
304         }\r
305         else //if (PXS->RXCNTR[idx_ch] < targetCount )\r
306         {\r
307           measInf[idx_ch] = PXS->RXCNTR[idx_ch];\r
308           CSinf[idx_ch] = PXS->RXCSSELR[idx_ch];\r
309           PXS->RXCSSELR[idx_ch] += CS_delta;\r
310         }\r
311 //        else\r
312 //        {\r
313         // Do nothing (MISRA requirement)\r
314 //        }\r
315       }\r
316     }\r
317   }\r
318   while ((CalibrationDone == FALSE) || (CS_delta != 0));\r
319 \r
320 \r
321   // Restore configuration\r
322 #if TSLPRM_ACQ_MAX > 0\r
323   PXS->MAXR = TSLPRM_ACQ_MAX;\r
324 #else\r
325   PXS->MAXENR = 0;\r
326 #endif\r
327 \r
328   WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;\r
329 #if TSLPRM_USE_ACQ_INTERRUPT == 0\r
330   disablePXSInterrupts(PXS_CR2_EOCITEN);\r
331 #endif\r
332 \r
333   // Store the CS\r
334   for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)\r
335   {\r
336     if ((measSup[idx_ch] == 0) || ((measSup[idx_ch] - targetCount) > (targetCount - measInf[idx_ch])))\r
337     {\r
338       PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSinf[idx_ch];\r
339     }\r
340     else\r
341     {\r
342       PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSsup[idx_ch];\r
343     }\r
344   }\r
345 }\r
346 \r
347 \r
348 /**\r
349   * @brief Calibrate the EPCC for a selected acquisition bank\r
350   * @param[in] idx_bk Index of the bank\r
351   * @retval Number Number of Receivers not correctly calibrated\r
352   */\r
353 int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T idx_bk)\r
354 {\r
355   TSL_tIndex_T idx_ch;\r
356   uint8_t currentEPCC, trial, goodEPCC = 0;\r
357   uint8_t EPCCtoCompute = 0; // Used to define if all the EPCC have their final value\r
358   uint8_t EPCC_delta = EPCC_INIT_VALUE; // Value to add/substract to/from the current EPCC\r
359   CONST TSL_Bank_T *bank;\r
360 \r
361   // Check parameters (if USE_FULL_ASSERT is defined)\r
362   assert_param(IS_BANK_INDEX_OK(idx_bk));\r
363 #if TSLPRM_USE_ACQ_INTERRUPT == 0\r
364   enablePXSInterrupts(PXS_CR2_EOCITEN);\r
365 #endif\r
366 \r
367   bank = &(TSL_Globals.Bank_Array[idx_bk]);\r
368   resetPXSLowPower();\r
369   TSL_acq_BankConfig(idx_bk);\r
370 \r
371   PXS->MAXR = 2 * TSLPRM_KEY_TARGET_REFERENCE;\r
372 \r
373   WFE->CR1 |= WFE_CR1_PXS_EV;\r
374   for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
375   {\r
376     PXS->RXEPCCSELR[idx_ch] = EPCC_delta;\r
377     if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))\r
378     {\r
379       EPCCtoCompute++;\r
380     }\r
381   }\r
382   do\r
383   {\r
384     EPCC_delta >>= 1;\r
385     startPXSAcquisition();\r
386     wfe();\r
387     clearPXS_ISR_EOCF;\r
388     for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
389     {\r
390       if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))\r
391       {\r
392         if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > TSLPRM_KEY_TARGET_REFERENCE))\r
393         {\r
394           PXS->RXEPCCSELR[idx_ch] -= EPCC_delta;\r
395         }\r
396         else if (PXS->RXCNTR[idx_ch] < TSLPRM_KEY_TARGET_REFERENCE)\r
397         {\r
398           PXS->RXEPCCSELR[idx_ch] += EPCC_delta;\r
399         }\r
400         else\r
401         {\r
402           // Do nothing (MISRA requirement)\r
403         }\r
404       }\r
405     }\r
406   }\r
407   while (EPCC_delta >= 1);\r
408   // Second pass to fine-tune\r
409   trial = TSLPRM_PXS_EPCC_FINE_TUNING_ITERATION;\r
410   do\r
411   {\r
412     startPXSAcquisition();\r
413     goodEPCC = 0; // Reset the goodEPCC variable\r
414     wfe();\r
415     clearPXS_ISR_EOCF;\r
416     for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)\r
417     {\r
418       if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))\r
419       {\r
420         currentEPCC = PXS->RXEPCCSELR[idx_ch]; //this affectation allow to avoid computation of the structure address\r
421         if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > (TSLPRM_KEY_TARGET_REFERENCE + TSLPRM_KEY_TARGET_REFERENCE_ERROR)))\r
422         {\r
423           if (currentEPCC > 0)\r
424           {\r
425             if ((currentEPCC & 0x07) != 0)\r
426             {\r
427               currentEPCC--;\r
428             }\r
429             else\r
430             {\r
431               currentEPCC -= 3; // This is due to the non linearity of the EPCC\r
432             }\r
433           }\r
434         }\r
435         else if (PXS->RXCNTR[idx_ch] < (TSLPRM_KEY_TARGET_REFERENCE - TSLPRM_KEY_TARGET_REFERENCE_ERROR))\r
436         {\r
437           if (currentEPCC < 0xFF)\r
438           {\r
439             if ((currentEPCC & 0x07) != 0x07)\r
440             {\r
441               currentEPCC++;\r
442             }\r
443             else\r
444             {\r
445               currentEPCC += 2; // This is due to the non linearity of the EPCC\r
446             }\r
447           }\r
448           else // Invert the change in case the sorting is not reliable\r
449           {\r
450             currentEPCC--;\r
451           }\r
452         }\r
453         else\r
454         {\r
455           goodEPCC++;\r
456         }\r
457         PXS->RXEPCCSELR[idx_ch] = currentEPCC;\r
458       }\r
459     }\r
460     trial--;\r
461   }\r
462   while ((goodEPCC < EPCCtoCompute) && (trial));\r
463 \r
464   // Restore configuration\r
465 #if TSLPRM_ACQ_MAX > 0\r
466   PXS->MAXR = TSLPRM_ACQ_MAX;\r
467 #else\r
468   PXS->MAXENR = 0;\r
469 #endif\r
470 \r
471   WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;\r
472 #if TSLPRM_USE_ACQ_INTERRUPT == 0\r
473   disablePXSInterrupts(PXS_CR2_EOCITEN);\r
474 #endif\r
475 \r
476   // Store the EPCC\r
477   for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)\r
478   {\r
479     PXS_BankConfig[idx_bk].EPCCSEL[idx_ch] = PXS->RXEPCCSELR[idx_ch];\r
480   }\r
481 \r
482   return((int8_t)(EPCCtoCompute - goodEPCC));\r
483 }\r
484 \r
485 \r
486 #if TSLPRM_USE_ZONE > 0\r
487 /**\r
488   * @brief Calibrate the EPCC for a set of acquisition banks.\r
489   * @param[in] zone Set of banks to calibrate the EPCC\r
490   * @retval Status\r
491   */\r
492 TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *zone)\r
493 {\r
494   uint16_t idx_bk;\r
495   TSL_Status_enum_T retval = TSL_STATUS_OK;\r
496   for (idx_bk = 0; idx_bk < zone->NbBanks; idx_bk++)\r
497   {\r
498     if (TSL_PXS_EPCC_CalibrateBank(zone->BankIndex[idx_bk]) > 0)\r
499     {\r
500       retval = TSL_STATUS_ERROR;\r
501     }\r
502   }\r
503   return(retval);\r
504 }\r
505 #endif\r
506 \r
507 \r
508 /**\r
509   * @brief Test the reference and update the EPCC/CS if needed\r
510   * @param[in] pCh pointer on the channel data information\r
511   * @retval Result\r
512   */\r
513 TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)\r
514 {\r
515   uint16_t reference, target_error = 0;\r
516   TSL_Bool_enum_T result = TSL_FALSE;\r
517 \r
518   if (pCh->Flags.EPCCStatus != TSL_EPCC_STATUS_LOCKED)\r
519   {\r
520     reference = pCh->Ref;\r
521 #if TSLPRM_TOTAL_TKEYS > 0\r
522     if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_TKEY_MASK)\r
523     {\r
524       target_error = TSLPRM_TOUCHKEY_REFERENCE_RANGE;\r
525     }\r
526 #endif\r
527 \r
528 #if TSLPRM_TOTAL_LNRTS > 0\r
529     if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_LINROT_MASK)\r
530     {\r
531       target_error = TSLPRM_LINROT_REFERENCE_RANGE;\r
532     }\r
533 #endif\r
534     if ((reference != 0) && ((reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error)) || (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))))\r
535     {\r
536       if (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))\r
537       {\r
538         pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_INCREASE;\r
539       }\r
540       else if (reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error))\r
541       {\r
542         pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_DECREASE;\r
543       }\r
544       else\r
545       {\r
546         // Do nothing (MISRA requirement)\r
547       }\r
548       result = TSL_TRUE;\r
549     }\r
550   }\r
551   return(result);\r
552 }\r
553 \r
554 /**\r
555   * @brief Test if the measure has crossed the reference target\r
556   * @param[in] pCh      Pointer to the channel Data under test\r
557   * @param[in] new_meas Measure of the last acquisition on this channel\r
558   * @retval Result Result of the test\r
559   */\r
560 TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)\r
561 {\r
562   TSL_Bool_enum_T result = TSL_TRUE;\r
563   TSL_EPCCStatus_enum_T EPCCStatus;\r
564 \r
565   EPCCStatus = pCh->Flags.EPCCStatus;\r
566   if (EPCCStatus & TSL_EPCC_CHANGE_MASK)\r
567   {\r
568     // If the previous reference and the new one are on each side of the reference target\r
569     // the EPCC is no more tested and the calibration continues.\r
570     if (((EPCCStatus == TSL_EPCC_STATUS_INCREASE) && (new_meas >= TSLPRM_KEY_TARGET_REFERENCE))\r
571         || ((EPCCStatus == TSL_EPCC_STATUS_DECREASE) && (new_meas <= TSLPRM_KEY_TARGET_REFERENCE)))\r
572     {\r
573       pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_UNLOCKED;\r
574     }\r
575     else\r
576     {\r
577       result = TSL_FALSE;\r
578     }\r
579   }\r
580 \r
581   return(result);\r
582 }\r
583 \r
584 \r
585 /**\r
586   * @brief Increase or decrease the CS value\r
587   * @param[in] pCSSEL Address of the CS to be modified\r
588   * @param[in] change Define if the Cs must be increased or decreased\r
589   * @retval None\r
590   */\r
591 void TSL_acq_UpdateCS(uint8_t *pCSSEL, TSL_EPCCStatus_enum_T change)\r
592 {\r
593   uint16_t indexCS;\r
594 \r
595   assert_param(IS_EPCC_STATUS_OK(change));\r
596   assert_param(IS_CSSEL_OK(*pCSSEL));\r
597 \r
598   if (*pCSSEL > CS_MIDDLE_VALUE)\r
599   {\r
600     indexCS = (CS_MIDDLE_VALUE - 1);\r
601   }\r
602   else\r
603   {\r
604     indexCS = 0;\r
605   }\r
606   while ((PXS_CSsorting[indexCS] != *pCSSEL) && (indexCS < CS_MAX_VALUE))\r
607   {\r
608     indexCS++;\r
609   }\r
610   if (change == TSL_EPCC_STATUS_INCREASE)\r
611   {\r
612     *pCSSEL = PXS_CSsorting[indexCS + 1];\r
613   }\r
614   else\r
615   {\r
616     *pCSSEL = PXS_CSsorting[indexCS - 1];\r
617   }\r
618 }\r
619 \r
620 \r
621 /**\r
622   * @brief Configures a Bank.\r
623   * @param[in] idx_bk Index of the Bank to configure\r
624   * @retval Status\r
625   */\r
626 TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)\r
627 {\r
628   TSL_Status_enum_T retval = TSL_STATUS_OK;\r
629   uint16_t idx_ch;\r
630   TSL_ChannelFlags_T flags;\r
631   CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);\r
632   CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;\r
633   CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;\r
634   TSL_tMaskRX enabledRX = 0;\r
635   uint8_t *pEPCCSEL, *pCSSEL;\r
636 \r
637   // Check parameters (if USE_FULL_ASSERT is defined)\r
638   assert_param(IS_BANK_INDEX_OK(idx_bk));\r
639 \r
640   TSL_Globals.This_Bank = idx_bk;\r
641 \r
642   selectPXSRxGroup(bank->msk_group);\r
643   for (idx_ch = 0;idx_ch < bank->NbChannels;idx_ch++)\r
644   {\r
645     flags = bank->p_chData[pchDest->IdxDest].Flags;\r
646     if (flags.ObjStatus == TSL_OBJ_STATUS_ON)\r
647     {\r
648       enabledRX |= (1 << pchSrc->IdxSrc);\r
649       if (flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)\r
650       {\r
651         pEPCCSEL = &PXS_BankConfig[idx_bk].EPCCSEL[pchSrc->IdxSrc];\r
652         if (flags.EPCCStatus == TSL_EPCC_STATUS_INCREASE)\r
653         {\r
654           if ((*pEPCCSEL) < 0xFF)\r
655           {\r
656             if (((*pEPCCSEL) & 0x07) != 0x07)\r
657             {\r
658               (*pEPCCSEL)++;\r
659             }\r
660             else\r
661             {\r
662               if ((*pEPCCSEL) < 0xFE)\r
663               {\r
664                 (*pEPCCSEL) += 2; // This is due to the non linearity of the PCC\r
665               }\r
666               else\r
667               {\r
668                 (*pEPCCSEL)++;\r
669               }\r
670             }\r
671 \r
672           }\r
673           else\r
674           {\r
675             pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];\r
676             if (*pCSSEL < 0x1F)\r
677             {\r
678               TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_INCREASE);\r
679             }\r
680             else\r
681             {}\r
682           }\r
683         }\r
684         else\r
685         {\r
686           if ((*pEPCCSEL) > 0)\r
687           {\r
688             if (((*pEPCCSEL) & 0x07) != 0)\r
689             {\r
690               (*pEPCCSEL)--;\r
691             }\r
692             else\r
693             {\r
694               if ((*pEPCCSEL) > 3)\r
695               {\r
696                 (*pEPCCSEL) -= 3; // This is due to the non linearity of the PCC\r
697               }\r
698               else\r
699               {\r
700                 (*pEPCCSEL)--;\r
701               }\r
702             }\r
703           }\r
704           else\r
705           {\r
706             pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];\r
707             if (*pCSSEL > 0)\r
708             {\r
709               TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_DECREASE);\r
710             }\r
711             else\r
712             {}\r
713           }\r
714         }\r
715       }\r
716     }\r
717 \r
718     // Next channel\r
719     pchSrc++;\r
720     pchDest++;\r
721   }\r
722 \r
723   // The two following loops are more efficient than the two instructions in the same loop\r
724   for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)\r
725   {\r
726     PXS->RXCSSELR[idx_ch] = PXS_BankConfig[idx_bk].CSSEL[idx_ch];\r
727   }\r
728   for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)\r
729   {\r
730     PXS->RXEPCCSELR[idx_ch] = PXS_BankConfig[idx_bk].EPCCSEL[idx_ch];\r
731   }\r
732 \r
733   PXS->TXENR = bank->msk_TX; // Enable the Tx selected (if any)\r
734   PXS->RXCR1 = bank->msk_channels; // Configure the Rx and the Tx function modes\r
735 \r
736   // Enable the Rx which are not disabled including the potential Rx configured as Tx\r
737   PXS->RXENR = bank->msk_RXEN & ((uint16_t)(~bank->msk_channels) | enabledRX);\r
738 \r
739   if (enabledRX == 0)\r
740   {\r
741     retval = TSL_STATUS_ERROR;\r
742   }\r
743 \r
744   return(retval);\r
745 \r
746 }\r
747 \r
748 \r
749 /**\r
750   * @brief Test if EPCC are changing\r
751   * @param[in] pCh Channel to be processed\r
752   * @retval bool Test result\r
753   */\r
754 TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)\r
755 {\r
756   if (pCh->Flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)\r
757   {\r
758     return (TSL_FALSE);\r
759   }\r
760   else\r
761   {\r
762     return(TSL_TRUE);\r
763   }\r
764 }\r
765 \r
766 \r
767 /**\r
768   * @brief Start acquisition on a previously configured bank\r
769   * @param None\r
770   * @retval None\r
771   */\r
772 void TSL_acq_BankStartAcq(void)\r
773 {\r
774   // Start acquisition\r
775   startPXSAcquisition();\r
776 }\r
777 \r
778 \r
779 /**\r
780   * @brief Wait end of acquisition\r
781   * @param None\r
782   * @retval Status\r
783   */\r
784 TSL_Status_enum_T TSL_acq_BankWaitEOC(void)\r
785 {\r
786   TSL_Status_enum_T retval = TSL_STATUS_BUSY;\r
787 \r
788   if (checkPXSInterruptStatusFlag(PXS_ISR_EOCF)) // Check EOC flag\r
789   {\r
790     if (PXS->RXSR != TSL_Globals.Bank_Array[TSL_Globals.This_Bank].msk_channels) // Check MCE flag\r
791     {\r
792       retval = TSL_STATUS_ERROR;\r
793     }\r
794     else\r
795     {\r
796       retval = TSL_STATUS_OK;\r
797     }\r
798   }\r
799 \r
800   return retval;\r
801 }\r
802 \r
803 \r
804 /**\r
805   * @brief Check noise detection\r
806   * @param None\r
807   * @retval Status\r
808   */\r
809 TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)\r
810 {\r
811   TSL_AcqStatus_enum_T retval = TSL_ACQ_STATUS_OK;\r
812 #if TSLPRM_PXS_RF_DETECTION > 0\r
813   if (checkPXSInterruptStatusFlag(PXS_ISR_NOISEDETF) == PXS_ISR_NOISEDETF)\r
814   {\r
815     retval = TSL_ACQ_STATUS_NOISE;\r
816   }\r
817 #endif\r
818   return(retval);\r
819 }\r
820 \r
821 \r
822 /**\r
823   * @brief Return the current measure\r
824   * @param[in] index Index of the measure source\r
825   * @retval Measure\r
826   */\r
827 TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndexSrc_T index)\r
828 {\r
829   uint16_t CurrentReceiver;\r
830 \r
831   // Check parameters (if USE_FULL_ASSERT is defined)\r
832   assert_param(IS_SOURCE_INDEX_OK(index));\r
833 \r
834   CurrentReceiver = (uint16_t)(((uint16_t)1) << index);\r
835 \r
836   if (PXS->RXSR & CurrentReceiver)\r
837   {\r
838     return(PXS->RXCNTR[index]);\r
839   }\r
840   else\r
841   {\r
842     return(MAX_MEASURE);\r
843   }\r
844 }\r
845 \r
846 \r
847 /**\r
848   * @brief  Process the PXS Interrupt routine\r
849   * @param  None\r
850   * @retval None\r
851   */\r
852 INTERRUPT_HANDLER(TSL_acq_ProcessIT, 2)\r
853 {\r
854   clearPXS_ISR_EOCF;\r
855 \r
856   TSL_acq_BankGetResult(TSL_Globals.This_Bank, 0, 0); // No noise filter\r
857 \r
858 #if TSLPRM_USE_ZONE > 0\r
859   if ((TSL_Globals.This_Zone == 0) || (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks))\r
860   {\r
861     CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing\r
862     PXS->RXENR = 0; // To reduce consumption\r
863     PXS->TXENR = 0; // To reduce consumption\r
864     TSL_Globals.This_Bank = 0;\r
865   }\r
866   else\r
867   {\r
868     if (TSL_acq_ZoneConfig(TSL_Globals.This_Zone, TSL_Globals.Index_In_This_Zone) != TSL_STATUS_ERROR)\r
869     {\r
870       // Start Bank acquisition\r
871       TSL_acq_BankStartAcq();\r
872 #if TSLPRM_PXS_LOW_POWER_MODE > 0\r
873       if (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks)\r
874       {\r
875         setPXSLowPower();\r
876       }\r
877 #endif\r
878     }\r
879 \r
880   }\r
881 #else\r
882   CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing\r
883   PXS->RXENR = 0; // To reduce consumption\r
884   PXS->TXENR = 0; // To reduce consumption\r
885 #endif\r
886 }\r
887 \r
888 \r
889 #ifdef __IAR_SYSTEMS_ICC__\r
890 #pragma optimize=low\r
891 #elif defined (__CC_ARM)\r
892 #pragma O1\r
893 #pragma Ospace\r
894 #endif\r
895 /**\r
896   * @brief  Software delay (private routine)\r
897   * @param  val Wait delay\r
898   * @retval None\r
899   */\r
900 void SoftDelay(uint32_t val)\r
901 {\r
902   uint32_t i;\r
903   for (i = val; i > 0; i--)\r
904   {}\r
905 }\r
906 \r
907 /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/\r