Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_NORDIC/TARGET_NRF5/sdk/libraries/pwm/app_pwm.c@150:02e0a0aed4ec, 2016-11-08 (annotated)
- Committer:
- <>
- Date:
- Tue Nov 08 17:45:16 2016 +0000
- Revision:
- 150:02e0a0aed4ec
- Parent:
- 149:156823d33999
This updates the lib to the mbed lib v129
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| <> | 149:156823d33999 | 1 | /* |
| <> | 149:156823d33999 | 2 | * Copyright (c) 2015 Nordic Semiconductor ASA |
| <> | 149:156823d33999 | 3 | * All rights reserved. |
| <> | 149:156823d33999 | 4 | * |
| <> | 149:156823d33999 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
| <> | 149:156823d33999 | 6 | * are permitted provided that the following conditions are met: |
| <> | 149:156823d33999 | 7 | * |
| <> | 149:156823d33999 | 8 | * 1. Redistributions of source code must retain the above copyright notice, this list |
| <> | 149:156823d33999 | 9 | * of conditions and the following disclaimer. |
| <> | 149:156823d33999 | 10 | * |
| <> | 149:156823d33999 | 11 | * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA |
| <> | 149:156823d33999 | 12 | * integrated circuit in a product or a software update for such product, must reproduce |
| <> | 149:156823d33999 | 13 | * the above copyright notice, this list of conditions and the following disclaimer in |
| <> | 149:156823d33999 | 14 | * the documentation and/or other materials provided with the distribution. |
| <> | 149:156823d33999 | 15 | * |
| <> | 149:156823d33999 | 16 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be |
| <> | 149:156823d33999 | 17 | * used to endorse or promote products derived from this software without specific prior |
| <> | 149:156823d33999 | 18 | * written permission. |
| <> | 149:156823d33999 | 19 | * |
| <> | 149:156823d33999 | 20 | * 4. This software, with or without modification, must only be used with a |
| <> | 149:156823d33999 | 21 | * Nordic Semiconductor ASA integrated circuit. |
| <> | 149:156823d33999 | 22 | * |
| <> | 149:156823d33999 | 23 | * 5. Any software provided in binary or object form under this license must not be reverse |
| <> | 149:156823d33999 | 24 | * engineered, decompiled, modified and/or disassembled. |
| <> | 149:156823d33999 | 25 | * |
| <> | 149:156823d33999 | 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| <> | 149:156823d33999 | 27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| <> | 149:156823d33999 | 28 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| <> | 149:156823d33999 | 29 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| <> | 149:156823d33999 | 30 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| <> | 149:156823d33999 | 31 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| <> | 149:156823d33999 | 32 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| <> | 149:156823d33999 | 33 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| <> | 149:156823d33999 | 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| <> | 149:156823d33999 | 35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| <> | 149:156823d33999 | 36 | * |
| <> | 149:156823d33999 | 37 | */ |
| <> | 149:156823d33999 | 38 | |
| <> | 149:156823d33999 | 39 | |
| <> | 149:156823d33999 | 40 | #include "app_pwm.h" |
| <> | 149:156823d33999 | 41 | #include "nrf_drv_timer.h" |
| <> | 149:156823d33999 | 42 | #include "nrf_drv_ppi.h" |
| <> | 149:156823d33999 | 43 | #include "nrf_drv_common.h" |
| <> | 149:156823d33999 | 44 | #include "nrf_drv_gpiote.h" |
| <> | 149:156823d33999 | 45 | #include "nrf_gpiote.h" |
| <> | 149:156823d33999 | 46 | #include "nrf_gpio.h" |
| <> | 149:156823d33999 | 47 | #include "app_util.h" |
| <> | 149:156823d33999 | 48 | #include "app_util_platform.h" |
| <> | 149:156823d33999 | 49 | #include "nrf_assert.h" |
| <> | 149:156823d33999 | 50 | |
| <> | 149:156823d33999 | 51 | #define APP_PWM_CHANNEL_INITIALIZED 1 |
| <> | 149:156823d33999 | 52 | #define APP_PWM_CHANNEL_UNINITIALIZED 0 |
| <> | 149:156823d33999 | 53 | |
| <> | 149:156823d33999 | 54 | #define APP_PWM_CHANNEL_ENABLED 1 |
| <> | 149:156823d33999 | 55 | #define APP_PWM_CHANNEL_DISABLED 0 |
| <> | 149:156823d33999 | 56 | |
| <> | 149:156823d33999 | 57 | #define TIMER_PRESCALER_MAX 9 |
| <> | 149:156823d33999 | 58 | #define TIMER_MAX_PULSEWIDTH_US_ON_16M 4095 |
| <> | 149:156823d33999 | 59 | |
| <> | 149:156823d33999 | 60 | #define APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE 2 |
| <> | 149:156823d33999 | 61 | #define APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL 2 |
| <> | 149:156823d33999 | 62 | |
| <> | 149:156823d33999 | 63 | #define UNALLOCATED 0xFFFFFFFFUL |
| <> | 149:156823d33999 | 64 | #define BUSY_STATE_CHANGING 0xFE |
| <> | 149:156823d33999 | 65 | #define BUSY_STATE_IDLE 0xFF |
| <> | 149:156823d33999 | 66 | |
| <> | 149:156823d33999 | 67 | #define PWM_MAIN_CC_CHANNEL 2 |
| <> | 149:156823d33999 | 68 | #define PWM_SECONDARY_CC_CHANNEL 3 |
| <> | 149:156823d33999 | 69 | |
| <> | 149:156823d33999 | 70 | #ifdef NRF52 |
| <> | 149:156823d33999 | 71 | static bool m_use_ppi_delay_workaround; |
| <> | 149:156823d33999 | 72 | #endif |
| <> | 149:156823d33999 | 73 | |
| <> | 149:156823d33999 | 74 | |
| <> | 149:156823d33999 | 75 | /** |
| <> | 149:156823d33999 | 76 | * @brief PWM busy status |
| <> | 149:156823d33999 | 77 | * |
| <> | 149:156823d33999 | 78 | * Stores the number of a channel being currently updated. |
| <> | 149:156823d33999 | 79 | * |
| <> | 149:156823d33999 | 80 | */ |
| <> | 149:156823d33999 | 81 | static volatile uint8_t m_pwm_busy[TIMER_COUNT]; |
| <> | 149:156823d33999 | 82 | |
| <> | 149:156823d33999 | 83 | |
| <> | 149:156823d33999 | 84 | /** |
| <> | 149:156823d33999 | 85 | * @brief New duty cycle value |
| <> | 149:156823d33999 | 86 | * |
| <> | 149:156823d33999 | 87 | * When the channel duty cycle reaches this value, the update process is complete. |
| <> | 149:156823d33999 | 88 | */ |
| <> | 149:156823d33999 | 89 | static volatile uint32_t m_pwm_target_value[TIMER_COUNT]; |
| <> | 149:156823d33999 | 90 | |
| <> | 149:156823d33999 | 91 | |
| <> | 149:156823d33999 | 92 | /** |
| <> | 149:156823d33999 | 93 | * @brief PWM ready counter |
| <> | 149:156823d33999 | 94 | * |
| <> | 149:156823d33999 | 95 | * The value in this counter is decremented in every PWM cycle after initiating the update. |
| <> | 149:156823d33999 | 96 | * If an event handler function was specified by the user, it is being called |
| <> | 149:156823d33999 | 97 | * after two cycle events (at least one full PWM cycle). |
| <> | 149:156823d33999 | 98 | */ |
| <> | 149:156823d33999 | 99 | volatile uint8_t m_pwm_ready_counter[TIMER_COUNT][APP_PWM_CHANNELS_PER_INSTANCE]; |
| <> | 149:156823d33999 | 100 | |
| <> | 149:156823d33999 | 101 | /** |
| <> | 149:156823d33999 | 102 | * @brief Pointers to instances |
| <> | 149:156823d33999 | 103 | * |
| <> | 149:156823d33999 | 104 | * This array connects any active timer instance number with the pointer to the PWM instance. |
| <> | 149:156823d33999 | 105 | * It is used by the interrupt runtime. |
| <> | 149:156823d33999 | 106 | */ |
| <> | 149:156823d33999 | 107 | static const app_pwm_t * m_instances[TIMER_COUNT]; |
| <> | 149:156823d33999 | 108 | |
| <> | 149:156823d33999 | 109 | // Macros for getting the polarity of given instance/channel. |
| <> | 149:156823d33999 | 110 | #define POLARITY_ACTIVE(INST,CH) (( ((INST)->p_cb)->channels_cb[(CH)].polarity == \ |
| <> | 149:156823d33999 | 111 | APP_PWM_POLARITY_ACTIVE_LOW)?(0):(1)) |
| <> | 149:156823d33999 | 112 | #define POLARITY_INACTIVE(INST,CH) (( ((INST)->p_cb)->channels_cb[(CH)].polarity == \ |
| <> | 149:156823d33999 | 113 | APP_PWM_POLARITY_ACTIVE_LOW)?(1):(0)) |
| <> | 149:156823d33999 | 114 | |
| <> | 149:156823d33999 | 115 | //lint -save -e534 |
| <> | 149:156823d33999 | 116 | |
| <> | 149:156823d33999 | 117 | /** |
| <> | 149:156823d33999 | 118 | * @brief Workaround for PAN-73. |
| <> | 149:156823d33999 | 119 | * |
| <> | 149:156823d33999 | 120 | * @param[in] timer Timer. |
| <> | 149:156823d33999 | 121 | * @param[in] enable Enable or disable. |
| <> | 149:156823d33999 | 122 | */ |
| <> | 149:156823d33999 | 123 | static void pan73_workaround(NRF_TIMER_Type * p_timer, bool enable) |
| <> | 149:156823d33999 | 124 | { |
| <> | 149:156823d33999 | 125 | #ifdef NRF51 |
| <> | 149:156823d33999 | 126 | if (p_timer == NRF_TIMER0) |
| <> | 149:156823d33999 | 127 | { |
| <> | 149:156823d33999 | 128 | *(uint32_t *)0x40008C0C = (enable ? 1 : 0); |
| <> | 149:156823d33999 | 129 | } |
| <> | 149:156823d33999 | 130 | else if (p_timer == NRF_TIMER1) |
| <> | 149:156823d33999 | 131 | { |
| <> | 149:156823d33999 | 132 | *(uint32_t *)0x40009C0C = (enable ? 1 : 0); |
| <> | 149:156823d33999 | 133 | } |
| <> | 149:156823d33999 | 134 | else if (p_timer == NRF_TIMER2) |
| <> | 149:156823d33999 | 135 | { |
| <> | 149:156823d33999 | 136 | *(uint32_t *)0x4000AC0C = (enable ? 1 : 0); |
| <> | 149:156823d33999 | 137 | } |
| <> | 149:156823d33999 | 138 | #endif |
| <> | 149:156823d33999 | 139 | return; |
| <> | 149:156823d33999 | 140 | } |
| <> | 149:156823d33999 | 141 | |
| <> | 149:156823d33999 | 142 | bool app_pwm_busy_check(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 143 | { |
| <> | 149:156823d33999 | 144 | uint8_t busy_state = (m_pwm_busy[p_instance->p_timer->instance_id]); |
| <> | 149:156823d33999 | 145 | bool busy = true; |
| <> | 149:156823d33999 | 146 | if (busy_state != BUSY_STATE_IDLE) |
| <> | 149:156823d33999 | 147 | { |
| <> | 149:156823d33999 | 148 | if (busy_state != BUSY_STATE_CHANGING) |
| <> | 149:156823d33999 | 149 | { |
| <> | 149:156823d33999 | 150 | if (nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) busy_state) |
| <> | 149:156823d33999 | 151 | == m_pwm_target_value[p_instance->p_timer->instance_id]) |
| <> | 149:156823d33999 | 152 | { |
| <> | 149:156823d33999 | 153 | m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE; |
| <> | 149:156823d33999 | 154 | busy = false; |
| <> | 149:156823d33999 | 155 | } |
| <> | 149:156823d33999 | 156 | } |
| <> | 149:156823d33999 | 157 | } |
| <> | 149:156823d33999 | 158 | else |
| <> | 149:156823d33999 | 159 | { |
| <> | 149:156823d33999 | 160 | busy = false; |
| <> | 149:156823d33999 | 161 | } |
| <> | 149:156823d33999 | 162 | return busy; |
| <> | 149:156823d33999 | 163 | } |
| <> | 149:156823d33999 | 164 | |
| <> | 149:156823d33999 | 165 | |
| <> | 149:156823d33999 | 166 | /** |
| <> | 149:156823d33999 | 167 | * @brief Function for enabling the IRQ for a given PWM instance. |
| <> | 149:156823d33999 | 168 | * |
| <> | 149:156823d33999 | 169 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 170 | */ |
| <> | 149:156823d33999 | 171 | __STATIC_INLINE void pwm_irq_enable(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 172 | { |
| <> | 149:156823d33999 | 173 | nrf_drv_timer_compare_int_enable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL); |
| <> | 149:156823d33999 | 174 | } |
| <> | 149:156823d33999 | 175 | |
| <> | 149:156823d33999 | 176 | |
| <> | 149:156823d33999 | 177 | /** |
| <> | 149:156823d33999 | 178 | * @brief Function for disabling the IRQ for a given PWM instance. |
| <> | 149:156823d33999 | 179 | * |
| <> | 149:156823d33999 | 180 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 181 | */ |
| <> | 149:156823d33999 | 182 | __STATIC_INLINE void pwm_irq_disable(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 183 | { |
| <> | 149:156823d33999 | 184 | nrf_drv_timer_compare_int_disable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL); |
| <> | 149:156823d33999 | 185 | } |
| <> | 149:156823d33999 | 186 | |
| <> | 149:156823d33999 | 187 | |
| <> | 149:156823d33999 | 188 | /** |
| <> | 149:156823d33999 | 189 | * @brief Function for disabling PWM channel PPI. |
| <> | 149:156823d33999 | 190 | * |
| <> | 149:156823d33999 | 191 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 192 | */ |
| <> | 149:156823d33999 | 193 | __STATIC_INLINE void pwm_channel_ppi_disable(app_pwm_t const * const p_instance, uint8_t channel) |
| <> | 149:156823d33999 | 194 | { |
| <> | 149:156823d33999 | 195 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 196 | |
| <> | 149:156823d33999 | 197 | nrf_drv_ppi_channel_disable(p_cb->channels_cb[channel].ppi_channels[0]); |
| <> | 149:156823d33999 | 198 | nrf_drv_ppi_channel_disable(p_cb->channels_cb[channel].ppi_channels[1]); |
| <> | 149:156823d33999 | 199 | } |
| <> | 149:156823d33999 | 200 | |
| <> | 149:156823d33999 | 201 | |
| <> | 149:156823d33999 | 202 | /** |
| <> | 149:156823d33999 | 203 | * @brief Function for disabling PWM PPI. |
| <> | 149:156823d33999 | 204 | * |
| <> | 149:156823d33999 | 205 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 206 | */ |
| <> | 149:156823d33999 | 207 | __STATIC_INLINE void pwm_ppi_disable(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 208 | { |
| <> | 149:156823d33999 | 209 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 210 | |
| <> | 149:156823d33999 | 211 | nrf_drv_ppi_channel_disable(p_cb->ppi_channels[0]); |
| <> | 149:156823d33999 | 212 | nrf_drv_ppi_channel_disable(p_cb->ppi_channels[1]); |
| <> | 149:156823d33999 | 213 | } |
| <> | 149:156823d33999 | 214 | |
| <> | 149:156823d33999 | 215 | |
| <> | 149:156823d33999 | 216 | /** |
| <> | 149:156823d33999 | 217 | * @brief This function is called on interrupt after duty set. |
| <> | 149:156823d33999 | 218 | * |
| <> | 149:156823d33999 | 219 | * @param[in] timer Timer used by PWM. |
| <> | 149:156823d33999 | 220 | * @param[in] timer_instance_id Timer index. |
| <> | 149:156823d33999 | 221 | */ |
| <> | 149:156823d33999 | 222 | void pwm_ready_tick(nrf_timer_event_t event_type, void * p_context) |
| <> | 149:156823d33999 | 223 | { |
| <> | 149:156823d33999 | 224 | uint32_t timer_instance_id = (uint32_t)p_context; |
| <> | 149:156823d33999 | 225 | uint8_t disable = 1; |
| <> | 149:156823d33999 | 226 | |
| <> | 149:156823d33999 | 227 | for (uint8_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel) |
| <> | 149:156823d33999 | 228 | { |
| <> | 149:156823d33999 | 229 | if (m_pwm_ready_counter[timer_instance_id][channel]) |
| <> | 149:156823d33999 | 230 | { |
| <> | 149:156823d33999 | 231 | --m_pwm_ready_counter[timer_instance_id][channel]; |
| <> | 149:156823d33999 | 232 | if (!m_pwm_ready_counter[timer_instance_id][channel]) |
| <> | 149:156823d33999 | 233 | { |
| <> | 149:156823d33999 | 234 | app_pwm_cb_t * p_cb = m_instances[timer_instance_id]->p_cb; |
| <> | 149:156823d33999 | 235 | p_cb->p_ready_callback(timer_instance_id); |
| <> | 149:156823d33999 | 236 | } |
| <> | 149:156823d33999 | 237 | else |
| <> | 149:156823d33999 | 238 | { |
| <> | 149:156823d33999 | 239 | disable = 0; |
| <> | 149:156823d33999 | 240 | } |
| <> | 149:156823d33999 | 241 | } |
| <> | 149:156823d33999 | 242 | } |
| <> | 149:156823d33999 | 243 | |
| <> | 149:156823d33999 | 244 | if (disable) |
| <> | 149:156823d33999 | 245 | { |
| <> | 149:156823d33999 | 246 | pwm_irq_disable(m_instances[timer_instance_id]); |
| <> | 149:156823d33999 | 247 | } |
| <> | 149:156823d33999 | 248 | } |
| <> | 149:156823d33999 | 249 | |
| <> | 149:156823d33999 | 250 | |
| <> | 149:156823d33999 | 251 | /** |
| <> | 149:156823d33999 | 252 | * @brief Function for resource de-allocation. |
| <> | 149:156823d33999 | 253 | * |
| <> | 149:156823d33999 | 254 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 255 | */ |
| <> | 149:156823d33999 | 256 | //lint -e{650} |
| <> | 149:156823d33999 | 257 | static void pwm_dealloc(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 258 | { |
| <> | 149:156823d33999 | 259 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 260 | |
| <> | 149:156823d33999 | 261 | for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++i) |
| <> | 149:156823d33999 | 262 | { |
| <> | 149:156823d33999 | 263 | if (p_cb->ppi_channels[i] != (nrf_ppi_channel_t)(uint8_t)(UNALLOCATED)) |
| <> | 149:156823d33999 | 264 | { |
| <> | 149:156823d33999 | 265 | nrf_drv_ppi_channel_free(p_cb->ppi_channels[i]); |
| <> | 149:156823d33999 | 266 | } |
| <> | 149:156823d33999 | 267 | } |
| <> | 149:156823d33999 | 268 | if (p_cb->ppi_group != (nrf_ppi_channel_group_t)UNALLOCATED) |
| <> | 149:156823d33999 | 269 | { |
| <> | 149:156823d33999 | 270 | nrf_drv_ppi_group_free(p_cb->ppi_group); |
| <> | 149:156823d33999 | 271 | } |
| <> | 149:156823d33999 | 272 | |
| <> | 149:156823d33999 | 273 | for (uint8_t ch = 0; ch < APP_PWM_CHANNELS_PER_INSTANCE; ++ch) |
| <> | 149:156823d33999 | 274 | { |
| <> | 149:156823d33999 | 275 | for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL; ++i) |
| <> | 149:156823d33999 | 276 | { |
| <> | 149:156823d33999 | 277 | if (p_cb->channels_cb[ch].ppi_channels[i] != (nrf_ppi_channel_t)UNALLOCATED) |
| <> | 149:156823d33999 | 278 | { |
| <> | 149:156823d33999 | 279 | nrf_drv_ppi_channel_free(p_cb->channels_cb[ch].ppi_channels[i]); |
| <> | 149:156823d33999 | 280 | p_cb->channels_cb[ch].ppi_channels[i] = (nrf_ppi_channel_t)UNALLOCATED; |
| <> | 149:156823d33999 | 281 | } |
| <> | 149:156823d33999 | 282 | } |
| <> | 149:156823d33999 | 283 | if (p_cb->channels_cb[ch].gpio_pin != UNALLOCATED) |
| <> | 149:156823d33999 | 284 | { |
| <> | 149:156823d33999 | 285 | nrf_drv_gpiote_out_uninit(p_cb->channels_cb[ch].gpio_pin); |
| <> | 149:156823d33999 | 286 | p_cb->channels_cb[ch].gpio_pin = UNALLOCATED; |
| <> | 149:156823d33999 | 287 | } |
| <> | 149:156823d33999 | 288 | p_cb->channels_cb[ch].initialized = APP_PWM_CHANNEL_UNINITIALIZED; |
| <> | 149:156823d33999 | 289 | } |
| <> | 149:156823d33999 | 290 | nrf_drv_timer_uninit(p_instance->p_timer); |
| <> | 149:156823d33999 | 291 | return; |
| <> | 149:156823d33999 | 292 | } |
| <> | 149:156823d33999 | 293 | |
| <> | 149:156823d33999 | 294 | |
| <> | 149:156823d33999 | 295 | /** |
| <> | 149:156823d33999 | 296 | * @brief PWM state transition from (0%, 100%) to 0% or 100%. |
| <> | 149:156823d33999 | 297 | * |
| <> | 149:156823d33999 | 298 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 299 | * @param[in] channel PWM channel number. |
| <> | 149:156823d33999 | 300 | * @param[in] ticks Number of clock ticks. |
| <> | 149:156823d33999 | 301 | */ |
| <> | 149:156823d33999 | 302 | static void pwm_transition_n_to_0or100(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 303 | uint8_t channel, uint16_t ticks) |
| <> | 149:156823d33999 | 304 | { |
| <> | 149:156823d33999 | 305 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 306 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 307 | nrf_ppi_channel_group_t p_ppigrp = p_cb->ppi_group; |
| <> | 149:156823d33999 | 308 | |
| <> | 149:156823d33999 | 309 | pwm_ppi_disable(p_instance); |
| <> | 149:156823d33999 | 310 | nrf_drv_ppi_group_clear(p_ppigrp); |
| <> | 149:156823d33999 | 311 | nrf_drv_ppi_channels_include_in_group( |
| <> | 149:156823d33999 | 312 | nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[0]) | |
| <> | 149:156823d33999 | 313 | nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[1]), |
| <> | 149:156823d33999 | 314 | p_ppigrp); |
| <> | 149:156823d33999 | 315 | |
| <> | 149:156823d33999 | 316 | if (!ticks) |
| <> | 149:156823d33999 | 317 | { |
| <> | 149:156823d33999 | 318 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 319 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel), |
| <> | 149:156823d33999 | 320 | nrf_drv_ppi_task_addr_group_disable_get(p_ppigrp)); |
| <> | 149:156823d33999 | 321 | nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 0, false); |
| <> | 149:156823d33999 | 322 | m_pwm_target_value[p_instance->p_timer->instance_id] = |
| <> | 149:156823d33999 | 323 | nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) channel); |
| <> | 149:156823d33999 | 324 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 325 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel), |
| <> | 149:156823d33999 | 326 | nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL)); |
| <> | 149:156823d33999 | 327 | } |
| <> | 149:156823d33999 | 328 | else |
| <> | 149:156823d33999 | 329 | { |
| <> | 149:156823d33999 | 330 | ticks = p_cb->period; |
| <> | 149:156823d33999 | 331 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 332 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL), |
| <> | 149:156823d33999 | 333 | nrf_drv_ppi_task_addr_group_disable_get(p_ppigrp)); |
| <> | 149:156823d33999 | 334 | // Set secondary CC channel to non-zero value: |
| <> | 149:156823d33999 | 335 | nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 1, false); |
| <> | 149:156823d33999 | 336 | m_pwm_target_value[p_instance->p_timer->instance_id] = 0; |
| <> | 149:156823d33999 | 337 | // The captured value will be equal to 0, because timer clear on main PWM CC channel compare is enabled. |
| <> | 149:156823d33999 | 338 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 339 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL), |
| <> | 149:156823d33999 | 340 | nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL)); |
| <> | 149:156823d33999 | 341 | } |
| <> | 149:156823d33999 | 342 | |
| <> | 149:156823d33999 | 343 | nrf_drv_ppi_channel_enable(p_cb->ppi_channels[0]); |
| <> | 149:156823d33999 | 344 | nrf_drv_ppi_channel_enable(p_cb->ppi_channels[1]); |
| <> | 149:156823d33999 | 345 | |
| <> | 149:156823d33999 | 346 | p_ch_cb->pulsewidth = ticks; |
| <> | 149:156823d33999 | 347 | m_pwm_busy[p_instance->p_timer->instance_id] = PWM_SECONDARY_CC_CHANNEL; |
| <> | 149:156823d33999 | 348 | } |
| <> | 149:156823d33999 | 349 | |
| <> | 149:156823d33999 | 350 | |
| <> | 149:156823d33999 | 351 | /** |
| <> | 149:156823d33999 | 352 | * @brief PWM state transition from (0%, 100%) to (0%, 100%). |
| <> | 149:156823d33999 | 353 | * |
| <> | 149:156823d33999 | 354 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 355 | * @param[in] channel PWM channel number. |
| <> | 149:156823d33999 | 356 | * @param[in] ticks Number of clock ticks. |
| <> | 149:156823d33999 | 357 | */ |
| <> | 149:156823d33999 | 358 | static void pwm_transition_n_to_m(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 359 | uint8_t channel, uint16_t ticks) |
| <> | 149:156823d33999 | 360 | { |
| <> | 149:156823d33999 | 361 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 362 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 363 | nrf_ppi_channel_group_t p_ppigrp = p_cb->ppi_group; |
| <> | 149:156823d33999 | 364 | |
| <> | 149:156823d33999 | 365 | pwm_ppi_disable(p_instance); |
| <> | 149:156823d33999 | 366 | nrf_drv_ppi_group_clear(p_ppigrp); |
| <> | 149:156823d33999 | 367 | nrf_drv_ppi_channels_include_in_group( |
| <> | 149:156823d33999 | 368 | nrf_drv_ppi_channel_to_mask(p_cb->ppi_channels[0]) | |
| <> | 149:156823d33999 | 369 | nrf_drv_ppi_channel_to_mask(p_cb->ppi_channels[1]), |
| <> | 149:156823d33999 | 370 | p_ppigrp); |
| <> | 149:156823d33999 | 371 | |
| <> | 149:156823d33999 | 372 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 373 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL), |
| <> | 149:156823d33999 | 374 | nrf_drv_timer_capture_task_address_get(p_instance->p_timer, channel)); |
| <> | 149:156823d33999 | 375 | |
| <> | 149:156823d33999 | 376 | #ifdef NRF52 |
| <> | 149:156823d33999 | 377 | if (ticks + ((nrf_timer_frequency_get(p_instance->p_timer->p_reg) == |
| <> | 149:156823d33999 | 378 | (m_use_ppi_delay_workaround ? NRF_TIMER_FREQ_8MHz : NRF_TIMER_FREQ_16MHz) ) ? 1U : 0U) |
| <> | 149:156823d33999 | 379 | < p_ch_cb->pulsewidth) |
| <> | 149:156823d33999 | 380 | #else |
| <> | 149:156823d33999 | 381 | if (ticks + ((nrf_timer_frequency_get(p_instance->p_timer->p_reg) == NRF_TIMER_FREQ_16MHz) ? 1U : 0U) |
| <> | 149:156823d33999 | 382 | < p_ch_cb->pulsewidth) |
| <> | 149:156823d33999 | 383 | #endif |
| <> | 149:156823d33999 | 384 | { |
| <> | 149:156823d33999 | 385 | // For lower value, we need one more transition. Timer task delay is included. |
| <> | 149:156823d33999 | 386 | // If prescaler is disabled, one tick must be added because of 1 PCLK16M clock cycle delay. |
| <> | 149:156823d33999 | 387 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 388 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL), |
| <> | 149:156823d33999 | 389 | nrf_drv_gpiote_out_task_addr_get(p_ch_cb->gpio_pin)); |
| <> | 149:156823d33999 | 390 | } |
| <> | 149:156823d33999 | 391 | else |
| <> | 149:156823d33999 | 392 | { |
| <> | 149:156823d33999 | 393 | nrf_drv_ppi_channel_remove_from_group(p_cb->ppi_channels[1], p_ppigrp); |
| <> | 149:156823d33999 | 394 | } |
| <> | 149:156823d33999 | 395 | p_ch_cb->pulsewidth = ticks; |
| <> | 149:156823d33999 | 396 | nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, ticks, false); |
| <> | 149:156823d33999 | 397 | nrf_drv_ppi_group_enable(p_ppigrp); |
| <> | 149:156823d33999 | 398 | |
| <> | 149:156823d33999 | 399 | m_pwm_target_value[p_instance->p_timer->instance_id] = ticks; |
| <> | 149:156823d33999 | 400 | m_pwm_busy[p_instance->p_timer->instance_id] = channel; |
| <> | 149:156823d33999 | 401 | } |
| <> | 149:156823d33999 | 402 | |
| <> | 149:156823d33999 | 403 | |
| <> | 149:156823d33999 | 404 | /** |
| <> | 149:156823d33999 | 405 | * @brief PWM state transition from 0% or 100% to (0%, 100%). |
| <> | 149:156823d33999 | 406 | * |
| <> | 149:156823d33999 | 407 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 408 | * @param[in] channel PWM channel number. |
| <> | 149:156823d33999 | 409 | * @param[in] ticks Number of clock ticks. |
| <> | 149:156823d33999 | 410 | */ |
| <> | 149:156823d33999 | 411 | static void pwm_transition_0or100_to_n(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 412 | uint8_t channel, uint16_t ticks) |
| <> | 149:156823d33999 | 413 | { |
| <> | 149:156823d33999 | 414 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 415 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 416 | nrf_ppi_channel_group_t p_ppigrp = p_cb->ppi_group; |
| <> | 149:156823d33999 | 417 | nrf_timer_cc_channel_t pwm_ch_cc = (nrf_timer_cc_channel_t)(channel); |
| <> | 149:156823d33999 | 418 | |
| <> | 149:156823d33999 | 419 | pwm_ppi_disable(p_instance); |
| <> | 149:156823d33999 | 420 | pwm_channel_ppi_disable(p_instance, channel); |
| <> | 149:156823d33999 | 421 | |
| <> | 149:156823d33999 | 422 | nrf_drv_timer_compare(p_instance->p_timer, pwm_ch_cc, ticks, false); |
| <> | 149:156823d33999 | 423 | nrf_drv_ppi_group_clear(p_ppigrp); |
| <> | 149:156823d33999 | 424 | nrf_drv_ppi_channels_include_in_group( |
| <> | 149:156823d33999 | 425 | nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[0])| |
| <> | 149:156823d33999 | 426 | nrf_drv_ppi_channel_to_mask(p_ch_cb->ppi_channels[1]), |
| <> | 149:156823d33999 | 427 | p_ppigrp); |
| <> | 149:156823d33999 | 428 | |
| <> | 149:156823d33999 | 429 | if (!p_ch_cb->pulsewidth) |
| <> | 149:156823d33999 | 430 | { |
| <> | 149:156823d33999 | 431 | // Channel is at 0%. |
| <> | 149:156823d33999 | 432 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 433 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel), |
| <> | 149:156823d33999 | 434 | nrf_drv_ppi_task_addr_group_enable_get(p_ppigrp)); |
| <> | 149:156823d33999 | 435 | nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 0, false); |
| <> | 149:156823d33999 | 436 | m_pwm_target_value[p_instance->p_timer->instance_id] = |
| <> | 149:156823d33999 | 437 | nrf_drv_timer_capture_get(p_instance->p_timer, (nrf_timer_cc_channel_t) channel); |
| <> | 149:156823d33999 | 438 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 439 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel), |
| <> | 149:156823d33999 | 440 | nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL)); |
| <> | 149:156823d33999 | 441 | |
| <> | 149:156823d33999 | 442 | } |
| <> | 149:156823d33999 | 443 | else |
| <> | 149:156823d33999 | 444 | { |
| <> | 149:156823d33999 | 445 | // Channel is at 100%. |
| <> | 149:156823d33999 | 446 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 447 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL), |
| <> | 149:156823d33999 | 448 | nrf_drv_ppi_task_addr_group_enable_get(p_ppigrp)); |
| <> | 149:156823d33999 | 449 | // Set secondary CC channel to non-zero value: |
| <> | 149:156823d33999 | 450 | nrf_drv_timer_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_SECONDARY_CC_CHANNEL, 1, false); |
| <> | 149:156823d33999 | 451 | m_pwm_target_value[p_instance->p_timer->instance_id] = 0; |
| <> | 149:156823d33999 | 452 | // The captured value will be equal to 0, because timer clear on main PWM CC channel compare is enabled. |
| <> | 149:156823d33999 | 453 | nrf_drv_ppi_channel_assign(p_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 454 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL), |
| <> | 149:156823d33999 | 455 | nrf_drv_timer_capture_task_address_get(p_instance->p_timer, PWM_SECONDARY_CC_CHANNEL)); |
| <> | 149:156823d33999 | 456 | } |
| <> | 149:156823d33999 | 457 | nrf_drv_ppi_channel_enable(p_cb->ppi_channels[0]); |
| <> | 149:156823d33999 | 458 | nrf_drv_ppi_channel_enable(p_cb->ppi_channels[1]); |
| <> | 149:156823d33999 | 459 | |
| <> | 149:156823d33999 | 460 | p_ch_cb->pulsewidth = ticks; |
| <> | 149:156823d33999 | 461 | m_pwm_busy[p_instance->p_timer->instance_id] = PWM_SECONDARY_CC_CHANNEL; |
| <> | 149:156823d33999 | 462 | } |
| <> | 149:156823d33999 | 463 | |
| <> | 149:156823d33999 | 464 | |
| <> | 149:156823d33999 | 465 | /** |
| <> | 149:156823d33999 | 466 | * @brief PWM state transition from 0% or 100% to 0% or 100%. |
| <> | 149:156823d33999 | 467 | * |
| <> | 149:156823d33999 | 468 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 469 | * @param[in] channel PWM channel number. |
| <> | 149:156823d33999 | 470 | * @param[in] ticks Number of clock ticks. |
| <> | 149:156823d33999 | 471 | */ |
| <> | 149:156823d33999 | 472 | static void pwm_transition_0or100_to_0or100(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 473 | uint8_t channel, uint16_t ticks) |
| <> | 149:156823d33999 | 474 | { |
| <> | 149:156823d33999 | 475 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 476 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 477 | nrf_timer_cc_channel_t pwm_ch_cc = (nrf_timer_cc_channel_t)(channel); |
| <> | 149:156823d33999 | 478 | |
| <> | 149:156823d33999 | 479 | pwm_ppi_disable(p_instance); |
| <> | 149:156823d33999 | 480 | pwm_channel_ppi_disable(p_instance, channel); |
| <> | 149:156823d33999 | 481 | if (!ticks) |
| <> | 149:156823d33999 | 482 | { |
| <> | 149:156823d33999 | 483 | // Set to 0%. |
| <> | 149:156823d33999 | 484 | nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_INACTIVE(p_instance, channel)); |
| <> | 149:156823d33999 | 485 | } |
| <> | 149:156823d33999 | 486 | else if (ticks >= p_cb->period) |
| <> | 149:156823d33999 | 487 | { |
| <> | 149:156823d33999 | 488 | // Set to 100%. |
| <> | 149:156823d33999 | 489 | ticks = p_cb->period; |
| <> | 149:156823d33999 | 490 | nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_ACTIVE(p_instance, channel)); |
| <> | 149:156823d33999 | 491 | } |
| <> | 149:156823d33999 | 492 | nrf_drv_timer_compare(p_instance->p_timer, pwm_ch_cc, ticks, false); |
| <> | 149:156823d33999 | 493 | p_ch_cb->pulsewidth = ticks; |
| <> | 149:156823d33999 | 494 | |
| <> | 149:156823d33999 | 495 | m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE; |
| <> | 149:156823d33999 | 496 | return; |
| <> | 149:156823d33999 | 497 | } |
| <> | 149:156823d33999 | 498 | |
| <> | 149:156823d33999 | 499 | |
| <> | 149:156823d33999 | 500 | ret_code_t app_pwm_channel_duty_ticks_set(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 501 | uint8_t channel, |
| <> | 149:156823d33999 | 502 | uint16_t ticks) |
| <> | 149:156823d33999 | 503 | { |
| <> | 149:156823d33999 | 504 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 505 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 506 | |
| <> | 149:156823d33999 | 507 | ASSERT(channel < APP_PWM_CHANNELS_PER_INSTANCE); |
| <> | 149:156823d33999 | 508 | ASSERT(p_ch_cb->initialized == APP_PWM_CHANNEL_INITIALIZED); |
| <> | 149:156823d33999 | 509 | |
| <> | 149:156823d33999 | 510 | if (p_cb->state != NRF_DRV_STATE_POWERED_ON) |
| <> | 149:156823d33999 | 511 | { |
| <> | 149:156823d33999 | 512 | return NRF_ERROR_INVALID_STATE; |
| <> | 149:156823d33999 | 513 | } |
| <> | 149:156823d33999 | 514 | if (ticks == p_ch_cb->pulsewidth) |
| <> | 149:156823d33999 | 515 | { |
| <> | 149:156823d33999 | 516 | if (p_cb->p_ready_callback) |
| <> | 149:156823d33999 | 517 | { |
| <> | 149:156823d33999 | 518 | p_cb->p_ready_callback(p_instance->p_timer->instance_id); |
| <> | 149:156823d33999 | 519 | } |
| <> | 149:156823d33999 | 520 | return NRF_SUCCESS; // No action required. |
| <> | 149:156823d33999 | 521 | } |
| <> | 149:156823d33999 | 522 | if (app_pwm_busy_check(p_instance)) |
| <> | 149:156823d33999 | 523 | { |
| <> | 149:156823d33999 | 524 | return NRF_ERROR_BUSY; // PPI channels for synchronization are still in use. |
| <> | 149:156823d33999 | 525 | } |
| <> | 149:156823d33999 | 526 | |
| <> | 149:156823d33999 | 527 | m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_CHANGING; |
| <> | 149:156823d33999 | 528 | |
| <> | 149:156823d33999 | 529 | // Pulse width change sequence: |
| <> | 149:156823d33999 | 530 | if (!p_ch_cb->pulsewidth || p_ch_cb->pulsewidth >= p_cb->period) |
| <> | 149:156823d33999 | 531 | { |
| <> | 149:156823d33999 | 532 | // Channel is disabled (0%) or at 100%. |
| <> | 149:156823d33999 | 533 | if (!ticks || ticks >= p_cb->period) |
| <> | 149:156823d33999 | 534 | { |
| <> | 149:156823d33999 | 535 | // Set to 0 or 100%. |
| <> | 149:156823d33999 | 536 | pwm_transition_0or100_to_0or100(p_instance, channel, ticks); |
| <> | 149:156823d33999 | 537 | } |
| <> | 149:156823d33999 | 538 | else |
| <> | 149:156823d33999 | 539 | { |
| <> | 149:156823d33999 | 540 | // Other value. |
| <> | 149:156823d33999 | 541 | pwm_transition_0or100_to_n(p_instance, channel, ticks); |
| <> | 149:156823d33999 | 542 | } |
| <> | 149:156823d33999 | 543 | } |
| <> | 149:156823d33999 | 544 | else |
| <> | 149:156823d33999 | 545 | { |
| <> | 149:156823d33999 | 546 | // Channel is at other value. |
| <> | 149:156823d33999 | 547 | if (!ticks || ticks >= p_cb->period) |
| <> | 149:156823d33999 | 548 | { |
| <> | 149:156823d33999 | 549 | // Disable channel (set to 0%) or set to 100%. |
| <> | 149:156823d33999 | 550 | pwm_transition_n_to_0or100(p_instance, channel, ticks); |
| <> | 149:156823d33999 | 551 | } |
| <> | 149:156823d33999 | 552 | else |
| <> | 149:156823d33999 | 553 | { |
| <> | 149:156823d33999 | 554 | // Set to any other value. |
| <> | 149:156823d33999 | 555 | pwm_transition_n_to_m(p_instance, channel, ticks); |
| <> | 149:156823d33999 | 556 | } |
| <> | 149:156823d33999 | 557 | } |
| <> | 149:156823d33999 | 558 | if (p_instance->p_cb->p_ready_callback) |
| <> | 149:156823d33999 | 559 | { |
| <> | 149:156823d33999 | 560 | //PWM ready interrupt handler will be called after one full period. |
| <> | 149:156823d33999 | 561 | m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 2; |
| <> | 149:156823d33999 | 562 | pwm_irq_enable(p_instance); |
| <> | 149:156823d33999 | 563 | } |
| <> | 149:156823d33999 | 564 | return NRF_SUCCESS; |
| <> | 149:156823d33999 | 565 | } |
| <> | 149:156823d33999 | 566 | |
| <> | 149:156823d33999 | 567 | uint16_t app_pwm_channel_duty_ticks_get(app_pwm_t const * const p_instance, uint8_t channel) |
| <> | 149:156823d33999 | 568 | { |
| <> | 149:156823d33999 | 569 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 570 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 571 | |
| <> | 149:156823d33999 | 572 | return p_ch_cb->pulsewidth; |
| <> | 149:156823d33999 | 573 | } |
| <> | 149:156823d33999 | 574 | |
| <> | 149:156823d33999 | 575 | uint16_t app_pwm_cycle_ticks_get(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 576 | { |
| <> | 149:156823d33999 | 577 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 578 | |
| <> | 149:156823d33999 | 579 | return (uint16_t)p_cb->period; |
| <> | 149:156823d33999 | 580 | } |
| <> | 149:156823d33999 | 581 | |
| <> | 149:156823d33999 | 582 | ret_code_t app_pwm_channel_duty_set(app_pwm_t const * const p_instance, |
| <> | 149:156823d33999 | 583 | uint8_t channel, app_pwm_duty_t duty) |
| <> | 149:156823d33999 | 584 | { |
| <> | 149:156823d33999 | 585 | uint32_t ticks = ((uint32_t)app_pwm_cycle_ticks_get(p_instance) * (uint32_t)duty) / 100UL; |
| <> | 149:156823d33999 | 586 | return app_pwm_channel_duty_ticks_set(p_instance, channel, ticks); |
| <> | 149:156823d33999 | 587 | } |
| <> | 149:156823d33999 | 588 | |
| <> | 149:156823d33999 | 589 | |
| <> | 149:156823d33999 | 590 | app_pwm_duty_t app_pwm_channel_duty_get(app_pwm_t const * const p_instance, uint8_t channel) |
| <> | 149:156823d33999 | 591 | { |
| <> | 149:156823d33999 | 592 | uint32_t value = ((uint32_t)app_pwm_channel_duty_ticks_get(p_instance, channel) * 100UL) \ |
| <> | 149:156823d33999 | 593 | / (uint32_t)app_pwm_cycle_ticks_get(p_instance); |
| <> | 149:156823d33999 | 594 | |
| <> | 149:156823d33999 | 595 | return (app_pwm_duty_t)value; |
| <> | 149:156823d33999 | 596 | } |
| <> | 149:156823d33999 | 597 | |
| <> | 149:156823d33999 | 598 | |
| <> | 149:156823d33999 | 599 | /** |
| <> | 149:156823d33999 | 600 | * @brief Function for initializing the PWM channel. |
| <> | 149:156823d33999 | 601 | * |
| <> | 149:156823d33999 | 602 | * @param[in] p_instance PWM instance. |
| <> | 149:156823d33999 | 603 | * @param[in] channel Channel number. |
| <> | 149:156823d33999 | 604 | * @param[in] pin GPIO pin number. |
| <> | 149:156823d33999 | 605 | * |
| <> | 149:156823d33999 | 606 | * @retval NRF_SUCCESS If initialization was successful. |
| <> | 149:156823d33999 | 607 | * @retval NRF_ERROR_NO_MEM If there were not enough free resources. |
| <> | 149:156823d33999 | 608 | * @retval NRF_ERROR_INVALID_STATE If the timer is already in use or initialization failed. |
| <> | 149:156823d33999 | 609 | */ |
| <> | 149:156823d33999 | 610 | static ret_code_t app_pwm_channel_init(app_pwm_t const * const p_instance, uint8_t channel, |
| <> | 149:156823d33999 | 611 | uint32_t pin, app_pwm_polarity_t polarity) |
| <> | 149:156823d33999 | 612 | { |
| <> | 149:156823d33999 | 613 | ASSERT(channel < APP_PWM_CHANNELS_PER_INSTANCE); |
| <> | 149:156823d33999 | 614 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 615 | app_pwm_channel_cb_t * p_channel_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 616 | |
| <> | 149:156823d33999 | 617 | if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) |
| <> | 149:156823d33999 | 618 | { |
| <> | 149:156823d33999 | 619 | return NRF_ERROR_INVALID_STATE; |
| <> | 149:156823d33999 | 620 | } |
| <> | 149:156823d33999 | 621 | |
| <> | 149:156823d33999 | 622 | p_channel_cb->pulsewidth = 0; |
| <> | 149:156823d33999 | 623 | p_channel_cb->polarity = polarity; |
| <> | 149:156823d33999 | 624 | ret_code_t err_code; |
| <> | 149:156823d33999 | 625 | |
| <> | 149:156823d33999 | 626 | /* GPIOTE setup: */ |
| <> | 149:156823d33999 | 627 | nrf_drv_gpiote_out_config_t out_cfg = GPIOTE_CONFIG_OUT_TASK_TOGGLE( POLARITY_INACTIVE(p_instance, channel) ); |
| <> | 149:156823d33999 | 628 | err_code = nrf_drv_gpiote_out_init((nrf_drv_gpiote_pin_t)pin,&out_cfg); |
| <> | 149:156823d33999 | 629 | if (err_code != NRF_SUCCESS) |
| <> | 149:156823d33999 | 630 | { |
| <> | 149:156823d33999 | 631 | return NRF_ERROR_NO_MEM; |
| <> | 149:156823d33999 | 632 | } |
| <> | 149:156823d33999 | 633 | p_cb->channels_cb[channel].gpio_pin = pin; |
| <> | 149:156823d33999 | 634 | |
| <> | 149:156823d33999 | 635 | // Set output to inactive state. |
| <> | 149:156823d33999 | 636 | if (polarity) |
| <> | 149:156823d33999 | 637 | { |
| <> | 149:156823d33999 | 638 | nrf_gpio_pin_clear(pin); |
| <> | 149:156823d33999 | 639 | } |
| <> | 149:156823d33999 | 640 | else |
| <> | 149:156823d33999 | 641 | { |
| <> | 149:156823d33999 | 642 | nrf_gpio_pin_set(pin); |
| <> | 149:156823d33999 | 643 | } |
| <> | 149:156823d33999 | 644 | |
| <> | 149:156823d33999 | 645 | /* PPI setup: */ |
| <> | 149:156823d33999 | 646 | for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_CHANNEL; ++i) |
| <> | 149:156823d33999 | 647 | { |
| <> | 149:156823d33999 | 648 | if (nrf_drv_ppi_channel_alloc(&p_channel_cb->ppi_channels[i]) != NRF_SUCCESS) |
| <> | 149:156823d33999 | 649 | { |
| <> | 149:156823d33999 | 650 | return NRF_ERROR_NO_MEM; // Resource de-allocation is done by callee. |
| <> | 149:156823d33999 | 651 | } |
| <> | 149:156823d33999 | 652 | } |
| <> | 149:156823d33999 | 653 | |
| <> | 149:156823d33999 | 654 | nrf_drv_ppi_channel_disable(p_channel_cb->ppi_channels[0]); |
| <> | 149:156823d33999 | 655 | nrf_drv_ppi_channel_disable(p_channel_cb->ppi_channels[1]); |
| <> | 149:156823d33999 | 656 | nrf_drv_ppi_channel_assign(p_channel_cb->ppi_channels[0], |
| <> | 149:156823d33999 | 657 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, channel), |
| <> | 149:156823d33999 | 658 | nrf_drv_gpiote_out_task_addr_get(p_channel_cb->gpio_pin)); |
| <> | 149:156823d33999 | 659 | nrf_drv_ppi_channel_assign(p_channel_cb->ppi_channels[1], |
| <> | 149:156823d33999 | 660 | nrf_drv_timer_compare_event_address_get(p_instance->p_timer, PWM_MAIN_CC_CHANNEL), |
| <> | 149:156823d33999 | 661 | nrf_drv_gpiote_out_task_addr_get(p_channel_cb->gpio_pin)); |
| <> | 149:156823d33999 | 662 | |
| <> | 149:156823d33999 | 663 | p_channel_cb->initialized = APP_PWM_CHANNEL_INITIALIZED; |
| <> | 149:156823d33999 | 664 | m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 0; |
| <> | 149:156823d33999 | 665 | |
| <> | 149:156823d33999 | 666 | return NRF_SUCCESS; |
| <> | 149:156823d33999 | 667 | } |
| <> | 149:156823d33999 | 668 | |
| <> | 149:156823d33999 | 669 | |
| <> | 149:156823d33999 | 670 | /** |
| <> | 149:156823d33999 | 671 | * @brief Function for calculating target timer frequency, which will allow to set given period length. |
| <> | 149:156823d33999 | 672 | * |
| <> | 149:156823d33999 | 673 | * @param[in] period_us Desired period in microseconds. |
| <> | 149:156823d33999 | 674 | * |
| <> | 149:156823d33999 | 675 | * @retval Timer frequency. |
| <> | 149:156823d33999 | 676 | */ |
| <> | 149:156823d33999 | 677 | __STATIC_INLINE nrf_timer_frequency_t pwm_calculate_timer_frequency(uint32_t period_us) |
| <> | 149:156823d33999 | 678 | { |
| <> | 149:156823d33999 | 679 | uint32_t f = (uint32_t) NRF_TIMER_FREQ_16MHz; |
| <> | 149:156823d33999 | 680 | uint32_t min = (uint32_t) NRF_TIMER_FREQ_31250Hz; |
| <> | 149:156823d33999 | 681 | |
| <> | 149:156823d33999 | 682 | while ((period_us > TIMER_MAX_PULSEWIDTH_US_ON_16M) && (f < min)) |
| <> | 149:156823d33999 | 683 | { |
| <> | 149:156823d33999 | 684 | period_us >>= 1; |
| <> | 149:156823d33999 | 685 | ++f; |
| <> | 149:156823d33999 | 686 | } |
| <> | 149:156823d33999 | 687 | |
| <> | 149:156823d33999 | 688 | #ifdef NRF52 |
| <> | 149:156823d33999 | 689 | if ((m_use_ppi_delay_workaround) && (f == (uint32_t) NRF_TIMER_FREQ_16MHz)) |
| <> | 149:156823d33999 | 690 | { |
| <> | 149:156823d33999 | 691 | f = (uint32_t) NRF_TIMER_FREQ_8MHz; |
| <> | 149:156823d33999 | 692 | } |
| <> | 149:156823d33999 | 693 | #endif |
| <> | 149:156823d33999 | 694 | |
| <> | 149:156823d33999 | 695 | return (nrf_timer_frequency_t) f; |
| <> | 149:156823d33999 | 696 | } |
| <> | 149:156823d33999 | 697 | |
| <> | 149:156823d33999 | 698 | |
| <> | 149:156823d33999 | 699 | ret_code_t app_pwm_init(app_pwm_t const * const p_instance, app_pwm_config_t const * const p_config, |
| <> | 149:156823d33999 | 700 | app_pwm_callback_t p_ready_callback) |
| <> | 149:156823d33999 | 701 | { |
| <> | 149:156823d33999 | 702 | ASSERT(p_instance); |
| <> | 149:156823d33999 | 703 | |
| <> | 149:156823d33999 | 704 | if (!p_config) |
| <> | 149:156823d33999 | 705 | { |
| <> | 149:156823d33999 | 706 | return NRF_ERROR_INVALID_DATA; |
| <> | 149:156823d33999 | 707 | } |
| <> | 149:156823d33999 | 708 | |
| <> | 149:156823d33999 | 709 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 710 | |
| <> | 149:156823d33999 | 711 | if (p_cb->state != NRF_DRV_STATE_UNINITIALIZED) |
| <> | 149:156823d33999 | 712 | { |
| <> | 149:156823d33999 | 713 | return NRF_ERROR_INVALID_STATE; |
| <> | 149:156823d33999 | 714 | } |
| <> | 149:156823d33999 | 715 | |
| <> | 149:156823d33999 | 716 | uint32_t err_code = nrf_drv_ppi_init(); |
| <> | 149:156823d33999 | 717 | if ((err_code != NRF_SUCCESS) && (err_code != MODULE_ALREADY_INITIALIZED)) |
| <> | 149:156823d33999 | 718 | { |
| <> | 149:156823d33999 | 719 | return NRF_ERROR_NO_MEM; |
| <> | 149:156823d33999 | 720 | } |
| <> | 149:156823d33999 | 721 | |
| <> | 149:156823d33999 | 722 | |
| <> | 149:156823d33999 | 723 | if (!nrf_drv_gpiote_is_init()) |
| <> | 149:156823d33999 | 724 | { |
| <> | 149:156823d33999 | 725 | err_code = nrf_drv_gpiote_init(); |
| <> | 149:156823d33999 | 726 | if (err_code != NRF_SUCCESS) |
| <> | 149:156823d33999 | 727 | { |
| <> | 149:156823d33999 | 728 | return NRF_ERROR_INTERNAL; |
| <> | 149:156823d33999 | 729 | } |
| <> | 149:156823d33999 | 730 | } |
| <> | 149:156823d33999 | 731 | |
| <> | 149:156823d33999 | 732 | #ifdef NRF52 |
| <> | 149:156823d33999 | 733 | if (((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30) |
| <> | 149:156823d33999 | 734 | { |
| <> | 149:156823d33999 | 735 | m_use_ppi_delay_workaround = false; |
| <> | 149:156823d33999 | 736 | } |
| <> | 149:156823d33999 | 737 | else |
| <> | 149:156823d33999 | 738 | { |
| <> | 149:156823d33999 | 739 | m_use_ppi_delay_workaround = true; |
| <> | 149:156823d33999 | 740 | } |
| <> | 149:156823d33999 | 741 | #endif |
| <> | 149:156823d33999 | 742 | |
| <> | 149:156823d33999 | 743 | // Innitialize resource status: |
| <> | 149:156823d33999 | 744 | p_cb->ppi_channels[0] = (nrf_ppi_channel_t)UNALLOCATED; |
| <> | 149:156823d33999 | 745 | p_cb->ppi_channels[1] = (nrf_ppi_channel_t)UNALLOCATED; |
| <> | 149:156823d33999 | 746 | p_cb->ppi_group = (nrf_ppi_channel_group_t)UNALLOCATED; |
| <> | 149:156823d33999 | 747 | |
| <> | 149:156823d33999 | 748 | for (uint8_t i = 0; i < APP_PWM_CHANNELS_PER_INSTANCE; ++i) |
| <> | 149:156823d33999 | 749 | { |
| <> | 149:156823d33999 | 750 | p_cb->channels_cb[i].initialized = APP_PWM_CHANNEL_UNINITIALIZED; |
| <> | 149:156823d33999 | 751 | p_cb->channels_cb[i].ppi_channels[0] = (nrf_ppi_channel_t)UNALLOCATED; |
| <> | 149:156823d33999 | 752 | p_cb->channels_cb[i].ppi_channels[1] = (nrf_ppi_channel_t)UNALLOCATED; |
| <> | 149:156823d33999 | 753 | p_cb->channels_cb[i].gpio_pin = UNALLOCATED; |
| <> | 149:156823d33999 | 754 | } |
| <> | 149:156823d33999 | 755 | |
| <> | 149:156823d33999 | 756 | // Allocate PPI channels and groups: |
| <> | 149:156823d33999 | 757 | for (uint8_t i = 0; i < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++i) |
| <> | 149:156823d33999 | 758 | { |
| <> | 149:156823d33999 | 759 | if (nrf_drv_ppi_channel_alloc(&p_cb->ppi_channels[i]) != NRF_SUCCESS) |
| <> | 149:156823d33999 | 760 | { |
| <> | 149:156823d33999 | 761 | pwm_dealloc(p_instance); |
| <> | 149:156823d33999 | 762 | return NRF_ERROR_NO_MEM; |
| <> | 149:156823d33999 | 763 | } |
| <> | 149:156823d33999 | 764 | } |
| <> | 149:156823d33999 | 765 | if (nrf_drv_ppi_group_alloc(&p_cb->ppi_group) != NRF_SUCCESS) |
| <> | 149:156823d33999 | 766 | { |
| <> | 149:156823d33999 | 767 | pwm_dealloc(p_instance); |
| <> | 149:156823d33999 | 768 | return NRF_ERROR_NO_MEM; |
| <> | 149:156823d33999 | 769 | } |
| <> | 149:156823d33999 | 770 | |
| <> | 149:156823d33999 | 771 | // Initialize channels: |
| <> | 149:156823d33999 | 772 | for (uint8_t i = 0; i < APP_PWM_CHANNELS_PER_INSTANCE; ++i) |
| <> | 149:156823d33999 | 773 | { |
| <> | 149:156823d33999 | 774 | if (p_config->pins[i] != APP_PWM_NOPIN) |
| <> | 149:156823d33999 | 775 | { |
| <> | 149:156823d33999 | 776 | err_code = app_pwm_channel_init(p_instance, i, p_config->pins[i], p_config->pin_polarity[i]); |
| <> | 149:156823d33999 | 777 | if (err_code != NRF_SUCCESS) |
| <> | 149:156823d33999 | 778 | { |
| <> | 149:156823d33999 | 779 | pwm_dealloc(p_instance); |
| <> | 149:156823d33999 | 780 | return err_code; |
| <> | 149:156823d33999 | 781 | } |
| <> | 149:156823d33999 | 782 | app_pwm_channel_duty_ticks_set(p_instance, i, 0); |
| <> | 149:156823d33999 | 783 | } |
| <> | 149:156823d33999 | 784 | } |
| <> | 149:156823d33999 | 785 | |
| <> | 149:156823d33999 | 786 | // Initialize timer: |
| <> | 149:156823d33999 | 787 | nrf_timer_frequency_t timer_freq = pwm_calculate_timer_frequency(p_config->period_us); |
| <> | 149:156823d33999 | 788 | nrf_drv_timer_config_t timer_cfg = { |
| <> | 149:156823d33999 | 789 | .frequency = timer_freq, |
| <> | 149:156823d33999 | 790 | .mode = NRF_TIMER_MODE_TIMER, |
| <> | 149:156823d33999 | 791 | .bit_width = NRF_TIMER_BIT_WIDTH_16, |
| <> | 150:02e0a0aed4ec | 792 | #ifdef NRF51 |
| <> | 149:156823d33999 | 793 | .interrupt_priority = APP_IRQ_PRIORITY_LOW, |
| <> | 150:02e0a0aed4ec | 794 | #elif defined(NRF52) |
| <> | 150:02e0a0aed4ec | 795 | .interrupt_priority = APP_IRQ_PRIORITY_LOWEST, |
| <> | 150:02e0a0aed4ec | 796 | #endif |
| <> | 149:156823d33999 | 797 | .p_context = (void *) (uint32_t) p_instance->p_timer->instance_id |
| <> | 149:156823d33999 | 798 | }; |
| <> | 149:156823d33999 | 799 | err_code = nrf_drv_timer_init(p_instance->p_timer, &timer_cfg, |
| <> | 149:156823d33999 | 800 | pwm_ready_tick); |
| <> | 149:156823d33999 | 801 | if (err_code != NRF_SUCCESS) |
| <> | 149:156823d33999 | 802 | { |
| <> | 149:156823d33999 | 803 | pwm_dealloc(p_instance); |
| <> | 149:156823d33999 | 804 | return err_code; |
| <> | 149:156823d33999 | 805 | } |
| <> | 149:156823d33999 | 806 | |
| <> | 149:156823d33999 | 807 | uint32_t ticks = nrf_drv_timer_us_to_ticks(p_instance->p_timer, p_config->period_us); |
| <> | 149:156823d33999 | 808 | p_cb->period = ticks; |
| <> | 149:156823d33999 | 809 | nrf_drv_timer_clear(p_instance->p_timer); |
| <> | 149:156823d33999 | 810 | nrf_drv_timer_extended_compare(p_instance->p_timer, (nrf_timer_cc_channel_t) PWM_MAIN_CC_CHANNEL, |
| <> | 149:156823d33999 | 811 | ticks, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true); |
| <> | 149:156823d33999 | 812 | nrf_drv_timer_compare_int_disable(p_instance->p_timer, PWM_MAIN_CC_CHANNEL); |
| <> | 149:156823d33999 | 813 | |
| <> | 149:156823d33999 | 814 | p_cb->p_ready_callback = p_ready_callback; |
| <> | 149:156823d33999 | 815 | m_instances[p_instance->p_timer->instance_id] = p_instance; |
| <> | 149:156823d33999 | 816 | m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE; |
| <> | 149:156823d33999 | 817 | p_cb->state = NRF_DRV_STATE_INITIALIZED; |
| <> | 149:156823d33999 | 818 | |
| <> | 149:156823d33999 | 819 | return NRF_SUCCESS; |
| <> | 149:156823d33999 | 820 | } |
| <> | 149:156823d33999 | 821 | |
| <> | 149:156823d33999 | 822 | |
| <> | 149:156823d33999 | 823 | void app_pwm_enable(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 824 | { |
| <> | 149:156823d33999 | 825 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 826 | |
| <> | 149:156823d33999 | 827 | ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); |
| <> | 149:156823d33999 | 828 | |
| <> | 149:156823d33999 | 829 | for (uint32_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel) |
| <> | 149:156823d33999 | 830 | { |
| <> | 149:156823d33999 | 831 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 832 | m_pwm_ready_counter[p_instance->p_timer->instance_id][channel] = 0; |
| <> | 149:156823d33999 | 833 | if (p_ch_cb->initialized) |
| <> | 149:156823d33999 | 834 | { |
| <> | 149:156823d33999 | 835 | nrf_drv_gpiote_out_task_force(p_ch_cb->gpio_pin, POLARITY_INACTIVE(p_instance, channel)); |
| <> | 149:156823d33999 | 836 | nrf_drv_gpiote_out_task_enable(p_ch_cb->gpio_pin); |
| <> | 149:156823d33999 | 837 | p_ch_cb->pulsewidth = 0; |
| <> | 149:156823d33999 | 838 | } |
| <> | 149:156823d33999 | 839 | } |
| <> | 149:156823d33999 | 840 | m_pwm_busy[p_instance->p_timer->instance_id] = BUSY_STATE_IDLE; |
| <> | 149:156823d33999 | 841 | pan73_workaround(p_instance->p_timer->p_reg, true); |
| <> | 149:156823d33999 | 842 | nrf_drv_timer_clear(p_instance->p_timer); |
| <> | 149:156823d33999 | 843 | nrf_drv_timer_enable(p_instance->p_timer); |
| <> | 149:156823d33999 | 844 | |
| <> | 149:156823d33999 | 845 | p_cb->state = NRF_DRV_STATE_POWERED_ON; |
| <> | 149:156823d33999 | 846 | return; |
| <> | 149:156823d33999 | 847 | } |
| <> | 149:156823d33999 | 848 | |
| <> | 149:156823d33999 | 849 | |
| <> | 149:156823d33999 | 850 | void app_pwm_disable(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 851 | { |
| <> | 149:156823d33999 | 852 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 853 | |
| <> | 149:156823d33999 | 854 | ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED); |
| <> | 149:156823d33999 | 855 | |
| <> | 149:156823d33999 | 856 | nrf_drv_timer_disable(p_instance->p_timer); |
| <> | 149:156823d33999 | 857 | pwm_irq_disable(p_instance); |
| <> | 149:156823d33999 | 858 | for (uint8_t ppi_channel = 0; ppi_channel < APP_PWM_REQUIRED_PPI_CHANNELS_PER_INSTANCE; ++ppi_channel) |
| <> | 149:156823d33999 | 859 | { |
| <> | 149:156823d33999 | 860 | nrf_drv_ppi_channel_disable(p_cb->ppi_channels[ppi_channel]); |
| <> | 149:156823d33999 | 861 | } |
| <> | 149:156823d33999 | 862 | for (uint8_t channel = 0; channel < APP_PWM_CHANNELS_PER_INSTANCE; ++channel) |
| <> | 149:156823d33999 | 863 | { |
| <> | 149:156823d33999 | 864 | app_pwm_channel_cb_t * p_ch_cb = &p_cb->channels_cb[channel]; |
| <> | 149:156823d33999 | 865 | if (p_ch_cb->initialized) |
| <> | 149:156823d33999 | 866 | { |
| <> | 149:156823d33999 | 867 | uint8_t polarity = POLARITY_INACTIVE(p_instance, channel); |
| <> | 149:156823d33999 | 868 | if (polarity) |
| <> | 149:156823d33999 | 869 | { |
| <> | 149:156823d33999 | 870 | nrf_gpio_pin_set(p_ch_cb->gpio_pin); |
| <> | 149:156823d33999 | 871 | } |
| <> | 149:156823d33999 | 872 | else |
| <> | 149:156823d33999 | 873 | { |
| <> | 149:156823d33999 | 874 | nrf_gpio_pin_clear(p_ch_cb->gpio_pin); |
| <> | 149:156823d33999 | 875 | } |
| <> | 149:156823d33999 | 876 | nrf_drv_gpiote_out_task_disable(p_ch_cb->gpio_pin); |
| <> | 149:156823d33999 | 877 | nrf_drv_ppi_channel_disable(p_ch_cb->ppi_channels[0]); |
| <> | 149:156823d33999 | 878 | nrf_drv_ppi_channel_disable(p_ch_cb->ppi_channels[1]); |
| <> | 149:156823d33999 | 879 | } |
| <> | 149:156823d33999 | 880 | } |
| <> | 149:156823d33999 | 881 | pan73_workaround(p_instance->p_timer->p_reg, false); |
| <> | 149:156823d33999 | 882 | |
| <> | 149:156823d33999 | 883 | p_cb->state = NRF_DRV_STATE_INITIALIZED; |
| <> | 149:156823d33999 | 884 | return; |
| <> | 149:156823d33999 | 885 | } |
| <> | 149:156823d33999 | 886 | |
| <> | 149:156823d33999 | 887 | |
| <> | 149:156823d33999 | 888 | ret_code_t app_pwm_uninit(app_pwm_t const * const p_instance) |
| <> | 149:156823d33999 | 889 | { |
| <> | 149:156823d33999 | 890 | app_pwm_cb_t * p_cb = p_instance->p_cb; |
| <> | 149:156823d33999 | 891 | |
| <> | 149:156823d33999 | 892 | if (p_cb->state == NRF_DRV_STATE_POWERED_ON) |
| <> | 149:156823d33999 | 893 | { |
| <> | 149:156823d33999 | 894 | app_pwm_disable(p_instance); |
| <> | 149:156823d33999 | 895 | } |
| <> | 149:156823d33999 | 896 | else if (p_cb->state == NRF_DRV_STATE_UNINITIALIZED) |
| <> | 149:156823d33999 | 897 | { |
| <> | 149:156823d33999 | 898 | return NRF_ERROR_INVALID_STATE; |
| <> | 149:156823d33999 | 899 | } |
| <> | 149:156823d33999 | 900 | pwm_dealloc(p_instance); |
| <> | 149:156823d33999 | 901 | |
| <> | 149:156823d33999 | 902 | p_cb->state = NRF_DRV_STATE_UNINITIALIZED; |
| <> | 149:156823d33999 | 903 | return NRF_SUCCESS; |
| <> | 149:156823d33999 | 904 | } |
| <> | 149:156823d33999 | 905 | |
| <> | 149:156823d33999 | 906 | |
| <> | 149:156823d33999 | 907 | //lint -restore |
