mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Tue Feb 24 13:45:08 2015 +0000
Revision:
480:69aad4cbc07a
Child:
516:b3fb5c6901a6
Synchronized with git revision 1b2a62100ab444910759144c041dcdd45f3dc7c6

Full URL: https://github.com/mbedmicro/mbed/commit/1b2a62100ab444910759144c041dcdd45f3dc7c6/

LPC81x - Update us_ticker.c, using MRT

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 480:69aad4cbc07a 1 /* mbed Microcontroller Library
mbed_official 480:69aad4cbc07a 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 480:69aad4cbc07a 3 *
mbed_official 480:69aad4cbc07a 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 480:69aad4cbc07a 5 * you may not use this file except in compliance with the License.
mbed_official 480:69aad4cbc07a 6 * You may obtain a copy of the License at
mbed_official 480:69aad4cbc07a 7 *
mbed_official 480:69aad4cbc07a 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 480:69aad4cbc07a 9 *
mbed_official 480:69aad4cbc07a 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 480:69aad4cbc07a 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 480:69aad4cbc07a 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 480:69aad4cbc07a 13 * See the License for the specific language governing permissions and
mbed_official 480:69aad4cbc07a 14 * limitations under the License.
mbed_official 480:69aad4cbc07a 15 */
mbed_official 480:69aad4cbc07a 16 #include "mbed_assert.h"
mbed_official 480:69aad4cbc07a 17 #include "pwmout_api.h"
mbed_official 480:69aad4cbc07a 18 #include "cmsis.h"
mbed_official 480:69aad4cbc07a 19 #include "pinmap.h"
mbed_official 480:69aad4cbc07a 20 #include "mbed_error.h"
mbed_official 480:69aad4cbc07a 21
mbed_official 480:69aad4cbc07a 22 // Ported from LPC824 and adapted.
mbed_official 480:69aad4cbc07a 23
mbed_official 480:69aad4cbc07a 24 #if DEVICE_PWMOUT
mbed_official 480:69aad4cbc07a 25
mbed_official 480:69aad4cbc07a 26 #define PWM_IRQn SCT_IRQn
mbed_official 480:69aad4cbc07a 27
mbed_official 480:69aad4cbc07a 28 // Bit flags for used SCT Outputs
mbed_official 480:69aad4cbc07a 29 static unsigned char sct_used = 0;
mbed_official 480:69aad4cbc07a 30 static int sct_inited = 0;
mbed_official 480:69aad4cbc07a 31
mbed_official 480:69aad4cbc07a 32 // Find available output channel
mbed_official 480:69aad4cbc07a 33 // Max number of PWM outputs is 4 on LPC812
mbed_official 480:69aad4cbc07a 34 static int get_available_sct() {
mbed_official 480:69aad4cbc07a 35 int i;
mbed_official 480:69aad4cbc07a 36
mbed_official 480:69aad4cbc07a 37 // Find available output channel 0..3
mbed_official 480:69aad4cbc07a 38 // Also need one Match register per channel
mbed_official 480:69aad4cbc07a 39 for (i = 0; i < CONFIG_SCT_nOU; i++) {
mbed_official 480:69aad4cbc07a 40 // for (i = 0; i < 4; i++) {
mbed_official 480:69aad4cbc07a 41 if ((sct_used & (1 << i)) == 0)
mbed_official 480:69aad4cbc07a 42 return i;
mbed_official 480:69aad4cbc07a 43 }
mbed_official 480:69aad4cbc07a 44 return -1;
mbed_official 480:69aad4cbc07a 45 }
mbed_official 480:69aad4cbc07a 46
mbed_official 480:69aad4cbc07a 47 // Any Port pin may be used for PWM.
mbed_official 480:69aad4cbc07a 48 // Max number of PWM outputs is 4
mbed_official 480:69aad4cbc07a 49 void pwmout_init(pwmout_t* obj, PinName pin) {
mbed_official 480:69aad4cbc07a 50 MBED_ASSERT(pin != (uint32_t)NC);
mbed_official 480:69aad4cbc07a 51
mbed_official 480:69aad4cbc07a 52 int sct_n = get_available_sct();
mbed_official 480:69aad4cbc07a 53 if (sct_n == -1) {
mbed_official 480:69aad4cbc07a 54 error("No available SCT Output");
mbed_official 480:69aad4cbc07a 55 }
mbed_official 480:69aad4cbc07a 56
mbed_official 480:69aad4cbc07a 57 sct_used |= (1 << sct_n);
mbed_official 480:69aad4cbc07a 58
mbed_official 480:69aad4cbc07a 59 obj->pwm = (LPC_SCT_TypeDef*)LPC_SCT;
mbed_official 480:69aad4cbc07a 60 obj->pwm_ch = sct_n;
mbed_official 480:69aad4cbc07a 61
mbed_official 480:69aad4cbc07a 62 LPC_SCT_TypeDef* pwm = obj->pwm;
mbed_official 480:69aad4cbc07a 63
mbed_official 480:69aad4cbc07a 64 // Init SCT on first use
mbed_official 480:69aad4cbc07a 65 if (! sct_inited) {
mbed_official 480:69aad4cbc07a 66 sct_inited = 1;
mbed_official 480:69aad4cbc07a 67
mbed_official 480:69aad4cbc07a 68 // Enable the SCT clock
mbed_official 480:69aad4cbc07a 69 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);
mbed_official 480:69aad4cbc07a 70
mbed_official 480:69aad4cbc07a 71 // Clear peripheral reset the SCT:
mbed_official 480:69aad4cbc07a 72 LPC_SYSCON->PRESETCTRL |= (1 << 8);
mbed_official 480:69aad4cbc07a 73
mbed_official 480:69aad4cbc07a 74 // Two 16-bit counters, autolimit (ie reset on Match_0)
mbed_official 480:69aad4cbc07a 75 pwm->CONFIG &= ~(0x1);
mbed_official 480:69aad4cbc07a 76 pwm->CONFIG |= (1 << 17);
mbed_official 480:69aad4cbc07a 77
mbed_official 480:69aad4cbc07a 78 // halt and clear the counter
mbed_official 480:69aad4cbc07a 79 pwm->CTRL_L |= (1 << 2) | (1 << 3);
mbed_official 480:69aad4cbc07a 80
mbed_official 480:69aad4cbc07a 81 // System Clock (30 Mhz) -> Prescaler -> us_ticker (1 MHz)
mbed_official 480:69aad4cbc07a 82 pwm->CTRL_L &= ~(0x7F << 5);
mbed_official 480:69aad4cbc07a 83 pwm->CTRL_L |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5);
mbed_official 480:69aad4cbc07a 84
mbed_official 480:69aad4cbc07a 85 pwm->EVENT[0].CTRL = (1 << 12) | 0; // Event_0 on Match_0
mbed_official 480:69aad4cbc07a 86 pwm->EVENT[0].STATE = 0xFFFFFFFF; // All states
mbed_official 480:69aad4cbc07a 87
mbed_official 480:69aad4cbc07a 88 // unhalt the counter:
mbed_official 480:69aad4cbc07a 89 // - clearing bit 2 of the CTRL register
mbed_official 480:69aad4cbc07a 90 pwm->CTRL_L &= ~(1 << 2);
mbed_official 480:69aad4cbc07a 91
mbed_official 480:69aad4cbc07a 92 // Not using IRQs
mbed_official 480:69aad4cbc07a 93 //NVIC_SetVector(PWM_IRQn, (uint32_t)pwm_irq_handler);
mbed_official 480:69aad4cbc07a 94 //NVIC_EnableIRQ(PWM_IRQn);
mbed_official 480:69aad4cbc07a 95 }
mbed_official 480:69aad4cbc07a 96
mbed_official 480:69aad4cbc07a 97 // LPC81x has only one SCT and 4 Outputs
mbed_official 480:69aad4cbc07a 98 // LPC82x has only one SCT and 6 Outputs
mbed_official 480:69aad4cbc07a 99 // LPC1549 has 4 SCTs and 16 Outputs
mbed_official 480:69aad4cbc07a 100 switch(sct_n) {
mbed_official 480:69aad4cbc07a 101 case 0:
mbed_official 480:69aad4cbc07a 102 // SCTx_OUT0
mbed_official 480:69aad4cbc07a 103 LPC_SWM->PINASSIGN[6] &= ~0xFF000000;
mbed_official 480:69aad4cbc07a 104 LPC_SWM->PINASSIGN[6] |= (pin << 24);
mbed_official 480:69aad4cbc07a 105 break;
mbed_official 480:69aad4cbc07a 106 case 1:
mbed_official 480:69aad4cbc07a 107 // SCTx_OUT1
mbed_official 480:69aad4cbc07a 108 LPC_SWM->PINASSIGN[7] &= ~0x000000FF;
mbed_official 480:69aad4cbc07a 109 LPC_SWM->PINASSIGN[7] |= (pin);
mbed_official 480:69aad4cbc07a 110 break;
mbed_official 480:69aad4cbc07a 111 case 2:
mbed_official 480:69aad4cbc07a 112 // SCTx_OUT2
mbed_official 480:69aad4cbc07a 113 LPC_SWM->PINASSIGN[7] &= ~0x0000FF00;
mbed_official 480:69aad4cbc07a 114 LPC_SWM->PINASSIGN[7] |= (pin << 8);
mbed_official 480:69aad4cbc07a 115 break;
mbed_official 480:69aad4cbc07a 116 case 3:
mbed_official 480:69aad4cbc07a 117 // SCTx_OUT3
mbed_official 480:69aad4cbc07a 118 LPC_SWM->PINASSIGN[7] &= ~0x00FF0000;
mbed_official 480:69aad4cbc07a 119 LPC_SWM->PINASSIGN[7] |= (pin << 16);
mbed_official 480:69aad4cbc07a 120 break;
mbed_official 480:69aad4cbc07a 121 default:
mbed_official 480:69aad4cbc07a 122 break;
mbed_official 480:69aad4cbc07a 123 }
mbed_official 480:69aad4cbc07a 124
mbed_official 480:69aad4cbc07a 125 pwm->EVENT[sct_n + 1].CTRL = (1 << 12) | (sct_n + 1); // Event_n on Match_n
mbed_official 480:69aad4cbc07a 126 pwm->EVENT[sct_n + 1].STATE = 0xFFFFFFFF; // All states
mbed_official 480:69aad4cbc07a 127
mbed_official 480:69aad4cbc07a 128 pwm->OUT[sct_n].SET = (1 << 0); // All PWM channels are SET on Event_0
mbed_official 480:69aad4cbc07a 129 pwm->OUT[sct_n].CLR = (1 << (sct_n + 1)); // PWM ch is CLRed on Event_(ch+1)
mbed_official 480:69aad4cbc07a 130
mbed_official 480:69aad4cbc07a 131 // default to 20ms: standard for servos, and fine for e.g. brightness control
mbed_official 480:69aad4cbc07a 132 pwmout_period_ms(obj, 20); // 20ms period
mbed_official 480:69aad4cbc07a 133 pwmout_write (obj, 0.0); // 0ms pulsewidth, dutycycle 0
mbed_official 480:69aad4cbc07a 134 }
mbed_official 480:69aad4cbc07a 135
mbed_official 480:69aad4cbc07a 136 void pwmout_free(pwmout_t* obj) {
mbed_official 480:69aad4cbc07a 137 // PWM channel is now free
mbed_official 480:69aad4cbc07a 138 sct_used &= ~(1 << obj->pwm_ch);
mbed_official 480:69aad4cbc07a 139
mbed_official 480:69aad4cbc07a 140 // Disable the SCT clock when all channels free
mbed_official 480:69aad4cbc07a 141 if (sct_used == 0) {
mbed_official 480:69aad4cbc07a 142 LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 8);
mbed_official 480:69aad4cbc07a 143 sct_inited = 0;
mbed_official 480:69aad4cbc07a 144 };
mbed_official 480:69aad4cbc07a 145 }
mbed_official 480:69aad4cbc07a 146
mbed_official 480:69aad4cbc07a 147 // Set new dutycycle (0.0 .. 1.0)
mbed_official 480:69aad4cbc07a 148 void pwmout_write(pwmout_t* obj, float value) {
mbed_official 480:69aad4cbc07a 149 //value is new dutycycle
mbed_official 480:69aad4cbc07a 150 if (value < 0.0f) {
mbed_official 480:69aad4cbc07a 151 value = 0.0;
mbed_official 480:69aad4cbc07a 152 } else if (value > 1.0f) {
mbed_official 480:69aad4cbc07a 153 value = 1.0;
mbed_official 480:69aad4cbc07a 154 }
mbed_official 480:69aad4cbc07a 155
mbed_official 480:69aad4cbc07a 156 // Match_0 is PWM period. Compute new endtime of pulse for current channel
mbed_official 480:69aad4cbc07a 157 uint32_t t_off = (uint32_t)((float)(obj->pwm->MATCHREL[0].L) * value);
mbed_official 480:69aad4cbc07a 158 obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = t_off; // New endtime
mbed_official 480:69aad4cbc07a 159 }
mbed_official 480:69aad4cbc07a 160
mbed_official 480:69aad4cbc07a 161 // Get dutycycle (0.0 .. 1.0)
mbed_official 480:69aad4cbc07a 162 float pwmout_read(pwmout_t* obj) {
mbed_official 480:69aad4cbc07a 163 uint32_t t_period = obj->pwm->MATCHREL[0].L;
mbed_official 480:69aad4cbc07a 164
mbed_official 480:69aad4cbc07a 165 //Sanity check
mbed_official 480:69aad4cbc07a 166 if (t_period == 0) {
mbed_official 480:69aad4cbc07a 167 return 0.0;
mbed_official 480:69aad4cbc07a 168 };
mbed_official 480:69aad4cbc07a 169
mbed_official 480:69aad4cbc07a 170 uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L;
mbed_official 480:69aad4cbc07a 171 float v = (float)t_off/(float)t_period;
mbed_official 480:69aad4cbc07a 172 //Sanity check
mbed_official 480:69aad4cbc07a 173 return (v > 1.0f) ? (1.0f) : (v);
mbed_official 480:69aad4cbc07a 174 }
mbed_official 480:69aad4cbc07a 175
mbed_official 480:69aad4cbc07a 176 // Set the PWM period, keeping the duty cycle the same (for this channel only!).
mbed_official 480:69aad4cbc07a 177 void pwmout_period(pwmout_t* obj, float seconds){
mbed_official 480:69aad4cbc07a 178 pwmout_period_us(obj, seconds * 1000000.0f);
mbed_official 480:69aad4cbc07a 179 }
mbed_official 480:69aad4cbc07a 180
mbed_official 480:69aad4cbc07a 181 // Set the PWM period, keeping the duty cycle the same (for this channel only!).
mbed_official 480:69aad4cbc07a 182 void pwmout_period_ms(pwmout_t* obj, int ms) {
mbed_official 480:69aad4cbc07a 183 pwmout_period_us(obj, ms * 1000);
mbed_official 480:69aad4cbc07a 184 }
mbed_official 480:69aad4cbc07a 185
mbed_official 480:69aad4cbc07a 186 // Set the PWM period, keeping the duty cycle the same (for this channel only!).
mbed_official 480:69aad4cbc07a 187 void pwmout_period_us(pwmout_t* obj, int us) {
mbed_official 480:69aad4cbc07a 188
mbed_official 480:69aad4cbc07a 189 uint32_t t_period = obj->pwm->MATCHREL[0].L; // Current PWM period
mbed_official 480:69aad4cbc07a 190 obj->pwm->MATCHREL[0].L = (uint64_t)us; // New PWM period
mbed_official 480:69aad4cbc07a 191
mbed_official 480:69aad4cbc07a 192 //Keep the dutycycle for the new PWM period
mbed_official 480:69aad4cbc07a 193 //Should really do this for all active channels!!
mbed_official 480:69aad4cbc07a 194 //This problem exists in all mbed libs.
mbed_official 480:69aad4cbc07a 195
mbed_official 480:69aad4cbc07a 196 //Sanity check
mbed_official 480:69aad4cbc07a 197 if (t_period == 0) {
mbed_official 480:69aad4cbc07a 198 return;
mbed_official 480:69aad4cbc07a 199 // obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = 0; // New endtime for this channel
mbed_official 480:69aad4cbc07a 200 }
mbed_official 480:69aad4cbc07a 201 else {
mbed_official 480:69aad4cbc07a 202 uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L;
mbed_official 480:69aad4cbc07a 203 float v = (float)t_off/(float)t_period;
mbed_official 480:69aad4cbc07a 204 obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = (uint64_t)((float)us * (float)v); // New endtime for this channel
mbed_official 480:69aad4cbc07a 205 }
mbed_official 480:69aad4cbc07a 206 }
mbed_official 480:69aad4cbc07a 207
mbed_official 480:69aad4cbc07a 208
mbed_official 480:69aad4cbc07a 209 //Set pulsewidth
mbed_official 480:69aad4cbc07a 210 void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
mbed_official 480:69aad4cbc07a 211 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
mbed_official 480:69aad4cbc07a 212 }
mbed_official 480:69aad4cbc07a 213
mbed_official 480:69aad4cbc07a 214 //Set pulsewidth
mbed_official 480:69aad4cbc07a 215 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms){
mbed_official 480:69aad4cbc07a 216 pwmout_pulsewidth_us(obj, ms * 1000);
mbed_official 480:69aad4cbc07a 217 }
mbed_official 480:69aad4cbc07a 218
mbed_official 480:69aad4cbc07a 219 //Set pulsewidth
mbed_official 480:69aad4cbc07a 220 void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
mbed_official 480:69aad4cbc07a 221
mbed_official 480:69aad4cbc07a 222 //Should add Sanity check to make sure pulsewidth < period!
mbed_official 480:69aad4cbc07a 223 obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = (uint64_t)us; // New endtime for this channel
mbed_official 480:69aad4cbc07a 224 }
mbed_official 480:69aad4cbc07a 225
mbed_official 480:69aad4cbc07a 226 #endif