/**
******************************************************************************
* @file tsl_acq.c
* @author MCD Application Team
* @version V1.4.4
* @date 31-March-2014
* @brief This file contains all functions to manage the acquisition in general.
******************************************************************************
* @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.h"
#include "tsl_globals.h"
#include "stm32f0xx_conf.h"
/* Private typedefs ----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
/* Private variables ---------------------------------------------------------*/
/* Private functions prototype -----------------------------------------------*/
/**
* @brief Read all channels measurement of a Bank, calculate Delta
* @param[in] idx_bk Index of the Bank to access
* @param[in] mfilter Pointer to the Measure filter function
* @param[in] dfilter Pointer to the Delta filter function
* @retval Status
*/
TSL_Status_enum_T TSL_acq_BankGetResult(TSL_tIndex_T idx_bk, TSL_pFuncMeasFilter_T mfilter, TSL_pFuncDeltaFilter_T dfilter)
{
TSL_Status_enum_T retval = TSL_STATUS_OK;
TSL_tIndex_T idx_ch;
TSL_tIndexDest_T idx_dest;
TSL_tMeas_T old_meas, new_meas;
TSL_tDelta_T new_delta;
CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
// For all channels in the bank copy the measure + calculate delta and store them.
for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
{
// Get the Destination Index of the current channel
idx_dest = pchDest->IdxDest;
if (bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_ON)
{
// Initialize flag to inform the Object of that a new data is ready
bank->p_chData[idx_dest].Flags.DataReady = TSL_DATA_READY;
// Get the new measure (the access is different between acquisitions)
new_meas = TSL_acq_GetMeas(pchSrc->IdxSrc);
// Store last measure for the filter below
#if TSLPRM_USE_MEAS > 0
old_meas = bank->p_chData[idx_dest].Meas;
#else
old_meas = new_meas;
#endif
// Store the new measure
#if TSLPRM_USE_MEAS > 0
bank->p_chData[idx_dest].Meas = new_meas;
#endif
// Check acquisition value min/max and set acquisition status flag
if (new_meas < TSL_Params.AcqMin)
{
bank->p_chData[idx_dest].Flags.AcqStatus = TSL_ACQ_STATUS_ERROR_MIN;
bank->p_chData[idx_dest].Delta = 0;
retval = TSL_STATUS_ERROR;
}
else
{
if (new_meas > TSL_Params.AcqMax)
{
bank->p_chData[idx_dest].Flags.AcqStatus = TSL_ACQ_STATUS_ERROR_MAX;
bank->p_chData[idx_dest].Delta = 0;
retval = TSL_STATUS_ERROR;
}
else // The measure is OK
{
if (TSL_acq_UseFilter(&bank->p_chData[idx_dest]))
{
// Apply Measure filter if it exists
if (mfilter)
{
new_meas = mfilter(old_meas, new_meas);
// Store the measure (optional - used for debug purpose)
#if TSLPRM_USE_MEAS > 0
bank->p_chData[idx_dest].Meas = new_meas;
#endif
}
// Calculate the new Delta
new_delta = TSL_acq_ComputeDelta(bank->p_chData[idx_dest].Ref, new_meas);
// Check Noise (TSL_ACQ_STATUS_OK if no Noise or if Noise detection is not supported)
bank->p_chData[idx_dest].Flags.AcqStatus = TSL_acq_CheckNoise();
// Apply Delta filter if it exists
if (dfilter)
{
bank->p_chData[idx_dest].Delta = dfilter(new_delta);
}
else
{
bank->p_chData[idx_dest].Delta = new_delta;
}
}
else
{
// Calculate the new Delta
bank->p_chData[idx_dest].Delta = TSL_acq_ComputeDelta(bank->p_chData[idx_dest].Ref, new_meas);
// Check Noise (TSL_ACQ_STATUS_OK if no Noise or if Noise detection is not supported)
bank->p_chData[idx_dest].Flags.AcqStatus = TSL_acq_CheckNoise();
}
}
}
}
// Next channel
pchDest++;
pchSrc++;
}
return retval;
}
/**
* @brief Calibrate a Bank
* @param[in] idx_bk Index of the Bank to access
* @retval Status
*/
TSL_Status_enum_T TSL_acq_BankCalibrate(TSL_tIndex_T idx_bk)
{
TSL_Status_enum_T retval;
TSL_Status_enum_T acq_status;
TSL_tIndex_T idx_ch;
TSL_tIndexDest_T idx_dest;
TSL_tMeas_T new_meas;
static TSL_tIndex_T calibration_ongoing = 0;
static TSL_tNb_T calibration_done = 0;
static TSL_tNb_T div;
CONST TSL_Bank_T *bank;
CONST TSL_ChannelDest_T *pchDest; // Pointer to the current channel
CONST TSL_ChannelSrc_T *pchSrc; // Pointer to the current channel
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
bank = &(TSL_Globals.Bank_Array[idx_bk]);
if (calibration_ongoing == 0)
{
switch (TSL_Params.NbCalibSamples)
{
case 4:
div = 2;
break;
case 16:
div = 4;
break;
default:
TSL_Params.NbCalibSamples = 8;
div = 3;
break;
}
// Clear data for all channels of the bank
TSL_acq_BankClearData(idx_bk);
// Configure bank
if (TSL_acq_BankConfig(idx_bk) == TSL_STATUS_OK)
{
// Start acquisition
TSL_acq_BankStartAcq();
calibration_ongoing = 1; // Calibration started
calibration_done = TSL_Params.NbCalibSamples;
retval = TSL_STATUS_BUSY;
}
else
{
// Stop calibration
// Clear data for all channels of the bank
TSL_acq_BankClearData(idx_bk);
calibration_ongoing = 0;
retval = TSL_STATUS_ERROR;
}
}
else // Calibration is on-going
{
// Check End of Acquisition
acq_status = TSL_acq_BankWaitEOC();
if (acq_status == TSL_STATUS_OK)
{
// Get the first channel of the bank
pchDest = bank->p_chDest;
pchSrc = bank->p_chSrc;
// Get new measurement for all channels of the bank
for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
{
// Get index of the current channel
idx_dest = pchDest->IdxDest;
// Get the new measure (the access is different between acquisitions)
new_meas = TSL_acq_GetMeas(pchSrc->IdxSrc);
// Check min/max and set status flag
if ((new_meas < TSL_Params.AcqMin) || (new_meas > TSL_Params.AcqMax))
{
// Stop calibration
// Clear data for all channels of the bank
TSL_acq_BankClearData(idx_bk);
calibration_ongoing = 0;
return TSL_STATUS_ERROR;
}
else
{
// Add the measure
bank->p_chData[idx_dest].Ref += new_meas;
}
// Next channel
pchDest++;
pchSrc++;
}
// Check that we have all the needed measurements
calibration_done--;
if (calibration_done == 0)
{
// Get the first channel of the bank
pchDest = bank->p_chDest;
// Calculate the Reference for all channels of the bank
for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
{
// Get index of the current channel
idx_dest = pchDest->IdxDest;
// Divide the Reference by the number of samples
bank->p_chData[idx_dest].Ref >>= div;
// Next channel
pchDest++;
}
// End
calibration_ongoing = 0;
retval = TSL_STATUS_OK;
}
else // Restart a new measurement on the bank
{
TSL_acq_BankStartAcq();
retval = TSL_STATUS_BUSY;
}
}
else
if (acq_status == TSL_STATUS_ERROR)
{
// Stop calibration
// Clear data for all channels of the bank
TSL_acq_BankClearData(idx_bk);
calibration_ongoing = 0;
retval = TSL_STATUS_ERROR;
}
else
{
retval = TSL_STATUS_BUSY;
}
}
return retval;
}
/**
* @brief Clear Reference and Delta on all channels of a Bank
* @param[in] idx_bk Index of the Bank to access
* @retval None
*/
void TSL_acq_BankClearData(TSL_tIndex_T idx_bk)
{
TSL_tIndex_T idx_ch;
TSL_tIndexDest_T idx_Dest;
CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
// For all channels of the bank
for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
{
idx_Dest = pchDest->IdxDest;
bank->p_chData[idx_Dest].Ref = 0;
bank->p_chData[idx_Dest].Delta = 0;
pchDest++; // Next channel
}
}
#if TSLPRM_USE_ZONE > 0
/**
* @brief Configures a Zone.
* @param[in] zone Zone to configure
* @param[in] idx_bk Bank index in the zone to configure
* @retval Status
*/
TSL_Status_enum_T TSL_acq_ZoneConfig(CONST TSL_Zone_T *zone, TSL_tIndex_T idx_bk)
{
TSL_Status_enum_T retval;
// Check parameters (if USE_FULL_ASSERT is defined)
assert_param(IS_BANK_INDEX_OK(idx_bk));
TSL_Globals.This_Zone = zone;
do
{
retval = TSL_acq_BankConfig(zone->BankIndex[idx_bk]);
TSL_Globals.This_Bank = zone->BankIndex[idx_bk];
idx_bk++;
}
while ((idx_bk < zone->NbBanks) && (retval == TSL_STATUS_ERROR));
TSL_Globals.Index_In_This_Zone = idx_bk;
#if TSLPRM_PXS_LOW_POWER_MODE > 0
if (idx_bk < zone->NbBanks)
{
resetPXSLowPower();
}
#endif
return(retval);
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/