added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
107:414e9c822e99
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 107:414e9c822e99 1 /* mbed Microcontroller Library
mbed_official 107:414e9c822e99 2 * Copyright (c) 2006-2015 ARM Limited
mbed_official 107:414e9c822e99 3 *
mbed_official 107:414e9c822e99 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 107:414e9c822e99 5 * you may not use this file except in compliance with the License.
mbed_official 107:414e9c822e99 6 * You may obtain a copy of the License at
mbed_official 107:414e9c822e99 7 *
mbed_official 107:414e9c822e99 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 107:414e9c822e99 9 *
mbed_official 107:414e9c822e99 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 107:414e9c822e99 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 107:414e9c822e99 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 107:414e9c822e99 13 * See the License for the specific language governing permissions and
mbed_official 107:414e9c822e99 14 * limitations under the License.
mbed_official 107:414e9c822e99 15 */
mbed_official 107:414e9c822e99 16 #include "mbed_assert.h"
mbed_official 107:414e9c822e99 17 #include "pwmout_api.h"
mbed_official 107:414e9c822e99 18
mbed_official 107:414e9c822e99 19 #include "cmsis.h"
mbed_official 107:414e9c822e99 20 #include "tc.h"
mbed_official 107:414e9c822e99 21 #include "sysclk.h"
mbed_official 107:414e9c822e99 22 #include "PeripheralPins.h"
mbed_official 107:414e9c822e99 23
mbed_official 107:414e9c822e99 24 extern uint8_t g_sys_init;
mbed_official 107:414e9c822e99 25
mbed_official 107:414e9c822e99 26 /** Use TC Peripheral 0 **/
mbed_official 107:414e9c822e99 27 #define TC TC0
mbed_official 107:414e9c822e99 28
mbed_official 107:414e9c822e99 29 static const uint32_t tc_prescalar[] = {
mbed_official 107:414e9c822e99 30 TC_CMR_TCCLKS_TIMER_CLOCK1, // MCK/2
mbed_official 107:414e9c822e99 31 TC_CMR_TCCLKS_TIMER_CLOCK2, // MCK/8
mbed_official 107:414e9c822e99 32 TC_CMR_TCCLKS_TIMER_CLOCK3, // MCK/32
mbed_official 107:414e9c822e99 33 TC_CMR_TCCLKS_TIMER_CLOCK4, // MCK/128
mbed_official 107:414e9c822e99 34 };
mbed_official 107:414e9c822e99 35 static const uint32_t tc_prescalar_divider[] = {
mbed_official 107:414e9c822e99 36 2, // MCK/2
mbed_official 107:414e9c822e99 37 8, // MCK/8
mbed_official 107:414e9c822e99 38 32, // MCK/32
mbed_official 107:414e9c822e99 39 128 // MCK/128
mbed_official 107:414e9c822e99 40 };
mbed_official 107:414e9c822e99 41
mbed_official 107:414e9c822e99 42 uint32_t getpwmchannelid (uint32_t channel)
mbed_official 107:414e9c822e99 43 {
mbed_official 107:414e9c822e99 44 switch (channel) {
mbed_official 107:414e9c822e99 45 case 0 :
mbed_official 107:414e9c822e99 46 return ID_TC0;
mbed_official 107:414e9c822e99 47 case 1 :
mbed_official 107:414e9c822e99 48 return ID_TC1;
mbed_official 107:414e9c822e99 49 case 2 :
mbed_official 107:414e9c822e99 50 return ID_TC2;
mbed_official 107:414e9c822e99 51 default :
mbed_official 107:414e9c822e99 52 MBED_ASSERT(false);
mbed_official 107:414e9c822e99 53 break;
mbed_official 107:414e9c822e99 54 }
mbed_official 107:414e9c822e99 55 }
mbed_official 107:414e9c822e99 56
mbed_official 107:414e9c822e99 57 uint32_t getprescalarindex (uint16_t frequency)
mbed_official 107:414e9c822e99 58 {
mbed_official 107:414e9c822e99 59 float time_period_ms;
mbed_official 107:414e9c822e99 60 time_period_ms = (1.0 / (float)frequency) * 1000.0;
mbed_official 107:414e9c822e99 61 if (time_period_ms <= 1.0) {
mbed_official 107:414e9c822e99 62 return 0;
mbed_official 107:414e9c822e99 63 } else if ((time_period_ms > 1.0) && (time_period_ms <= 4.0)) {
mbed_official 107:414e9c822e99 64 return 1;
mbed_official 107:414e9c822e99 65 } else if ((time_period_ms > 4.0) && (time_period_ms <= 16.0)) {
mbed_official 107:414e9c822e99 66 return 2;
mbed_official 107:414e9c822e99 67 } else {
mbed_official 107:414e9c822e99 68 return 3;
mbed_official 107:414e9c822e99 69 }
mbed_official 107:414e9c822e99 70 }
mbed_official 107:414e9c822e99 71
mbed_official 107:414e9c822e99 72 static void setregisterabc (pwmout_t* obj)
mbed_official 107:414e9c822e99 73 {
mbed_official 107:414e9c822e99 74 uint32_t ra, rb, rc;
mbed_official 107:414e9c822e99 75 /* Sanity check arguments */
mbed_official 107:414e9c822e99 76 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 77
mbed_official 107:414e9c822e99 78 /* Configure waveform frequency and duty cycle. */
mbed_official 107:414e9c822e99 79 rc = (sysclk_get_peripheral_bus_hz(TC) /
mbed_official 107:414e9c822e99 80 tc_prescalar_divider[obj->prescalarindex] )/
mbed_official 107:414e9c822e99 81 obj->waveconfig.us_frequency;
mbed_official 107:414e9c822e99 82 tc_write_rc(TC, obj->channel, rc);
mbed_official 107:414e9c822e99 83 switch (obj->ioline) {
mbed_official 107:414e9c822e99 84 case 0 :
mbed_official 107:414e9c822e99 85 ra = (100 - obj->waveconfig.us_dutycycle) * rc / 100;
mbed_official 107:414e9c822e99 86 if(ra <= 0) ra = 1; /*non zero value only*/
mbed_official 107:414e9c822e99 87 tc_write_ra(TC, obj->channel, ra);
mbed_official 107:414e9c822e99 88 break;
mbed_official 107:414e9c822e99 89 case 1 :
mbed_official 107:414e9c822e99 90 rb = (100 - obj->waveconfig.us_dutycycle) * rc / 100;
mbed_official 107:414e9c822e99 91 if(rb <= 0) rb = 1; /*non zero value only*/
mbed_official 107:414e9c822e99 92 tc_write_rb(TC, obj->channel, rb);
mbed_official 107:414e9c822e99 93 break;
mbed_official 107:414e9c822e99 94 default :
mbed_official 107:414e9c822e99 95 MBED_ASSERT(false);
mbed_official 107:414e9c822e99 96 break;
mbed_official 107:414e9c822e99 97 }
mbed_official 107:414e9c822e99 98 }
mbed_official 107:414e9c822e99 99
mbed_official 107:414e9c822e99 100 void pwmout_inithw(pwmout_t* obj)
mbed_official 107:414e9c822e99 101 {
mbed_official 107:414e9c822e99 102 uint32_t mode = 0;
mbed_official 107:414e9c822e99 103 /* Configure the PMC to enable the TC module. */
mbed_official 107:414e9c822e99 104 sysclk_enable_peripheral_clock(getpwmchannelid(obj->channel));
mbed_official 107:414e9c822e99 105 #if SAMG55
mbed_official 107:414e9c822e99 106 /* Enable PCK output */
mbed_official 107:414e9c822e99 107 pmc_disable_pck(PMC_PCK_3);
mbed_official 107:414e9c822e99 108 pmc_switch_pck_to_mck(PMC_PCK_3, PMC_PCK_PRES_CLK_1);
mbed_official 107:414e9c822e99 109 pmc_enable_pck(PMC_PCK_3);
mbed_official 107:414e9c822e99 110 #endif
mbed_official 107:414e9c822e99 111 switch (obj->ioline) {
mbed_official 107:414e9c822e99 112 case 0 :
mbed_official 107:414e9c822e99 113 mode = TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR; /* RA Compare Effect: set */ /* RC Compare Effect: clear */
mbed_official 107:414e9c822e99 114 break;
mbed_official 107:414e9c822e99 115 case 1 :
mbed_official 107:414e9c822e99 116 mode = TC_CMR_BCPB_SET | TC_CMR_BCPC_CLEAR | TC_CMR_ABETRG; /* RB Compare Effect: set */ /* RC Compare Effect: clear */ /*Change external event selection from TIOB*/
mbed_official 107:414e9c822e99 117 break;
mbed_official 107:414e9c822e99 118 default :
mbed_official 107:414e9c822e99 119 MBED_ASSERT(false);
mbed_official 107:414e9c822e99 120 break;
mbed_official 107:414e9c822e99 121 }
mbed_official 107:414e9c822e99 122 /* Disable TC TC_CHANNEL_WAVEFORM. */
mbed_official 107:414e9c822e99 123 tc_stop(TC, obj->channel);
mbed_official 107:414e9c822e99 124 /* Init TC to waveform mode. */
mbed_official 107:414e9c822e99 125 tc_init(TC, obj->channel,
mbed_official 107:414e9c822e99 126 /* Waveform Clock Selection */
mbed_official 107:414e9c822e99 127 obj->waveconfig.ul_intclock
mbed_official 107:414e9c822e99 128 | TC_CMR_WAVE /* Waveform mode is enabled */
mbed_official 107:414e9c822e99 129 | TC_CMR_CPCTRG /* UP mode with automatic trigger on RC Compare */
mbed_official 107:414e9c822e99 130 | mode
mbed_official 107:414e9c822e99 131 );
mbed_official 107:414e9c822e99 132 }
mbed_official 107:414e9c822e99 133
mbed_official 107:414e9c822e99 134 /** Initialize PWM Module
mbed_official 107:414e9c822e99 135 *
mbed_official 107:414e9c822e99 136 * @param[in][out] obj The PWM object to initialize
mbed_official 107:414e9c822e99 137 * @return void
mbed_official 107:414e9c822e99 138 */
mbed_official 107:414e9c822e99 139 void pwmout_init(pwmout_t* obj, PinName pin)
mbed_official 107:414e9c822e99 140 {
mbed_official 107:414e9c822e99 141 /* Sanity check arguments */
mbed_official 107:414e9c822e99 142 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 143 uint32_t ioline = NC;
mbed_official 107:414e9c822e99 144 uint32_t channel = NC;
mbed_official 107:414e9c822e99 145
mbed_official 107:414e9c822e99 146 if (g_sys_init == 0) {
mbed_official 107:414e9c822e99 147 sysclk_init();
mbed_official 107:414e9c822e99 148 system_board_init();
mbed_official 107:414e9c822e99 149 g_sys_init = 1;
mbed_official 107:414e9c822e99 150 }
mbed_official 107:414e9c822e99 151 if(pin != NC) {
mbed_official 107:414e9c822e99 152 pin_function(pin, pinmap_find_function(pin, PinMap_PWM));
mbed_official 107:414e9c822e99 153 ioport_disable_pin(pin);
mbed_official 107:414e9c822e99 154 }
mbed_official 107:414e9c822e99 155 obj->pin = pin;
mbed_official 107:414e9c822e99 156
mbed_official 107:414e9c822e99 157 ioline = pinmap_find_function(pin, PinMap_PWM_IO_Line); /*To find out which IO Line is associated with the pin and initialise accordingly*/ /*pinmap_find_function reused to find out iolin used*/
mbed_official 107:414e9c822e99 158 MBED_ASSERT(ioline != NC);
mbed_official 107:414e9c822e99 159 obj->ioline = ioline;
mbed_official 107:414e9c822e99 160
mbed_official 107:414e9c822e99 161 channel = pinmap_find_peripheral(pin, PinMap_PWM_IO_Line); /* PinMap_PWM_IO_Line contains channel number and ioline to be used*/ /*pinmap_find_peripheral function reused to find out channel number*/
mbed_official 107:414e9c822e99 162 MBED_ASSERT(channel != NC);
mbed_official 107:414e9c822e99 163 obj->channel = channel;
mbed_official 107:414e9c822e99 164 obj->waveconfig.us_frequency = 500;
mbed_official 107:414e9c822e99 165 obj->waveconfig.us_dutycycle = 50;
mbed_official 107:414e9c822e99 166
mbed_official 107:414e9c822e99 167 obj->prescalarindex = getprescalarindex(obj->waveconfig.us_frequency);
mbed_official 107:414e9c822e99 168 obj->waveconfig.ul_intclock = tc_prescalar[obj->prescalarindex];
mbed_official 107:414e9c822e99 169 pwmout_inithw(obj);
mbed_official 107:414e9c822e99 170
mbed_official 107:414e9c822e99 171 /*Set the registers a,b,c*/
mbed_official 107:414e9c822e99 172 setregisterabc(obj);
mbed_official 107:414e9c822e99 173
mbed_official 107:414e9c822e99 174 /* Enable TC TC_CHANNEL_WAVEFORM. */
mbed_official 107:414e9c822e99 175 tc_start(TC, channel);
mbed_official 107:414e9c822e99 176 }
mbed_official 107:414e9c822e99 177
mbed_official 107:414e9c822e99 178 /** Free the PWM Module
mbed_official 107:414e9c822e99 179 *
mbed_official 107:414e9c822e99 180 * @param[in] obj The PWM object to free
mbed_official 107:414e9c822e99 181 * @return void
mbed_official 107:414e9c822e99 182 */
mbed_official 107:414e9c822e99 183 void pwmout_free(pwmout_t* obj)
mbed_official 107:414e9c822e99 184 {
mbed_official 107:414e9c822e99 185 /* Sanity check arguments */
mbed_official 107:414e9c822e99 186 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 187 tc_stop(TC, obj->channel);
mbed_official 107:414e9c822e99 188 }
mbed_official 107:414e9c822e99 189
mbed_official 107:414e9c822e99 190 /** Set the duty cycle of PWM Waveform
mbed_official 107:414e9c822e99 191 *
mbed_official 107:414e9c822e99 192 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 193 * @param[in] value New duty cycle to be set
mbed_official 107:414e9c822e99 194 * @return void
mbed_official 107:414e9c822e99 195 */
mbed_official 107:414e9c822e99 196 void pwmout_write(pwmout_t* obj, float value)
mbed_official 107:414e9c822e99 197 {
mbed_official 107:414e9c822e99 198 /* Sanity check arguments */
mbed_official 107:414e9c822e99 199 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 200 if (value < 0.0f) {
mbed_official 107:414e9c822e99 201 value = 0;
mbed_official 107:414e9c822e99 202 } else if (value > 1.0f) {
mbed_official 107:414e9c822e99 203 value = 1;
mbed_official 107:414e9c822e99 204 }
mbed_official 107:414e9c822e99 205 obj->waveconfig.us_dutycycle = (uint16_t)(value * 100);
mbed_official 107:414e9c822e99 206 tc_stop(TC, obj->channel);
mbed_official 107:414e9c822e99 207
mbed_official 107:414e9c822e99 208 /*Set the registers a,b,c*/
mbed_official 107:414e9c822e99 209 setregisterabc(obj);
mbed_official 107:414e9c822e99 210
mbed_official 107:414e9c822e99 211 /* Enable TC TC_CHANNEL_WAVEFORM. */
mbed_official 107:414e9c822e99 212 tc_start(TC, obj->channel);
mbed_official 107:414e9c822e99 213 }
mbed_official 107:414e9c822e99 214
mbed_official 107:414e9c822e99 215 /** Get the duty cycle of PWM Waveform
mbed_official 107:414e9c822e99 216 *
mbed_official 107:414e9c822e99 217 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 218 * @return Current duty cycle
mbed_official 107:414e9c822e99 219 */
mbed_official 107:414e9c822e99 220 float pwmout_read(pwmout_t* obj)
mbed_official 107:414e9c822e99 221 {
mbed_official 107:414e9c822e99 222 /* Sanity check arguments */
mbed_official 107:414e9c822e99 223 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 224 return (obj->waveconfig.us_dutycycle / 100.0);
mbed_official 107:414e9c822e99 225 }
mbed_official 107:414e9c822e99 226
mbed_official 107:414e9c822e99 227 /** Set the period of PWM Waveform
mbed_official 107:414e9c822e99 228 *
mbed_official 107:414e9c822e99 229 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 230 * @param[in] seconds New period in seconds
mbed_official 107:414e9c822e99 231 * @return void
mbed_official 107:414e9c822e99 232 */
mbed_official 107:414e9c822e99 233 void pwmout_period(pwmout_t* obj, float seconds)
mbed_official 107:414e9c822e99 234 {
mbed_official 107:414e9c822e99 235 pwmout_period_us(obj, seconds * 1000000.0f);
mbed_official 107:414e9c822e99 236 }
mbed_official 107:414e9c822e99 237
mbed_official 107:414e9c822e99 238 /** Set the period of PWM Waveform
mbed_official 107:414e9c822e99 239 *
mbed_official 107:414e9c822e99 240 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 241 * @param[in] value New period in milliseconds
mbed_official 107:414e9c822e99 242 * @return void
mbed_official 107:414e9c822e99 243 */
mbed_official 107:414e9c822e99 244 void pwmout_period_ms(pwmout_t* obj, int ms)
mbed_official 107:414e9c822e99 245 {
mbed_official 107:414e9c822e99 246 pwmout_period_us(obj, ms * 1000);
mbed_official 107:414e9c822e99 247 }
mbed_official 107:414e9c822e99 248
mbed_official 107:414e9c822e99 249 /** Set the period of PWM Waveform
mbed_official 107:414e9c822e99 250 *
mbed_official 107:414e9c822e99 251 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 252 * @param[in] us New period in microseconds
mbed_official 107:414e9c822e99 253 * @return void
mbed_official 107:414e9c822e99 254 */
mbed_official 107:414e9c822e99 255 void pwmout_period_us(pwmout_t* obj, int us)
mbed_official 107:414e9c822e99 256 {
mbed_official 107:414e9c822e99 257 /* Sanity check arguments */
mbed_official 107:414e9c822e99 258 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 259 float freq = ( 1.0 / us ) * 1000000.0;
mbed_official 107:414e9c822e99 260
mbed_official 107:414e9c822e99 261 obj->waveconfig.us_frequency = (uint16_t) freq;
mbed_official 107:414e9c822e99 262 obj->prescalarindex = getprescalarindex(obj->waveconfig.us_frequency);
mbed_official 107:414e9c822e99 263 obj->waveconfig.ul_intclock = tc_prescalar[obj->prescalarindex];
mbed_official 107:414e9c822e99 264 pwmout_inithw(obj);
mbed_official 107:414e9c822e99 265
mbed_official 107:414e9c822e99 266 /*Set the registers a,b,c*/
mbed_official 107:414e9c822e99 267 setregisterabc(obj);
mbed_official 107:414e9c822e99 268
mbed_official 107:414e9c822e99 269 /* Enable TC TC_CHANNEL_WAVEFORM. */
mbed_official 107:414e9c822e99 270 tc_start(TC, obj->channel);
mbed_official 107:414e9c822e99 271 }
mbed_official 107:414e9c822e99 272
mbed_official 107:414e9c822e99 273 /** Set the pulse width of PWM Waveform
mbed_official 107:414e9c822e99 274 *
mbed_official 107:414e9c822e99 275 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 276 * @param[in] seconds New pulse width in seconds
mbed_official 107:414e9c822e99 277 * @return void
mbed_official 107:414e9c822e99 278 */
mbed_official 107:414e9c822e99 279 void pwmout_pulsewidth(pwmout_t* obj, float seconds)
mbed_official 107:414e9c822e99 280 {
mbed_official 107:414e9c822e99 281 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
mbed_official 107:414e9c822e99 282 }
mbed_official 107:414e9c822e99 283
mbed_official 107:414e9c822e99 284 /** Set the pulse width of PWM Waveform
mbed_official 107:414e9c822e99 285 *
mbed_official 107:414e9c822e99 286 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 287 * @param[in] ms New pulse width in milliseconds
mbed_official 107:414e9c822e99 288 * @return void
mbed_official 107:414e9c822e99 289 */
mbed_official 107:414e9c822e99 290 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
mbed_official 107:414e9c822e99 291 {
mbed_official 107:414e9c822e99 292 pwmout_pulsewidth_us(obj, ms * 1000);
mbed_official 107:414e9c822e99 293 }
mbed_official 107:414e9c822e99 294
mbed_official 107:414e9c822e99 295 /** Set the pulse width of PWM Waveform
mbed_official 107:414e9c822e99 296 *
mbed_official 107:414e9c822e99 297 * @param[in] obj The PWM object
mbed_official 107:414e9c822e99 298 * @param[in] us New pulse width in microseconds
mbed_official 107:414e9c822e99 299 * @return void
mbed_official 107:414e9c822e99 300 */
mbed_official 107:414e9c822e99 301 void pwmout_pulsewidth_us(pwmout_t* obj, int us)
mbed_official 107:414e9c822e99 302 {
mbed_official 107:414e9c822e99 303 /* Sanity check arguments */
mbed_official 107:414e9c822e99 304 MBED_ASSERT(obj);
mbed_official 107:414e9c822e99 305 float new_duty = (us / 1000000.0) * (float)obj->waveconfig.us_frequency;
mbed_official 107:414e9c822e99 306 pwmout_write(obj, new_duty);
mbed_official 107:414e9c822e99 307 }