Timer based PWM output for MAX326XXFTHR platforms

Dependents:   MAX32620FTHR_PwmBlinky

Fork of MAX326XXFTHR_PwmOut by Jesse Marroquin

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

TimerGPIO Port and Pin
TMR1P0_1, P0_7, P1_5, P3_1, P4_5, P5_3
TMR2P0_2, P1_0, P1_6, P2_4, P3_2, P4_0, P4_6, P5_4
TMR3P0_3, P1_1, P1_7, P2_5, P3_3, P4_7, P5_5
TMR4P0_4, P1_2, P2_6, P3_4, P5_0, P5_6
TMR5P0_5, P1_3, P2_7, P3_5, P5_1, P5_7

MAX32630FTHR 32-Bit Timer PWM Mapping

TimerGPIO Port and Pin
TMR1P3_1, P5_3
TMR2P2_4, P3_2, P4_0, P5_4
TMR3P2_5, P3_3, P5_5
TMR4P2_6, P3_4, P5_0, P5_6
TMR5P3_5, P5_1

Note GPIO P2_4, P2_5 and P2_6 are connected to onboard LEDs 1, 2 and 3.

Committer:
jessexm
Date:
Mon Apr 23 18:24:11 2018 +0000
Revision:
0:bb005bb0a24c
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew 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 }