| /***************************************************************************//** |
| * @file em_idac.h |
| * @brief Current Digital to Analog Converter (IDAC) peripheral API |
| * @version 5.6.0 |
| ******************************************************************************* |
| * # License |
| * <b>Copyright 2016 Silicon Laboratories, Inc. www.silabs.com</b> |
| ******************************************************************************* |
| * |
| * 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. |
| * 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. |
| * |
| * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
| * obligation to support this Software. Silicon Labs is providing the |
| * Software "AS IS", with no express or implied warranties of any kind, |
| * including, but not limited to, any implied warranties of merchantability |
| * or fitness for any particular purpose or warranties against infringement |
| * of any proprietary rights of a third party. |
| * |
| * Silicon Labs will not be liable for any consequential, incidental, or |
| * special damages, or any other relief, or for any claim by any third party, |
| * arising from your use of this Software. |
| * |
| ******************************************************************************/ |
| |
| #ifndef EM_IDAC_H |
| #define EM_IDAC_H |
| |
| #include "em_device.h" |
| |
| #if defined(IDAC_COUNT) && (IDAC_COUNT > 0) |
| #include <stdbool.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /***************************************************************************//** |
| * @addtogroup emlib |
| * @{ |
| ******************************************************************************/ |
| |
| /***************************************************************************//** |
| * @addtogroup IDAC |
| * @brief |
| * Current Digital-to-Analog Converter (IDAC) Peripheral API. |
| * |
| * @details |
| * IDAC can source or sink a configurable constant current, |
| * which can be output on, or sinked from pin or ADC. Current |
| * is configurable with several ranges of various step sizes. |
| * IDAC can be used with PRS and can operate down to EM3. |
| * |
| * The following steps are necessary for basic operation: |
| * |
| * Clock enable: |
| * @include em_idac_clock_enable.c |
| * |
| * Initialize peripheral with default settings and modify selected fields, |
| * such as output select: |
| * @if DOXYDOC_P1_DEVICE |
| * @include em_idac_init_adc.c |
| * @endif |
| * @if DOXYDOC_P2_DEVICE |
| * @include em_idac_init_aport.c |
| * @endif |
| * |
| * Set output: |
| * @include em_idac_basic_usage.c |
| * |
| * @{ |
| ******************************************************************************/ |
| |
| /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
| |
| /** Validation of IDAC register block pointer reference for assert statements. */ |
| #define IDAC_REF_VALID(ref) ((ref) == IDAC0) |
| |
| /** @endcond */ |
| |
| /******************************************************************************* |
| ******************************** ENUMS ************************************ |
| ******************************************************************************/ |
| |
| /** Output mode. */ |
| typedef enum { |
| #if defined(_IDAC_CTRL_OUTMODE_MASK) |
| idacOutputPin = IDAC_CTRL_OUTMODE_PIN, /**< Output to IDAC OUT pin. */ |
| idacOutputADC = IDAC_CTRL_OUTMODE_ADC /**< Output to ADC. */ |
| #elif ( _IDAC_CTRL_APORTOUTSEL_MASK ) |
| idacOutputAPORT1XCH0 = IDAC_CTRL_APORTOUTSEL_APORT1XCH0, /**< Output to APORT 1X CH0. */ |
| idacOutputAPORT1YCH1 = IDAC_CTRL_APORTOUTSEL_APORT1YCH1, /**< Output to APORT 1Y CH1. */ |
| idacOutputAPORT1XCH2 = IDAC_CTRL_APORTOUTSEL_APORT1XCH2, /**< Output to APORT 1X CH2. */ |
| idacOutputAPORT1YCH3 = IDAC_CTRL_APORTOUTSEL_APORT1YCH3, /**< Output to APORT 1Y CH3. */ |
| idacOutputAPORT1XCH4 = IDAC_CTRL_APORTOUTSEL_APORT1XCH4, /**< Output to APORT 1X CH4. */ |
| idacOutputAPORT1YCH5 = IDAC_CTRL_APORTOUTSEL_APORT1YCH5, /**< Output to APORT 1Y CH5. */ |
| idacOutputAPORT1XCH6 = IDAC_CTRL_APORTOUTSEL_APORT1XCH6, /**< Output to APORT 1X CH6. */ |
| idacOutputAPORT1YCH7 = IDAC_CTRL_APORTOUTSEL_APORT1YCH7, /**< Output to APORT 1Y CH7. */ |
| idacOutputAPORT1XCH8 = IDAC_CTRL_APORTOUTSEL_APORT1XCH8, /**< Output to APORT 1X CH8. */ |
| idacOutputAPORT1YCH9 = IDAC_CTRL_APORTOUTSEL_APORT1YCH9, /**< Output to APORT 1Y CH9. */ |
| idacOutputAPORT1XCH10 = IDAC_CTRL_APORTOUTSEL_APORT1XCH10, /**< Output to APORT 1X CH10. */ |
| idacOutputAPORT1YCH11 = IDAC_CTRL_APORTOUTSEL_APORT1YCH11, /**< Output to APORT 1Y CH11. */ |
| idacOutputAPORT1XCH12 = IDAC_CTRL_APORTOUTSEL_APORT1XCH12, /**< Output to APORT 1X CH12. */ |
| idacOutputAPORT1YCH13 = IDAC_CTRL_APORTOUTSEL_APORT1YCH13, /**< Output to APORT 1Y CH13. */ |
| idacOutputAPORT1XCH14 = IDAC_CTRL_APORTOUTSEL_APORT1XCH14, /**< Output to APORT 1X CH14. */ |
| idacOutputAPORT1YCH15 = IDAC_CTRL_APORTOUTSEL_APORT1YCH15, /**< Output to APORT 1Y CH15. */ |
| idacOutputAPORT1XCH16 = IDAC_CTRL_APORTOUTSEL_APORT1XCH16, /**< Output to APORT 1X CH16. */ |
| idacOutputAPORT1YCH17 = IDAC_CTRL_APORTOUTSEL_APORT1YCH17, /**< Output to APORT 1Y CH17. */ |
| idacOutputAPORT1XCH18 = IDAC_CTRL_APORTOUTSEL_APORT1XCH18, /**< Output to APORT 1X CH18. */ |
| idacOutputAPORT1YCH19 = IDAC_CTRL_APORTOUTSEL_APORT1YCH19, /**< Output to APORT 1Y CH19. */ |
| idacOutputAPORT1XCH20 = IDAC_CTRL_APORTOUTSEL_APORT1XCH20, /**< Output to APORT 1X CH20. */ |
| idacOutputAPORT1YCH21 = IDAC_CTRL_APORTOUTSEL_APORT1YCH21, /**< Output to APORT 1Y CH21. */ |
| idacOutputAPORT1XCH22 = IDAC_CTRL_APORTOUTSEL_APORT1XCH22, /**< Output to APORT 1X CH22. */ |
| idacOutputAPORT1YCH23 = IDAC_CTRL_APORTOUTSEL_APORT1YCH23, /**< Output to APORT 1Y CH23. */ |
| idacOutputAPORT1XCH24 = IDAC_CTRL_APORTOUTSEL_APORT1XCH24, /**< Output to APORT 1X CH24. */ |
| idacOutputAPORT1YCH25 = IDAC_CTRL_APORTOUTSEL_APORT1YCH25, /**< Output to APORT 1Y CH25. */ |
| idacOutputAPORT1XCH26 = IDAC_CTRL_APORTOUTSEL_APORT1XCH26, /**< Output to APORT 1X CH26. */ |
| idacOutputAPORT1YCH27 = IDAC_CTRL_APORTOUTSEL_APORT1YCH27, /**< Output to APORT 1Y CH27. */ |
| idacOutputAPORT1XCH28 = IDAC_CTRL_APORTOUTSEL_APORT1XCH28, /**< Output to APORT 1X CH28. */ |
| idacOutputAPORT1YCH29 = IDAC_CTRL_APORTOUTSEL_APORT1YCH29, /**< Output to APORT 1Y CH29. */ |
| idacOutputAPORT1XCH30 = IDAC_CTRL_APORTOUTSEL_APORT1XCH30, /**< Output to APORT 1X CH30. */ |
| idacOutputAPORT1YCH31 = IDAC_CTRL_APORTOUTSEL_APORT1YCH31, /**< Output to APORT 1Y CH31. */ |
| #endif |
| } IDAC_OutMode_TypeDef; |
| |
| /** Selects which Peripheral Reflex System (PRS) signal to use when |
| PRS is set to control IDAC output. */ |
| typedef enum { |
| idacPRSSELCh0 = IDAC_CTRL_PRSSEL_PRSCH0, /**< PRS channel 0. */ |
| idacPRSSELCh1 = IDAC_CTRL_PRSSEL_PRSCH1, /**< PRS channel 1. */ |
| idacPRSSELCh2 = IDAC_CTRL_PRSSEL_PRSCH2, /**< PRS channel 2. */ |
| idacPRSSELCh3 = IDAC_CTRL_PRSSEL_PRSCH3, /**< PRS channel 3. */ |
| #if defined(IDAC_CTRL_PRSSEL_PRSCH4) |
| idacPRSSELCh4 = IDAC_CTRL_PRSSEL_PRSCH4, /**< PRS channel 4. */ |
| idacPRSSELCh5 = IDAC_CTRL_PRSSEL_PRSCH5, /**< PRS channel 5. */ |
| #endif |
| #if defined(IDAC_CTRL_PRSSEL_PRSCH6) |
| idacPRSSELCh6 = IDAC_CTRL_PRSSEL_PRSCH6, /**< PRS channel 6. */ |
| idacPRSSELCh7 = IDAC_CTRL_PRSSEL_PRSCH7, /**< PRS channel 7. */ |
| idacPRSSELCh8 = IDAC_CTRL_PRSSEL_PRSCH8, /**< PRS channel 8. */ |
| idacPRSSELCh9 = IDAC_CTRL_PRSSEL_PRSCH9, /**< PRS channel 9. */ |
| idacPRSSELCh10 = IDAC_CTRL_PRSSEL_PRSCH10, /**< PRS channel 10 */ |
| idacPRSSELCh11 = IDAC_CTRL_PRSSEL_PRSCH11, /**< PRS channel 11 */ |
| #endif |
| } IDAC_PRSSEL_TypeDef; |
| |
| /** Selects which current range to use. */ |
| typedef enum { |
| idacCurrentRange0 = IDAC_CURPROG_RANGESEL_RANGE0, /**< current range 0. */ |
| idacCurrentRange1 = IDAC_CURPROG_RANGESEL_RANGE1, /**< current range 1. */ |
| idacCurrentRange2 = IDAC_CURPROG_RANGESEL_RANGE2, /**< current range 2. */ |
| idacCurrentRange3 = IDAC_CURPROG_RANGESEL_RANGE3, /**< current range 3. */ |
| } IDAC_Range_TypeDef; |
| |
| /******************************************************************************* |
| ******************************* STRUCTS *********************************** |
| ******************************************************************************/ |
| |
| /** IDAC initialization structure, common for both channels. */ |
| typedef struct { |
| /** Enable IDAC. */ |
| bool enable; |
| |
| /** Output mode */ |
| IDAC_OutMode_TypeDef outMode; |
| |
| /** |
| * Enables Peripheral reflex system (PRS) to control IDAC output. If false, |
| * IDAC output is controlled by writing to IDAC_OUTEN in IDAC_CTRL or |
| * by calling IDAC_OutEnable(). |
| */ |
| bool prsEnable; |
| |
| /** |
| * Peripheral reflex system channel selection. Only applicable if @p prsEnable |
| * is enabled. |
| */ |
| IDAC_PRSSEL_TypeDef prsSel; |
| |
| /** Enable/disable current sink mode. */ |
| bool sinkEnable; |
| } IDAC_Init_TypeDef; |
| |
| /** Default configuration for IDAC initialization structure. */ |
| #if defined(_IDAC_CTRL_OUTMODE_MASK) |
| #define IDAC_INIT_DEFAULT \ |
| { \ |
| false, /**< Leave IDAC disabled when initialization done. */ \ |
| idacOutputPin, /**< Output to IDAC output pin. */ \ |
| false, /**< Disable PRS triggering. */ \ |
| idacPRSSELCh0, /**< Select PRS ch0 (if PRS triggering enabled). */ \ |
| false /**< Disable current sink mode. */ \ |
| } |
| #elif (_IDAC_CTRL_APORTOUTSEL_MASK) |
| #define IDAC_INIT_DEFAULT \ |
| { \ |
| false, /**< Leave IDAC disabled when initialization done. */ \ |
| idacOutputAPORT1XCH0, /**< Output to APORT. */ \ |
| false, /**< Disable PRS triggering. */ \ |
| idacPRSSELCh0, /**< Select PRS ch0 (if PRS triggering enabled). */ \ |
| false /**< Disable current sink mode. */ \ |
| } |
| #endif |
| |
| /******************************************************************************* |
| ***************************** PROTOTYPES ********************************** |
| ******************************************************************************/ |
| |
| void IDAC_Init(IDAC_TypeDef *idac, const IDAC_Init_TypeDef *init); |
| void IDAC_Enable(IDAC_TypeDef *idac, bool enable); |
| void IDAC_Reset(IDAC_TypeDef *idac); |
| void IDAC_MinimalOutputTransitionMode(IDAC_TypeDef *idac, bool enable); |
| void IDAC_RangeSet(IDAC_TypeDef *idac, const IDAC_Range_TypeDef range); |
| void IDAC_StepSet(IDAC_TypeDef *idac, const uint32_t step); |
| void IDAC_OutEnable(IDAC_TypeDef *idac, bool enable); |
| |
| #if defined(_IDAC_IEN_MASK) |
| /***************************************************************************//** |
| * @brief |
| * Clear one or more pending IDAC interrupts. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @param[in] flags |
| * Pending IDAC interrupt source(s) to clear. Use one or more valid |
| * interrupt flags for the IDAC module (IDAC_IF_nnn) OR'ed together. |
| ******************************************************************************/ |
| __STATIC_INLINE void IDAC_IntClear(IDAC_TypeDef *idac, uint32_t flags) |
| { |
| idac->IFC = flags; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Disable one or more IDAC interrupts. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @param[in] flags |
| * IDAC interrupt source(s) to disable. Use one or more valid |
| * interrupt flags for the IDAC module (IDAC_IF_nnn) OR'ed together. |
| ******************************************************************************/ |
| __STATIC_INLINE void IDAC_IntDisable(IDAC_TypeDef *idac, uint32_t flags) |
| { |
| idac->IEN &= ~flags; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Enable one or more IDAC 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 |
| * IDAC_IntClear() prior to enabling the interrupt. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @param[in] flags |
| * IDAC interrupt source(s) to enable. Use one or more valid |
| * interrupt flags for IDAC module (IDAC_IF_nnn) OR'ed together. |
| ******************************************************************************/ |
| __STATIC_INLINE void IDAC_IntEnable(IDAC_TypeDef *idac, uint32_t flags) |
| { |
| idac->IEN |= flags; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get pending IDAC interrupt flags. |
| * |
| * @note |
| * Event bits are not cleared by the use of this function. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @return |
| * IDAC interrupt source(s) pending. Returns one or more valid |
| * interrupt flags for IDAC module (IDAC_IF_nnn) OR'ed together. |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t IDAC_IntGet(IDAC_TypeDef *idac) |
| { |
| return idac->IF; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Get enabled and pending IDAC interrupt flags. |
| * Useful for handling more interrupt sources in the same interrupt handler. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @note |
| * Interrupt flags are not cleared by the use of this function. |
| * |
| * @return |
| * Pending and enabled IDAC interrupt sources. |
| * Return value is the bitwise AND combination of |
| * - the OR combination of enabled interrupt sources in IDACx_IEN_nnn |
| * register (IDACx_IEN_nnn) and |
| * - the OR combination of valid interrupt flags of IDAC module |
| * (IDACx_IF_nnn). |
| ******************************************************************************/ |
| __STATIC_INLINE uint32_t IDAC_IntGetEnabled(IDAC_TypeDef *idac) |
| { |
| uint32_t ien; |
| |
| /* Stores flags in temporary variable in order to define explicit order |
| * of volatile accesses. */ |
| ien = idac->IEN; |
| |
| /* Bitwise AND of pending and enabled interrupts. */ |
| return idac->IF & ien; |
| } |
| |
| /***************************************************************************//** |
| * @brief |
| * Set one or more pending IDAC interrupts from SW. |
| * |
| * @param[in] idac |
| * Pointer to IDAC peripheral register block. |
| * |
| * @param[in] flags |
| * IDAC interrupt source(s) to set to pending. Use one or more valid |
| * interrupt flags for IDAC module (IDAC_IF_nnn) OR'ed together. |
| ******************************************************************************/ |
| __STATIC_INLINE void IDAC_IntSet(IDAC_TypeDef *idac, uint32_t flags) |
| { |
| idac->IFS = flags; |
| } |
| #endif |
| |
| /** @} (end addtogroup IDAC) */ |
| /** @} (end addtogroup emlib) */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* defined(IDAC_COUNT) && (IDAC_COUNT > 0) */ |
| |
| #endif /* EM_IDAC_H */ |