MCUXpresso_MCXA153/devices/MCXA153/drivers/fsl_eqdc.c
Yilin Sun 35e678394a
Initial commit v2.14.2
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-02-11 19:33:06 +08:00

298 lines
13 KiB
C

/*
* Copyright 2022, 2023 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_eqdc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.eqdc"
#endif
#if defined(EQDC_RSTS)
#define EQDC_RESETS_ARRAY EQDC_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for EQDC module.
*
* @param base EQDC peripheral base address
*/
static uint32_t EQDC_GetInstance(EQDC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to EQDC bases for each instance. */
static EQDC_Type *const s_eqdcBases[] = EQDC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to EQDC clocks for each instance. */
#if defined(QDC_CLOCKS)
static const clock_ip_name_t s_eqdcClocks[] = QDC_CLOCKS;
#elif defined(ENC_CLOCKS)
static const clock_ip_name_t s_eqdcClocks[] = ENC_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(EQDC_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_eqdcResets[] = EQDC_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t EQDC_GetInstance(EQDC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_eqdcBases); instance++)
{
if (s_eqdcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_eqdcBases));
return instance;
}
/*
* Initializes the EQDC module.
*
* This function initializes the EQDC by enabling the IP bus clock (optional).
*
* param base EQDC peripheral base address.
* param psConfig Pointer to configuration structure.
*/
void EQDC_Init(EQDC_Type *base, const eqdc_config_t *psConfig)
{
assert(NULL != psConfig);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(EQDC_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_eqdcResets[EQDC_GetInstance(base)]);
#endif
/* Initialize Double-set registers */
EQDC_ClearBufferedRegisterLoadUpdateMode(base);
EQDC_ClearEqdcLdok(base);
/* Counter value. */
EQDC_SetPositionCounterValue(base, psConfig->positionCounterValue);
/* Initial value. */
EQDC_SetInitialPositionValue(base, psConfig->positionInitialValue);
/* Modulus value. */
EQDC_SetPositionModulusValue(base, psConfig->positionModulusValue);
/* Compare value. */
EQDC_SetPositionCompare0Value(base, psConfig->positionCompareValue[0]);
EQDC_SetPositionCompare1Value(base, psConfig->positionCompareValue[1]);
EQDC_SetPositionCompare2Value(base, psConfig->positionCompareValue[2]);
EQDC_SetPositionCompare3Value(base, psConfig->positionCompareValue[3]);
EQDC_SetEqdcLdok(base);
while (EQDC_GetEqdcLdok(base) != 0U)
{
}
/* Watchdog. */
EQDC_SetWatchdogTimeout(base, psConfig->watchdogTimeoutValue);
/* EQDC_IMR. */
base->IMR = EQDC_IMR_FPHA(psConfig->filterPhaseA) | EQDC_IMR_FPHB(psConfig->filterPhaseB) |
EQDC_IMR_FIND_PRE(psConfig->filterIndPre) | EQDC_IMR_FHOM_ENA(psConfig->filterHomEna);
/* EQDC_FILT. */
base->FILT = EQDC_FILT_PRSC(psConfig->prescaler) | /* Prescaler used by LASTEDGE and POSDPER. */
EQDC_FILT_FILT_CS(psConfig->filterClockSourceselection) |
EQDC_FILT_FILT_CNT(psConfig->filterSampleCount) | EQDC_FILT_FILT_PER(psConfig->filterSamplePeriod);
/* EQDC_CTRL. */
base->CTRL = EQDC_CTRL_W1C_FLAGS | /* W1C flags. */
(uint16_t)psConfig->homeEnableInitPosCounterMode | /* HOME Enable trigger. */
(uint16_t)psConfig->indexPresetInitPosCounterMode | /* INDEX Preset trigger. */
EQDC_CTRL_REV(psConfig->enableReverseDirection) | /* Reverse direction. */
EQDC_CTRL_WDE(psConfig->enableWatchdog) | /* Enable watchdog. */
EQDC_CTRL_DMAEN(psConfig->enableDma); /* Enable Dma. */
/* Set mode of count. */
EQDC_SetCountMode(base, psConfig->countMode); /* eqdcoder count mode. */
/* EQDC_CTRL2. */
base->CTRL2 =
EQDC_CTRL2_ONCE(psConfig->countOnce) |
EQDC_CTRL2_INITPOS(psConfig->enableTriggerInitPositionCounter) | /* TRIGGER initializes position counter. */
#if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
EQDC_CTRL2_EMIP(psConfig->enableIndexInitPositionCounter)| /* Index Event Edge Mark initializes position counter */
#endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
EQDC_CTRL2_PMEN(psConfig->enablePeriodMeasurement) | /* Enable period measurement. */
EQDC_CTRL2_OUTCTL(psConfig->outputPulseMode) | /* Output pulse. */
EQDC_CTRL2_REVMOD(psConfig->revolutionCountCondition) | /* Revolution count condition. */
EQDC_CTRL2_LDMOD(psConfig->bufferedRegisterLoadMode) | /* Buffered register load (Update) mode select. */
EQDC_CTRL2_UPDPOS(psConfig->enableTriggerClearPositionRegisters) | /* TRIGGER clears position register. */
EQDC_CTRL2_UPDHLD(psConfig->enableTriggerHoldPositionRegisters); /* TRIGGER loads position registers. */
/* Set mode of operation. */
EQDC_SetOperateMode(base, psConfig->operateMode); /* eqdcoder work mode. */
/* Enable interrupts. */
EQDC_EnableInterrupts(base, psConfig->enabledInterruptsMask);
}
/*
* De-initializes the EQDC module.
*
* This function deinitializes the EQDC by:
* 1. Disables the IP bus clock (optional).
*
* param base EQDC peripheral base address.
*/
void EQDC_Deinit(EQDC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* Gets an available pre-defined configuration.
*
* The default value are:
* psConfig->enableReverseDirection = false;
* psConfig->countOnce = false;
* psConfig->operateMode = kEQDC_QuadratureDecodeOperationMode;
* psConfig->countMode = kEQDC_QuadratureX4;
* psConfig->homeEnableInitPosCounterMode = kEQDC_HomeInitPosCounterDisabled;
* psConfig->indexPresetInitPosCounterMode = kEQDC_IndexInitPosCounterDisabled;
* psConfig->enableIndexInitPositionCounter = false;
* psConfig->enableDma = false;
* psConfig->bufferedRegisterLoadMode = false;
* psConfig->enableTriggerInitPositionCounter = false;
* psConfig->enableTriggerClearPositionRegisters = false;
* psConfig->enableTriggerHoldPositionRegisters = false;
* psConfig->enableWatchdog = false;
* psConfig->watchdogTimeoutValue = 0xFFFFU;
* psConfig->filterPhaseA = 0U;
* psConfig->filterPhaseB = 0U;
* psConfig->filterIndPre = 0U;
* psConfig->filterHomEna = 0U;
* psConfig->filterClockSourceselection = false;
* psConfig->filterSampleCount = kEQDC_Filter3Samples;
* psConfig->filterSamplePeriod = 0U;
* psConfig->outputPulseMode = kEQDC_OutputPulseOnCounterEqualCompare;
* psConfig->positionCompareValue[0] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[1] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[2] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[3] = 0xFFFFFFFFU;
* psConfig->revolutionCountCondition = kEQDC_RevolutionCountOnIndexPulse;
* psConfig->positionModulusValue = 0U;
* psConfig->positionInitialValue = 0U;
* psConfig->positionCounterValue = 0U;
* psConfig->enablePeriodMeasurement = false;
* psConfig->prescaler = kEQDC_Prescaler1;
* psConfig->enabledInterruptsMask = 0U;
*
* param psConfig Pointer to configuration structure.
*/
void EQDC_GetDefaultConfig(eqdc_config_t *psConfig)
{
assert(NULL != psConfig);
psConfig->enableReverseDirection = false;
psConfig->countOnce = false;
psConfig->operateMode = kEQDC_QuadratureDecodeOperationMode; /*!< Decode Mode. */
psConfig->countMode = kEQDC_QuadratureX4;
psConfig->homeEnableInitPosCounterMode = kEQDC_HomeInitPosCounterDisabled;
psConfig->indexPresetInitPosCounterMode = kEQDC_IndexInitPosCounterDisabled;
#if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
psConfig->enableIndexInitPositionCounter = false;
#endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
psConfig->enableDma = false;
psConfig->bufferedRegisterLoadMode = false;
psConfig->enableTriggerInitPositionCounter = false;
psConfig->enableTriggerClearPositionRegisters = false;
psConfig->enableTriggerHoldPositionRegisters = false;
psConfig->enableWatchdog = false;
psConfig->watchdogTimeoutValue = 0xFFFFU;
psConfig->filterPhaseA = 0U;
psConfig->filterPhaseB = 0U;
psConfig->filterIndPre = 0U;
psConfig->filterHomEna = 0U;
psConfig->filterClockSourceselection = false;
psConfig->filterSampleCount = kEQDC_Filter3Samples;
psConfig->filterSamplePeriod = 0U;
psConfig->outputPulseMode = kEQDC_OutputPulseOnCounterEqualCompare;
psConfig->positionCompareValue[0] = 0xFFFFFFFFU;
psConfig->positionCompareValue[1] = 0xFFFFFFFFU;
psConfig->positionCompareValue[2] = 0xFFFFFFFFU;
psConfig->positionCompareValue[3] = 0xFFFFFFFFU;
psConfig->revolutionCountCondition = kEQDC_RevolutionCountOnIndexPulse;
psConfig->positionModulusValue = 0U;
psConfig->positionInitialValue = 0U;
psConfig->positionCounterValue = 0U;
psConfig->enablePeriodMeasurement = false;
psConfig->prescaler = kEQDC_Prescaler1;
psConfig->enabledInterruptsMask = 0U;
}
/*
* Initializes the mode of operation.
*
* The Quadrature Decoder operates in following 4 operation modes:
* 1.Quadrature Decode(QDC) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 0)
* 2.Quadrature Count(QCT) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 1)
* 3.Single Phase Decode(PH1DC) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 0)
* 4.Single Phase Count(PH1CT) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 1)
*
* param base EQDC peripheral base address.
* param psConfig Pointer to configuration structure.
*/
void EQDC_SetOperateMode(EQDC_Type *base, eqdc_operate_mode_t operateMode)
{
switch (operateMode)
{
case kEQDC_QuadratureDecodeOperationMode:
base->CTRL &= ~EQDC_CTRL_PH1_MASK;
base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_QuadratureCountOperationMode:
base->CTRL &= ~EQDC_CTRL_PH1_MASK;
base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_SinglePhaseDecodeOperationMode:
base->CTRL |= EQDC_CTRL_PH1_MASK;
base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_SinglePhaseCountOperationMode:
base->CTRL |= EQDC_CTRL_PH1_MASK;
base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
break;
default:
assert(false);
break;
}
}