added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
144:ef7eb2e8f9f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K66F/drivers/fsl_adc16.c	Fri Sep 02 15:07:44 2016 +0100
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_adc16.h"
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief Get instance number for ADC16 module.
+ *
+ * @param base ADC16 peripheral base address
+ */
+static uint32_t ADC16_GetInstance(ADC_Type *base);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief Pointers to ADC16 bases for each instance. */
+static ADC_Type *const s_adc16Bases[] = ADC_BASE_PTRS;
+
+/*! @brief Pointers to ADC16 clocks for each instance. */
+const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS;
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+static uint32_t ADC16_GetInstance(ADC_Type *base)
+{
+    uint32_t instance;
+
+    /* Find the instance index from base address mappings. */
+    for (instance = 0; instance < FSL_FEATURE_SOC_ADC16_COUNT; instance++)
+    {
+        if (s_adc16Bases[instance] == base)
+        {
+            break;
+        }
+    }
+
+    assert(instance < FSL_FEATURE_SOC_ADC16_COUNT);
+
+    return instance;
+}
+
+void ADC16_Init(ADC_Type *base, const adc16_config_t *config)
+{
+    assert(NULL != config);
+
+    uint32_t tmp32;
+
+    /* Enable the clock. */
+    CLOCK_EnableClock(s_adc16Clocks[ADC16_GetInstance(base)]);
+
+    /* ADCx_CFG1. */
+    tmp32 = ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_MODE(config->resolution);
+    if (kADC16_LongSampleDisabled != config->longSampleMode)
+    {
+        tmp32 |= ADC_CFG1_ADLSMP_MASK;
+    }
+    tmp32 |= ADC_CFG1_ADIV(config->clockDivider);
+    if (config->enableLowPower)
+    {
+        tmp32 |= ADC_CFG1_ADLPC_MASK;
+    }
+    base->CFG1 = tmp32;
+
+    /* ADCx_CFG2. */
+    tmp32 = base->CFG2 & ~(ADC_CFG2_ADACKEN_MASK | ADC_CFG2_ADHSC_MASK | ADC_CFG2_ADLSTS_MASK);
+    if (kADC16_LongSampleDisabled != config->longSampleMode)
+    {
+        tmp32 |= ADC_CFG2_ADLSTS(config->longSampleMode);
+    }
+    if (config->enableHighSpeed)
+    {
+        tmp32 |= ADC_CFG2_ADHSC_MASK;
+    }
+    if (config->enableAsynchronousClock)
+    {
+        tmp32 |= ADC_CFG2_ADACKEN_MASK;
+    }
+    base->CFG2 = tmp32;
+
+    /* ADCx_SC2. */
+    tmp32 = base->SC2 & ~(ADC_SC2_REFSEL_MASK);
+    tmp32 |= ADC_SC2_REFSEL(config->referenceVoltageSource);
+    base->SC2 = tmp32;
+
+    /* ADCx_SC3. */
+    if (config->enableContinuousConversion)
+    {
+        base->SC3 |= ADC_SC3_ADCO_MASK;
+    }
+    else
+    {
+        base->SC3 &= ~ADC_SC3_ADCO_MASK;
+    }
+}
+
+void ADC16_Deinit(ADC_Type *base)
+{
+    /* Disable the clock. */
+    CLOCK_DisableClock(s_adc16Clocks[ADC16_GetInstance(base)]);
+}
+
+void ADC16_GetDefaultConfig(adc16_config_t *config)
+{
+    assert(NULL != config);
+
+    config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
+    config->clockSource = kADC16_ClockSourceAsynchronousClock;
+    config->enableAsynchronousClock = true;
+    config->clockDivider = kADC16_ClockDivider8;
+    config->resolution = kADC16_ResolutionSE12Bit;
+    config->longSampleMode = kADC16_LongSampleDisabled;
+    config->enableHighSpeed = false;
+    config->enableLowPower = false;
+    config->enableContinuousConversion = false;
+}
+
+#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
+status_t ADC16_DoAutoCalibration(ADC_Type *base)
+{
+    bool bHWTrigger = false;
+    uint32_t tmp32;
+    status_t status = kStatus_Success;
+
+    /* The calibration would be failed when in hardwar mode.
+     * Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/
+    if (0U != (ADC_SC2_ADTRG_MASK & base->SC2))
+    {
+        bHWTrigger = true;
+        base->SC2 &= ~ADC_SC2_ADTRG_MASK;
+    }
+
+    /* Clear the CALF and launch the calibration. */
+    base->SC3 |= ADC_SC3_CAL_MASK | ADC_SC3_CALF_MASK;
+    while (0U == (kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(base, 0U)))
+    {
+        /* Check the CALF when the calibration is active. */
+        if (0U != (kADC16_CalibrationFailedFlag & ADC16_GetStatusFlags(base)))
+        {
+            status = kStatus_Fail;
+            break;
+        }
+    }
+
+    /* Restore the hardware trigger setting if it was enabled before. */
+    if (bHWTrigger)
+    {
+        base->SC2 |= ADC_SC2_ADTRG_MASK;
+    }
+    /* Check the CALF at the end of calibration. */
+    if (0U != (kADC16_CalibrationFailedFlag & ADC16_GetStatusFlags(base)))
+    {
+        status = kStatus_Fail;
+    }
+    if (kStatus_Success != status) /* Check if the calibration process is succeed. */
+    {
+        return status;
+    }
+
+    /* Calculate the calibration values. */
+    tmp32 = base->CLP0 + base->CLP1 + base->CLP2 + base->CLP3 + base->CLP4 + base->CLPS;
+    tmp32 = 0x8000U | (tmp32 >> 1U);
+    base->PG = tmp32;
+
+#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
+    tmp32 = base->CLM0 + base->CLM1 + base->CLM2 + base->CLM3 + base->CLM4 + base->CLMS;
+    tmp32 = 0x8000U | (tmp32 >> 1U);
+    base->MG = tmp32;
+#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
+
+    return kStatus_Success;
+}
+#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
+
+#if defined(FSL_FEATURE_ADC16_HAS_MUX_SELECT) && FSL_FEATURE_ADC16_HAS_MUX_SELECT
+void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode)
+{
+    if (kADC16_ChannelMuxA == mode)
+    {
+        base->CFG2 &= ~ADC_CFG2_MUXSEL_MASK;
+    }
+    else /* kADC16_ChannelMuxB. */
+    {
+        base->CFG2 |= ADC_CFG2_MUXSEL_MASK;
+    }
+}
+#endif /* FSL_FEATURE_ADC16_HAS_MUX_SELECT */
+
+void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config)
+{
+    uint32_t tmp32 = base->SC2 & ~(ADC_SC2_ACFE_MASK | ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK);
+
+    if (!config) /* Pass "NULL" to disable the feature. */
+    {
+        base->SC2 = tmp32;
+        return;
+    }
+    /* Enable the feature. */
+    tmp32 |= ADC_SC2_ACFE_MASK;
+
+    /* Select the hardware compare working mode. */
+    switch (config->hardwareCompareMode)
+    {
+        case kADC16_HardwareCompareMode0:
+            break;
+        case kADC16_HardwareCompareMode1:
+            tmp32 |= ADC_SC2_ACFGT_MASK;
+            break;
+        case kADC16_HardwareCompareMode2:
+            tmp32 |= ADC_SC2_ACREN_MASK;
+            break;
+        case kADC16_HardwareCompareMode3:
+            tmp32 |= ADC_SC2_ACFGT_MASK | ADC_SC2_ACREN_MASK;
+            break;
+        default:
+            break;
+    }
+    base->SC2 = tmp32;
+
+    /* Load the compare values. */
+    base->CV1 = ADC_CV1_CV(config->value1);
+    base->CV2 = ADC_CV2_CV(config->value2);
+}
+
+#if defined(FSL_FEATURE_ADC16_HAS_HW_AVERAGE) && FSL_FEATURE_ADC16_HAS_HW_AVERAGE
+void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode)
+{
+    uint32_t tmp32 = base->SC3 & ~(ADC_SC3_AVGE_MASK | ADC_SC3_AVGS_MASK);
+
+    if (kADC16_HardwareAverageDisabled != mode)
+    {
+        tmp32 |= ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(mode);
+    }
+    base->SC3 = tmp32;
+}
+#endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */
+
+#if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA
+void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config)
+{
+    uint32_t tmp32;
+
+    if (!config) /* Passing "NULL" is to disable the feature. */
+    {
+        base->PGA = 0U;
+        return;
+    }
+
+    /* Enable the PGA and set the gain value. */
+    tmp32 = ADC_PGA_PGAEN_MASK | ADC_PGA_PGAG(config->pgaGain);
+
+    /* Configure the misc features for PGA. */
+    if (config->enableRunInNormalMode)
+    {
+        tmp32 |= ADC_PGA_PGALPb_MASK;
+    }
+#if defined(FSL_FEATURE_ADC16_HAS_PGA_CHOPPING) && FSL_FEATURE_ADC16_HAS_PGA_CHOPPING
+    if (config->disablePgaChopping)
+    {
+        tmp32 |= ADC_PGA_PGACHPb_MASK;
+    }
+#endif /* FSL_FEATURE_ADC16_HAS_PGA_CHOPPING */
+#if defined(FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT) && FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT
+    if (config->enableRunInOffsetMeasurement)
+    {
+        tmp32 |= ADC_PGA_PGAOFSM_MASK;
+    }
+#endif /* FSL_FEATURE_ADC16_HAS_PGA_OFFSET_MEASUREMENT */
+    base->PGA = tmp32;
+}
+#endif /* FSL_FEATURE_ADC16_HAS_PGA */
+
+uint32_t ADC16_GetStatusFlags(ADC_Type *base)
+{
+    uint32_t ret = 0;
+
+    if (0U != (base->SC2 & ADC_SC2_ADACT_MASK))
+    {
+        ret |= kADC16_ActiveFlag;
+    }
+#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
+    if (0U != (base->SC3 & ADC_SC3_CALF_MASK))
+    {
+        ret |= kADC16_CalibrationFailedFlag;
+    }
+#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
+    return ret;
+}
+
+void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask)
+{
+#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
+    if (0U != (mask & kADC16_CalibrationFailedFlag))
+    {
+        base->SC3 |= ADC_SC3_CALF_MASK;
+    }
+#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */
+}
+
+void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config)
+{
+    assert(channelGroup < ADC_SC1_COUNT);
+    assert(NULL != config);
+
+    uint32_t sc1 = ADC_SC1_ADCH(config->channelNumber); /* Set the channel number. */
+
+#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
+    /* Enable the differential conversion. */
+    if (config->enableDifferentialConversion)
+    {
+        sc1 |= ADC_SC1_DIFF_MASK;
+    }
+#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
+    /* Enable the interrupt when the conversion is done. */
+    if (config->enableInterruptOnConversionCompleted)
+    {
+        sc1 |= ADC_SC1_AIEN_MASK;
+    }
+    base->SC1[channelGroup] = sc1;
+}
+
+uint32_t ADC16_GetChannelStatusFlags(ADC_Type *base, uint32_t channelGroup)
+{
+    assert(channelGroup < ADC_SC1_COUNT);
+
+    uint32_t ret = 0U;
+
+    if (0U != (base->SC1[channelGroup] & ADC_SC1_COCO_MASK))
+    {
+        ret |= kADC16_ChannelConversionDoneFlag;
+    }
+    return ret;
+}