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:
mbed_official
Date:
Fri Sep 25 14:15:10 2015 +0100
Revision:
627:4fa1328d9c60
Parent:
556:a217bc785985
Synchronized with git revision fe238a91ab7a4d1d72c4cab9da04967c619d54ad

Full URL: https://github.com/mbedmicro/mbed/commit/fe238a91ab7a4d1d72c4cab9da04967c619d54ad/

Silicon Labs - Add support for low-power async Serial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 627:4fa1328d9c60 1 /***************************************************************************//**
mbed_official 627:4fa1328d9c60 2 * @file pwmout_api.c
mbed_official 627:4fa1328d9c60 3 *******************************************************************************
mbed_official 627:4fa1328d9c60 4 * @section License
mbed_official 627:4fa1328d9c60 5 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
mbed_official 627:4fa1328d9c60 6 *******************************************************************************
mbed_official 525:c320967f86b9 7 *
mbed_official 627:4fa1328d9c60 8 * Permission is granted to anyone to use this software for any purpose,
mbed_official 627:4fa1328d9c60 9 * including commercial applications, and to alter it and redistribute it
mbed_official 627:4fa1328d9c60 10 * freely, subject to the following restrictions:
mbed_official 525:c320967f86b9 11 *
mbed_official 627:4fa1328d9c60 12 * 1. The origin of this software must not be misrepresented; you must not
mbed_official 627:4fa1328d9c60 13 * claim that you wrote the original software.
mbed_official 627:4fa1328d9c60 14 * 2. Altered source versions must be plainly marked as such, and must not be
mbed_official 627:4fa1328d9c60 15 * misrepresented as being the original software.
mbed_official 627:4fa1328d9c60 16 * 3. This notice may not be removed or altered from any source distribution.
mbed_official 525:c320967f86b9 17 *
mbed_official 627:4fa1328d9c60 18 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
mbed_official 627:4fa1328d9c60 19 * obligation to support this Software. Silicon Labs is providing the
mbed_official 627:4fa1328d9c60 20 * Software "AS IS", with no express or implied warranties of any kind,
mbed_official 627:4fa1328d9c60 21 * including, but not limited to, any implied warranties of merchantability
mbed_official 627:4fa1328d9c60 22 * or fitness for any particular purpose or warranties against infringement
mbed_official 627:4fa1328d9c60 23 * of any proprietary rights of a third party.
mbed_official 627:4fa1328d9c60 24 *
mbed_official 627:4fa1328d9c60 25 * Silicon Labs will not be liable for any consequential, incidental, or
mbed_official 627:4fa1328d9c60 26 * special damages, or any other relief, or for any claim by any third party,
mbed_official 627:4fa1328d9c60 27 * arising from your use of this Software.
mbed_official 627:4fa1328d9c60 28 *
mbed_official 627:4fa1328d9c60 29 ******************************************************************************/
mbed_official 525:c320967f86b9 30
mbed_official 525:c320967f86b9 31 #include "device.h"
mbed_official 525:c320967f86b9 32 #include "clocking.h"
mbed_official 525:c320967f86b9 33 #if DEVICE_PWMOUT
mbed_official 525:c320967f86b9 34
mbed_official 525:c320967f86b9 35 #include "mbed_assert.h"
mbed_official 525:c320967f86b9 36 #include "pwmout_api.h"
mbed_official 525:c320967f86b9 37 #include "cmsis.h"
mbed_official 525:c320967f86b9 38 #include "pinmap.h"
mbed_official 525:c320967f86b9 39 #include "PeripheralPins.h"
mbed_official 525:c320967f86b9 40 #include "device_peripherals.h"
mbed_official 544:1af5f1c39e80 41 #include "sleepmodes.h"
mbed_official 525:c320967f86b9 42
mbed_official 525:c320967f86b9 43 #include "em_cmu.h"
mbed_official 525:c320967f86b9 44 #include "em_gpio.h"
mbed_official 525:c320967f86b9 45 #include "em_timer.h"
mbed_official 525:c320967f86b9 46
mbed_official 544:1af5f1c39e80 47 static int pwm_prescaler_div;
mbed_official 525:c320967f86b9 48
mbed_official 548:1abac31e188e 49 uint32_t pwmout_get_channel_route(pwmout_t *obj)
mbed_official 548:1abac31e188e 50 {
mbed_official 548:1abac31e188e 51 MBED_ASSERT(obj->channel != (PWMName) NC);
mbed_official 525:c320967f86b9 52
mbed_official 548:1abac31e188e 53 switch (obj->channel) {
mbed_official 548:1abac31e188e 54 case PWM_CH0:
mbed_official 548:1abac31e188e 55 return TIMER_ROUTE_CC0PEN;
mbed_official 548:1abac31e188e 56 break;
mbed_official 548:1abac31e188e 57 case PWM_CH1:
mbed_official 548:1abac31e188e 58 return TIMER_ROUTE_CC1PEN;
mbed_official 548:1abac31e188e 59 break;
mbed_official 548:1abac31e188e 60 case PWM_CH2:
mbed_official 548:1abac31e188e 61 return TIMER_ROUTE_CC2PEN;
mbed_official 548:1abac31e188e 62 break;
mbed_official 548:1abac31e188e 63 default:
mbed_official 548:1abac31e188e 64 return 0;
mbed_official 548:1abac31e188e 65 }
mbed_official 525:c320967f86b9 66 }
mbed_official 525:c320967f86b9 67
mbed_official 525:c320967f86b9 68 void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 69 {
mbed_official 525:c320967f86b9 70 if (enable) {
mbed_official 525:c320967f86b9 71 pin_mode(obj->pin, PushPull);
mbed_official 525:c320967f86b9 72 } else {
mbed_official 525:c320967f86b9 73 // TODO_LP return PinMode to the previous state
mbed_official 525:c320967f86b9 74 pin_mode(obj->pin, Disabled);
mbed_official 525:c320967f86b9 75 }
mbed_official 525:c320967f86b9 76 }
mbed_official 525:c320967f86b9 77
mbed_official 525:c320967f86b9 78 void pwmout_enable(pwmout_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 79 {
mbed_official 548:1abac31e188e 80 /* Start with default CC (Compare/Capture) channel parameters */
mbed_official 548:1abac31e188e 81 TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
mbed_official 525:c320967f86b9 82 if (enable) {
mbed_official 525:c320967f86b9 83 /* Set mode to PWM */
mbed_official 525:c320967f86b9 84 timerCCInit.mode = timerCCModePWM;
mbed_official 544:1af5f1c39e80 85 }
mbed_official 525:c320967f86b9 86
mbed_official 544:1af5f1c39e80 87 /* Configure CC channel */
mbed_official 544:1af5f1c39e80 88 TIMER_InitCC(PWM_TIMER, obj->channel, &timerCCInit);
mbed_official 525:c320967f86b9 89 }
mbed_official 525:c320967f86b9 90
mbed_official 544:1af5f1c39e80 91 void pwmout_init(pwmout_t *obj, PinName pin)
mbed_official 544:1af5f1c39e80 92 {
mbed_official 548:1abac31e188e 93 obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
mbed_official 548:1abac31e188e 94 obj->pin = pin;
mbed_official 548:1abac31e188e 95 MBED_ASSERT(obj->channel != (PWMName) NC);
mbed_official 544:1af5f1c39e80 96
mbed_official 548:1abac31e188e 97 /* Turn on clock */
mbed_official 548:1abac31e188e 98 CMU_ClockEnable(PWM_TIMER_CLOCK, true);
mbed_official 544:1af5f1c39e80 99
mbed_official 548:1abac31e188e 100 /* Turn on timer */
mbed_official 548:1abac31e188e 101 if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
mbed_official 548:1abac31e188e 102 TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
mbed_official 548:1abac31e188e 103 TIMER_Init(PWM_TIMER, &timerInit);
mbed_official 548:1abac31e188e 104 }
mbed_official 544:1af5f1c39e80 105
mbed_official 544:1af5f1c39e80 106 /* Enable correct channel */
mbed_official 548:1abac31e188e 107 uint32_t routeloc = pwmout_get_channel_route(obj);
mbed_official 548:1abac31e188e 108 if(PWM_TIMER->ROUTE & routeloc) {
mbed_official 548:1abac31e188e 109 //This channel was already in use
mbed_official 548:1abac31e188e 110 //TODO: gracefully handle this case
mbed_official 548:1abac31e188e 111 } else {
mbed_official 548:1abac31e188e 112 //This channel was unused up to now
mbed_official 548:1abac31e188e 113 PWM_TIMER->ROUTE |= routeloc;
mbed_official 548:1abac31e188e 114 blockSleepMode(EM1);
mbed_official 544:1af5f1c39e80 115
mbed_official 548:1abac31e188e 116 //TODO: check if any channel was up already, then don't re-init timer
mbed_official 548:1abac31e188e 117 pwmout_enable(obj, true);
mbed_official 548:1abac31e188e 118 pwmout_enable_pins(obj, true);
mbed_official 548:1abac31e188e 119 }
mbed_official 544:1af5f1c39e80 120
mbed_official 544:1af5f1c39e80 121 /* Route correct channel to location 1 */
mbed_official 544:1af5f1c39e80 122 PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
mbed_official 544:1af5f1c39e80 123 PWM_TIMER->ROUTE |= PWM_ROUTE;
mbed_official 544:1af5f1c39e80 124
mbed_official 544:1af5f1c39e80 125 /* Set default 20ms frequency and 0ms pulse width */
mbed_official 544:1af5f1c39e80 126 pwmout_period(obj, 0.02);
mbed_official 544:1af5f1c39e80 127 }
mbed_official 544:1af5f1c39e80 128
mbed_official 548:1abac31e188e 129 void pwmout_free(pwmout_t *obj)
mbed_official 548:1abac31e188e 130 {
mbed_official 548:1abac31e188e 131 uint32_t routeloc = pwmout_get_channel_route(obj);
mbed_official 548:1abac31e188e 132 if(PWM_TIMER->ROUTE & routeloc) {
mbed_official 548:1abac31e188e 133 //This channel was in use, so disable
mbed_official 548:1abac31e188e 134 PWM_TIMER->ROUTE &= ~routeloc;
mbed_official 548:1abac31e188e 135 pwmout_enable_pins(obj, false);
mbed_official 548:1abac31e188e 136 unblockSleepMode(EM1);
mbed_official 544:1af5f1c39e80 137
mbed_official 548:1abac31e188e 138 //TODO: check if all channels are down, then switch off timer
mbed_official 548:1abac31e188e 139 } else {
mbed_official 548:1abac31e188e 140 //This channel was disabled already
mbed_official 548:1abac31e188e 141 }
mbed_official 544:1af5f1c39e80 142 }
mbed_official 525:c320967f86b9 143
mbed_official 525:c320967f86b9 144 void pwmout_write(pwmout_t *obj, float value)
mbed_official 525:c320967f86b9 145 {
mbed_official 525:c320967f86b9 146 if (value < 0.0f) {
mbed_official 525:c320967f86b9 147 value = 0;
mbed_official 525:c320967f86b9 148 } else if (value > 1.0f) {
mbed_official 525:c320967f86b9 149 value = 1;
mbed_official 525:c320967f86b9 150 }
mbed_official 525:c320967f86b9 151
mbed_official 556:a217bc785985 152 float pulse_period_in_s = obj->period_cycles / ((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div));
mbed_official 525:c320967f86b9 153 pwmout_pulsewidth(obj, value * pulse_period_in_s);
mbed_official 525:c320967f86b9 154 }
mbed_official 525:c320967f86b9 155
mbed_official 525:c320967f86b9 156 float pwmout_read(pwmout_t *obj)
mbed_official 525:c320967f86b9 157 {
mbed_official 525:c320967f86b9 158 return obj->width_cycles / (float) obj->period_cycles;
mbed_official 525:c320967f86b9 159 }
mbed_official 525:c320967f86b9 160
mbed_official 525:c320967f86b9 161 // Set the PWM period, keeping the absolute pulse width the same.
mbed_official 525:c320967f86b9 162 void pwmout_period(pwmout_t *obj, float seconds)
mbed_official 525:c320967f86b9 163 {
mbed_official 525:c320967f86b9 164 // Find the lowest prescaler divider possible.
mbed_official 525:c320967f86b9 165 // This gives us max resolution for a given period
mbed_official 525:c320967f86b9 166
mbed_official 525:c320967f86b9 167 //The value of the top register if prescaler is set to 0
mbed_official 556:a217bc785985 168 int cycles = REFERENCE_FREQUENCY * seconds;
mbed_official 544:1af5f1c39e80 169 pwm_prescaler_div = 0;
mbed_official 525:c320967f86b9 170
mbed_official 525:c320967f86b9 171 //The top register is only 16 bits, so we keep dividing till we are below 0xFFFF
mbed_official 525:c320967f86b9 172 while (cycles > 0xFFFF) {
mbed_official 525:c320967f86b9 173 cycles /= 2;
mbed_official 544:1af5f1c39e80 174 pwm_prescaler_div++;
mbed_official 525:c320967f86b9 175
mbed_official 544:1af5f1c39e80 176 //Max pwm_prescaler_div supported is 10
mbed_official 544:1af5f1c39e80 177 if (pwm_prescaler_div > 10) {
mbed_official 544:1af5f1c39e80 178 pwm_prescaler_div = 10;
mbed_official 525:c320967f86b9 179 cycles = 0xFFFF; //Set it to max possible value;
mbed_official 525:c320967f86b9 180 break;
mbed_official 525:c320967f86b9 181 }
mbed_official 525:c320967f86b9 182 }
mbed_official 525:c320967f86b9 183
mbed_official 525:c320967f86b9 184 obj->period_cycles = cycles;
mbed_official 525:c320967f86b9 185
mbed_official 525:c320967f86b9 186 //Set prescaler
mbed_official 544:1af5f1c39e80 187 PWM_TIMER->CTRL = (PWM_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT);
mbed_official 525:c320967f86b9 188
mbed_official 525:c320967f86b9 189 /* Set Top Value, which controls the PWM period */
mbed_official 525:c320967f86b9 190 TIMER_TopSet(PWM_TIMER, obj->period_cycles);
mbed_official 525:c320967f86b9 191 }
mbed_official 525:c320967f86b9 192
mbed_official 525:c320967f86b9 193 void pwmout_period_ms(pwmout_t *obj, int ms)
mbed_official 525:c320967f86b9 194 {
mbed_official 525:c320967f86b9 195 pwmout_period(obj, ms / 1000.0f);
mbed_official 525:c320967f86b9 196 }
mbed_official 525:c320967f86b9 197
mbed_official 525:c320967f86b9 198 void pwmout_period_us(pwmout_t *obj, int us)
mbed_official 525:c320967f86b9 199 {
mbed_official 556:a217bc785985 200 pwmout_period(obj, us / 1000000.0f);
mbed_official 525:c320967f86b9 201 }
mbed_official 525:c320967f86b9 202
mbed_official 525:c320967f86b9 203 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
mbed_official 525:c320967f86b9 204 {
mbed_official 556:a217bc785985 205 obj->width_cycles = (uint32_t) (((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
mbed_official 525:c320967f86b9 206 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 207 }
mbed_official 525:c320967f86b9 208
mbed_official 525:c320967f86b9 209 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
mbed_official 525:c320967f86b9 210 {
mbed_official 556:a217bc785985 211 obj->width_cycles = (uint32_t) ((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000;
mbed_official 556:a217bc785985 212 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 213 }
mbed_official 525:c320967f86b9 214
mbed_official 525:c320967f86b9 215 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
mbed_official 525:c320967f86b9 216 {
mbed_official 556:a217bc785985 217 obj->width_cycles = (uint32_t) ((REFERENCE_FREQUENCY >> pwm_prescaler_div) * us) / 1000000;
mbed_official 556:a217bc785985 218 TIMER_CompareBufSet(PWM_TIMER, obj->channel, obj->width_cycles);
mbed_official 525:c320967f86b9 219 }
mbed_official 525:c320967f86b9 220
mbed_official 525:c320967f86b9 221 #endif