rt-thread-official/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_dcic.c

173 lines
5.7 KiB
C

/*
* Copyright 2020-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dcic.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.dcic"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DCIC module.
*
* @param base DCIC peripheral base address.
*/
static uint32_t DCIC_GetInstance(DCIC_Type *base);
static void DCIC_ResetRegister(DCIC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to DCIC bases for each instance. */
static DCIC_Type *const s_dcicBases[] = DCIC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to dcic clocks for each instance. */
static const clock_ip_name_t s_dcicClocks[] = DCIC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DCIC_GetInstance(DCIC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_dcicBases); instance++)
{
if (s_dcicBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_dcicBases));
return instance;
}
#define DCIC_DCCIC_RESET_VALUE (DCIC_DCICC_VSYNC_POL_MASK | DCIC_DCICC_HSYNC_POL_MASK | DCIC_DCICC_DE_POL_MASK)
#define DCIC_DCICIC_RESET_VALUE (DCIC_DCICIC_FI_MASK_MASK | DCIC_DCICIC_EI_MASK_MASK)
static void DCIC_ResetRegister(DCIC_Type *base)
{
uint32_t i;
base->DCICC = DCIC_DCCIC_RESET_VALUE;
base->DCICIC = DCIC_DCICIC_RESET_VALUE;
/* Reset region registers. */
for (i = 0; i < DCIC_REGION_COUNT; i++)
{
base->REGION[i].DCICRC = 0UL;
base->REGION[i].DCICRS = 0UL;
base->REGION[i].DCICRRS = 0UL;
}
/* Clear all status. */
base->DCICS = (DCIC_DCICS_EI_STAT_MASK | DCIC_DCICS_FI_STAT_MASK | DCIC_DCICS_ROI_MATCH_STAT_MASK);
}
/*
* brief Initializes the DCIC.
*
* param base DCIC peripheral base address.
* param config Pointer to the configuration.
*/
void DCIC_Init(DCIC_Type *base, const dcic_config_t *config)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
(void)CLOCK_EnableClock(s_dcicClocks[DCIC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
DCIC_ResetRegister(base);
base->DCICC = config->polarityFlags;
DCIC_EnableMismatchExternalSignal(base, config->enableExternalSignal);
DCIC_EnableInterrupts(base, config->enableInterrupts);
}
/*
* brief Disable the DCIC.
*
* param base DCIC peripheral base address.
*/
void DCIC_Deinit(DCIC_Type *base)
{
base->DCICC = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
(void)CLOCK_DisableClock(s_dcicClocks[DCIC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* Get the default configuration to initialize DCIC.
*
* The default configuration is:
*
config->polarityFlags = kDCIC_VsyncActiveLow | kDCIC_HsyncActiveLow |
kDCIC_DataEnableActiveLow | kDCIC_DriveDataOnFallingClkEdge;
config->enableExternalSignal = false;
config->enableInterrupts = 0;
*
* param config Pointer to the configuration.
*/
void DCIC_GetDefaultConfig(dcic_config_t *config)
{
assert(NULL != config);
config->polarityFlags = (uint8_t)kDCIC_VsyncActiveLow | (uint8_t)kDCIC_HsyncActiveLow |
(uint8_t)kDCIC_DataEnableActiveLow | (uint8_t)kDCIC_DriveDataOnFallingClkEdge;
config->enableExternalSignal = false;
config->enableInterrupts = 0;
}
/*
* brief Enable the region of interest (ROI) with configuration.
*
* Enable the ROI with configuration. To change the configuration except reference
* CRC value, the region should be disabled first by ref DCIC_DisableRegion,
* then call this function again. The reference CRC value could be changed by
* ref DCIC_SetRegionRefCrc without disabling the region.
* If the configuration is locked, only the reference CRC value could be changed,
* the region size and position, enable status could not be changed until reset.
*
* param base DCIC peripheral base address.
* param regionIdx Region index, from 0 to (DCIC_REGION_COUNT - 1).
* param config Pointer to the configuration.
*/
void DCIC_EnableRegion(DCIC_Type *base, uint8_t regionIdx, const dcic_region_config_t *config)
{
assert(regionIdx < DCIC_REGION_COUNT);
assert(NULL != config);
base->REGION[regionIdx].DCICRRS = config->refCrc;
base->REGION[regionIdx].DCICRS = (((uint32_t)config->lowerRightX << DCIC_DCICRS_END_OFFSET_X_SHIFT) |
((uint32_t)config->lowerRightY << DCIC_DCICRS_END_OFFSET_Y_SHIFT));
base->REGION[regionIdx].DCICRC = (((uint32_t)config->upperLeftX << DCIC_DCICRC_START_OFFSET_X_SHIFT) |
((uint32_t)config->upperLeftY << DCIC_DCICRC_START_OFFSET_Y_SHIFT) |
(config->lock ? DCIC_DCICRC_ROI_FREEZE_MASK : 0UL) | DCIC_DCICRC_ROI_EN_MASK);
}