added prescaler for 16 bit pwm in LPC1347 target
Fork of mbed-dev by
targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_pcnt.c@144:ef7eb2e8f9f7, 2016-09-02 (annotated)
- Committer:
- <>
- Date:
- Fri Sep 02 15:07:44 2016 +0100
- Revision:
- 144:ef7eb2e8f9f7
- Parent:
- 50:a417edff4437
This updates the lib to the mbed lib v125
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 144:ef7eb2e8f9f7 | 1 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 2 | * @file em_pcnt.c |
<> | 144:ef7eb2e8f9f7 | 3 | * @brief Pulse Counter (PCNT) peripheral API |
<> | 144:ef7eb2e8f9f7 | 4 | * @version 4.2.1 |
<> | 144:ef7eb2e8f9f7 | 5 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 6 | * @section License |
<> | 144:ef7eb2e8f9f7 | 7 | * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> |
<> | 144:ef7eb2e8f9f7 | 8 | ******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 9 | * |
<> | 144:ef7eb2e8f9f7 | 10 | * Permission is granted to anyone to use this software for any purpose, |
<> | 144:ef7eb2e8f9f7 | 11 | * including commercial applications, and to alter it and redistribute it |
<> | 144:ef7eb2e8f9f7 | 12 | * freely, subject to the following restrictions: |
<> | 144:ef7eb2e8f9f7 | 13 | * |
<> | 144:ef7eb2e8f9f7 | 14 | * 1. The origin of this software must not be misrepresented; you must not |
<> | 144:ef7eb2e8f9f7 | 15 | * claim that you wrote the original software. |
<> | 144:ef7eb2e8f9f7 | 16 | * 2. Altered source versions must be plainly marked as such, and must not be |
<> | 144:ef7eb2e8f9f7 | 17 | * misrepresented as being the original software. |
<> | 144:ef7eb2e8f9f7 | 18 | * 3. This notice may not be removed or altered from any source distribution. |
<> | 144:ef7eb2e8f9f7 | 19 | * |
<> | 144:ef7eb2e8f9f7 | 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no |
<> | 144:ef7eb2e8f9f7 | 21 | * obligation to support this Software. Silicon Labs is providing the |
<> | 144:ef7eb2e8f9f7 | 22 | * Software "AS IS", with no express or implied warranties of any kind, |
<> | 144:ef7eb2e8f9f7 | 23 | * including, but not limited to, any implied warranties of merchantability |
<> | 144:ef7eb2e8f9f7 | 24 | * or fitness for any particular purpose or warranties against infringement |
<> | 144:ef7eb2e8f9f7 | 25 | * of any proprietary rights of a third party. |
<> | 144:ef7eb2e8f9f7 | 26 | * |
<> | 144:ef7eb2e8f9f7 | 27 | * Silicon Labs will not be liable for any consequential, incidental, or |
<> | 144:ef7eb2e8f9f7 | 28 | * special damages, or any other relief, or for any claim by any third party, |
<> | 144:ef7eb2e8f9f7 | 29 | * arising from your use of this Software. |
<> | 144:ef7eb2e8f9f7 | 30 | * |
<> | 144:ef7eb2e8f9f7 | 31 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 32 | |
<> | 144:ef7eb2e8f9f7 | 33 | #include "em_pcnt.h" |
<> | 144:ef7eb2e8f9f7 | 34 | #if defined(PCNT_COUNT) && (PCNT_COUNT > 0) |
<> | 144:ef7eb2e8f9f7 | 35 | |
<> | 144:ef7eb2e8f9f7 | 36 | #include "em_cmu.h" |
<> | 144:ef7eb2e8f9f7 | 37 | #include "em_assert.h" |
<> | 144:ef7eb2e8f9f7 | 38 | #include "em_bus.h" |
<> | 144:ef7eb2e8f9f7 | 39 | |
<> | 144:ef7eb2e8f9f7 | 40 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 41 | * @addtogroup EM_Library |
<> | 144:ef7eb2e8f9f7 | 42 | * @{ |
<> | 144:ef7eb2e8f9f7 | 43 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 44 | |
<> | 144:ef7eb2e8f9f7 | 45 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 46 | * @addtogroup PCNT |
<> | 144:ef7eb2e8f9f7 | 47 | * @brief Pulse Counter (PCNT) Peripheral API |
<> | 144:ef7eb2e8f9f7 | 48 | * @{ |
<> | 144:ef7eb2e8f9f7 | 49 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 50 | |
<> | 144:ef7eb2e8f9f7 | 51 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 52 | ******************************* DEFINES *********************************** |
<> | 144:ef7eb2e8f9f7 | 53 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 54 | |
<> | 144:ef7eb2e8f9f7 | 55 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
<> | 144:ef7eb2e8f9f7 | 56 | |
<> | 144:ef7eb2e8f9f7 | 57 | |
<> | 144:ef7eb2e8f9f7 | 58 | /** Validation of PCNT register block pointer reference for assert statements. */ |
<> | 144:ef7eb2e8f9f7 | 59 | #if (PCNT_COUNT == 1) |
<> | 144:ef7eb2e8f9f7 | 60 | #define PCNT_REF_VALID(ref) ((ref) == PCNT0) |
<> | 144:ef7eb2e8f9f7 | 61 | #elif (PCNT_COUNT == 2) |
<> | 144:ef7eb2e8f9f7 | 62 | #define PCNT_REF_VALID(ref) (((ref) == PCNT0) || ((ref) == PCNT1)) |
<> | 144:ef7eb2e8f9f7 | 63 | #elif (PCNT_COUNT == 3) |
<> | 144:ef7eb2e8f9f7 | 64 | #define PCNT_REF_VALID(ref) (((ref) == PCNT0) || ((ref) == PCNT1) || \ |
<> | 144:ef7eb2e8f9f7 | 65 | ((ref) == PCNT2)) |
<> | 144:ef7eb2e8f9f7 | 66 | #else |
<> | 144:ef7eb2e8f9f7 | 67 | #error "Undefined number of pulse counters (PCNT)." |
<> | 144:ef7eb2e8f9f7 | 68 | #endif |
<> | 144:ef7eb2e8f9f7 | 69 | |
<> | 144:ef7eb2e8f9f7 | 70 | /** @endcond */ |
<> | 144:ef7eb2e8f9f7 | 71 | |
<> | 144:ef7eb2e8f9f7 | 72 | |
<> | 144:ef7eb2e8f9f7 | 73 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 74 | ************************** LOCAL FUNCTIONS ******************************** |
<> | 144:ef7eb2e8f9f7 | 75 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 76 | |
<> | 144:ef7eb2e8f9f7 | 77 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ |
<> | 144:ef7eb2e8f9f7 | 78 | |
<> | 144:ef7eb2e8f9f7 | 79 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 80 | * @brief |
<> | 144:ef7eb2e8f9f7 | 81 | * Map PCNT structure into instance number. |
<> | 144:ef7eb2e8f9f7 | 82 | * |
<> | 144:ef7eb2e8f9f7 | 83 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 84 | * Pointer to PCNT peripheral register block |
<> | 144:ef7eb2e8f9f7 | 85 | * |
<> | 144:ef7eb2e8f9f7 | 86 | * @return |
<> | 144:ef7eb2e8f9f7 | 87 | * Instance number. |
<> | 144:ef7eb2e8f9f7 | 88 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 89 | __STATIC_INLINE unsigned int PCNT_Map(PCNT_TypeDef *pcnt) |
<> | 144:ef7eb2e8f9f7 | 90 | { |
<> | 144:ef7eb2e8f9f7 | 91 | return ((uint32_t)pcnt - PCNT0_BASE) / 0x400; |
<> | 144:ef7eb2e8f9f7 | 92 | } |
<> | 144:ef7eb2e8f9f7 | 93 | |
<> | 144:ef7eb2e8f9f7 | 94 | |
<> | 144:ef7eb2e8f9f7 | 95 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 96 | * @brief |
<> | 144:ef7eb2e8f9f7 | 97 | * Wait for ongoing sync of register(s) to low frequency domain to complete. |
<> | 144:ef7eb2e8f9f7 | 98 | * |
<> | 144:ef7eb2e8f9f7 | 99 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 100 | * Pointer to PCNT peripheral register block |
<> | 144:ef7eb2e8f9f7 | 101 | * |
<> | 144:ef7eb2e8f9f7 | 102 | * @param[in] mask |
<> | 144:ef7eb2e8f9f7 | 103 | * Bitmask corresponding to SYNCBUSY register defined bits, indicating |
<> | 144:ef7eb2e8f9f7 | 104 | * registers that must complete any ongoing synchronization. |
<> | 144:ef7eb2e8f9f7 | 105 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 106 | __STATIC_INLINE void PCNT_Sync(PCNT_TypeDef *pcnt, uint32_t mask) |
<> | 144:ef7eb2e8f9f7 | 107 | { |
<> | 144:ef7eb2e8f9f7 | 108 | /* Avoid deadlock if modifying the same register twice when freeze mode is |
<> | 144:ef7eb2e8f9f7 | 109 | * activated. */ |
<> | 144:ef7eb2e8f9f7 | 110 | if (pcnt->FREEZE & PCNT_FREEZE_REGFREEZE) |
<> | 144:ef7eb2e8f9f7 | 111 | { |
<> | 144:ef7eb2e8f9f7 | 112 | return; |
<> | 144:ef7eb2e8f9f7 | 113 | } |
<> | 144:ef7eb2e8f9f7 | 114 | |
<> | 144:ef7eb2e8f9f7 | 115 | /* Wait for any pending previous write operation to have been completed in low |
<> | 144:ef7eb2e8f9f7 | 116 | * frequency domain. */ |
<> | 144:ef7eb2e8f9f7 | 117 | while (pcnt->SYNCBUSY & mask) |
<> | 144:ef7eb2e8f9f7 | 118 | ; |
<> | 144:ef7eb2e8f9f7 | 119 | } |
<> | 144:ef7eb2e8f9f7 | 120 | |
<> | 144:ef7eb2e8f9f7 | 121 | /** @endcond */ |
<> | 144:ef7eb2e8f9f7 | 122 | |
<> | 144:ef7eb2e8f9f7 | 123 | /******************************************************************************* |
<> | 144:ef7eb2e8f9f7 | 124 | ************************** GLOBAL FUNCTIONS ******************************* |
<> | 144:ef7eb2e8f9f7 | 125 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 126 | |
<> | 144:ef7eb2e8f9f7 | 127 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 128 | * @brief |
<> | 144:ef7eb2e8f9f7 | 129 | * Reset PCNT counters and TOP register. |
<> | 144:ef7eb2e8f9f7 | 130 | * |
<> | 144:ef7eb2e8f9f7 | 131 | * @note |
<> | 144:ef7eb2e8f9f7 | 132 | * Notice that special SYNCBUSY handling is not applicable for the RSTEN |
<> | 144:ef7eb2e8f9f7 | 133 | * bit of the control register, so we don't need to wait for it when only |
<> | 144:ef7eb2e8f9f7 | 134 | * modifying RSTEN. (It would mean undefined wait time if clocked by external |
<> | 144:ef7eb2e8f9f7 | 135 | * clock.) The SYNCBUSY bit will however be set, leading to a synchronization |
<> | 144:ef7eb2e8f9f7 | 136 | * in the LF domain, with in reality no changes. |
<> | 144:ef7eb2e8f9f7 | 137 | * |
<> | 144:ef7eb2e8f9f7 | 138 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 139 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 140 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 141 | void PCNT_CounterReset(PCNT_TypeDef *pcnt) |
<> | 144:ef7eb2e8f9f7 | 142 | { |
<> | 144:ef7eb2e8f9f7 | 143 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 144 | |
<> | 144:ef7eb2e8f9f7 | 145 | /* Enable reset of CNT and TOP register */ |
<> | 144:ef7eb2e8f9f7 | 146 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1); |
<> | 144:ef7eb2e8f9f7 | 147 | |
<> | 144:ef7eb2e8f9f7 | 148 | /* Disable reset of CNT and TOP register */ |
<> | 144:ef7eb2e8f9f7 | 149 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0); |
<> | 144:ef7eb2e8f9f7 | 150 | } |
<> | 144:ef7eb2e8f9f7 | 151 | |
<> | 144:ef7eb2e8f9f7 | 152 | |
<> | 144:ef7eb2e8f9f7 | 153 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 154 | * @brief |
<> | 144:ef7eb2e8f9f7 | 155 | * Set counter and top values. |
<> | 144:ef7eb2e8f9f7 | 156 | * |
<> | 144:ef7eb2e8f9f7 | 157 | * @details |
<> | 144:ef7eb2e8f9f7 | 158 | * The pulse counter is disabled while changing these values, and reenabled |
<> | 144:ef7eb2e8f9f7 | 159 | * (if originally enabled) when values have been set. |
<> | 144:ef7eb2e8f9f7 | 160 | * |
<> | 144:ef7eb2e8f9f7 | 161 | * @note |
<> | 144:ef7eb2e8f9f7 | 162 | * This function will stall until synchronization to low frequency domain is |
<> | 144:ef7eb2e8f9f7 | 163 | * completed. For that reason, it should normally not be used when using |
<> | 144:ef7eb2e8f9f7 | 164 | * an external clock to clock the PCNT module, since stall time may be |
<> | 144:ef7eb2e8f9f7 | 165 | * undefined in that case. The counter should normally only be set when |
<> | 144:ef7eb2e8f9f7 | 166 | * operating in (or about to enable) #pcntModeOvsSingle mode. |
<> | 144:ef7eb2e8f9f7 | 167 | * |
<> | 144:ef7eb2e8f9f7 | 168 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 169 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 170 | * |
<> | 144:ef7eb2e8f9f7 | 171 | * @param[in] count |
<> | 144:ef7eb2e8f9f7 | 172 | * Value to set in counter register. |
<> | 144:ef7eb2e8f9f7 | 173 | * |
<> | 144:ef7eb2e8f9f7 | 174 | * @param[in] top |
<> | 144:ef7eb2e8f9f7 | 175 | * Value to set in top register. |
<> | 144:ef7eb2e8f9f7 | 176 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 177 | void PCNT_CounterTopSet(PCNT_TypeDef *pcnt, uint32_t count, uint32_t top) |
<> | 144:ef7eb2e8f9f7 | 178 | { |
<> | 144:ef7eb2e8f9f7 | 179 | uint32_t ctrl; |
<> | 144:ef7eb2e8f9f7 | 180 | |
<> | 144:ef7eb2e8f9f7 | 181 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 182 | |
<> | 144:ef7eb2e8f9f7 | 183 | #ifdef PCNT0 |
<> | 144:ef7eb2e8f9f7 | 184 | if (PCNT0 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 185 | { |
<> | 144:ef7eb2e8f9f7 | 186 | EFM_ASSERT((1<<PCNT0_CNT_SIZE) > count); |
<> | 144:ef7eb2e8f9f7 | 187 | EFM_ASSERT((1<<PCNT0_CNT_SIZE) > top); |
<> | 144:ef7eb2e8f9f7 | 188 | } |
<> | 144:ef7eb2e8f9f7 | 189 | #endif |
<> | 144:ef7eb2e8f9f7 | 190 | |
<> | 144:ef7eb2e8f9f7 | 191 | #ifdef PCNT1 |
<> | 144:ef7eb2e8f9f7 | 192 | if (PCNT1 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 193 | { |
<> | 144:ef7eb2e8f9f7 | 194 | EFM_ASSERT((1<<PCNT1_CNT_SIZE) > count); |
<> | 144:ef7eb2e8f9f7 | 195 | EFM_ASSERT((1<<PCNT1_CNT_SIZE) > top); |
<> | 144:ef7eb2e8f9f7 | 196 | } |
<> | 144:ef7eb2e8f9f7 | 197 | #endif |
<> | 144:ef7eb2e8f9f7 | 198 | |
<> | 144:ef7eb2e8f9f7 | 199 | #ifdef PCNT2 |
<> | 144:ef7eb2e8f9f7 | 200 | if (PCNT2 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 201 | { |
<> | 144:ef7eb2e8f9f7 | 202 | EFM_ASSERT((1<<PCNT2_CNT_SIZE) > count); |
<> | 144:ef7eb2e8f9f7 | 203 | EFM_ASSERT((1<<PCNT2_CNT_SIZE) > top); |
<> | 144:ef7eb2e8f9f7 | 204 | } |
<> | 144:ef7eb2e8f9f7 | 205 | #endif |
<> | 144:ef7eb2e8f9f7 | 206 | |
<> | 144:ef7eb2e8f9f7 | 207 | /* Keep current control setting, must be restored */ |
<> | 144:ef7eb2e8f9f7 | 208 | ctrl = pcnt->CTRL; |
<> | 144:ef7eb2e8f9f7 | 209 | |
<> | 144:ef7eb2e8f9f7 | 210 | /* If enabled, disable pulse counter before changing values */ |
<> | 144:ef7eb2e8f9f7 | 211 | if ((ctrl & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE) |
<> | 144:ef7eb2e8f9f7 | 212 | { |
<> | 144:ef7eb2e8f9f7 | 213 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 214 | pcnt->CTRL = (ctrl & ~_PCNT_CTRL_MODE_MASK) | PCNT_CTRL_MODE_DISABLE; |
<> | 144:ef7eb2e8f9f7 | 215 | } |
<> | 144:ef7eb2e8f9f7 | 216 | |
<> | 144:ef7eb2e8f9f7 | 217 | /* Load into TOPB */ |
<> | 144:ef7eb2e8f9f7 | 218 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB); |
<> | 144:ef7eb2e8f9f7 | 219 | pcnt->TOPB = count; |
<> | 144:ef7eb2e8f9f7 | 220 | |
<> | 144:ef7eb2e8f9f7 | 221 | /* Load TOPB value into TOP */ |
<> | 144:ef7eb2e8f9f7 | 222 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 223 | |
<> | 144:ef7eb2e8f9f7 | 224 | /* This bit has no effect on rev. C and onwards parts - for compatibility */ |
<> | 144:ef7eb2e8f9f7 | 225 | pcnt->CMD = PCNT_CMD_LTOPBIM; |
<> | 144:ef7eb2e8f9f7 | 226 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 227 | |
<> | 144:ef7eb2e8f9f7 | 228 | /* Load TOP into CNT */ |
<> | 144:ef7eb2e8f9f7 | 229 | pcnt->CMD = PCNT_CMD_LCNTIM; |
<> | 144:ef7eb2e8f9f7 | 230 | |
<> | 144:ef7eb2e8f9f7 | 231 | /* Restore TOP? ('count' setting has been loaded into pcnt->TOP, better |
<> | 144:ef7eb2e8f9f7 | 232 | * to use 'top' than pcnt->TOP in compare, since latter may in theory not |
<> | 144:ef7eb2e8f9f7 | 233 | * be visible yet.) */ |
<> | 144:ef7eb2e8f9f7 | 234 | if (top != count) |
<> | 144:ef7eb2e8f9f7 | 235 | { |
<> | 144:ef7eb2e8f9f7 | 236 | /* Wait for command to sync LCNTIM before setting TOPB */ |
<> | 144:ef7eb2e8f9f7 | 237 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 238 | |
<> | 144:ef7eb2e8f9f7 | 239 | /* Load into TOPB, we don't need to check for TOPB sync complete here, |
<> | 144:ef7eb2e8f9f7 | 240 | * it has been ensured above. */ |
<> | 144:ef7eb2e8f9f7 | 241 | pcnt->TOPB = top; |
<> | 144:ef7eb2e8f9f7 | 242 | |
<> | 144:ef7eb2e8f9f7 | 243 | /* Load TOPB value into TOP */ |
<> | 144:ef7eb2e8f9f7 | 244 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 245 | pcnt->CMD = PCNT_CMD_LTOPBIM; |
<> | 144:ef7eb2e8f9f7 | 246 | } |
<> | 144:ef7eb2e8f9f7 | 247 | |
<> | 144:ef7eb2e8f9f7 | 248 | /* Reenable if it was enabled */ |
<> | 144:ef7eb2e8f9f7 | 249 | if ((ctrl & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE) |
<> | 144:ef7eb2e8f9f7 | 250 | { |
<> | 144:ef7eb2e8f9f7 | 251 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL | PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 252 | pcnt->CTRL = ctrl; |
<> | 144:ef7eb2e8f9f7 | 253 | } |
<> | 144:ef7eb2e8f9f7 | 254 | } |
<> | 144:ef7eb2e8f9f7 | 255 | |
<> | 144:ef7eb2e8f9f7 | 256 | |
<> | 144:ef7eb2e8f9f7 | 257 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 258 | * @brief |
<> | 144:ef7eb2e8f9f7 | 259 | * Set PCNT operational mode. |
<> | 144:ef7eb2e8f9f7 | 260 | * |
<> | 144:ef7eb2e8f9f7 | 261 | * @details |
<> | 144:ef7eb2e8f9f7 | 262 | * Notice that this function does not do any configuration. Setting operational |
<> | 144:ef7eb2e8f9f7 | 263 | * mode is normally only required after initialization is done, and if not |
<> | 144:ef7eb2e8f9f7 | 264 | * done as part of initialization. Or if requiring to disable/reenable pulse |
<> | 144:ef7eb2e8f9f7 | 265 | * counter. |
<> | 144:ef7eb2e8f9f7 | 266 | * |
<> | 144:ef7eb2e8f9f7 | 267 | * @note |
<> | 144:ef7eb2e8f9f7 | 268 | * This function may stall until synchronization to low frequency domain is |
<> | 144:ef7eb2e8f9f7 | 269 | * completed. For that reason, it should normally not be used when using |
<> | 144:ef7eb2e8f9f7 | 270 | * an external clock to clock the PCNT module, since stall time may be |
<> | 144:ef7eb2e8f9f7 | 271 | * undefined in that case. |
<> | 144:ef7eb2e8f9f7 | 272 | * |
<> | 144:ef7eb2e8f9f7 | 273 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 274 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 275 | * |
<> | 144:ef7eb2e8f9f7 | 276 | * @param[in] mode |
<> | 144:ef7eb2e8f9f7 | 277 | * Operational mode to use for PCNT. |
<> | 144:ef7eb2e8f9f7 | 278 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 279 | void PCNT_Enable(PCNT_TypeDef *pcnt, PCNT_Mode_TypeDef mode) |
<> | 144:ef7eb2e8f9f7 | 280 | { |
<> | 144:ef7eb2e8f9f7 | 281 | uint32_t tmp; |
<> | 144:ef7eb2e8f9f7 | 282 | |
<> | 144:ef7eb2e8f9f7 | 283 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 284 | |
<> | 144:ef7eb2e8f9f7 | 285 | /* Set as specified */ |
<> | 144:ef7eb2e8f9f7 | 286 | tmp = pcnt->CTRL & ~_PCNT_CTRL_MODE_MASK; |
<> | 144:ef7eb2e8f9f7 | 287 | tmp |= (uint32_t)mode << _PCNT_CTRL_MODE_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 288 | |
<> | 144:ef7eb2e8f9f7 | 289 | /* LF register about to be modified require sync. busy check */ |
<> | 144:ef7eb2e8f9f7 | 290 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 291 | pcnt->CTRL = tmp; |
<> | 144:ef7eb2e8f9f7 | 292 | } |
<> | 144:ef7eb2e8f9f7 | 293 | |
<> | 144:ef7eb2e8f9f7 | 294 | #if defined(_PCNT_INPUT_MASK) |
<> | 144:ef7eb2e8f9f7 | 295 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 296 | * @brief |
<> | 144:ef7eb2e8f9f7 | 297 | * Enable/disable the selected PRS input of PCNT. |
<> | 144:ef7eb2e8f9f7 | 298 | * |
<> | 144:ef7eb2e8f9f7 | 299 | * @details |
<> | 144:ef7eb2e8f9f7 | 300 | * Notice that this function does not do any configuration. |
<> | 144:ef7eb2e8f9f7 | 301 | * |
<> | 144:ef7eb2e8f9f7 | 302 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 303 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 304 | * |
<> | 144:ef7eb2e8f9f7 | 305 | * @param[in] prsInput |
<> | 144:ef7eb2e8f9f7 | 306 | * PRS input (S0 or S1) of the selected PCNT module. |
<> | 144:ef7eb2e8f9f7 | 307 | * |
<> | 144:ef7eb2e8f9f7 | 308 | * @param[in] enable |
<> | 144:ef7eb2e8f9f7 | 309 | * Set to true to enable, false to disable the selected PRS input. |
<> | 144:ef7eb2e8f9f7 | 310 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 311 | void PCNT_PRSInputEnable(PCNT_TypeDef *pcnt, |
<> | 144:ef7eb2e8f9f7 | 312 | PCNT_PRSInput_TypeDef prsInput, |
<> | 144:ef7eb2e8f9f7 | 313 | bool enable) |
<> | 144:ef7eb2e8f9f7 | 314 | { |
<> | 144:ef7eb2e8f9f7 | 315 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 316 | |
<> | 144:ef7eb2e8f9f7 | 317 | /* Enable/disable the selected PRS input on the selected PCNT module. */ |
<> | 144:ef7eb2e8f9f7 | 318 | switch (prsInput) |
<> | 144:ef7eb2e8f9f7 | 319 | { |
<> | 144:ef7eb2e8f9f7 | 320 | /* Enable/disable PRS input S0. */ |
<> | 144:ef7eb2e8f9f7 | 321 | case pcntPRSInputS0: |
<> | 144:ef7eb2e8f9f7 | 322 | BUS_RegBitWrite(&(pcnt->INPUT), _PCNT_INPUT_S0PRSEN_SHIFT, enable); |
<> | 144:ef7eb2e8f9f7 | 323 | break; |
<> | 144:ef7eb2e8f9f7 | 324 | |
<> | 144:ef7eb2e8f9f7 | 325 | /* Enable/disable PRS input S1. */ |
<> | 144:ef7eb2e8f9f7 | 326 | case pcntPRSInputS1: |
<> | 144:ef7eb2e8f9f7 | 327 | BUS_RegBitWrite(&(pcnt->INPUT), _PCNT_INPUT_S1PRSEN_SHIFT, enable); |
<> | 144:ef7eb2e8f9f7 | 328 | break; |
<> | 144:ef7eb2e8f9f7 | 329 | |
<> | 144:ef7eb2e8f9f7 | 330 | /* Invalid parameter, asserted. */ |
<> | 144:ef7eb2e8f9f7 | 331 | default: |
<> | 144:ef7eb2e8f9f7 | 332 | EFM_ASSERT(0); |
<> | 144:ef7eb2e8f9f7 | 333 | break; |
<> | 144:ef7eb2e8f9f7 | 334 | } |
<> | 144:ef7eb2e8f9f7 | 335 | } |
<> | 144:ef7eb2e8f9f7 | 336 | #endif |
<> | 144:ef7eb2e8f9f7 | 337 | |
<> | 144:ef7eb2e8f9f7 | 338 | |
<> | 144:ef7eb2e8f9f7 | 339 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 340 | * @brief |
<> | 144:ef7eb2e8f9f7 | 341 | * PCNT register synchronization freeze control. |
<> | 144:ef7eb2e8f9f7 | 342 | * |
<> | 144:ef7eb2e8f9f7 | 343 | * @details |
<> | 144:ef7eb2e8f9f7 | 344 | * Some PCNT registers require synchronization into the low frequency (LF) |
<> | 144:ef7eb2e8f9f7 | 345 | * domain. The freeze feature allows for several such registers to be |
<> | 144:ef7eb2e8f9f7 | 346 | * modified before passing them to the LF domain simultaneously (which |
<> | 144:ef7eb2e8f9f7 | 347 | * takes place when the freeze mode is disabled). |
<> | 144:ef7eb2e8f9f7 | 348 | * |
<> | 144:ef7eb2e8f9f7 | 349 | * @note |
<> | 144:ef7eb2e8f9f7 | 350 | * When enabling freeze mode, this function will wait for all current |
<> | 144:ef7eb2e8f9f7 | 351 | * ongoing PCNT synchronization to LF domain to complete (Normally |
<> | 144:ef7eb2e8f9f7 | 352 | * synchronization will not be in progress.) However for this reason, when |
<> | 144:ef7eb2e8f9f7 | 353 | * using freeze mode, modifications of registers requiring LF synchronization |
<> | 144:ef7eb2e8f9f7 | 354 | * should be done within one freeze enable/disable block to avoid unecessary |
<> | 144:ef7eb2e8f9f7 | 355 | * stalling. |
<> | 144:ef7eb2e8f9f7 | 356 | * |
<> | 144:ef7eb2e8f9f7 | 357 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 358 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 359 | * |
<> | 144:ef7eb2e8f9f7 | 360 | * @param[in] enable |
<> | 144:ef7eb2e8f9f7 | 361 | * @li true - enable freeze, modified registers are not propagated to the |
<> | 144:ef7eb2e8f9f7 | 362 | * LF domain |
<> | 144:ef7eb2e8f9f7 | 363 | * @li false - disables freeze, modified registers are propagated to LF |
<> | 144:ef7eb2e8f9f7 | 364 | * domain |
<> | 144:ef7eb2e8f9f7 | 365 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 366 | void PCNT_FreezeEnable(PCNT_TypeDef *pcnt, bool enable) |
<> | 144:ef7eb2e8f9f7 | 367 | { |
<> | 144:ef7eb2e8f9f7 | 368 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 369 | |
<> | 144:ef7eb2e8f9f7 | 370 | if (enable) |
<> | 144:ef7eb2e8f9f7 | 371 | { |
<> | 144:ef7eb2e8f9f7 | 372 | /* Wait for any ongoing LF synchronization to complete. This is just to |
<> | 144:ef7eb2e8f9f7 | 373 | * protect against the rare case when a user: |
<> | 144:ef7eb2e8f9f7 | 374 | * - modifies a register requiring LF sync |
<> | 144:ef7eb2e8f9f7 | 375 | * - then enables freeze before LF sync completed |
<> | 144:ef7eb2e8f9f7 | 376 | * - then modifies the same register again |
<> | 144:ef7eb2e8f9f7 | 377 | * since modifying a register while it is in sync progress should be |
<> | 144:ef7eb2e8f9f7 | 378 | * avoided. */ |
<> | 144:ef7eb2e8f9f7 | 379 | while (pcnt->SYNCBUSY) |
<> | 144:ef7eb2e8f9f7 | 380 | ; |
<> | 144:ef7eb2e8f9f7 | 381 | |
<> | 144:ef7eb2e8f9f7 | 382 | pcnt->FREEZE = PCNT_FREEZE_REGFREEZE; |
<> | 144:ef7eb2e8f9f7 | 383 | } |
<> | 144:ef7eb2e8f9f7 | 384 | else |
<> | 144:ef7eb2e8f9f7 | 385 | { |
<> | 144:ef7eb2e8f9f7 | 386 | pcnt->FREEZE = 0; |
<> | 144:ef7eb2e8f9f7 | 387 | } |
<> | 144:ef7eb2e8f9f7 | 388 | } |
<> | 144:ef7eb2e8f9f7 | 389 | |
<> | 144:ef7eb2e8f9f7 | 390 | |
<> | 144:ef7eb2e8f9f7 | 391 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 392 | * @brief |
<> | 144:ef7eb2e8f9f7 | 393 | * Init pulse counter. |
<> | 144:ef7eb2e8f9f7 | 394 | * |
<> | 144:ef7eb2e8f9f7 | 395 | * @details |
<> | 144:ef7eb2e8f9f7 | 396 | * This function will configure the pulse counter. The clock selection is |
<> | 144:ef7eb2e8f9f7 | 397 | * configured as follows, depending on operational mode: |
<> | 144:ef7eb2e8f9f7 | 398 | * |
<> | 144:ef7eb2e8f9f7 | 399 | * @li #pcntModeOvsSingle - Use LFACLK. |
<> | 144:ef7eb2e8f9f7 | 400 | * @li #pcntModeExtSingle - Use external PCNTn_S0 pin. |
<> | 144:ef7eb2e8f9f7 | 401 | * @li #pcntModeExtQuad - Use external PCNTn_S0 pin. |
<> | 144:ef7eb2e8f9f7 | 402 | * |
<> | 144:ef7eb2e8f9f7 | 403 | * Notice that the LFACLK must be enabled in all modes, since some basic setup |
<> | 144:ef7eb2e8f9f7 | 404 | * is done with this clock even if external pin clock usage mode is chosen. |
<> | 144:ef7eb2e8f9f7 | 405 | * The pulse counter clock for the selected instance must also be enabled |
<> | 144:ef7eb2e8f9f7 | 406 | * prior to init. |
<> | 144:ef7eb2e8f9f7 | 407 | * |
<> | 144:ef7eb2e8f9f7 | 408 | * Notice that pins used by the PCNT module must be properly configured |
<> | 144:ef7eb2e8f9f7 | 409 | * by the user explicitly through setting the ROUTE register, in order for |
<> | 144:ef7eb2e8f9f7 | 410 | * the PCNT to work as intended. |
<> | 144:ef7eb2e8f9f7 | 411 | * |
<> | 144:ef7eb2e8f9f7 | 412 | * Writing to CNT will not occur in external clock modes (EXTCLKQUAD and |
<> | 144:ef7eb2e8f9f7 | 413 | * EXTCLKSINGLE) because the external clock rate is unknown. The user should |
<> | 144:ef7eb2e8f9f7 | 414 | * handle it manually depending on the application |
<> | 144:ef7eb2e8f9f7 | 415 | * |
<> | 144:ef7eb2e8f9f7 | 416 | * TOPB is written for all modes but in external clock mode it will take |
<> | 144:ef7eb2e8f9f7 | 417 | * 3 external clock cycles to sync to TOP |
<> | 144:ef7eb2e8f9f7 | 418 | * |
<> | 144:ef7eb2e8f9f7 | 419 | * |
<> | 144:ef7eb2e8f9f7 | 420 | * @note |
<> | 144:ef7eb2e8f9f7 | 421 | * Initializing requires synchronization into the low frequency domain. This |
<> | 144:ef7eb2e8f9f7 | 422 | * may cause some delay. |
<> | 144:ef7eb2e8f9f7 | 423 | * |
<> | 144:ef7eb2e8f9f7 | 424 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 425 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 426 | * |
<> | 144:ef7eb2e8f9f7 | 427 | * @param[in] init |
<> | 144:ef7eb2e8f9f7 | 428 | * Pointer to initialization structure used to initialize. |
<> | 144:ef7eb2e8f9f7 | 429 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 430 | void PCNT_Init(PCNT_TypeDef *pcnt, const PCNT_Init_TypeDef *init) |
<> | 144:ef7eb2e8f9f7 | 431 | { |
<> | 144:ef7eb2e8f9f7 | 432 | unsigned int inst; |
<> | 144:ef7eb2e8f9f7 | 433 | uint32_t tmp; |
<> | 144:ef7eb2e8f9f7 | 434 | |
<> | 144:ef7eb2e8f9f7 | 435 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 436 | |
<> | 144:ef7eb2e8f9f7 | 437 | #ifdef PCNT0 |
<> | 144:ef7eb2e8f9f7 | 438 | if (PCNT0 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 439 | { |
<> | 144:ef7eb2e8f9f7 | 440 | EFM_ASSERT((1<<PCNT0_CNT_SIZE) > init->counter); |
<> | 144:ef7eb2e8f9f7 | 441 | EFM_ASSERT((1<<PCNT0_CNT_SIZE) > init->top); |
<> | 144:ef7eb2e8f9f7 | 442 | } |
<> | 144:ef7eb2e8f9f7 | 443 | #endif |
<> | 144:ef7eb2e8f9f7 | 444 | |
<> | 144:ef7eb2e8f9f7 | 445 | #ifdef PCNT1 |
<> | 144:ef7eb2e8f9f7 | 446 | if (PCNT1 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 447 | { |
<> | 144:ef7eb2e8f9f7 | 448 | EFM_ASSERT((1<<PCNT1_CNT_SIZE) > init->counter); |
<> | 144:ef7eb2e8f9f7 | 449 | EFM_ASSERT((1<<PCNT1_CNT_SIZE) > init->top); |
<> | 144:ef7eb2e8f9f7 | 450 | } |
<> | 144:ef7eb2e8f9f7 | 451 | #endif |
<> | 144:ef7eb2e8f9f7 | 452 | |
<> | 144:ef7eb2e8f9f7 | 453 | #ifdef PCNT2 |
<> | 144:ef7eb2e8f9f7 | 454 | if (PCNT2 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 455 | { |
<> | 144:ef7eb2e8f9f7 | 456 | EFM_ASSERT((1<<PCNT2_CNT_SIZE) > init->counter); |
<> | 144:ef7eb2e8f9f7 | 457 | EFM_ASSERT((1<<PCNT2_CNT_SIZE) > init->top); |
<> | 144:ef7eb2e8f9f7 | 458 | } |
<> | 144:ef7eb2e8f9f7 | 459 | #endif |
<> | 144:ef7eb2e8f9f7 | 460 | |
<> | 144:ef7eb2e8f9f7 | 461 | /* Map pointer to instance */ |
<> | 144:ef7eb2e8f9f7 | 462 | inst = PCNT_Map(pcnt); |
<> | 144:ef7eb2e8f9f7 | 463 | |
<> | 144:ef7eb2e8f9f7 | 464 | #if defined(_PCNT_INPUT_MASK) |
<> | 144:ef7eb2e8f9f7 | 465 | /* Selecting the PRS channels for the PRS input sources of the PCNT. These are |
<> | 144:ef7eb2e8f9f7 | 466 | * written with a Read-Modify-Write sequence in order to keep the value of the |
<> | 144:ef7eb2e8f9f7 | 467 | * input enable bits which can be modified using PCNT_PRSInputEnable(). */ |
<> | 144:ef7eb2e8f9f7 | 468 | tmp = pcnt->INPUT & ~(_PCNT_INPUT_S0PRSSEL_MASK | _PCNT_INPUT_S1PRSSEL_MASK); |
<> | 144:ef7eb2e8f9f7 | 469 | tmp |= ((uint32_t)init->s0PRS << _PCNT_INPUT_S0PRSSEL_SHIFT) | |
<> | 144:ef7eb2e8f9f7 | 470 | ((uint32_t)init->s1PRS << _PCNT_INPUT_S1PRSSEL_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 471 | pcnt->INPUT = tmp; |
<> | 144:ef7eb2e8f9f7 | 472 | #endif |
<> | 144:ef7eb2e8f9f7 | 473 | |
<> | 144:ef7eb2e8f9f7 | 474 | /* Build CTRL setting, except for mode */ |
<> | 144:ef7eb2e8f9f7 | 475 | tmp = 0; |
<> | 144:ef7eb2e8f9f7 | 476 | if (init->negEdge) |
<> | 144:ef7eb2e8f9f7 | 477 | { |
<> | 144:ef7eb2e8f9f7 | 478 | tmp |= PCNT_CTRL_EDGE_NEG; |
<> | 144:ef7eb2e8f9f7 | 479 | } |
<> | 144:ef7eb2e8f9f7 | 480 | |
<> | 144:ef7eb2e8f9f7 | 481 | if (init->countDown) |
<> | 144:ef7eb2e8f9f7 | 482 | { |
<> | 144:ef7eb2e8f9f7 | 483 | tmp |= PCNT_CTRL_CNTDIR_DOWN; |
<> | 144:ef7eb2e8f9f7 | 484 | } |
<> | 144:ef7eb2e8f9f7 | 485 | |
<> | 144:ef7eb2e8f9f7 | 486 | if (init->filter) |
<> | 144:ef7eb2e8f9f7 | 487 | { |
<> | 144:ef7eb2e8f9f7 | 488 | tmp |= PCNT_CTRL_FILT; |
<> | 144:ef7eb2e8f9f7 | 489 | } |
<> | 144:ef7eb2e8f9f7 | 490 | |
<> | 144:ef7eb2e8f9f7 | 491 | #if defined(PCNT_CTRL_HYST) |
<> | 144:ef7eb2e8f9f7 | 492 | if (init->hyst) |
<> | 144:ef7eb2e8f9f7 | 493 | { |
<> | 144:ef7eb2e8f9f7 | 494 | tmp |= PCNT_CTRL_HYST; |
<> | 144:ef7eb2e8f9f7 | 495 | } |
<> | 144:ef7eb2e8f9f7 | 496 | #endif |
<> | 144:ef7eb2e8f9f7 | 497 | |
<> | 144:ef7eb2e8f9f7 | 498 | #if defined(PCNT_CTRL_S1CDIR) |
<> | 144:ef7eb2e8f9f7 | 499 | if (init->s1CntDir) |
<> | 144:ef7eb2e8f9f7 | 500 | { |
<> | 144:ef7eb2e8f9f7 | 501 | tmp |= PCNT_CTRL_S1CDIR; |
<> | 144:ef7eb2e8f9f7 | 502 | } |
<> | 144:ef7eb2e8f9f7 | 503 | #endif |
<> | 144:ef7eb2e8f9f7 | 504 | |
<> | 144:ef7eb2e8f9f7 | 505 | /* Configure counter events for regular and auxiliary counter. */ |
<> | 144:ef7eb2e8f9f7 | 506 | #if defined(_PCNT_CTRL_CNTEV_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 507 | tmp |= init->cntEvent << _PCNT_CTRL_CNTEV_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 508 | #endif |
<> | 144:ef7eb2e8f9f7 | 509 | |
<> | 144:ef7eb2e8f9f7 | 510 | #if defined(_PCNT_CTRL_AUXCNTEV_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 511 | { |
<> | 144:ef7eb2e8f9f7 | 512 | /* Modify the auxCntEvent value before writing to the AUXCNTEV field in |
<> | 144:ef7eb2e8f9f7 | 513 | the CTRL register because the AUXCNTEV field values are different from |
<> | 144:ef7eb2e8f9f7 | 514 | the CNTEV field values, and cntEvent and auxCntEvent are of the same type |
<> | 144:ef7eb2e8f9f7 | 515 | PCNT_CntEvent_TypeDef. |
<> | 144:ef7eb2e8f9f7 | 516 | */ |
<> | 144:ef7eb2e8f9f7 | 517 | uint32_t auxCntEventField = 0; /* Get rid of compiler warning. */ |
<> | 144:ef7eb2e8f9f7 | 518 | switch (init->auxCntEvent) |
<> | 144:ef7eb2e8f9f7 | 519 | { |
<> | 144:ef7eb2e8f9f7 | 520 | case pcntCntEventBoth: |
<> | 144:ef7eb2e8f9f7 | 521 | auxCntEventField = pcntCntEventNone; |
<> | 144:ef7eb2e8f9f7 | 522 | break; |
<> | 144:ef7eb2e8f9f7 | 523 | case pcntCntEventNone: |
<> | 144:ef7eb2e8f9f7 | 524 | auxCntEventField = pcntCntEventBoth; |
<> | 144:ef7eb2e8f9f7 | 525 | break; |
<> | 144:ef7eb2e8f9f7 | 526 | case pcntCntEventUp: |
<> | 144:ef7eb2e8f9f7 | 527 | case pcntCntEventDown: |
<> | 144:ef7eb2e8f9f7 | 528 | auxCntEventField = init->auxCntEvent; |
<> | 144:ef7eb2e8f9f7 | 529 | break; |
<> | 144:ef7eb2e8f9f7 | 530 | default: |
<> | 144:ef7eb2e8f9f7 | 531 | /* Invalid parameter, asserted. */ |
<> | 144:ef7eb2e8f9f7 | 532 | EFM_ASSERT(0); |
<> | 144:ef7eb2e8f9f7 | 533 | break; |
<> | 144:ef7eb2e8f9f7 | 534 | } |
<> | 144:ef7eb2e8f9f7 | 535 | tmp |= auxCntEventField << _PCNT_CTRL_AUXCNTEV_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 536 | } |
<> | 144:ef7eb2e8f9f7 | 537 | #endif |
<> | 144:ef7eb2e8f9f7 | 538 | |
<> | 144:ef7eb2e8f9f7 | 539 | /* Reset pulse counter while changing clock source. The reset bit */ |
<> | 144:ef7eb2e8f9f7 | 540 | /* is asynchronous, we don't have to check for SYNCBUSY. */ |
<> | 144:ef7eb2e8f9f7 | 541 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1); |
<> | 144:ef7eb2e8f9f7 | 542 | |
<> | 144:ef7eb2e8f9f7 | 543 | /* Select LFACLK to clock in control setting */ |
<> | 144:ef7eb2e8f9f7 | 544 | CMU_PCNTClockExternalSet(inst, false); |
<> | 144:ef7eb2e8f9f7 | 545 | |
<> | 144:ef7eb2e8f9f7 | 546 | /* Handling depends on whether using external clock or not. */ |
<> | 144:ef7eb2e8f9f7 | 547 | switch (init->mode) |
<> | 144:ef7eb2e8f9f7 | 548 | { |
<> | 144:ef7eb2e8f9f7 | 549 | case pcntModeExtSingle: |
<> | 144:ef7eb2e8f9f7 | 550 | case pcntModeExtQuad: |
<> | 144:ef7eb2e8f9f7 | 551 | tmp |= init->mode << _PCNT_CTRL_MODE_SHIFT; |
<> | 144:ef7eb2e8f9f7 | 552 | |
<> | 144:ef7eb2e8f9f7 | 553 | /* In most cases, the SYNCBUSY bit is set due to reset bit set, and waiting |
<> | 144:ef7eb2e8f9f7 | 554 | * for asynchronous reset bit is strictly not necessary. |
<> | 144:ef7eb2e8f9f7 | 555 | * But in theory, other operations on CTRL register may have been done |
<> | 144:ef7eb2e8f9f7 | 556 | * outside this function, so wait. */ |
<> | 144:ef7eb2e8f9f7 | 557 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 558 | |
<> | 144:ef7eb2e8f9f7 | 559 | /* Enable PCNT Clock Domain Reset. The PCNT must be in reset before changing |
<> | 144:ef7eb2e8f9f7 | 560 | * the clock source to an external clock */ |
<> | 144:ef7eb2e8f9f7 | 561 | pcnt->CTRL = PCNT_CTRL_RSTEN; |
<> | 144:ef7eb2e8f9f7 | 562 | |
<> | 144:ef7eb2e8f9f7 | 563 | /* Wait until CTRL write synchronized into LF domain. */ |
<> | 144:ef7eb2e8f9f7 | 564 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 565 | |
<> | 144:ef7eb2e8f9f7 | 566 | /* Change to external clock BEFORE disabling reset */ |
<> | 144:ef7eb2e8f9f7 | 567 | CMU_PCNTClockExternalSet(inst, true); |
<> | 144:ef7eb2e8f9f7 | 568 | |
<> | 144:ef7eb2e8f9f7 | 569 | /* Write to TOPB. If using external clock TOPB will sync to TOP at the same |
<> | 144:ef7eb2e8f9f7 | 570 | * time as the mode. This will insure that if the user chooses to count |
<> | 144:ef7eb2e8f9f7 | 571 | * down, the first "countable" pulse will make CNT go to TOP and not 0xFF |
<> | 144:ef7eb2e8f9f7 | 572 | * (default TOP value). */ |
<> | 144:ef7eb2e8f9f7 | 573 | pcnt->TOPB = init->top; |
<> | 144:ef7eb2e8f9f7 | 574 | |
<> | 144:ef7eb2e8f9f7 | 575 | /* This bit has no effect on rev. C and onwards parts - for compatibility */ |
<> | 144:ef7eb2e8f9f7 | 576 | pcnt->CMD = PCNT_CMD_LTOPBIM; |
<> | 144:ef7eb2e8f9f7 | 577 | |
<> | 144:ef7eb2e8f9f7 | 578 | /* Write the CTRL register with the configurations. |
<> | 144:ef7eb2e8f9f7 | 579 | * This should be written after TOPB in the eventuality of a pulse between |
<> | 144:ef7eb2e8f9f7 | 580 | * these two writes that would cause the CTRL register to be synced one |
<> | 144:ef7eb2e8f9f7 | 581 | * clock cycle earlier than the TOPB. */ |
<> | 144:ef7eb2e8f9f7 | 582 | pcnt->CTRL = tmp; |
<> | 144:ef7eb2e8f9f7 | 583 | |
<> | 144:ef7eb2e8f9f7 | 584 | /* There are no syncs for TOP, CMD or CTRL because the clock rate is unknown |
<> | 144:ef7eb2e8f9f7 | 585 | * and the program could stall |
<> | 144:ef7eb2e8f9f7 | 586 | * These will be synced within 3 clock cycles of the external clock / |
<> | 144:ef7eb2e8f9f7 | 587 | * For the same reason CNT cannot be written here. */ |
<> | 144:ef7eb2e8f9f7 | 588 | break; |
<> | 144:ef7eb2e8f9f7 | 589 | |
<> | 144:ef7eb2e8f9f7 | 590 | /* pcntModeDisable */ |
<> | 144:ef7eb2e8f9f7 | 591 | /* pcntModeOvsSingle */ |
<> | 144:ef7eb2e8f9f7 | 592 | default: |
<> | 144:ef7eb2e8f9f7 | 593 | /* No need to set disabled mode if already disabled. */ |
<> | 144:ef7eb2e8f9f7 | 594 | if ((pcnt->CTRL & _PCNT_CTRL_MODE_MASK) != PCNT_CTRL_MODE_DISABLE) |
<> | 144:ef7eb2e8f9f7 | 595 | { |
<> | 144:ef7eb2e8f9f7 | 596 | /* Set control to disabled mode, leave reset on until ensured disabled. |
<> | 144:ef7eb2e8f9f7 | 597 | * We don't need to wait for CTRL SYNCBUSY completion here, it was |
<> | 144:ef7eb2e8f9f7 | 598 | * triggered by reset bit above, which is asynchronous. */ |
<> | 144:ef7eb2e8f9f7 | 599 | pcnt->CTRL = tmp | PCNT_CTRL_MODE_DISABLE | PCNT_CTRL_RSTEN; |
<> | 144:ef7eb2e8f9f7 | 600 | |
<> | 144:ef7eb2e8f9f7 | 601 | /* Wait until CTRL write synchronized into LF domain before proceeding |
<> | 144:ef7eb2e8f9f7 | 602 | * to disable reset. */ |
<> | 144:ef7eb2e8f9f7 | 603 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 604 | } |
<> | 144:ef7eb2e8f9f7 | 605 | |
<> | 144:ef7eb2e8f9f7 | 606 | /* Disable reset bit, counter should now be in disabled mode. */ |
<> | 144:ef7eb2e8f9f7 | 607 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0); |
<> | 144:ef7eb2e8f9f7 | 608 | |
<> | 144:ef7eb2e8f9f7 | 609 | /* Set counter and top values as specified. */ |
<> | 144:ef7eb2e8f9f7 | 610 | PCNT_CounterTopSet(pcnt, init->counter, init->top); |
<> | 144:ef7eb2e8f9f7 | 611 | |
<> | 144:ef7eb2e8f9f7 | 612 | /* Enter oversampling mode if selected. */ |
<> | 144:ef7eb2e8f9f7 | 613 | if (init->mode == pcntModeOvsSingle) |
<> | 144:ef7eb2e8f9f7 | 614 | { |
<> | 144:ef7eb2e8f9f7 | 615 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 616 | pcnt->CTRL = tmp | (init->mode << _PCNT_CTRL_MODE_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 617 | } |
<> | 144:ef7eb2e8f9f7 | 618 | break; |
<> | 144:ef7eb2e8f9f7 | 619 | } |
<> | 144:ef7eb2e8f9f7 | 620 | } |
<> | 144:ef7eb2e8f9f7 | 621 | |
<> | 144:ef7eb2e8f9f7 | 622 | |
<> | 144:ef7eb2e8f9f7 | 623 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 624 | * @brief |
<> | 144:ef7eb2e8f9f7 | 625 | * Reset PCNT to same state as after a HW reset. |
<> | 144:ef7eb2e8f9f7 | 626 | * |
<> | 144:ef7eb2e8f9f7 | 627 | * @details |
<> | 144:ef7eb2e8f9f7 | 628 | * Notice the LFACLK must be enabled, since some basic reset is done with |
<> | 144:ef7eb2e8f9f7 | 629 | * this clock. The pulse counter clock for the selected instance must also |
<> | 144:ef7eb2e8f9f7 | 630 | * be enabled prior to init. |
<> | 144:ef7eb2e8f9f7 | 631 | * |
<> | 144:ef7eb2e8f9f7 | 632 | * @note |
<> | 144:ef7eb2e8f9f7 | 633 | * The ROUTE register is NOT reset by this function, in order to allow for |
<> | 144:ef7eb2e8f9f7 | 634 | * centralized setup of this feature. |
<> | 144:ef7eb2e8f9f7 | 635 | * |
<> | 144:ef7eb2e8f9f7 | 636 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 637 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 638 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 639 | void PCNT_Reset(PCNT_TypeDef *pcnt) |
<> | 144:ef7eb2e8f9f7 | 640 | { |
<> | 144:ef7eb2e8f9f7 | 641 | unsigned int inst; |
<> | 144:ef7eb2e8f9f7 | 642 | |
<> | 144:ef7eb2e8f9f7 | 643 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 644 | |
<> | 144:ef7eb2e8f9f7 | 645 | /* Map pointer to instance and clock info */ |
<> | 144:ef7eb2e8f9f7 | 646 | inst = PCNT_Map(pcnt); |
<> | 144:ef7eb2e8f9f7 | 647 | |
<> | 144:ef7eb2e8f9f7 | 648 | pcnt->IEN = _PCNT_IEN_RESETVALUE; |
<> | 144:ef7eb2e8f9f7 | 649 | |
<> | 144:ef7eb2e8f9f7 | 650 | /* Notice that special SYNCBUSY handling is not applicable for the RSTEN |
<> | 144:ef7eb2e8f9f7 | 651 | * bit of the control register, so we don't need to wait for it when only |
<> | 144:ef7eb2e8f9f7 | 652 | * modifying RSTEN. The SYNCBUSY bit will be set, leading to a |
<> | 144:ef7eb2e8f9f7 | 653 | * synchronization in the LF domain, with in reality no changes to LF domain. |
<> | 144:ef7eb2e8f9f7 | 654 | * Enable reset of CNT and TOP register. */ |
<> | 144:ef7eb2e8f9f7 | 655 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 1); |
<> | 144:ef7eb2e8f9f7 | 656 | |
<> | 144:ef7eb2e8f9f7 | 657 | /* Select LFACLK as default */ |
<> | 144:ef7eb2e8f9f7 | 658 | CMU_PCNTClockExternalSet(inst, false); |
<> | 144:ef7eb2e8f9f7 | 659 | |
<> | 144:ef7eb2e8f9f7 | 660 | PCNT_TopBufferSet(pcnt, _PCNT_TOPB_RESETVALUE); |
<> | 144:ef7eb2e8f9f7 | 661 | |
<> | 144:ef7eb2e8f9f7 | 662 | /* Reset CTRL leaving RSTEN set */ |
<> | 144:ef7eb2e8f9f7 | 663 | pcnt->CTRL = _PCNT_CTRL_RESETVALUE | PCNT_CTRL_RSTEN; |
<> | 144:ef7eb2e8f9f7 | 664 | |
<> | 144:ef7eb2e8f9f7 | 665 | /* Disable reset after CTRL reg has been synchronized */ |
<> | 144:ef7eb2e8f9f7 | 666 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 667 | BUS_RegBitWrite(&(pcnt->CTRL), _PCNT_CTRL_RSTEN_SHIFT, 0); |
<> | 144:ef7eb2e8f9f7 | 668 | |
<> | 144:ef7eb2e8f9f7 | 669 | /* Clear pending interrupts */ |
<> | 144:ef7eb2e8f9f7 | 670 | pcnt->IFC = _PCNT_IFC_MASK; |
<> | 144:ef7eb2e8f9f7 | 671 | |
<> | 144:ef7eb2e8f9f7 | 672 | /* Do not reset route register, setting should be done independently */ |
<> | 144:ef7eb2e8f9f7 | 673 | } |
<> | 144:ef7eb2e8f9f7 | 674 | |
<> | 144:ef7eb2e8f9f7 | 675 | #if defined(PCNT_OVSCFG_FILTLEN_DEFAULT) |
<> | 144:ef7eb2e8f9f7 | 676 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 677 | * @brief |
<> | 144:ef7eb2e8f9f7 | 678 | * Set filter configuration. |
<> | 144:ef7eb2e8f9f7 | 679 | * |
<> | 144:ef7eb2e8f9f7 | 680 | * @details |
<> | 144:ef7eb2e8f9f7 | 681 | * This function will configure the PCNT input filter, when the PCNT mode is |
<> | 144:ef7eb2e8f9f7 | 682 | * configured to take an LFA-derived clock as input clock. |
<> | 144:ef7eb2e8f9f7 | 683 | * |
<> | 144:ef7eb2e8f9f7 | 684 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 685 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 686 | * |
<> | 144:ef7eb2e8f9f7 | 687 | * @param[in] config |
<> | 144:ef7eb2e8f9f7 | 688 | * Pointer to configuration structure to be applied. |
<> | 144:ef7eb2e8f9f7 | 689 | * |
<> | 144:ef7eb2e8f9f7 | 690 | * @param[in] enable |
<> | 144:ef7eb2e8f9f7 | 691 | * Whether to enable or disable filtering |
<> | 144:ef7eb2e8f9f7 | 692 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 693 | void PCNT_FilterConfiguration(PCNT_TypeDef *pcnt, const PCNT_Filter_TypeDef *config, bool enable) { |
<> | 144:ef7eb2e8f9f7 | 694 | uint32_t ovscfg = 0; |
<> | 144:ef7eb2e8f9f7 | 695 | |
<> | 144:ef7eb2e8f9f7 | 696 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 697 | |
<> | 144:ef7eb2e8f9f7 | 698 | /* Construct new filter setting value */ |
<> | 144:ef7eb2e8f9f7 | 699 | ovscfg = ((config->filtLen & _PCNT_OVSCFG_FILTLEN_MASK) << _PCNT_OVSCFG_FILTLEN_SHIFT) |
<> | 144:ef7eb2e8f9f7 | 700 | | ((config->flutterrm & 0x1) << _PCNT_OVSCFG_FLUTTERRM_SHIFT); |
<> | 144:ef7eb2e8f9f7 | 701 | |
<> | 144:ef7eb2e8f9f7 | 702 | /* Set new configuration. LF register requires sync check before writing. */ |
<> | 144:ef7eb2e8f9f7 | 703 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_OVSCFG); |
<> | 144:ef7eb2e8f9f7 | 704 | pcnt->OVSCFG = ovscfg; |
<> | 144:ef7eb2e8f9f7 | 705 | |
<> | 144:ef7eb2e8f9f7 | 706 | |
<> | 144:ef7eb2e8f9f7 | 707 | /* Set new state of filter. LF register requires sync check before writing. */ |
<> | 144:ef7eb2e8f9f7 | 708 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 709 | if(enable) |
<> | 144:ef7eb2e8f9f7 | 710 | { |
<> | 144:ef7eb2e8f9f7 | 711 | pcnt->CTRL |= PCNT_CTRL_FILT; |
<> | 144:ef7eb2e8f9f7 | 712 | } |
<> | 144:ef7eb2e8f9f7 | 713 | else |
<> | 144:ef7eb2e8f9f7 | 714 | { |
<> | 144:ef7eb2e8f9f7 | 715 | pcnt->CTRL &= ~PCNT_CTRL_FILT; |
<> | 144:ef7eb2e8f9f7 | 716 | } |
<> | 144:ef7eb2e8f9f7 | 717 | } |
<> | 144:ef7eb2e8f9f7 | 718 | #endif |
<> | 144:ef7eb2e8f9f7 | 719 | |
<> | 144:ef7eb2e8f9f7 | 720 | #if defined(PCNT_CTRL_TCCMODE_DEFAULT) |
<> | 144:ef7eb2e8f9f7 | 721 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 722 | * @brief |
<> | 144:ef7eb2e8f9f7 | 723 | * Set Triggered Compare and Clear configuration. |
<> | 144:ef7eb2e8f9f7 | 724 | * |
<> | 144:ef7eb2e8f9f7 | 725 | * @details |
<> | 144:ef7eb2e8f9f7 | 726 | * This function will configure the PCNT TCC (Triggered Compare and Clear) |
<> | 144:ef7eb2e8f9f7 | 727 | * module. This module can, upon a configurable trigger source, compare the |
<> | 144:ef7eb2e8f9f7 | 728 | * current counter value with the configured TOP value. Upon match, the counter |
<> | 144:ef7eb2e8f9f7 | 729 | * will be reset, and the TCC PRS output and TCC interrupt flag will be set. |
<> | 144:ef7eb2e8f9f7 | 730 | * |
<> | 144:ef7eb2e8f9f7 | 731 | * Since there is a comparison with the TOP value, the counter will not stop |
<> | 144:ef7eb2e8f9f7 | 732 | * counting nor wrap when hitting the TOP value, but it will keep on counting |
<> | 144:ef7eb2e8f9f7 | 733 | * until its maximum value. Then, it will not wrap, but instead stop counting |
<> | 144:ef7eb2e8f9f7 | 734 | * and set the overflow flag. |
<> | 144:ef7eb2e8f9f7 | 735 | * |
<> | 144:ef7eb2e8f9f7 | 736 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 737 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 738 | * |
<> | 144:ef7eb2e8f9f7 | 739 | * @param[in] config |
<> | 144:ef7eb2e8f9f7 | 740 | * Pointer to configuration structure to be applied. |
<> | 144:ef7eb2e8f9f7 | 741 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 742 | void PCNT_TCCConfiguration(PCNT_TypeDef *pcnt, const PCNT_TCC_TypeDef *config){ |
<> | 144:ef7eb2e8f9f7 | 743 | uint32_t ctrl = 0; |
<> | 144:ef7eb2e8f9f7 | 744 | uint32_t mask = _PCNT_CTRL_TCCMODE_MASK |
<> | 144:ef7eb2e8f9f7 | 745 | | _PCNT_CTRL_TCCPRESC_MASK |
<> | 144:ef7eb2e8f9f7 | 746 | | _PCNT_CTRL_TCCCOMP_MASK |
<> | 144:ef7eb2e8f9f7 | 747 | | _PCNT_CTRL_PRSGATEEN_MASK |
<> | 144:ef7eb2e8f9f7 | 748 | | _PCNT_CTRL_TCCPRSPOL_MASK |
<> | 144:ef7eb2e8f9f7 | 749 | | _PCNT_CTRL_TCCPRSSEL_MASK; |
<> | 144:ef7eb2e8f9f7 | 750 | |
<> | 144:ef7eb2e8f9f7 | 751 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 752 | |
<> | 144:ef7eb2e8f9f7 | 753 | /* construct TCC part of configuration register */ |
<> | 144:ef7eb2e8f9f7 | 754 | ctrl |= (config->mode << _PCNT_CTRL_TCCMODE_SHIFT ) & _PCNT_CTRL_TCCMODE_MASK; |
<> | 144:ef7eb2e8f9f7 | 755 | ctrl |= (config->prescaler << _PCNT_CTRL_TCCPRESC_SHIFT ) & _PCNT_CTRL_TCCPRESC_MASK; |
<> | 144:ef7eb2e8f9f7 | 756 | ctrl |= (config->compare << _PCNT_CTRL_TCCCOMP_SHIFT ) & _PCNT_CTRL_TCCCOMP_MASK; |
<> | 144:ef7eb2e8f9f7 | 757 | ctrl |= (config->tccPRS << _PCNT_CTRL_TCCPRSSEL_SHIFT ) & _PCNT_CTRL_TCCPRSSEL_MASK; |
<> | 144:ef7eb2e8f9f7 | 758 | ctrl |= (config->prsPolarity << _PCNT_CTRL_TCCPRSPOL_SHIFT ) & _PCNT_CTRL_TCCPRSPOL_MASK; |
<> | 144:ef7eb2e8f9f7 | 759 | ctrl |= (config->prsGateEnable << _PCNT_CTRL_PRSGATEEN_SHIFT ) & _PCNT_CTRL_PRSGATEEN_MASK; |
<> | 144:ef7eb2e8f9f7 | 760 | |
<> | 144:ef7eb2e8f9f7 | 761 | /* Load new TCC config to PCNT. LF register requires sync check before write. */ |
<> | 144:ef7eb2e8f9f7 | 762 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_CTRL); |
<> | 144:ef7eb2e8f9f7 | 763 | pcnt->CTRL = (pcnt->CTRL & (~mask)) | ctrl; |
<> | 144:ef7eb2e8f9f7 | 764 | } |
<> | 144:ef7eb2e8f9f7 | 765 | #endif |
<> | 144:ef7eb2e8f9f7 | 766 | |
<> | 144:ef7eb2e8f9f7 | 767 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 768 | * @brief |
<> | 144:ef7eb2e8f9f7 | 769 | * Set top buffer value. |
<> | 144:ef7eb2e8f9f7 | 770 | * |
<> | 144:ef7eb2e8f9f7 | 771 | * @note |
<> | 144:ef7eb2e8f9f7 | 772 | * This function may stall until synchronization to low frequency domain is |
<> | 144:ef7eb2e8f9f7 | 773 | * completed. For that reason, it should normally not be used when using |
<> | 144:ef7eb2e8f9f7 | 774 | * an external clock to clock the PCNT module, since stall time may be |
<> | 144:ef7eb2e8f9f7 | 775 | * undefined in that case. |
<> | 144:ef7eb2e8f9f7 | 776 | * |
<> | 144:ef7eb2e8f9f7 | 777 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 778 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 779 | * |
<> | 144:ef7eb2e8f9f7 | 780 | * @param[in] val |
<> | 144:ef7eb2e8f9f7 | 781 | * Value to set in top buffer register. |
<> | 144:ef7eb2e8f9f7 | 782 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 783 | void PCNT_TopBufferSet(PCNT_TypeDef *pcnt, uint32_t val) |
<> | 144:ef7eb2e8f9f7 | 784 | { |
<> | 144:ef7eb2e8f9f7 | 785 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 786 | |
<> | 144:ef7eb2e8f9f7 | 787 | /* LF register about to be modified require sync. busy check */ |
<> | 144:ef7eb2e8f9f7 | 788 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB); |
<> | 144:ef7eb2e8f9f7 | 789 | pcnt->TOPB = val; |
<> | 144:ef7eb2e8f9f7 | 790 | } |
<> | 144:ef7eb2e8f9f7 | 791 | |
<> | 144:ef7eb2e8f9f7 | 792 | |
<> | 144:ef7eb2e8f9f7 | 793 | /***************************************************************************//** |
<> | 144:ef7eb2e8f9f7 | 794 | * @brief |
<> | 144:ef7eb2e8f9f7 | 795 | * Set top value. |
<> | 144:ef7eb2e8f9f7 | 796 | * |
<> | 144:ef7eb2e8f9f7 | 797 | * @note |
<> | 144:ef7eb2e8f9f7 | 798 | * This function will stall until synchronization to low frequency domain is |
<> | 144:ef7eb2e8f9f7 | 799 | * completed. For that reason, it should normally not be used when using |
<> | 144:ef7eb2e8f9f7 | 800 | * an external clock to clock the PCNT module, since stall time may be |
<> | 144:ef7eb2e8f9f7 | 801 | * undefined in that case. |
<> | 144:ef7eb2e8f9f7 | 802 | * |
<> | 144:ef7eb2e8f9f7 | 803 | * @param[in] pcnt |
<> | 144:ef7eb2e8f9f7 | 804 | * Pointer to PCNT peripheral register block. |
<> | 144:ef7eb2e8f9f7 | 805 | * |
<> | 144:ef7eb2e8f9f7 | 806 | * @param[in] val |
<> | 144:ef7eb2e8f9f7 | 807 | * Value to set in top register. |
<> | 144:ef7eb2e8f9f7 | 808 | ******************************************************************************/ |
<> | 144:ef7eb2e8f9f7 | 809 | void PCNT_TopSet(PCNT_TypeDef *pcnt, uint32_t val) |
<> | 144:ef7eb2e8f9f7 | 810 | { |
<> | 144:ef7eb2e8f9f7 | 811 | EFM_ASSERT(PCNT_REF_VALID(pcnt)); |
<> | 144:ef7eb2e8f9f7 | 812 | |
<> | 144:ef7eb2e8f9f7 | 813 | #ifdef PCNT0 |
<> | 144:ef7eb2e8f9f7 | 814 | if (PCNT0 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 815 | { |
<> | 144:ef7eb2e8f9f7 | 816 | EFM_ASSERT((1<<PCNT0_CNT_SIZE) > val); |
<> | 144:ef7eb2e8f9f7 | 817 | } |
<> | 144:ef7eb2e8f9f7 | 818 | #endif |
<> | 144:ef7eb2e8f9f7 | 819 | |
<> | 144:ef7eb2e8f9f7 | 820 | #ifdef PCNT1 |
<> | 144:ef7eb2e8f9f7 | 821 | if (PCNT1 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 822 | { |
<> | 144:ef7eb2e8f9f7 | 823 | EFM_ASSERT((1<<PCNT1_CNT_SIZE) > val); |
<> | 144:ef7eb2e8f9f7 | 824 | } |
<> | 144:ef7eb2e8f9f7 | 825 | #endif |
<> | 144:ef7eb2e8f9f7 | 826 | |
<> | 144:ef7eb2e8f9f7 | 827 | #ifdef PCNT2 |
<> | 144:ef7eb2e8f9f7 | 828 | if (PCNT2 == pcnt) |
<> | 144:ef7eb2e8f9f7 | 829 | { |
<> | 144:ef7eb2e8f9f7 | 830 | EFM_ASSERT((1<<PCNT2_CNT_SIZE) > val); |
<> | 144:ef7eb2e8f9f7 | 831 | } |
<> | 144:ef7eb2e8f9f7 | 832 | #endif |
<> | 144:ef7eb2e8f9f7 | 833 | |
<> | 144:ef7eb2e8f9f7 | 834 | /* LF register about to be modified require sync. busy check */ |
<> | 144:ef7eb2e8f9f7 | 835 | |
<> | 144:ef7eb2e8f9f7 | 836 | /* Load into TOPB */ |
<> | 144:ef7eb2e8f9f7 | 837 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB); |
<> | 144:ef7eb2e8f9f7 | 838 | pcnt->TOPB = val; |
<> | 144:ef7eb2e8f9f7 | 839 | |
<> | 144:ef7eb2e8f9f7 | 840 | /* Load TOPB value into TOP */ |
<> | 144:ef7eb2e8f9f7 | 841 | PCNT_Sync(pcnt, PCNT_SYNCBUSY_TOPB | PCNT_SYNCBUSY_CMD); |
<> | 144:ef7eb2e8f9f7 | 842 | pcnt->CMD = PCNT_CMD_LTOPBIM; |
<> | 144:ef7eb2e8f9f7 | 843 | } |
<> | 144:ef7eb2e8f9f7 | 844 | |
<> | 144:ef7eb2e8f9f7 | 845 | /** @} (end addtogroup PCNT) */ |
<> | 144:ef7eb2e8f9f7 | 846 | /** @} (end addtogroup EM_Library) */ |
<> | 144:ef7eb2e8f9f7 | 847 | #endif /* defined(PCNT_COUNT) && (PCNT_COUNT > 0) */ |