774 lines
34 KiB
C
774 lines
34 KiB
C
/***************************************************************************//**
|
|
* @file
|
|
* @brief Digital to Analog Converter (VDAC) peripheral API
|
|
*******************************************************************************
|
|
* # License
|
|
* <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
|
|
*******************************************************************************
|
|
*
|
|
* SPDX-License-Identifier: Zlib
|
|
*
|
|
* The licensor of this software is Silicon Laboratories Inc.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event will the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software
|
|
* in a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifndef EM_VDAC_H
|
|
#define EM_VDAC_H
|
|
|
|
#include "em_device.h"
|
|
|
|
#if defined(VDAC_COUNT) && (VDAC_COUNT > 0)
|
|
|
|
#include "sl_assert.h"
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/***************************************************************************//**
|
|
* @addtogroup vdac VDAC - Voltage DAC
|
|
* @brief Digital to Analog Voltage Converter (VDAC) Peripheral API
|
|
*
|
|
* @details
|
|
* This module contains functions to control the VDAC peripheral of Silicon
|
|
* Labs' 32-bit MCUs and SoCs. VDAC converts digital values to analog
|
|
* signals at up to 500 ksps with 12-bit accuracy. VDAC is designed for
|
|
* low energy consumption, but can also provide very good performance.
|
|
*
|
|
* The following steps are necessary for basic operation:
|
|
*
|
|
* Clock enable:
|
|
* @code
|
|
CMU_ClockEnable(cmuClock_VDAC0, true);@endcode
|
|
*
|
|
* Initialize the VDAC with default settings and modify selected fields:
|
|
* @code
|
|
VDAC_Init_TypeDef vdacInit = VDAC_INIT_DEFAULT;
|
|
VDAC_InitChannel_TypeDef vdacChInit = VDAC_INITCHANNEL_DEFAULT;
|
|
|
|
// Set prescaler to get 1 MHz VDAC clock frequency.
|
|
vdacInit.prescaler = VDAC_PrescaleCalc(1000000, true, 0); // function call for series 0/1
|
|
VDAC_Init(VDAC0, &vdacInit);
|
|
|
|
vdacChInit.enable = true;
|
|
VDAC_InitChannel(VDAC0, &vdacChInit, 0);@endcode
|
|
*
|
|
* Perform a conversion:
|
|
* @code
|
|
VDAC_ChannelOutputSet(VDAC0, 0, 250);@endcode
|
|
*
|
|
* @note The output stage of a VDAC channel consists of an on-chip operational
|
|
* amplifier (OPAMP) in the OPAMP module. This OPAMP is highly configurable;
|
|
* and to exploit the VDAC functionality fully, configure the OPAMP using
|
|
* the OPAMP API. Using the OPAMP API also loads OPAMP calibration values.
|
|
* The default (reset) settings of OPAMP is sufficient for many applications.
|
|
* @{
|
|
******************************************************************************/
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
|
|
/** Validation of VDAC register block pointer reference for assert statements.*/
|
|
|
|
#if VDAC_COUNT == 1
|
|
#define VDAC_REF_VALID(ref) ((ref) == VDAC0)
|
|
#elif VDAC_COUNT == 2
|
|
#define VDAC_REF_VALID(ref) (((ref) == VDAC0) || ((ref) == VDAC1))
|
|
#else
|
|
#error "Undefined number of VDACs."
|
|
#endif
|
|
|
|
/** @endcond */
|
|
|
|
/*******************************************************************************
|
|
******************************** ENUMS ************************************
|
|
******************************************************************************/
|
|
|
|
#if !defined(_SILICON_LABS_32B_SERIES_2)
|
|
/** Channel refresh period. */
|
|
typedef enum {
|
|
vdacRefresh8 = _VDAC_CTRL_REFRESHPERIOD_8CYCLES, /**< Refresh every 8 clock cycles. */
|
|
vdacRefresh16 = _VDAC_CTRL_REFRESHPERIOD_16CYCLES, /**< Refresh every 16 clock cycles. */
|
|
vdacRefresh32 = _VDAC_CTRL_REFRESHPERIOD_32CYCLES, /**< Refresh every 32 clock cycles. */
|
|
vdacRefresh64 = _VDAC_CTRL_REFRESHPERIOD_64CYCLES, /**< Refresh every 64 clock cycles. */
|
|
} VDAC_Refresh_TypeDef;
|
|
|
|
/** Reference voltage for VDAC. */
|
|
typedef enum {
|
|
vdacRef1V25Ln = _VDAC_CTRL_REFSEL_1V25LN, /**< Internal low noise 1.25 V band gap reference. */
|
|
vdacRef2V5Ln = _VDAC_CTRL_REFSEL_2V5LN, /**< Internal low noise 2.5 V band gap reference. */
|
|
vdacRef1V25 = _VDAC_CTRL_REFSEL_1V25, /**< Internal 1.25 V band gap reference. */
|
|
vdacRef2V5 = _VDAC_CTRL_REFSEL_2V5, /**< Internal 2.5 V band gap reference. */
|
|
vdacRefAvdd = _VDAC_CTRL_REFSEL_VDD, /**< AVDD reference. */
|
|
vdacRefExtPin = _VDAC_CTRL_REFSEL_EXT, /**< External pin reference. */
|
|
} VDAC_Ref_TypeDef;
|
|
|
|
/** Peripheral Reflex System signal used to trigger VDAC channel conversion. */
|
|
typedef enum {
|
|
vdacPrsSelCh0 = _VDAC_CH0CTRL_PRSSEL_PRSCH0, /**< PRS ch 0 triggers conversion. */
|
|
vdacPrsSelCh1 = _VDAC_CH0CTRL_PRSSEL_PRSCH1, /**< PRS ch 1 triggers conversion. */
|
|
vdacPrsSelCh2 = _VDAC_CH0CTRL_PRSSEL_PRSCH2, /**< PRS ch 2 triggers conversion. */
|
|
vdacPrsSelCh3 = _VDAC_CH0CTRL_PRSSEL_PRSCH3, /**< PRS ch 3 triggers conversion. */
|
|
vdacPrsSelCh4 = _VDAC_CH0CTRL_PRSSEL_PRSCH4, /**< PRS ch 4 triggers conversion. */
|
|
vdacPrsSelCh5 = _VDAC_CH0CTRL_PRSSEL_PRSCH5, /**< PRS ch 5 triggers conversion. */
|
|
vdacPrsSelCh6 = _VDAC_CH0CTRL_PRSSEL_PRSCH6, /**< PRS ch 6 triggers conversion. */
|
|
vdacPrsSelCh7 = _VDAC_CH0CTRL_PRSSEL_PRSCH7, /**< PRS ch 7 triggers conversion. */
|
|
#if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH8)
|
|
vdacPrsSelCh8 = _VDAC_CH0CTRL_PRSSEL_PRSCH8, /**< PRS ch 8 triggers conversion. */
|
|
#endif
|
|
#if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH9)
|
|
vdacPrsSelCh9 = _VDAC_CH0CTRL_PRSSEL_PRSCH9, /**< PRS ch 9 triggers conversion. */
|
|
#endif
|
|
#if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH10)
|
|
vdacPrsSelCh10 = _VDAC_CH0CTRL_PRSSEL_PRSCH10, /**< PRS ch 10 triggers conversion. */
|
|
#endif
|
|
#if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH11)
|
|
vdacPrsSelCh11 = _VDAC_CH0CTRL_PRSSEL_PRSCH11, /**< PRS ch 11 triggers conversion. */
|
|
#endif
|
|
} VDAC_PrsSel_TypeDef;
|
|
|
|
/** Channel conversion trigger mode. */
|
|
typedef enum {
|
|
vdacTrigModeSw = _VDAC_CH0CTRL_TRIGMODE_SW, /**< Channel is triggered by CHnDATA or COMBDATA write. */
|
|
vdacTrigModePrs = _VDAC_CH0CTRL_TRIGMODE_PRS, /**< Channel is triggered by PRS input. */
|
|
vdacTrigModeRefresh = _VDAC_CH0CTRL_TRIGMODE_REFRESH, /**< Channel is triggered by Refresh timer. */
|
|
vdacTrigModeSwPrs = _VDAC_CH0CTRL_TRIGMODE_SWPRS, /**< Channel is triggered by CHnDATA/COMBDATA write or PRS input. */
|
|
vdacTrigModeSwRefresh = _VDAC_CH0CTRL_TRIGMODE_SWREFRESH, /**< Channel is triggered by CHnDATA/COMBDATA write or Refresh timer. */
|
|
vdacTrigModeLesense = _VDAC_CH0CTRL_TRIGMODE_LESENSE, /**< Channel is triggered by LESENSE. */
|
|
} VDAC_TrigMode_TypeDef;
|
|
|
|
/*******************************************************************************
|
|
******************************* STRUCTS ***********************************
|
|
******************************************************************************/
|
|
|
|
/** VDAC initialization structure, common for both channels. */
|
|
typedef struct {
|
|
/** Selects between main and alternate output path calibration values. */
|
|
bool mainCalibration;
|
|
|
|
/** Selects clock from asynchronous or synchronous (with respect to
|
|
peripheral clock) source. */
|
|
bool asyncClockMode;
|
|
|
|
/** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
|
|
bool warmupKeepOn;
|
|
|
|
/** Channel refresh period. */
|
|
VDAC_Refresh_TypeDef refresh;
|
|
|
|
/** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
|
|
uint32_t prescaler;
|
|
|
|
/** Reference voltage to use. */
|
|
VDAC_Ref_TypeDef reference;
|
|
|
|
/** Enable/disable reset of prescaler on CH 0 start. */
|
|
bool ch0ResetPre;
|
|
|
|
/** Enable/disable output enable control by CH1 PRS signal. */
|
|
bool outEnablePRS;
|
|
|
|
/** Enable/disable sine mode. */
|
|
bool sineEnable;
|
|
|
|
/** Select if single ended or differential output mode. */
|
|
bool diff;
|
|
} VDAC_Init_TypeDef;
|
|
|
|
/** Default configuration for VDAC initialization structure. */
|
|
#define VDAC_INIT_DEFAULT \
|
|
{ \
|
|
true, /* Use main output path calibration values. */ \
|
|
false, /* Use synchronous clock mode. */ \
|
|
false, /* Turn off between sample off conversions.*/ \
|
|
vdacRefresh8, /* Refresh every 8th cycle. */ \
|
|
0, /* No prescaling. */ \
|
|
vdacRef1V25Ln, /* 1.25 V internal low noise reference. */ \
|
|
false, /* Do not reset prescaler on CH 0 start. */ \
|
|
false, /* VDAC output enable always on. */ \
|
|
false, /* Disable sine mode. */ \
|
|
false /* Single ended mode. */ \
|
|
}
|
|
|
|
/** VDAC channel initialization structure. */
|
|
typedef struct {
|
|
/** Enable channel. */
|
|
bool enable;
|
|
|
|
/**
|
|
* Peripheral reflex system trigger selection. Only applicable if @p trigMode
|
|
* is set to @p vdacTrigModePrs or @p vdacTrigModeSwPrs. */
|
|
VDAC_PrsSel_TypeDef prsSel;
|
|
|
|
/** Treat the PRS signal asynchronously. */
|
|
bool prsAsync;
|
|
|
|
/** Channel conversion trigger mode. */
|
|
VDAC_TrigMode_TypeDef trigMode;
|
|
|
|
/** Set channel conversion mode to sample/shut-off mode. Default is
|
|
* continuous.*/
|
|
bool sampleOffMode;
|
|
} VDAC_InitChannel_TypeDef;
|
|
|
|
/** Default configuration for VDAC channel initialization structure. */
|
|
#define VDAC_INITCHANNEL_DEFAULT \
|
|
{ \
|
|
false, /* Leave channel disabled when initialization is done. */ \
|
|
vdacPrsSelCh0, /* PRS CH 0 triggers conversion. */ \
|
|
false, /* Treat PRS channel as a synchronous signal. */ \
|
|
vdacTrigModeSw, /* Conversion trigged by CH0DATA or COMBDATA write. */ \
|
|
false, /* Channel conversion set to continuous. */ \
|
|
}
|
|
#else // defined(_SILICON_LABS_32B_SERIES_2)
|
|
|
|
/** Channel refresh period. */
|
|
typedef enum {
|
|
vdacRefresh2 = _VDAC_CFG_REFRESHPERIOD_CYCLES2, /**< Refresh every 2 clock cycles. */
|
|
vdacRefresh4 = _VDAC_CFG_REFRESHPERIOD_CYCLES4, /**< Refresh every 4 clock cycles. */
|
|
vdacRefresh8 = _VDAC_CFG_REFRESHPERIOD_CYCLES8, /**< Refresh every 8 clock cycles. */
|
|
vdacRefresh16 = _VDAC_CFG_REFRESHPERIOD_CYCLES16, /**< Refresh every 16 clock cycles. */
|
|
vdacRefresh32 = _VDAC_CFG_REFRESHPERIOD_CYCLES32, /**< Refresh every 32 clock cycles. */
|
|
vdacRefresh64 = _VDAC_CFG_REFRESHPERIOD_CYCLES64, /**< Refresh every 64 clock cycles. */
|
|
vdacRefresh128 = _VDAC_CFG_REFRESHPERIOD_CYCLES128, /**< Refresh every 128 clock cycles. */
|
|
vdacRefresh256 = _VDAC_CFG_REFRESHPERIOD_CYCLES256, /**< Refresh every 256 clock cycles. */
|
|
} VDAC_Refresh_TypeDef;
|
|
|
|
/** Timer overflow period. */
|
|
typedef enum {
|
|
vdacCycles2 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES2, /**< Overflows every 2 clock cycles. */
|
|
vdacCycles4 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES4, /**< Overflows every 4 clock cycles. */
|
|
vdacCycles8 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES8, /**< Overflows every 8 clock cycles. */
|
|
vdacCycles16 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES16, /**< Overflows every 16 clock cycles. */
|
|
vdacCycles32 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES32, /**< Overflows every 32 clock cycles. */
|
|
vdacCycles64 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES64 /**< Overflows every 64 clock cycles. */
|
|
} VDAC_TimerOverflow_TypeDef;
|
|
|
|
/** Reference voltage for VDAC. */
|
|
typedef enum {
|
|
vdacRef1V25 = _VDAC_CFG_REFRSEL_V125, /**< Internal 1.25 V band gap reference. */
|
|
vdacRef2V5 = _VDAC_CFG_REFRSEL_V25, /**< Internal 2.5 V band gap reference. */
|
|
vdacRefAvdd = _VDAC_CFG_REFRSEL_VDD, /**< AVDD reference. */
|
|
vdacRefExtPin = _VDAC_CFG_REFRSEL_EXT, /**< External pin reference. */
|
|
} VDAC_Ref_TypeDef;
|
|
|
|
/** Refresh source for VDAC. */
|
|
typedef enum {
|
|
vdacRefreshSrcNone = _VDAC_CH0CFG_REFRESHSOURCE_NONE, /**< No refresh source. */
|
|
vdacRefreshSrcRefreshTimer = _VDAC_CH0CFG_REFRESHSOURCE_REFRESHTIMER,/**< Refresh triggered by refresh timer overflow. */
|
|
vdacRefreshSrcSyncPrs = _VDAC_CH0CFG_REFRESHSOURCE_SYNCPRS, /**< Refresh triggered by sync PRS. */
|
|
vdacRefreshSrcAsyncPrs = _VDAC_CH0CFG_REFRESHSOURCE_ASYNCPRS, /**< Refresh triggered by async PRS. */
|
|
} VDAC_RefreshSource_TypeDef;
|
|
|
|
/** Channel conversion trigger mode. */
|
|
typedef enum {
|
|
vdacTrigModeNone = _VDAC_CH0CFG_TRIGMODE_NONE, /**< No conversion trigger source selected. */
|
|
vdacTrigModeSw = _VDAC_CH0CFG_TRIGMODE_SW, /**< Channel is triggered by CHnDATA or COMBDATA write. */
|
|
vdacTrigModeSyncPrs = _VDAC_CH0CFG_TRIGMODE_SYNCPRS, /**< Channel is triggered by Sync PRS input. */
|
|
#if defined(LESENSE_PRESENT) && defined(_VDAC_CH0CFG_TRIGMODE_LESENSE)
|
|
vdacTrigModeLesense = _VDAC_CH0CFG_TRIGMODE_LESENSE, /**< Channel is triggered by LESENSE. */
|
|
#endif
|
|
vdacTrigModeInternalTimer = _VDAC_CH0CFG_TRIGMODE_INTERNALTIMER, /**< Channel is triggered by Internal Timer. */
|
|
vdacTrigModeAsyncPrs = _VDAC_CH0CFG_TRIGMODE_ASYNCPRS /**< Channel is triggered by Async PRS input. */
|
|
} VDAC_TrigMode_TypeDef;
|
|
|
|
/** Channel power mode. */
|
|
typedef enum {
|
|
vdacPowerModeHighPower = _VDAC_CH0CFG_POWERMODE_HIGHPOWER, /**< High power buffer mode. */
|
|
vdacPowerModeLowPower = _VDAC_CH0CFG_POWERMODE_LOWPOWER /**< Low power buffer mode. */
|
|
} VDAC_PowerMode_TypeDef;
|
|
|
|
/** VDAC channel Abus port selection. */
|
|
typedef enum {
|
|
/** No GPIO selected. */
|
|
vdacChPortNone = _VDAC_OUTCTRL_ABUSPORTSELCH0_NONE,
|
|
/** Port A selected. */
|
|
vdacChPortA = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTA,
|
|
/** Port B selected. */
|
|
vdacChPortB = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTB,
|
|
/** Port C selected. */
|
|
vdacChPortC = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTC,
|
|
/** Port D selected. */
|
|
vdacChPortD = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTD,
|
|
} VDAC_ChPortSel_t;
|
|
|
|
/*******************************************************************************
|
|
******************************* STRUCTS ***********************************
|
|
******************************************************************************/
|
|
|
|
/** VDAC initialization structure, common for both channels. */
|
|
typedef struct {
|
|
/** Number of prescaled CLK_DAC + 1 for the vdac to warmup. */
|
|
uint32_t warmupTime;
|
|
|
|
/** Halt during debug. */
|
|
bool dbgHalt;
|
|
|
|
/** Always allow clk_dac. */
|
|
bool onDemandClk;
|
|
|
|
/** DMA Wakeup. */
|
|
bool dmaWakeUp;
|
|
|
|
/** Bias keep warm enable. */
|
|
bool biasKeepWarm;
|
|
|
|
/** Channel refresh period. */
|
|
VDAC_Refresh_TypeDef refresh;
|
|
|
|
/** Internal timer overflow period. */
|
|
VDAC_TimerOverflow_TypeDef timerOverflow;
|
|
|
|
/** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
|
|
uint32_t prescaler;
|
|
|
|
/** Reference voltage to use. */
|
|
VDAC_Ref_TypeDef reference;
|
|
|
|
/** Enable/disable reset of prescaler on CH 0 start. */
|
|
bool ch0ResetPre;
|
|
|
|
/** Sine reset mode. */
|
|
bool sineReset;
|
|
|
|
/** Enable/disable sine mode. */
|
|
bool sineEnable;
|
|
|
|
/** Select if single ended or differential output mode. */
|
|
bool diff;
|
|
|
|
#if defined(VDAC_CFG_SINEMODEPRS)
|
|
/** PRS controlled sinemode enable. */
|
|
bool sineModePrsEnable;
|
|
#endif
|
|
#if defined(VDAC_CFG_OUTENPRS)
|
|
/** PRS controlled channel output enable. */
|
|
bool prsOutEnable;
|
|
#endif
|
|
} VDAC_Init_TypeDef;
|
|
|
|
#if defined(VDAC_CFG_SINEMODEPRS)
|
|
/** Default configuration for VDAC initialization structure. */
|
|
#define VDAC_INIT_DEFAULT \
|
|
{ \
|
|
_VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */ \
|
|
false, /* Continue while debugging. */ \
|
|
false, /* On demand clock. */ \
|
|
false, /* DMA wake up. */ \
|
|
false, /* Bias keep warm. */ \
|
|
vdacRefresh2, /* Refresh every 2th cycle. */ \
|
|
vdacCycles2, /* Internal overflow every 2th cycle. */ \
|
|
0, /* No prescaling. */ \
|
|
vdacRef1V25, /* 1.25 V internal low noise reference. */ \
|
|
false, /* Do not reset prescaler on CH 0 start. */ \
|
|
false, /* Sine wave is stopped at the sample its currently outputting. */ \
|
|
false, /* Disable sine mode. */ \
|
|
false, /* Differential mode. */ \
|
|
false, /* PRS controlled sinemode. */ \
|
|
false, /* PRS controlled output enable. */ \
|
|
}
|
|
#else
|
|
/** Default configuration for VDAC initialization structure. */
|
|
#define VDAC_INIT_DEFAULT \
|
|
{ \
|
|
_VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */ \
|
|
false, /* Continue while debugging. */ \
|
|
false, /* On demand clock. */ \
|
|
false, /* DMA wake up. */ \
|
|
false, /* Bias keep warm. */ \
|
|
vdacRefresh2, /* Refresh every 2th cycle. */ \
|
|
vdacCycles2, /* Internal overflow every 2th cycle. */ \
|
|
0, /* No prescaling. */ \
|
|
vdacRef1V25, /* 1.25 V internal low noise reference. */ \
|
|
false, /* Do not reset prescaler on CH 0 start. */ \
|
|
false, /* Sine wave is stopped at the sample its currently outputting. */ \
|
|
false, /* Disable sine mode. */ \
|
|
false, /* Differential mode. */ \
|
|
}
|
|
#endif
|
|
|
|
#if defined(VDAC_CFG_SINEMODEPRS)
|
|
/** Sine mode configuration for VDAC initialization structure. */
|
|
#define VDAC_INIT_SINE_GENERATION_MODE \
|
|
{ \
|
|
_VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */ \
|
|
false, /* Continue while debugging. */ \
|
|
true, /* On demand clock. */ \
|
|
false, /* DMA wake up. */ \
|
|
false, /* Bias keep warm. */ \
|
|
vdacRefresh8, /* Refresh every 8th cycle. */ \
|
|
vdacCycles2, /* Internal overflow every 8th cycle. */ \
|
|
0, /* No prescaling. */ \
|
|
vdacRef1V25, /* 1.25 V internal low noise reference. */ \
|
|
false, /* Do not reset prescaler on CH 0 start. */ \
|
|
false, /* Sine wave is stopped at the sample its currently outputting. */ \
|
|
true, /* Enable sine mode. */ \
|
|
false, /* Differential mode. */ \
|
|
false, /* PRS controlled sinemode. */ \
|
|
false, /* PRS controlled output enable. */ \
|
|
}
|
|
#else
|
|
/** Sine mode configuration for VDAC initialization structure. */
|
|
#define VDAC_INIT_SINE_GENERATION_MODE \
|
|
{ \
|
|
_VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */ \
|
|
false, /* Continue while debugging. */ \
|
|
true, /* On demand clock. */ \
|
|
false, /* DMA wake up. */ \
|
|
false, /* Bias keep warm. */ \
|
|
vdacRefresh8, /* Refresh every 8th cycle. */ \
|
|
vdacCycles2, /* Internal overflow every 8th cycle. */ \
|
|
0, /* No prescaling. */ \
|
|
vdacRef1V25, /* 1.25 V internal low noise reference. */ \
|
|
false, /* Do not reset prescaler on CH 0 start. */ \
|
|
false, /* Sine wave is stopped at the sample its currently outputting. */ \
|
|
true, /* Enable sine mode. */ \
|
|
false, /* Differential mode. */ \
|
|
}
|
|
#endif
|
|
|
|
/** VDAC channel initialization structure. */
|
|
typedef struct {
|
|
/** Enable channel. */
|
|
bool enable;
|
|
|
|
/** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
|
|
bool warmupKeepOn;
|
|
|
|
/** Select high capacitance load mode in conjunction with high power. */
|
|
bool highCapLoadEnable;
|
|
|
|
/** Channel x FIFO Low threshold data valid level. */
|
|
uint32_t fifoLowDataThreshold;
|
|
|
|
/** Channel refresh source. */
|
|
VDAC_RefreshSource_TypeDef chRefreshSource;
|
|
|
|
/** Channel conversion trigger mode. */
|
|
VDAC_TrigMode_TypeDef trigMode;
|
|
|
|
/** Channel power mode. */
|
|
VDAC_PowerMode_TypeDef powerMode;
|
|
|
|
/** Set channel conversion mode to sample/shut-off mode. Default is
|
|
* continuous.*/
|
|
bool sampleOffMode;
|
|
|
|
/** Vdac channel output pin. */
|
|
uint32_t pin;
|
|
|
|
/** Vdac channel output port. */
|
|
VDAC_ChPortSel_t port;
|
|
|
|
/** Short High power and low power output. */
|
|
bool shortOutput;
|
|
|
|
/** Alternative output enable. */
|
|
bool auxOutEnable;
|
|
|
|
/** Main output enable. */
|
|
bool mainOutEnable;
|
|
|
|
/** Channel output hold time. */
|
|
uint32_t holdOutTime;
|
|
} VDAC_InitChannel_TypeDef;
|
|
|
|
/** Default configuration for VDAC channel initialization structure. */
|
|
#define VDAC_INITCHANNEL_DEFAULT \
|
|
{ \
|
|
false, /* Leave channel disabled when initialization is done. */ \
|
|
false, /* Turn off between sample off conversions.*/ \
|
|
true, /* Enable High cap mode. */ \
|
|
0, /* FIFO data low watermark at 0. */ \
|
|
vdacRefreshSrcNone, /* Channel refresh source. */ \
|
|
vdacTrigModeSw, /* Conversion trigged by CH0DATA or COMBDATA write. */ \
|
|
vdacPowerModeHighPower, /* High power mode enabled. */ \
|
|
false, /* Continuous conversion mode. */ \
|
|
0, /* ABUS pin selected. */ \
|
|
vdacChPortNone, /* No Analog bus port selected. */ \
|
|
false, /* Output not shorted */ \
|
|
false, /* Alternative output disabled. */ \
|
|
true, /* Main output enabled. */ \
|
|
0, /* Hold out time. Previously called settle time */ \
|
|
}
|
|
|
|
#endif
|
|
/*******************************************************************************
|
|
***************************** PROTOTYPES **********************************
|
|
******************************************************************************/
|
|
|
|
void VDAC_ChannelOutputSet(VDAC_TypeDef *vdac,
|
|
unsigned int channel,
|
|
uint32_t value);
|
|
void VDAC_Enable(VDAC_TypeDef *vdac, unsigned int ch, bool enable);
|
|
void VDAC_Init(VDAC_TypeDef *vdac, const VDAC_Init_TypeDef *init);
|
|
void VDAC_InitChannel(VDAC_TypeDef *vdac,
|
|
const VDAC_InitChannel_TypeDef *init,
|
|
unsigned int ch);
|
|
|
|
#if defined(_SILICON_LABS_32B_SERIES_2)
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Start/stop Sinemode.
|
|
*
|
|
* @details
|
|
* This function sends the sine mode start/stop signal to the DAC.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] start
|
|
* True to start the Sine mode, false to stop it.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_SineModeStart(VDAC_TypeDef *vdac, bool start)
|
|
{
|
|
EFM_ASSERT(VDAC_REF_VALID(vdac));
|
|
|
|
while (0UL != (vdac->STATUS & VDAC_STATUS_SYNCBUSY)) {
|
|
}
|
|
|
|
if (start) {
|
|
vdac->CMD = VDAC_CMD_SINEMODESTART;
|
|
while (0UL == (vdac->STATUS & VDAC_STATUS_SINEACTIVE)) {
|
|
}
|
|
} else {
|
|
vdac->CMD = VDAC_CMD_SINEMODESTOP;
|
|
while (0UL != (vdac->STATUS & VDAC_STATUS_SINEACTIVE)) {
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the output signal of VDAC channel 0 to a given value.
|
|
*
|
|
* @details
|
|
* This function sets the output signal of VDAC channel 0 by writing @p value
|
|
* to the CH0DATA register.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] value
|
|
* Value to write to channel 0 output register CH0DATA.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_Channel0OutputSet(VDAC_TypeDef *vdac,
|
|
uint32_t value)
|
|
{
|
|
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
|
|
EFM_ASSERT(value <= _VDAC_CH0DATA_MASK);
|
|
vdac->CH0DATA = value;
|
|
#elif defined(_SILICON_LABS_32B_SERIES_2)
|
|
EFM_ASSERT(value <= _VDAC_CH0F_MASK);
|
|
vdac->CH0F = value;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set the output signal of VDAC channel 1 to a given value.
|
|
*
|
|
* @details
|
|
* This function sets the output signal of VDAC channel 1 by writing @p value
|
|
* to the CH1DATA register.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] value
|
|
* Value to write to channel 1 output register CH1DATA.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_Channel1OutputSet(VDAC_TypeDef *vdac,
|
|
uint32_t value)
|
|
{
|
|
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
|
|
EFM_ASSERT(value <= _VDAC_CH1DATA_MASK);
|
|
vdac->CH1DATA = value;
|
|
#elif defined(_SILICON_LABS_32B_SERIES_2)
|
|
EFM_ASSERT(value <= _VDAC_CH1F_MASK);
|
|
vdac->CH1F = value;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Clear one or more pending VDAC interrupts.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* Pending VDAC interrupt source to clear. Use a bitwise logic OR combination
|
|
* of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_IntClear(VDAC_TypeDef *vdac, uint32_t flags)
|
|
{
|
|
#if defined(VDAC_HAS_SET_CLEAR)
|
|
vdac->IF_CLR = flags;
|
|
#else
|
|
vdac->IFC = flags;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Disable one or more VDAC interrupts.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* VDAC interrupt sources to disable. Use a bitwise logic OR combination of
|
|
* valid interrupt flags for the VDAC module (VDAC_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_IntDisable(VDAC_TypeDef *vdac, uint32_t flags)
|
|
{
|
|
#if defined(VDAC_HAS_SET_CLEAR)
|
|
vdac->IEN_CLR = flags;
|
|
#else
|
|
vdac->IEN &= ~flags;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Enable one or more VDAC interrupts.
|
|
*
|
|
* @note
|
|
* Depending on the use, a pending interrupt may already be set prior to
|
|
* enabling the interrupt. To ignore a pending interrupt, consider using
|
|
* VDAC_IntClear() prior to enabling the interrupt.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* VDAC interrupt sources to enable. Use a bitwise logic OR combination
|
|
* of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_IntEnable(VDAC_TypeDef *vdac, uint32_t flags)
|
|
{
|
|
#if defined(VDAC_HAS_SET_CLEAR)
|
|
vdac->IEN_SET = flags;
|
|
#else
|
|
vdac->IEN |= flags;
|
|
#endif
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get pending VDAC interrupt flags.
|
|
*
|
|
* @note
|
|
* The event bits are not cleared by the use of this function.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @return
|
|
* VDAC interrupt sources pending. Use a bitwise logic OR combination
|
|
* of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t VDAC_IntGet(VDAC_TypeDef *vdac)
|
|
{
|
|
return vdac->IF;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get enabled and pending VDAC interrupt flags.
|
|
* Useful for handling more interrupt sources in the same interrupt handler.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @note
|
|
* Interrupt flags are not cleared by the use of this function.
|
|
*
|
|
* @return
|
|
* Pending and enabled VDAC interrupt sources.
|
|
* The return value is the bitwise AND combination of
|
|
* - the OR combination of enabled interrupt sources in VDACx_IEN_nnn
|
|
* register (VDACx_IEN_nnn) and
|
|
* - the OR combination of valid interrupt flags of the VDAC module
|
|
* (VDACx_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t VDAC_IntGetEnabled(VDAC_TypeDef *vdac)
|
|
{
|
|
uint32_t ien = vdac->IEN;
|
|
|
|
/* Bitwise AND of pending and enabled interrupts */
|
|
return vdac->IF & ien;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Set one or more pending VDAC interrupts from SW.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @param[in] flags
|
|
* VDAC interrupt sources to set to pending. Use a bitwise logic OR
|
|
* combination of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
|
|
******************************************************************************/
|
|
__STATIC_INLINE void VDAC_IntSet(VDAC_TypeDef *vdac, uint32_t flags)
|
|
{
|
|
#if defined(VDAC_HAS_SET_CLEAR)
|
|
vdac->IF_SET = flags;
|
|
#else
|
|
vdac->IFS = flags;
|
|
#endif
|
|
}
|
|
|
|
#if defined(_SILICON_LABS_32B_SERIES_2)
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Get the VDAC Status register.
|
|
*
|
|
* @param[in] vdac
|
|
* Pointer to VDAC peripheral register block.
|
|
*
|
|
* @return
|
|
* Current STATUS register value.
|
|
******************************************************************************/
|
|
__STATIC_INLINE uint32_t VDAC_GetStatus(VDAC_TypeDef *vdac)
|
|
{
|
|
return vdac->STATUS;
|
|
}
|
|
#endif
|
|
|
|
#if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
|
|
uint32_t VDAC_PrescaleCalc(uint32_t vdacFreq, bool syncMode, uint32_t hfperFreq);
|
|
#else
|
|
uint32_t VDAC_PrescaleCalc(VDAC_TypeDef *vdac, uint32_t vdacFreq);
|
|
#endif
|
|
|
|
void VDAC_Reset(VDAC_TypeDef *vdac);
|
|
|
|
/** @} (end addtogroup vdac) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* defined(VDAC_COUNT) && (VDAC_COUNT > 0) */
|
|
#endif /* EM_VDAC_H */
|