/**
******************************************************************************
* @file tsl_acq_stm8tl5x.c
* @author MCD Application Team
* @version V1.4.4
* @date 31-March-2014
* @brief This file contains all functions to manage the PXS acquisition
* on STM8TL5x products.
******************************************************************************
* @attention
*
*
© COPYRIGHT 2014 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "tsl_acq_stm8tl5x.h"
#include "tsl_globals.h"
#include "stm8tl5x_it.h"
/* Private typedefs ----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define EPCC_INIT_VALUE (0x80)
#define CS_MIDDLE_VALUE (17)
#define CS_MAX_VALUE (32)
#define MAX_MEASURE (0xFFFF)
/* Private macros ------------------------------------------------------------*/
#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
#define IS_SOURCE_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_CHANNELS)))
#define IS_EPCC_STATUS_OK(STATUS) ((STATUS & TSL_EPCC_CHANGE_MASK) != 0)
#define IS_CSSEL_OK(CSSEL) (((CSSEL) == 0) || (((CSSEL) > 0) && ((CSSEL) < CS_MAX_VALUE)))
/* Private variables ---------------------------------------------------------*/
TSL_BankConfig_T PXS_BankConfig[TSLPRM_TOTAL_BANKS];
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};
/* Private functions prototype -----------------------------------------------*/
void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk);
int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T bank);
TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *);
void SoftDelay(uint16_t val);
/**
* @brief Initializes the acquisition module.
* @param None
* @retval Status
*/
TSL_Status_enum_T TSL_acq_Init(void)
{
TSL_Status_enum_T retval = TSL_STATUS_OK;
TSL_tIndex_T i;
TSL_tIndex_T j;
TSL_tIndex_T idx_bk; // Bank index
uint16_t TxInUseMask = 0;
uint16_t RxInUseMask = 0;
CONST TSL_Bank_T *bank;
uint8_t *CSArray;
// Enable the PXS IP clock
CLK->PCKENR1 |= CLK_PCKENR1_PXS;
// Initialization of PXS IP
PXS->CKCR1 &= (uint8_t)~PXS_CKCR1_PRESC;
#if (TSLPRM_PXS_HSI == 16000)
PXS->CKCR1 |= PXS_CKCR1_16MHZ;
#elif (TSLPRM_PXS_HSI == 8000)
PXS->CKCR1 |= PXS_CKCR1_8MHZ;
#elif (TSLPRM_PXS_HSI == 4000)
PXS->CKCR1 |= PXS_CKCR1_4MHZ;
#elif (TSLPRM_PXS_HSI == 2000)
PXS->CKCR1 |= PXS_CKCR1_2MHZ;
#elif (TSLPRM_PXS_HSI == 1000)
PXS->CKCR1 |= PXS_CKCR1_1MHZ;
#elif (TSLPRM_PXS_HSI == 500)
PXS->CKCR1 |= PXS_CKCR1_500KHZ;
#elif (TSLPRM_PXS_HSI == 250)
PXS->CKCR1 |= PXS_CKCR1_250KHZ;
#elif (TSLPRM_PXS_HSI == 125)
PXS->CKCR1 |= PXS_CKCR1_125KHZ;
#else
PXS->CKCR1 |= PXS_CKCR1_16MHZ; // Default
#endif
PXS->CKCR2 = (uint8_t)(((uint8_t)TSLPRM_PXS_UP_LENGTH & 0x07) << 4) | ((uint8_t)TSLPRM_PXS_PASS_LENGTH & 0x07);
#if TSLPRM_PXS_RF_DETECTION > 0
enablePXSNoiseDetection();
#endif
setPXSStab(TSLPRM_PXS_STAB);
setPXSBias(TSLPRM_PXS_BIAS);
// Initialization of the GPIO shared with the used TX
for (i = 0; i < TSLPRM_TOTAL_BANKS; i++)
{
bank = &(TSL_Globals.Bank_Array[i]);
CSArray = PXS_BankConfig[i].CSSEL;
TxInUseMask |= bank->msk_TX;
// Set the mask with the receivers use as receiver or as transmitter
RxInUseMask |= bank->msk_RXEN;
// Set the CS to 0
for (j = 0; j <= TSLPRM_HIGH_CHANNEL_NB; j++)
{
*CSArray = 0;
CSArray++;
}
}
GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));
// Set the port as output
GPIOD->DDR |= (uint8_t)(TxInUseMask & 0x00FF);
// Configure the port as open-drain
GPIOD->CR1 &= (uint8_t)(~(TxInUseMask & 0x00FF));
#if TSLPRM_PXS_INACTIVE_TX > 0
// Configure as floating
GPIOD->ODR |= (uint8_t)(TxInUseMask & 0x00FF);
#else
// Drive them to VSS
GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));
#endif
GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
// Set the port as output
GPIOB->DDR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);
// Configure the port as open-drain
GPIOB->CR1 &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
#if TSLPRM_PXS_INACTIVE_TX > 0
// Configure as floating
GPIOB->ODR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);
#else
// Drive it to VSS
GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
#endif
enablePXS();
#if TSLPRM_PXS_INACTIVE_RX > 0
PXS->RXINSR = 0x3FF;
#else
PXS->RXINSR = 0x0000;
#endif
#if TSLPRM_PXS_RX_COUPLING > 0
enablePXSCoupling();
#else
disablePXSCoupling()
#endif
#if TSLPRM_PXS_SYNCHRONIZE > 0
enablePXSSync();
#if TSLPRM_PXS_SYNCHRO_EDGE > 0
selectPXSSyncRisingEdge();
#else
selectPXSSyncFallingEdge();
#endif
#else
disablePXSSync();
#endif
#if TSLPRM_USE_ACQ_INTERRUPT > 0
enablePXSInterrupts(PXS_CR2_EOCITEN);
#endif
// Configure the acquisition mode
PXS->RXCR3 = (uint16_t)RxInUseMask;
PXS->RXCR2 = (uint16_t)RxInUseMask;
#if TSLPRM_ACQ_MAX > 0
PXS->MAXR = TSLPRM_ACQ_MAX;
PXS->MAXENR = 0x03FF;
#else
PXS->MAXENR = 0;
#endif
// Calibrate the CS for all banks
for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
{
TSL_PXS_CS_CalibrateBank(idx_bk);
}
// Calibrate the EPCC for all banks
for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
{
if (TSL_PXS_EPCC_CalibrateBank(idx_bk) > 0)
{
retval = TSL_STATUS_ERROR;
}
}
#if TSLPRM_PXS_LOW_POWER_MODE > 0
setPXSLowPower();
#else
resetPXSLowPower();
#endif
return retval;
}
/**
* @brief Calibrate the CS for a selected acquisition bank
* @param[in] idx_bk Index of the bank
* @retval Number of Receivers not correctly calibrated
*/
void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk)
{
TSL_tIndex_T idx_ch;
uint8_t currentCS = 24;
uint8_t CS_delta = 4; // Value to add/substract to/from the current CS
CONST TSL_Bank_T *bank;
CONST uint16_t targetCount = TSLPRM_KEY_TARGET_REFERENCE / TSLPRM_KEY_TARGET_ATTENUATION;
CONST uint16_t targetCountError = targetCount >> 3;
bool CalibrationDone = FALSE;
uint16_t measSup[TSLPRM_HIGH_CHANNEL_NB+1];
uint16_t measInf[TSLPRM_HIGH_CHANNEL_NB+1];
uint8_t CSsup[TSLPRM_HIGH_CHANNEL_NB+1];
uint8_t CSinf[TSLPRM_HIGH_CHANNEL_NB+1];
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
#if TSLPRM_USE_ACQ_INTERRUPT == 0
enablePXSInterrupts(PXS_CR2_EOCITEN);
#endif
bank = &(TSL_Globals.Bank_Array[idx_bk]);
resetPXSLowPower();
TSL_acq_BankConfig(idx_bk);
PXS->MAXR = TSLPRM_KEY_TARGET_REFERENCE;
WFE->CR1 |= WFE_CR1_PXS_EV;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
PXS->RXEPCCSELR[idx_ch] = 0;
PXS->RXCSSELR[idx_ch] = currentCS;
CSsup[idx_ch] = 0;
CSinf[idx_ch] = 0;
measInf[idx_ch] = 0;
measSup[idx_ch] = 0xFFFF;
}
do
{
startPXSAcquisition();
wfe();
clearPXS_ISR_EOCF;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
{
if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount - targetCountError))
{
PXS->RXCSSELR[idx_ch] -= 8;
}
}
}
currentCS -= 8;
}
while (currentCS);
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
PXS->RXCSSELR[idx_ch] += CS_delta;
}
do
{
CS_delta >>= 1;
if ((CS_delta == 0) && (CalibrationDone == FALSE))
{
CalibrationDone = TRUE;
CS_delta = 1;
}
startPXSAcquisition();
wfe();
clearPXS_ISR_EOCF;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
{
if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount))
{
measSup[idx_ch] = PXS->RXCNTR[idx_ch];
CSsup[idx_ch] = PXS->RXCSSELR[idx_ch];
PXS->RXCSSELR[idx_ch] -= CS_delta;
}
else //if (PXS->RXCNTR[idx_ch] < targetCount )
{
measInf[idx_ch] = PXS->RXCNTR[idx_ch];
CSinf[idx_ch] = PXS->RXCSSELR[idx_ch];
PXS->RXCSSELR[idx_ch] += CS_delta;
}
// else
// {
// Do nothing (MISRA requirement)
// }
}
}
}
while ((CalibrationDone == FALSE) || (CS_delta != 0));
// Restore configuration
#if TSLPRM_ACQ_MAX > 0
PXS->MAXR = TSLPRM_ACQ_MAX;
#else
PXS->MAXENR = 0;
#endif
WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;
#if TSLPRM_USE_ACQ_INTERRUPT == 0
disablePXSInterrupts(PXS_CR2_EOCITEN);
#endif
// Store the CS
for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
{
if ((measSup[idx_ch] == 0) || ((measSup[idx_ch] - targetCount) > (targetCount - measInf[idx_ch])))
{
PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSinf[idx_ch];
}
else
{
PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSsup[idx_ch];
}
}
}
/**
* @brief Calibrate the EPCC for a selected acquisition bank
* @param[in] idx_bk Index of the bank
* @retval Number Number of Receivers not correctly calibrated
*/
int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T idx_bk)
{
TSL_tIndex_T idx_ch;
uint8_t currentEPCC, trial, goodEPCC = 0;
uint8_t EPCCtoCompute = 0; // Used to define if all the EPCC have their final value
uint8_t EPCC_delta = EPCC_INIT_VALUE; // Value to add/substract to/from the current EPCC
CONST TSL_Bank_T *bank;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
#if TSLPRM_USE_ACQ_INTERRUPT == 0
enablePXSInterrupts(PXS_CR2_EOCITEN);
#endif
bank = &(TSL_Globals.Bank_Array[idx_bk]);
resetPXSLowPower();
TSL_acq_BankConfig(idx_bk);
PXS->MAXR = 2 * TSLPRM_KEY_TARGET_REFERENCE;
WFE->CR1 |= WFE_CR1_PXS_EV;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
PXS->RXEPCCSELR[idx_ch] = EPCC_delta;
if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
{
EPCCtoCompute++;
}
}
do
{
EPCC_delta >>= 1;
startPXSAcquisition();
wfe();
clearPXS_ISR_EOCF;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
{
if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > TSLPRM_KEY_TARGET_REFERENCE))
{
PXS->RXEPCCSELR[idx_ch] -= EPCC_delta;
}
else if (PXS->RXCNTR[idx_ch] < TSLPRM_KEY_TARGET_REFERENCE)
{
PXS->RXEPCCSELR[idx_ch] += EPCC_delta;
}
else
{
// Do nothing (MISRA requirement)
}
}
}
}
while (EPCC_delta >= 1);
// Second pass to fine-tune
trial = TSLPRM_PXS_EPCC_FINE_TUNING_ITERATION;
do
{
startPXSAcquisition();
goodEPCC = 0; // Reset the goodEPCC variable
wfe();
clearPXS_ISR_EOCF;
for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
{
if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
{
currentEPCC = PXS->RXEPCCSELR[idx_ch]; //this affectation allow to avoid computation of the structure address
if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > (TSLPRM_KEY_TARGET_REFERENCE + TSLPRM_KEY_TARGET_REFERENCE_ERROR)))
{
if (currentEPCC > 0)
{
if ((currentEPCC & 0x07) != 0)
{
currentEPCC--;
}
else
{
currentEPCC -= 3; // This is due to the non linearity of the EPCC
}
}
}
else if (PXS->RXCNTR[idx_ch] < (TSLPRM_KEY_TARGET_REFERENCE - TSLPRM_KEY_TARGET_REFERENCE_ERROR))
{
if (currentEPCC < 0xFF)
{
if ((currentEPCC & 0x07) != 0x07)
{
currentEPCC++;
}
else
{
currentEPCC += 2; // This is due to the non linearity of the EPCC
}
}
else // Invert the change in case the sorting is not reliable
{
currentEPCC--;
}
}
else
{
goodEPCC++;
}
PXS->RXEPCCSELR[idx_ch] = currentEPCC;
}
}
trial--;
}
while ((goodEPCC < EPCCtoCompute) && (trial));
// Restore configuration
#if TSLPRM_ACQ_MAX > 0
PXS->MAXR = TSLPRM_ACQ_MAX;
#else
PXS->MAXENR = 0;
#endif
WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;
#if TSLPRM_USE_ACQ_INTERRUPT == 0
disablePXSInterrupts(PXS_CR2_EOCITEN);
#endif
// Store the EPCC
for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
{
PXS_BankConfig[idx_bk].EPCCSEL[idx_ch] = PXS->RXEPCCSELR[idx_ch];
}
return((int8_t)(EPCCtoCompute - goodEPCC));
}
#if TSLPRM_USE_ZONE > 0
/**
* @brief Calibrate the EPCC for a set of acquisition banks.
* @param[in] zone Set of banks to calibrate the EPCC
* @retval Status
*/
TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *zone)
{
uint16_t idx_bk;
TSL_Status_enum_T retval = TSL_STATUS_OK;
for (idx_bk = 0; idx_bk < zone->NbBanks; idx_bk++)
{
if (TSL_PXS_EPCC_CalibrateBank(zone->BankIndex[idx_bk]) > 0)
{
retval = TSL_STATUS_ERROR;
}
}
return(retval);
}
#endif
/**
* @brief Test the reference and update the EPCC/CS if needed
* @param[in] pCh pointer on the channel data information
* @retval Result
*/
TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
{
uint16_t reference, target_error = 0;
TSL_Bool_enum_T result = TSL_FALSE;
if (pCh->Flags.EPCCStatus != TSL_EPCC_STATUS_LOCKED)
{
reference = pCh->Ref;
#if TSLPRM_TOTAL_TKEYS > 0
if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_TKEY_MASK)
{
target_error = TSLPRM_TOUCHKEY_REFERENCE_RANGE;
}
#endif
#if TSLPRM_TOTAL_LNRTS > 0
if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_LINROT_MASK)
{
target_error = TSLPRM_LINROT_REFERENCE_RANGE;
}
#endif
if ((reference != 0) && ((reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error)) || (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))))
{
if (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))
{
pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_INCREASE;
}
else if (reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error))
{
pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_DECREASE;
}
else
{
// Do nothing (MISRA requirement)
}
result = TSL_TRUE;
}
}
return(result);
}
/**
* @brief Test if the measure has crossed the reference target
* @param[in] pCh Pointer to the channel Data under test
* @param[in] new_meas Measure of the last acquisition on this channel
* @retval Result Result of the test
*/
TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
{
TSL_Bool_enum_T result = TSL_TRUE;
TSL_EPCCStatus_enum_T EPCCStatus;
EPCCStatus = pCh->Flags.EPCCStatus;
if (EPCCStatus & TSL_EPCC_CHANGE_MASK)
{
// If the previous reference and the new one are on each side of the reference target
// the EPCC is no more tested and the calibration continues.
if (((EPCCStatus == TSL_EPCC_STATUS_INCREASE) && (new_meas >= TSLPRM_KEY_TARGET_REFERENCE))
|| ((EPCCStatus == TSL_EPCC_STATUS_DECREASE) && (new_meas <= TSLPRM_KEY_TARGET_REFERENCE)))
{
pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_UNLOCKED;
}
else
{
result = TSL_FALSE;
}
}
return(result);
}
/**
* @brief Increase or decrease the CS value
* @param[in] pCSSEL Address of the CS to be modified
* @param[in] change Define if the Cs must be increased or decreased
* @retval None
*/
void TSL_acq_UpdateCS(uint8_t *pCSSEL, TSL_EPCCStatus_enum_T change)
{
uint16_t indexCS;
assert_param(IS_EPCC_STATUS_OK(change));
assert_param(IS_CSSEL_OK(*pCSSEL));
if (*pCSSEL > CS_MIDDLE_VALUE)
{
indexCS = (CS_MIDDLE_VALUE - 1);
}
else
{
indexCS = 0;
}
while ((PXS_CSsorting[indexCS] != *pCSSEL) && (indexCS < CS_MAX_VALUE))
{
indexCS++;
}
if (change == TSL_EPCC_STATUS_INCREASE)
{
*pCSSEL = PXS_CSsorting[indexCS + 1];
}
else
{
*pCSSEL = PXS_CSsorting[indexCS - 1];
}
}
/**
* @brief Configures a Bank.
* @param[in] idx_bk Index of the Bank to configure
* @retval Status
*/
TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
{
TSL_Status_enum_T retval = TSL_STATUS_OK;
uint16_t idx_ch;
TSL_ChannelFlags_T flags;
CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
TSL_tMaskRX enabledRX = 0;
uint8_t *pEPCCSEL, *pCSSEL;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
TSL_Globals.This_Bank = idx_bk;
selectPXSRxGroup(bank->msk_group);
for (idx_ch = 0;idx_ch < bank->NbChannels;idx_ch++)
{
flags = bank->p_chData[pchDest->IdxDest].Flags;
if (flags.ObjStatus == TSL_OBJ_STATUS_ON)
{
enabledRX |= (1 << pchSrc->IdxSrc);
if (flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)
{
pEPCCSEL = &PXS_BankConfig[idx_bk].EPCCSEL[pchSrc->IdxSrc];
if (flags.EPCCStatus == TSL_EPCC_STATUS_INCREASE)
{
if ((*pEPCCSEL) < 0xFF)
{
if (((*pEPCCSEL) & 0x07) != 0x07)
{
(*pEPCCSEL)++;
}
else
{
if ((*pEPCCSEL) < 0xFE)
{
(*pEPCCSEL) += 2; // This is due to the non linearity of the PCC
}
else
{
(*pEPCCSEL)++;
}
}
}
else
{
pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];
if (*pCSSEL < 0x1F)
{
TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_INCREASE);
}
else
{}
}
}
else
{
if ((*pEPCCSEL) > 0)
{
if (((*pEPCCSEL) & 0x07) != 0)
{
(*pEPCCSEL)--;
}
else
{
if ((*pEPCCSEL) > 3)
{
(*pEPCCSEL) -= 3; // This is due to the non linearity of the PCC
}
else
{
(*pEPCCSEL)--;
}
}
}
else
{
pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];
if (*pCSSEL > 0)
{
TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_DECREASE);
}
else
{}
}
}
}
}
// Next channel
pchSrc++;
pchDest++;
}
// The two following loops are more efficient than the two instructions in the same loop
for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
{
PXS->RXCSSELR[idx_ch] = PXS_BankConfig[idx_bk].CSSEL[idx_ch];
}
for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
{
PXS->RXEPCCSELR[idx_ch] = PXS_BankConfig[idx_bk].EPCCSEL[idx_ch];
}
PXS->TXENR = bank->msk_TX; // Enable the Tx selected (if any)
PXS->RXCR1 = bank->msk_channels; // Configure the Rx and the Tx function modes
// Enable the Rx which are not disabled including the potential Rx configured as Tx
PXS->RXENR = bank->msk_RXEN & ((uint16_t)(~bank->msk_channels) | enabledRX);
if (enabledRX == 0)
{
retval = TSL_STATUS_ERROR;
}
return(retval);
}
/**
* @brief Test if EPCC are changing
* @param[in] pCh Channel to be processed
* @retval bool Test result
*/
TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
{
if (pCh->Flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)
{
return (TSL_FALSE);
}
else
{
return(TSL_TRUE);
}
}
/**
* @brief Start acquisition on a previously configured bank
* @param None
* @retval None
*/
void TSL_acq_BankStartAcq(void)
{
// Start acquisition
startPXSAcquisition();
}
/**
* @brief Wait end of acquisition
* @param None
* @retval Status
*/
TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
{
TSL_Status_enum_T retval = TSL_STATUS_BUSY;
if (checkPXSInterruptStatusFlag(PXS_ISR_EOCF)) // Check EOC flag
{
if (PXS->RXSR != TSL_Globals.Bank_Array[TSL_Globals.This_Bank].msk_channels) // Check MCE flag
{
retval = TSL_STATUS_ERROR;
}
else
{
retval = TSL_STATUS_OK;
}
}
return retval;
}
/**
* @brief Check noise detection
* @param None
* @retval Status
*/
TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
{
TSL_AcqStatus_enum_T retval = TSL_ACQ_STATUS_OK;
#if TSLPRM_PXS_RF_DETECTION > 0
if (checkPXSInterruptStatusFlag(PXS_ISR_NOISEDETF) == PXS_ISR_NOISEDETF)
{
retval = TSL_ACQ_STATUS_NOISE;
}
#endif
return(retval);
}
/**
* @brief Return the current measure
* @param[in] index Index of the measure source
* @retval Measure
*/
TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndexSrc_T index)
{
uint16_t CurrentReceiver;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_SOURCE_INDEX_OK(index));
CurrentReceiver = (uint16_t)(((uint16_t)1) << index);
if (PXS->RXSR & CurrentReceiver)
{
return(PXS->RXCNTR[index]);
}
else
{
return(MAX_MEASURE);
}
}
/**
* @brief Process the PXS Interrupt routine
* @param None
* @retval None
*/
INTERRUPT_HANDLER(TSL_acq_ProcessIT, 2)
{
clearPXS_ISR_EOCF;
TSL_acq_BankGetResult(TSL_Globals.This_Bank, 0, 0); // No noise filter
#if TSLPRM_USE_ZONE > 0
if ((TSL_Globals.This_Zone == 0) || (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks))
{
CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
PXS->RXENR = 0; // To reduce consumption
PXS->TXENR = 0; // To reduce consumption
TSL_Globals.This_Bank = 0;
}
else
{
if (TSL_acq_ZoneConfig(TSL_Globals.This_Zone, TSL_Globals.Index_In_This_Zone) != TSL_STATUS_ERROR)
{
// Start Bank acquisition
TSL_acq_BankStartAcq();
#if TSLPRM_PXS_LOW_POWER_MODE > 0
if (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks)
{
setPXSLowPower();
}
#endif
}
}
#else
CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
PXS->RXENR = 0; // To reduce consumption
PXS->TXENR = 0; // To reduce consumption
#endif
}
#if defined(__ICCSTM8__)
#pragma optimize=low
#endif
/**
* @brief Software delay (private routine)
* @param val Wait delay
* @retval None
*/
void SoftDelay(uint16_t val)
{
__IO uint16_t idx;
for (idx = val; idx > 0; idx--)
{
nop();
}
}
/******************* (C) COPYRIGHT 2014 STMicroelectronics *****END OF FILE****/