mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
bogdanm
Date:
Mon Aug 19 18:17:02 2013 +0300
Revision:
19:398f4c622e1b
Child:
20:4263a77256ae
Sync with official mbed library release 66

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 19:398f4c622e1b 1 /* mbed Microcontroller Library
bogdanm 19:398f4c622e1b 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 19:398f4c622e1b 3 *
bogdanm 19:398f4c622e1b 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 19:398f4c622e1b 5 * you may not use this file except in compliance with the License.
bogdanm 19:398f4c622e1b 6 * You may obtain a copy of the License at
bogdanm 19:398f4c622e1b 7 *
bogdanm 19:398f4c622e1b 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 19:398f4c622e1b 9 *
bogdanm 19:398f4c622e1b 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 19:398f4c622e1b 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 19:398f4c622e1b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 19:398f4c622e1b 13 * See the License for the specific language governing permissions and
bogdanm 19:398f4c622e1b 14 * limitations under the License.
bogdanm 19:398f4c622e1b 15 */
bogdanm 19:398f4c622e1b 16 #include "pwmout_api.h"
bogdanm 19:398f4c622e1b 17 #include "cmsis.h"
bogdanm 19:398f4c622e1b 18 #include "pinmap.h"
bogdanm 19:398f4c622e1b 19 #include "error.h"
bogdanm 19:398f4c622e1b 20
bogdanm 19:398f4c622e1b 21 #define TCR_CNT_EN 0x00000001
bogdanm 19:398f4c622e1b 22 #define TCR_RESET 0x00000002
bogdanm 19:398f4c622e1b 23
bogdanm 19:398f4c622e1b 24 /* To have a PWM where we can change both the period and the duty cycle,
bogdanm 19:398f4c622e1b 25 * we need an entire timer. With the following conventions:
bogdanm 19:398f4c622e1b 26 * * MR3 is used for the PWM period
bogdanm 19:398f4c622e1b 27 * * MR0, MR1, MR2 are used for the duty cycle
bogdanm 19:398f4c622e1b 28 */
bogdanm 19:398f4c622e1b 29 static const PinMap PinMap_PWM[] = {
bogdanm 19:398f4c622e1b 30 /* CT16B0 */
bogdanm 19:398f4c622e1b 31 {P0_8 , PWM_1, 0x02}, /* MR0 */
bogdanm 19:398f4c622e1b 32 {P0_9 , PWM_2, 0x02}, /* MR1 */
bogdanm 19:398f4c622e1b 33
bogdanm 19:398f4c622e1b 34 /* CT16B1 */
bogdanm 19:398f4c622e1b 35 {P1_9 , PWM_4, 0x01}, /* MR0 */
bogdanm 19:398f4c622e1b 36 {P1_10, PWM_5, 0x02}, /* MR1 */
bogdanm 19:398f4c622e1b 37
bogdanm 19:398f4c622e1b 38 /* CT32B0 */
bogdanm 19:398f4c622e1b 39 {P1_6 , PWM_6, 0x02}, /* MR0 */
bogdanm 19:398f4c622e1b 40 {P1_7 , PWM_7, 0x02}, /* MR1 */
bogdanm 19:398f4c622e1b 41 {P0_1 , PWM_8, 0x02}, /* MR2 */
bogdanm 19:398f4c622e1b 42
bogdanm 19:398f4c622e1b 43 /* CT32B1 */
bogdanm 19:398f4c622e1b 44 {P1_1 , PWM_9 ,0x03}, /* MR0 */
bogdanm 19:398f4c622e1b 45 {P1_2 , PWM_10,0x03}, /* MR1 */
bogdanm 19:398f4c622e1b 46
bogdanm 19:398f4c622e1b 47 {NC , NC ,0x00}
bogdanm 19:398f4c622e1b 48 };
bogdanm 19:398f4c622e1b 49
bogdanm 19:398f4c622e1b 50 typedef struct {
bogdanm 19:398f4c622e1b 51 uint8_t timer;
bogdanm 19:398f4c622e1b 52 uint8_t mr;
bogdanm 19:398f4c622e1b 53 } timer_mr;
bogdanm 19:398f4c622e1b 54
bogdanm 19:398f4c622e1b 55 static timer_mr pwm_timer_map[9] = {
bogdanm 19:398f4c622e1b 56 {0, 0}, /* CT16B0, MR0 */
bogdanm 19:398f4c622e1b 57 {0, 1}, /* CT16B0, MR1 */
bogdanm 19:398f4c622e1b 58
bogdanm 19:398f4c622e1b 59 {1, 0}, /* CT16B1, MR0 */
bogdanm 19:398f4c622e1b 60 {1, 1}, /* CT16B1, MR1 */
bogdanm 19:398f4c622e1b 61
bogdanm 19:398f4c622e1b 62 {2, 0}, /* CT32B0, MR0 */
bogdanm 19:398f4c622e1b 63 {2, 1}, /* CT32B0, MR1 */
bogdanm 19:398f4c622e1b 64 {2, 2}, /* CT32B0, MR2 */
bogdanm 19:398f4c622e1b 65
bogdanm 19:398f4c622e1b 66 {3, 0}, /* CT32B1, MR0 */
bogdanm 19:398f4c622e1b 67 {3, 1}, /* CT32B1, MR1 */
bogdanm 19:398f4c622e1b 68 };
bogdanm 19:398f4c622e1b 69
bogdanm 19:398f4c622e1b 70 static LPC_TMR_TypeDef *Timers[4] = {
bogdanm 19:398f4c622e1b 71 LPC_TMR16B0, LPC_TMR16B1,
bogdanm 19:398f4c622e1b 72 LPC_TMR32B0, LPC_TMR32B1
bogdanm 19:398f4c622e1b 73 };
bogdanm 19:398f4c622e1b 74
bogdanm 19:398f4c622e1b 75 static unsigned int pwm_clock_mhz;
bogdanm 19:398f4c622e1b 76
bogdanm 19:398f4c622e1b 77 void pwmout_init(pwmout_t* obj, PinName pin) {
bogdanm 19:398f4c622e1b 78 // determine the channel
bogdanm 19:398f4c622e1b 79 PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
bogdanm 19:398f4c622e1b 80 if (pwm == (uint32_t)NC)
bogdanm 19:398f4c622e1b 81 error("PwmOut pin mapping failed");
bogdanm 19:398f4c622e1b 82
bogdanm 19:398f4c622e1b 83 obj->pwm = pwm;
bogdanm 19:398f4c622e1b 84
bogdanm 19:398f4c622e1b 85 // Timer registers
bogdanm 19:398f4c622e1b 86 timer_mr tid = pwm_timer_map[pwm];
bogdanm 19:398f4c622e1b 87 LPC_TMR_TypeDef *timer = Timers[tid.timer];
bogdanm 19:398f4c622e1b 88
bogdanm 19:398f4c622e1b 89 // Disable timer
bogdanm 19:398f4c622e1b 90 timer->TCR = 0;
bogdanm 19:398f4c622e1b 91
bogdanm 19:398f4c622e1b 92 // Power the correspondent timer
bogdanm 19:398f4c622e1b 93 LPC_SYSCON->SYSAHBCLKCTRL |= 1 << (tid.timer + 7);
bogdanm 19:398f4c622e1b 94
bogdanm 19:398f4c622e1b 95 /* Enable PWM function */
bogdanm 19:398f4c622e1b 96 timer->PWMC = (1 << 3)|(1 << 2)|(1 << 1)|(1 << 0);
bogdanm 19:398f4c622e1b 97
bogdanm 19:398f4c622e1b 98 /* Reset Functionality on MR3 controlling the PWM period */
bogdanm 19:398f4c622e1b 99 timer->MCR = 1 << 10;
bogdanm 19:398f4c622e1b 100
bogdanm 19:398f4c622e1b 101 pwm_clock_mhz = SystemCoreClock / 1000000;
bogdanm 19:398f4c622e1b 102
bogdanm 19:398f4c622e1b 103 // default to 20ms: standard for servos, and fine for e.g. brightness control
bogdanm 19:398f4c622e1b 104 pwmout_period_ms(obj, 20);
bogdanm 19:398f4c622e1b 105 pwmout_write (obj, 0);
bogdanm 19:398f4c622e1b 106
bogdanm 19:398f4c622e1b 107 // Wire pinout
bogdanm 19:398f4c622e1b 108 pinmap_pinout(pin, PinMap_PWM);
bogdanm 19:398f4c622e1b 109 }
bogdanm 19:398f4c622e1b 110
bogdanm 19:398f4c622e1b 111 void pwmout_free(pwmout_t* obj) {
bogdanm 19:398f4c622e1b 112 // [TODO]
bogdanm 19:398f4c622e1b 113 }
bogdanm 19:398f4c622e1b 114
bogdanm 19:398f4c622e1b 115 void pwmout_write(pwmout_t* obj, float value) {
bogdanm 19:398f4c622e1b 116 if (value < 0.0f) {
bogdanm 19:398f4c622e1b 117 value = 0.0;
bogdanm 19:398f4c622e1b 118 } else if (value > 1.0f) {
bogdanm 19:398f4c622e1b 119 value = 1.0;
bogdanm 19:398f4c622e1b 120 }
bogdanm 19:398f4c622e1b 121
bogdanm 19:398f4c622e1b 122 timer_mr tid = pwm_timer_map[obj->pwm];
bogdanm 19:398f4c622e1b 123 LPC_TMR_TypeDef *timer = Timers[tid.timer];
bogdanm 19:398f4c622e1b 124 uint32_t t_off = timer->MR3 - (uint32_t)((float)(timer->MR3) * value);
bogdanm 19:398f4c622e1b 125
bogdanm 19:398f4c622e1b 126 timer->TCR = TCR_RESET;
bogdanm 19:398f4c622e1b 127 timer->MR[tid.mr] = t_off;
bogdanm 19:398f4c622e1b 128 timer->TCR = TCR_CNT_EN;
bogdanm 19:398f4c622e1b 129 }
bogdanm 19:398f4c622e1b 130
bogdanm 19:398f4c622e1b 131 float pwmout_read(pwmout_t* obj) {
bogdanm 19:398f4c622e1b 132 timer_mr tid = pwm_timer_map[obj->pwm];
bogdanm 19:398f4c622e1b 133 LPC_TMR_TypeDef *timer = Timers[tid.timer];
bogdanm 19:398f4c622e1b 134
bogdanm 19:398f4c622e1b 135 float v = (float)(timer->MR3 - timer->MR[tid.mr]) / (float)(timer->MR3);
bogdanm 19:398f4c622e1b 136 return (v > 1.0f) ? (1.0f) : (v);
bogdanm 19:398f4c622e1b 137 }
bogdanm 19:398f4c622e1b 138
bogdanm 19:398f4c622e1b 139 void pwmout_period(pwmout_t* obj, float seconds) {
bogdanm 19:398f4c622e1b 140 pwmout_period_us(obj, seconds * 1000000.0f);
bogdanm 19:398f4c622e1b 141 }
bogdanm 19:398f4c622e1b 142
bogdanm 19:398f4c622e1b 143 void pwmout_period_ms(pwmout_t* obj, int ms) {
bogdanm 19:398f4c622e1b 144 pwmout_period_us(obj, ms * 1000);
bogdanm 19:398f4c622e1b 145 }
bogdanm 19:398f4c622e1b 146
bogdanm 19:398f4c622e1b 147 // Set the PWM period, keeping the duty cycle the same.
bogdanm 19:398f4c622e1b 148 void pwmout_period_us(pwmout_t* obj, int us) {
bogdanm 19:398f4c622e1b 149 int i = 0;
bogdanm 19:398f4c622e1b 150 uint32_t period_ticks = pwm_clock_mhz * us;
bogdanm 19:398f4c622e1b 151
bogdanm 19:398f4c622e1b 152 timer_mr tid = pwm_timer_map[obj->pwm];
bogdanm 19:398f4c622e1b 153 LPC_TMR_TypeDef *timer = Timers[tid.timer];
bogdanm 19:398f4c622e1b 154 uint32_t old_period_ticks = timer->MR3;
bogdanm 19:398f4c622e1b 155
bogdanm 19:398f4c622e1b 156 timer->TCR = TCR_RESET;
bogdanm 19:398f4c622e1b 157 timer->MR3 = period_ticks;
bogdanm 19:398f4c622e1b 158
bogdanm 19:398f4c622e1b 159 // Scale the pulse width to preserve the duty ratio
bogdanm 19:398f4c622e1b 160 if (old_period_ticks > 0) {
bogdanm 19:398f4c622e1b 161 for (i=0; i<3; i++) {
bogdanm 19:398f4c622e1b 162 uint32_t t_off = period_ticks - (uint32_t)(((uint64_t)timer->MR[i] * (uint64_t)period_ticks) / (uint64_t)old_period_ticks);
bogdanm 19:398f4c622e1b 163 timer->MR[i] = t_off;
bogdanm 19:398f4c622e1b 164 }
bogdanm 19:398f4c622e1b 165 }
bogdanm 19:398f4c622e1b 166 timer->TCR = TCR_CNT_EN;
bogdanm 19:398f4c622e1b 167 }
bogdanm 19:398f4c622e1b 168
bogdanm 19:398f4c622e1b 169 void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
bogdanm 19:398f4c622e1b 170 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
bogdanm 19:398f4c622e1b 171 }
bogdanm 19:398f4c622e1b 172
bogdanm 19:398f4c622e1b 173 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
bogdanm 19:398f4c622e1b 174 pwmout_pulsewidth_us(obj, ms * 1000);
bogdanm 19:398f4c622e1b 175 }
bogdanm 19:398f4c622e1b 176
bogdanm 19:398f4c622e1b 177 void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
bogdanm 19:398f4c622e1b 178 uint32_t t_on = (uint32_t)(((uint64_t)SystemCoreClock * (uint64_t)us) / (uint64_t)1000000);
bogdanm 19:398f4c622e1b 179 timer_mr tid = pwm_timer_map[obj->pwm];
bogdanm 19:398f4c622e1b 180 LPC_TMR_TypeDef *timer = Timers[tid.timer];
bogdanm 19:398f4c622e1b 181
bogdanm 19:398f4c622e1b 182 timer->TCR = TCR_RESET;
bogdanm 19:398f4c622e1b 183 if (t_on > timer->MR3) {
bogdanm 19:398f4c622e1b 184 pwmout_period_us(obj, us);
bogdanm 19:398f4c622e1b 185 }
bogdanm 19:398f4c622e1b 186 uint32_t t_off = timer->MR3 - t_on;
bogdanm 19:398f4c622e1b 187 timer->MR[tid.mr] = t_off;
bogdanm 19:398f4c622e1b 188 timer->TCR = TCR_CNT_EN;
bogdanm 19:398f4c622e1b 189 }