Timer based PWM output for MAX326XXFTHR platforms
Dependents: MAX32620FTHR_PwmBlinky
Fork of MAX326XXFTHR_PwmOut by
This library provides PWM output using the MAX32620/MAX32630 32-bit timers.
The mbed PwmOut API implementation uses Pulse Train peripherals.
The tables below contain the available GPIO pins that can be connected to the six 32-bit timers (TMR0-5). Timer 0 is used for the microsecond ticker API and is not available for PWM output. On the MAX32630FTHR platform, timer 5 is used by the BLE API and will not be available for PWM output if the BLE API is used.
MAX32620FTHR 32-Bit Timer PWM Mapping
Timer | GPIO Port and Pin |
TMR1 | P0_1, P0_7, P1_5, P3_1, P4_5, P5_3 |
TMR2 | P0_2, P1_0, P1_6, P2_4, P3_2, P4_0, P4_6, P5_4 |
TMR3 | P0_3, P1_1, P1_7, P2_5, P3_3, P4_7, P5_5 |
TMR4 | P0_4, P1_2, P2_6, P3_4, P5_0, P5_6 |
TMR5 | P0_5, P1_3, P2_7, P3_5, P5_1, P5_7 |
MAX32630FTHR 32-Bit Timer PWM Mapping
Timer | GPIO Port and Pin |
TMR1 | P3_1, P5_3 |
TMR2 | P2_4, P3_2, P4_0, P5_4 |
TMR3 | P2_5, P3_3, P5_5 |
TMR4 | P2_6, P3_4, P5_0, P5_6 |
TMR5 | P3_5, P5_1 |
Note GPIO P2_4, P2_5 and P2_6 are connected to onboard LEDs 1, 2 and 3.
MAX326XXFTHR_PwmOut.cpp@0:bb005bb0a24c, 2018-04-23 (annotated)
- Committer:
- jessexm
- Date:
- Mon Apr 23 18:24:11 2018 +0000
- Revision:
- 0:bb005bb0a24c
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jessexm | 0:bb005bb0a24c | 1 | /******************************************************************************* |
jessexm | 0:bb005bb0a24c | 2 | * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. |
jessexm | 0:bb005bb0a24c | 3 | * |
jessexm | 0:bb005bb0a24c | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
jessexm | 0:bb005bb0a24c | 5 | * copy of this software and associated documentation files (the "Software"), |
jessexm | 0:bb005bb0a24c | 6 | * to deal in the Software without restriction, including without limitation |
jessexm | 0:bb005bb0a24c | 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
jessexm | 0:bb005bb0a24c | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
jessexm | 0:bb005bb0a24c | 9 | * Software is furnished to do so, subject to the following conditions: |
jessexm | 0:bb005bb0a24c | 10 | * |
jessexm | 0:bb005bb0a24c | 11 | * The above copyright notice and this permission notice shall be included |
jessexm | 0:bb005bb0a24c | 12 | * in all copies or substantial portions of the Software. |
jessexm | 0:bb005bb0a24c | 13 | * |
jessexm | 0:bb005bb0a24c | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
jessexm | 0:bb005bb0a24c | 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
jessexm | 0:bb005bb0a24c | 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
jessexm | 0:bb005bb0a24c | 17 | * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES |
jessexm | 0:bb005bb0a24c | 18 | * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
jessexm | 0:bb005bb0a24c | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
jessexm | 0:bb005bb0a24c | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
jessexm | 0:bb005bb0a24c | 21 | * |
jessexm | 0:bb005bb0a24c | 22 | * Except as contained in this notice, the name of Maxim Integrated |
jessexm | 0:bb005bb0a24c | 23 | * Products, Inc. shall not be used except as stated in the Maxim Integrated |
jessexm | 0:bb005bb0a24c | 24 | * Products, Inc. Branding Policy. |
jessexm | 0:bb005bb0a24c | 25 | * |
jessexm | 0:bb005bb0a24c | 26 | * The mere transfer of this software does not imply any licenses |
jessexm | 0:bb005bb0a24c | 27 | * of trade secrets, proprietary technology, copyrights, patents, |
jessexm | 0:bb005bb0a24c | 28 | * trademarks, maskwork rights, or any other form of intellectual |
jessexm | 0:bb005bb0a24c | 29 | * property whatsoever. Maxim Integrated Products, Inc. retains all |
jessexm | 0:bb005bb0a24c | 30 | * ownership rights. |
jessexm | 0:bb005bb0a24c | 31 | ******************************************************************************* |
jessexm | 0:bb005bb0a24c | 32 | */ |
jessexm | 0:bb005bb0a24c | 33 | |
jessexm | 0:bb005bb0a24c | 34 | #include "MAX326XXFTHR_PwmOut.h" |
jessexm | 0:bb005bb0a24c | 35 | #include "mbed_assert.h" |
jessexm | 0:bb005bb0a24c | 36 | #include "pinmap.h" |
jessexm | 0:bb005bb0a24c | 37 | #include "gpio_regs.h" |
jessexm | 0:bb005bb0a24c | 38 | #include "tmr_regs.h" |
jessexm | 0:bb005bb0a24c | 39 | |
jessexm | 0:bb005bb0a24c | 40 | #define PWM_TMR_PRESCALE MXC_V_TMR_CTRL_PRESCALE_DIVIDE_BY_4 |
jessexm | 0:bb005bb0a24c | 41 | #define PWM_TICKS_PER_US ((SystemCoreClock / 1000000) >> PWM_TMR_PRESCALE) |
jessexm | 0:bb005bb0a24c | 42 | #define PWM_MAX_US (0xFFFFFFFFUL / PWM_TICKS_PER_US) |
jessexm | 0:bb005bb0a24c | 43 | |
jessexm | 0:bb005bb0a24c | 44 | #define MXC_GPIO_OUT_MODE_FIELD_WIDTH 4 |
jessexm | 0:bb005bb0a24c | 45 | #define MXC_GPIO_OUT_MODE_FIELD_MASK ((uint32_t)0xFFFFFFFF >> (32 - MXC_GPIO_OUT_MODE_FIELD_WIDTH)) |
jessexm | 0:bb005bb0a24c | 46 | #define MXC_GPIO_FUNC_SEL_FIELD_WIDTH 4 |
jessexm | 0:bb005bb0a24c | 47 | #define MXC_GPIO_FUNC_SEL_FIELD_MASK ((uint32_t)0xFFFFFFFF >> (32 - MXC_GPIO_FUNC_SEL_FIELD_WIDTH)) |
jessexm | 0:bb005bb0a24c | 48 | |
jessexm | 0:bb005bb0a24c | 49 | static const PinMap PinMap_PWM[] = { |
jessexm | 0:bb005bb0a24c | 50 | #if defined(TARGET_MAX32620FTHR) |
jessexm | 0:bb005bb0a24c | 51 | // Timer 0 not available; used for micro-second ticker |
jessexm | 0:bb005bb0a24c | 52 | { P0_1, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 53 | { P0_2, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 54 | { P0_3, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 55 | { P0_4, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 56 | { P0_5, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 57 | { P0_7, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 58 | { P1_0, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 59 | { P1_1, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 60 | { P1_2, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 61 | { P1_3, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 62 | { P1_5, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 63 | { P1_6, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 64 | { P1_7, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 65 | { P2_4, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 66 | { P2_5, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 67 | { P2_6, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 68 | { P2_7, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 69 | { P3_1, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 70 | { P3_2, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 71 | { P3_3, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 72 | { P3_4, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 73 | { P3_5, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 74 | { P4_0, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 75 | { P4_5, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 76 | { P4_6, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 77 | { P4_7, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 78 | { P5_0, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 79 | { P5_1, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 80 | { P5_3, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 81 | { P5_4, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 82 | { P5_5, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 83 | { P5_6, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 84 | { P5_7, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 85 | #elif defined(TARGET_MAX32630FTHR) |
jessexm | 0:bb005bb0a24c | 86 | // Timer 0 not available; used for micro-second ticker |
jessexm | 0:bb005bb0a24c | 87 | // Timer 5 not available if using BLE |
jessexm | 0:bb005bb0a24c | 88 | { P2_4, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 89 | { P2_5, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 90 | { P2_6, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 91 | { P3_1, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 92 | { P3_2, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 93 | { P3_3, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 94 | { P3_4, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 95 | { P3_5, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 96 | { P4_0, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 97 | { P5_0, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 98 | { P5_1, MXC_BASE_TMR5, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 99 | { P5_3, MXC_BASE_TMR1, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 100 | { P5_4, MXC_BASE_TMR2, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 101 | { P5_5, MXC_BASE_TMR3, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 102 | { P5_6, MXC_BASE_TMR4, MXC_V_GPIO_FUNC_SEL_MODE_TMR }, |
jessexm | 0:bb005bb0a24c | 103 | #else |
jessexm | 0:bb005bb0a24c | 104 | // Platform not supported |
jessexm | 0:bb005bb0a24c | 105 | #endif |
jessexm | 0:bb005bb0a24c | 106 | { NC, NC, 0 } |
jessexm | 0:bb005bb0a24c | 107 | }; |
jessexm | 0:bb005bb0a24c | 108 | |
jessexm | 0:bb005bb0a24c | 109 | typedef struct { |
jessexm | 0:bb005bb0a24c | 110 | mxc_tmr_regs_t *tmr; |
jessexm | 0:bb005bb0a24c | 111 | uint32_t term_cnt32; |
jessexm | 0:bb005bb0a24c | 112 | uint32_t pwm_cap32; |
jessexm | 0:bb005bb0a24c | 113 | unsigned int port; |
jessexm | 0:bb005bb0a24c | 114 | unsigned int port_pin; |
jessexm | 0:bb005bb0a24c | 115 | } tmr_obj_t; |
jessexm | 0:bb005bb0a24c | 116 | |
jessexm | 0:bb005bb0a24c | 117 | static tmr_obj_t tmr_obj[MXC_CFG_TMR_INSTANCES]; |
jessexm | 0:bb005bb0a24c | 118 | |
jessexm | 0:bb005bb0a24c | 119 | static void tmr_handler(tmr_obj_t *obj) |
jessexm | 0:bb005bb0a24c | 120 | { |
jessexm | 0:bb005bb0a24c | 121 | mxc_tmr_regs_t *tmr = obj->tmr; |
jessexm | 0:bb005bb0a24c | 122 | |
jessexm | 0:bb005bb0a24c | 123 | // Assert GPIO control to have steady state low/zero percent duty-cycle |
jessexm | 0:bb005bb0a24c | 124 | // Update function required to restore timer control of pin |
jessexm | 0:bb005bb0a24c | 125 | if (obj->pwm_cap32 == 0) { |
jessexm | 0:bb005bb0a24c | 126 | MXC_GPIO->func_sel[obj->port] &= ~(MXC_GPIO_FUNC_SEL_FIELD_MASK << (MXC_GPIO_FUNC_SEL_FIELD_WIDTH * obj->port_pin)); |
jessexm | 0:bb005bb0a24c | 127 | } else { |
jessexm | 0:bb005bb0a24c | 128 | tmr->term_cnt32 = obj->term_cnt32; |
jessexm | 0:bb005bb0a24c | 129 | tmr->pwm_cap32 = obj->pwm_cap32; |
jessexm | 0:bb005bb0a24c | 130 | } |
jessexm | 0:bb005bb0a24c | 131 | |
jessexm | 0:bb005bb0a24c | 132 | tmr->intfl = 1; |
jessexm | 0:bb005bb0a24c | 133 | tmr->inten = 0; |
jessexm | 0:bb005bb0a24c | 134 | } |
jessexm | 0:bb005bb0a24c | 135 | |
jessexm | 0:bb005bb0a24c | 136 | static void tmr1_handler(void) { tmr_handler(&tmr_obj[1]); }; |
jessexm | 0:bb005bb0a24c | 137 | static void tmr2_handler(void) { tmr_handler(&tmr_obj[2]); }; |
jessexm | 0:bb005bb0a24c | 138 | static void tmr3_handler(void) { tmr_handler(&tmr_obj[3]); }; |
jessexm | 0:bb005bb0a24c | 139 | static void tmr4_handler(void) { tmr_handler(&tmr_obj[4]); }; |
jessexm | 0:bb005bb0a24c | 140 | static void tmr5_handler(void) { tmr_handler(&tmr_obj[5]); }; |
jessexm | 0:bb005bb0a24c | 141 | |
jessexm | 0:bb005bb0a24c | 142 | void MAX326XXFTHR_PwmOut::pwmout_update(void) |
jessexm | 0:bb005bb0a24c | 143 | { |
jessexm | 0:bb005bb0a24c | 144 | uint32_t tcnt = (pwm_period * PWM_TICKS_PER_US); |
jessexm | 0:bb005bb0a24c | 145 | uint32_t tcap = (pulse_width * PWM_TICKS_PER_US); |
jessexm | 0:bb005bb0a24c | 146 | |
jessexm | 0:bb005bb0a24c | 147 | // At init the timer will not be running |
jessexm | 0:bb005bb0a24c | 148 | if (!(tmr->ctrl & MXC_F_TMR_CTRL_ENABLE0)) { |
jessexm | 0:bb005bb0a24c | 149 | tmr->term_cnt32 = tcnt; |
jessexm | 0:bb005bb0a24c | 150 | tmr->pwm_cap32 = tcap; |
jessexm | 0:bb005bb0a24c | 151 | } else { |
jessexm | 0:bb005bb0a24c | 152 | tmr_obj[tmr_idx].term_cnt32 = tcnt; |
jessexm | 0:bb005bb0a24c | 153 | if (pulse_width == 0) { |
jessexm | 0:bb005bb0a24c | 154 | tmr_obj[tmr_idx].pwm_cap32 = 0; |
jessexm | 0:bb005bb0a24c | 155 | MXC_GPIO->out_val[tmr_obj[tmr_idx].port] &= ~(1 << tmr_obj[tmr_idx].port_pin); |
jessexm | 0:bb005bb0a24c | 156 | } else if (pulse_width == pwm_period) { |
jessexm | 0:bb005bb0a24c | 157 | tmr_obj[tmr_idx].pwm_cap32 = tcnt; |
jessexm | 0:bb005bb0a24c | 158 | } else { |
jessexm | 0:bb005bb0a24c | 159 | tmr_obj[tmr_idx].pwm_cap32 = tcap; |
jessexm | 0:bb005bb0a24c | 160 | } |
jessexm | 0:bb005bb0a24c | 161 | |
jessexm | 0:bb005bb0a24c | 162 | if ((last_pulse_width == 0) && (pulse_width != 0)) { |
jessexm | 0:bb005bb0a24c | 163 | MXC_GPIO->func_sel[tmr_obj[tmr_idx].port] |= (MXC_V_GPIO_FUNC_SEL_MODE_TMR << (MXC_GPIO_FUNC_SEL_FIELD_WIDTH * tmr_obj[tmr_idx].port_pin)); |
jessexm | 0:bb005bb0a24c | 164 | } |
jessexm | 0:bb005bb0a24c | 165 | |
jessexm | 0:bb005bb0a24c | 166 | last_pulse_width = pulse_width; |
jessexm | 0:bb005bb0a24c | 167 | |
jessexm | 0:bb005bb0a24c | 168 | tmr->intfl = 1; |
jessexm | 0:bb005bb0a24c | 169 | tmr->inten = 1; |
jessexm | 0:bb005bb0a24c | 170 | } |
jessexm | 0:bb005bb0a24c | 171 | } |
jessexm | 0:bb005bb0a24c | 172 | |
jessexm | 0:bb005bb0a24c | 173 | void MAX326XXFTHR_PwmOut::pwmout_init(PinName pin) |
jessexm | 0:bb005bb0a24c | 174 | { |
jessexm | 0:bb005bb0a24c | 175 | int i; |
jessexm | 0:bb005bb0a24c | 176 | |
jessexm | 0:bb005bb0a24c | 177 | // Make sure the pin is free for GPIO use |
jessexm | 0:bb005bb0a24c | 178 | unsigned int port = (unsigned int)pin >> PORT_SHIFT; |
jessexm | 0:bb005bb0a24c | 179 | unsigned int port_pin = (unsigned int)pin & ~(0xFFFFFFFF << PORT_SHIFT); |
jessexm | 0:bb005bb0a24c | 180 | MBED_ASSERT(MXC_GPIO->free[port] & (MXC_V_GPIO_FREE_AVAILABLE << port_pin)); |
jessexm | 0:bb005bb0a24c | 181 | |
jessexm | 0:bb005bb0a24c | 182 | // Make sure the pin is not associated with a PT or TIMER |
jessexm | 0:bb005bb0a24c | 183 | int pin_func = (MXC_GPIO->func_sel[port] >> (MXC_GPIO_FUNC_SEL_FIELD_WIDTH * port_pin)) & MXC_GPIO_FUNC_SEL_FIELD_MASK; |
jessexm | 0:bb005bb0a24c | 184 | MBED_ASSERT(pin_func == MXC_V_GPIO_FUNC_SEL_MODE_GPIO); |
jessexm | 0:bb005bb0a24c | 185 | |
jessexm | 0:bb005bb0a24c | 186 | // Search through PinMap to find the pin |
jessexm | 0:bb005bb0a24c | 187 | for (i = 0; (PinMap_PWM[i].pin != NC) && (PinMap_PWM[i].pin != pin); i++); |
jessexm | 0:bb005bb0a24c | 188 | MBED_ASSERT(PinMap_PWM[i].pin != NC); |
jessexm | 0:bb005bb0a24c | 189 | |
jessexm | 0:bb005bb0a24c | 190 | // Check timer is available |
jessexm | 0:bb005bb0a24c | 191 | tmr = (mxc_tmr_regs_t*)PinMap_PWM[i].peripheral; |
jessexm | 0:bb005bb0a24c | 192 | MBED_ASSERT(!(tmr->ctrl & MXC_F_TMR_CTRL_ENABLE0)); |
jessexm | 0:bb005bb0a24c | 193 | |
jessexm | 0:bb005bb0a24c | 194 | // Prep for interrupt handler |
jessexm | 0:bb005bb0a24c | 195 | tmr_idx = MXC_TMR_GET_IDX(tmr); |
jessexm | 0:bb005bb0a24c | 196 | switch (tmr_idx) { |
jessexm | 0:bb005bb0a24c | 197 | case 1: |
jessexm | 0:bb005bb0a24c | 198 | NVIC_SetVector(TMR1_0_IRQn, (uint32_t)tmr1_handler); |
jessexm | 0:bb005bb0a24c | 199 | NVIC_EnableIRQ(TMR1_0_IRQn); |
jessexm | 0:bb005bb0a24c | 200 | break; |
jessexm | 0:bb005bb0a24c | 201 | case 2: |
jessexm | 0:bb005bb0a24c | 202 | NVIC_SetVector(TMR2_0_IRQn, (uint32_t)tmr2_handler); |
jessexm | 0:bb005bb0a24c | 203 | NVIC_EnableIRQ(TMR2_0_IRQn); |
jessexm | 0:bb005bb0a24c | 204 | break; |
jessexm | 0:bb005bb0a24c | 205 | case 3: |
jessexm | 0:bb005bb0a24c | 206 | NVIC_SetVector(TMR3_0_IRQn, (uint32_t)tmr3_handler); |
jessexm | 0:bb005bb0a24c | 207 | NVIC_EnableIRQ(TMR3_0_IRQn); |
jessexm | 0:bb005bb0a24c | 208 | break; |
jessexm | 0:bb005bb0a24c | 209 | case 4: |
jessexm | 0:bb005bb0a24c | 210 | NVIC_SetVector(TMR4_0_IRQn, (uint32_t)tmr4_handler); |
jessexm | 0:bb005bb0a24c | 211 | NVIC_EnableIRQ(TMR4_0_IRQn); |
jessexm | 0:bb005bb0a24c | 212 | break; |
jessexm | 0:bb005bb0a24c | 213 | case 5: |
jessexm | 0:bb005bb0a24c | 214 | NVIC_SetVector(TMR5_0_IRQn, (uint32_t)tmr5_handler); |
jessexm | 0:bb005bb0a24c | 215 | NVIC_EnableIRQ(TMR5_0_IRQn); |
jessexm | 0:bb005bb0a24c | 216 | break; |
jessexm | 0:bb005bb0a24c | 217 | case 0: |
jessexm | 0:bb005bb0a24c | 218 | default: |
jessexm | 0:bb005bb0a24c | 219 | MBED_ASSERT(0); |
jessexm | 0:bb005bb0a24c | 220 | } |
jessexm | 0:bb005bb0a24c | 221 | |
jessexm | 0:bb005bb0a24c | 222 | tmr_obj[tmr_idx].tmr = tmr; |
jessexm | 0:bb005bb0a24c | 223 | tmr_obj[tmr_idx].term_cnt32 = 0; |
jessexm | 0:bb005bb0a24c | 224 | tmr_obj[tmr_idx].pwm_cap32 = 0; |
jessexm | 0:bb005bb0a24c | 225 | tmr_obj[tmr_idx].port = port; |
jessexm | 0:bb005bb0a24c | 226 | tmr_obj[tmr_idx].port_pin = port_pin; |
jessexm | 0:bb005bb0a24c | 227 | |
jessexm | 0:bb005bb0a24c | 228 | this->pin = pin; |
jessexm | 0:bb005bb0a24c | 229 | |
jessexm | 0:bb005bb0a24c | 230 | // Initial state |
jessexm | 0:bb005bb0a24c | 231 | pwm_period = -1; |
jessexm | 0:bb005bb0a24c | 232 | pulse_width = -1; |
jessexm | 0:bb005bb0a24c | 233 | last_pulse_width = -1; |
jessexm | 0:bb005bb0a24c | 234 | |
jessexm | 0:bb005bb0a24c | 235 | // Disable timer/clear settings |
jessexm | 0:bb005bb0a24c | 236 | tmr->ctrl = 0; |
jessexm | 0:bb005bb0a24c | 237 | |
jessexm | 0:bb005bb0a24c | 238 | // Set mode and polarity |
jessexm | 0:bb005bb0a24c | 239 | tmr->ctrl = MXC_S_TMR_CTRL_MODE_PWM | |
jessexm | 0:bb005bb0a24c | 240 | MXC_F_TMR_CTRL_POLARITY | |
jessexm | 0:bb005bb0a24c | 241 | (PWM_TMR_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS); |
jessexm | 0:bb005bb0a24c | 242 | |
jessexm | 0:bb005bb0a24c | 243 | // Reset counts |
jessexm | 0:bb005bb0a24c | 244 | tmr->count32 = 1; |
jessexm | 0:bb005bb0a24c | 245 | tmr->term_cnt32 = 0; |
jessexm | 0:bb005bb0a24c | 246 | tmr->pwm_cap32 = 0; |
jessexm | 0:bb005bb0a24c | 247 | |
jessexm | 0:bb005bb0a24c | 248 | // Configure the pin |
jessexm | 0:bb005bb0a24c | 249 | PinMode mode = (PinMode)PullNone; |
jessexm | 0:bb005bb0a24c | 250 | #ifdef OPEN_DRAIN_LEDS |
jessexm | 0:bb005bb0a24c | 251 | if ((pin == LED1) || (pin == LED2) || (pin == LED3) || (pin == LED4)) { |
jessexm | 0:bb005bb0a24c | 252 | mode = (PinMode)OpenDrain; |
jessexm | 0:bb005bb0a24c | 253 | MXC_IOMAN->use_vddioh_0 |= (1 << ((8 * port) + port_pin)); |
jessexm | 0:bb005bb0a24c | 254 | } |
jessexm | 0:bb005bb0a24c | 255 | #endif |
jessexm | 0:bb005bb0a24c | 256 | pin_mode(pin, mode); |
jessexm | 0:bb005bb0a24c | 257 | pin_function(pin, PinMap_PWM[i].function); |
jessexm | 0:bb005bb0a24c | 258 | |
jessexm | 0:bb005bb0a24c | 259 | // Default to 20ms: standard for servos, and fine for e.g. brightness control |
jessexm | 0:bb005bb0a24c | 260 | pwmout_period_us(20000); |
jessexm | 0:bb005bb0a24c | 261 | pwmout_write(0.0f); |
jessexm | 0:bb005bb0a24c | 262 | |
jessexm | 0:bb005bb0a24c | 263 | // Set the drive mode to normal |
jessexm | 0:bb005bb0a24c | 264 | MXC_SET_FIELD(&MXC_GPIO->out_mode[port], |
jessexm | 0:bb005bb0a24c | 265 | (MXC_GPIO_OUT_MODE_FIELD_MASK << (port_pin * MXC_GPIO_OUT_MODE_FIELD_WIDTH)), |
jessexm | 0:bb005bb0a24c | 266 | (MXC_V_GPIO_OUT_MODE_NORMAL << (port_pin * MXC_GPIO_OUT_MODE_FIELD_WIDTH))); |
jessexm | 0:bb005bb0a24c | 267 | |
jessexm | 0:bb005bb0a24c | 268 | // Enable timer |
jessexm | 0:bb005bb0a24c | 269 | tmr->ctrl |= MXC_F_TMR_CTRL_ENABLE0; |
jessexm | 0:bb005bb0a24c | 270 | } |
jessexm | 0:bb005bb0a24c | 271 | |
jessexm | 0:bb005bb0a24c | 272 | void MAX326XXFTHR_PwmOut::pwmout_free() |
jessexm | 0:bb005bb0a24c | 273 | { |
jessexm | 0:bb005bb0a24c | 274 | // GPIO control of pin |
jessexm | 0:bb005bb0a24c | 275 | MXC_GPIO->func_sel[(unsigned int)pin >> PORT_SHIFT] &= |
jessexm | 0:bb005bb0a24c | 276 | ~(MXC_GPIO_FUNC_SEL_FIELD_MASK << (MXC_GPIO_FUNC_SEL_FIELD_WIDTH * |
jessexm | 0:bb005bb0a24c | 277 | (unsigned int)pin & ~(0xFFFFFFFF << PORT_SHIFT))); |
jessexm | 0:bb005bb0a24c | 278 | // Disable timer |
jessexm | 0:bb005bb0a24c | 279 | tmr->ctrl = 0; |
jessexm | 0:bb005bb0a24c | 280 | } |
jessexm | 0:bb005bb0a24c | 281 | |
jessexm | 0:bb005bb0a24c | 282 | void MAX326XXFTHR_PwmOut::pwmout_write(float percent) |
jessexm | 0:bb005bb0a24c | 283 | { |
jessexm | 0:bb005bb0a24c | 284 | // Saturate percent if outside of range |
jessexm | 0:bb005bb0a24c | 285 | if (percent < 0.0f) { |
jessexm | 0:bb005bb0a24c | 286 | percent = 0.0f; |
jessexm | 0:bb005bb0a24c | 287 | } else if (percent > 1.0f) { |
jessexm | 0:bb005bb0a24c | 288 | percent = 1.0f; |
jessexm | 0:bb005bb0a24c | 289 | } |
jessexm | 0:bb005bb0a24c | 290 | |
jessexm | 0:bb005bb0a24c | 291 | // Resize the pulse width to set the duty cycle |
jessexm | 0:bb005bb0a24c | 292 | pwmout_pulsewidth_us((int)(percent * pwm_period)); |
jessexm | 0:bb005bb0a24c | 293 | } |
jessexm | 0:bb005bb0a24c | 294 | |
jessexm | 0:bb005bb0a24c | 295 | float MAX326XXFTHR_PwmOut::pwmout_read() |
jessexm | 0:bb005bb0a24c | 296 | { |
jessexm | 0:bb005bb0a24c | 297 | // Check for when pulsewidth or period equals 0 |
jessexm | 0:bb005bb0a24c | 298 | if((pulse_width == 0) || (pwm_period == 0)) { |
jessexm | 0:bb005bb0a24c | 299 | return 0.0f; |
jessexm | 0:bb005bb0a24c | 300 | } |
jessexm | 0:bb005bb0a24c | 301 | |
jessexm | 0:bb005bb0a24c | 302 | // Return the duty cycle |
jessexm | 0:bb005bb0a24c | 303 | return ((float)pulse_width / (float)pwm_period); |
jessexm | 0:bb005bb0a24c | 304 | } |
jessexm | 0:bb005bb0a24c | 305 | |
jessexm | 0:bb005bb0a24c | 306 | void MAX326XXFTHR_PwmOut::pwmout_period(float seconds) |
jessexm | 0:bb005bb0a24c | 307 | { |
jessexm | 0:bb005bb0a24c | 308 | pwmout_period_us((int)(seconds * 1000000.0f)); |
jessexm | 0:bb005bb0a24c | 309 | } |
jessexm | 0:bb005bb0a24c | 310 | |
jessexm | 0:bb005bb0a24c | 311 | void MAX326XXFTHR_PwmOut::pwmout_period_ms(int ms) |
jessexm | 0:bb005bb0a24c | 312 | { |
jessexm | 0:bb005bb0a24c | 313 | pwmout_period_us(ms * 1000); |
jessexm | 0:bb005bb0a24c | 314 | } |
jessexm | 0:bb005bb0a24c | 315 | |
jessexm | 0:bb005bb0a24c | 316 | void MAX326XXFTHR_PwmOut::pwmout_period_us(int us) |
jessexm | 0:bb005bb0a24c | 317 | { |
jessexm | 0:bb005bb0a24c | 318 | // Check the range of the period |
jessexm | 0:bb005bb0a24c | 319 | MBED_ASSERT((us >= 0) && (us <= (int)PWM_MAX_US)); |
jessexm | 0:bb005bb0a24c | 320 | |
jessexm | 0:bb005bb0a24c | 321 | // Set pulse width to half the period if uninitialized |
jessexm | 0:bb005bb0a24c | 322 | if (pulse_width == -1) { |
jessexm | 0:bb005bb0a24c | 323 | pulse_width = us / 2; |
jessexm | 0:bb005bb0a24c | 324 | } |
jessexm | 0:bb005bb0a24c | 325 | |
jessexm | 0:bb005bb0a24c | 326 | // Save the period |
jessexm | 0:bb005bb0a24c | 327 | pwm_period = us; |
jessexm | 0:bb005bb0a24c | 328 | |
jessexm | 0:bb005bb0a24c | 329 | // Update the registers |
jessexm | 0:bb005bb0a24c | 330 | pwmout_update(); |
jessexm | 0:bb005bb0a24c | 331 | } |
jessexm | 0:bb005bb0a24c | 332 | |
jessexm | 0:bb005bb0a24c | 333 | void MAX326XXFTHR_PwmOut::pwmout_pulsewidth(float seconds) |
jessexm | 0:bb005bb0a24c | 334 | { |
jessexm | 0:bb005bb0a24c | 335 | pwmout_pulsewidth_us((int)(seconds * 1000000.0f)); |
jessexm | 0:bb005bb0a24c | 336 | } |
jessexm | 0:bb005bb0a24c | 337 | |
jessexm | 0:bb005bb0a24c | 338 | void MAX326XXFTHR_PwmOut::pwmout_pulsewidth_ms(int ms) |
jessexm | 0:bb005bb0a24c | 339 | { |
jessexm | 0:bb005bb0a24c | 340 | pwmout_pulsewidth_us(ms * 1000); |
jessexm | 0:bb005bb0a24c | 341 | } |
jessexm | 0:bb005bb0a24c | 342 | |
jessexm | 0:bb005bb0a24c | 343 | void MAX326XXFTHR_PwmOut::pwmout_pulsewidth_us(int us) |
jessexm | 0:bb005bb0a24c | 344 | { |
jessexm | 0:bb005bb0a24c | 345 | // Check the range of the pulsewidth |
jessexm | 0:bb005bb0a24c | 346 | MBED_ASSERT((us >= 0) && (us <= (int)PWM_MAX_US)); |
jessexm | 0:bb005bb0a24c | 347 | |
jessexm | 0:bb005bb0a24c | 348 | // Initialize period to double the pulsewidth if uninitialized |
jessexm | 0:bb005bb0a24c | 349 | if (pwm_period == -1) { |
jessexm | 0:bb005bb0a24c | 350 | pwm_period = 2 * us; |
jessexm | 0:bb005bb0a24c | 351 | } |
jessexm | 0:bb005bb0a24c | 352 | |
jessexm | 0:bb005bb0a24c | 353 | // Save the pulsewidth |
jessexm | 0:bb005bb0a24c | 354 | pulse_width = us; |
jessexm | 0:bb005bb0a24c | 355 | |
jessexm | 0:bb005bb0a24c | 356 | // Update the register |
jessexm | 0:bb005bb0a24c | 357 | pwmout_update(); |
jessexm | 0:bb005bb0a24c | 358 | } |