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