mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /**
elessair 0:f269e3021894 2 ******************************************************************************
elessair 0:f269e3021894 3 * @file pwmout_api.c
elessair 0:f269e3021894 4 * @brief Implementation of a PWM driver
elessair 0:f269e3021894 5 * @internal
elessair 0:f269e3021894 6 * @author ON Semiconductor
elessair 0:f269e3021894 7 * $Rev:
elessair 0:f269e3021894 8 * $Date:
elessair 0:f269e3021894 9 ******************************************************************************
elessair 0:f269e3021894 10 * Copyright 2016 Semiconductor Components Industries LLC (d/b/a “ON Semiconductor”).
elessair 0:f269e3021894 11 * All rights reserved. This software and/or documentation is licensed by ON Semiconductor
elessair 0:f269e3021894 12 * under limited terms and conditions. The terms and conditions pertaining to the software
elessair 0:f269e3021894 13 * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf
elessair 0:f269e3021894 14 * (“ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software”) and
elessair 0:f269e3021894 15 * if applicable the software license agreement. Do not use this software and/or
elessair 0:f269e3021894 16 * documentation unless you have carefully read and you agree to the limited terms and
elessair 0:f269e3021894 17 * conditions. By using this software and/or documentation, you agree to the limited
elessair 0:f269e3021894 18 * terms and conditions.
elessair 0:f269e3021894 19 *
elessair 0:f269e3021894 20 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
elessair 0:f269e3021894 21 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
elessair 0:f269e3021894 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
elessair 0:f269e3021894 23 * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,
elessair 0:f269e3021894 24 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
elessair 0:f269e3021894 25 * @endinternal
elessair 0:f269e3021894 26 */
elessair 0:f269e3021894 27 #include "pwmout_api.h"
elessair 0:f269e3021894 28 #include "PeripheralPins.h"
elessair 0:f269e3021894 29 #include "mbed_assert.h"
elessair 0:f269e3021894 30 #include "clock.h"
elessair 0:f269e3021894 31
elessair 0:f269e3021894 32 #if DEVICE_PWMOUT
elessair 0:f269e3021894 33
elessair 0:f269e3021894 34 /**
elessair 0:f269e3021894 35 * \defgroup hal_pwmout Pwmout hal functions
elessair 0:f269e3021894 36 * @{
elessair 0:f269e3021894 37 */
elessair 0:f269e3021894 38
elessair 0:f269e3021894 39 /** Initialize the pwm out peripheral and configure the pin
elessair 0:f269e3021894 40 *
elessair 0:f269e3021894 41 * @param obj The pwmout object to initialize
elessair 0:f269e3021894 42 * @param pin The pwmout pin to initialize
elessair 0:f269e3021894 43 */
elessair 0:f269e3021894 44 void pwmout_init(pwmout_t *obj, PinName pin)
elessair 0:f269e3021894 45 {
elessair 0:f269e3021894 46 /* Get the base address of the PWM register using the pinmap functions ; pwmout_s struct contains base address only */
elessair 0:f269e3021894 47 PWMName pwm;
elessair 0:f269e3021894 48
elessair 0:f269e3021894 49 pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
elessair 0:f269e3021894 50 MBED_ASSERT(pwm != (PWMName)NC);
elessair 0:f269e3021894 51
elessair 0:f269e3021894 52 pinmap_pinout(pin, PinMap_PWM);
elessair 0:f269e3021894 53
elessair 0:f269e3021894 54 obj->pwmReg = (PwmReg_pt)pwm;
elessair 0:f269e3021894 55 MBED_ASSERT(obj->pwmReg != 0x00000000);
elessair 0:f269e3021894 56
elessair 0:f269e3021894 57 CLOCK_ENABLE(CLOCK_PWM);
elessair 0:f269e3021894 58
elessair 0:f269e3021894 59 /* Configuration parameters of duty cycle 0x4000B000, and prescaler 0x4000B00C, shall be set to default values */
elessair 0:f269e3021894 60 /* Duty cycle shall be 50% and prescaler shall be disabled by default */
elessair 0:f269e3021894 61 obj->pwmReg->DUTYCYCLE = 0x80;
elessair 0:f269e3021894 62
elessair 0:f269e3021894 63 /* Write the PWM output enable register 0x4000B004, to 1 */
elessair 0:f269e3021894 64 obj->pwmReg->PWM_ENABLE.WORD = 0x1;
elessair 0:f269e3021894 65
elessair 0:f269e3021894 66 obj->pwmReg->PRESCALE_DISABLE = 0x1;
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 }
elessair 0:f269e3021894 69
elessair 0:f269e3021894 70 /** Deinitialize the pwmout object
elessair 0:f269e3021894 71 *
elessair 0:f269e3021894 72 * @param obj The pwmout object
elessair 0:f269e3021894 73 */
elessair 0:f269e3021894 74 void pwmout_free(pwmout_t *obj)
elessair 0:f269e3021894 75 {
elessair 0:f269e3021894 76 /* Write the PWM output disable register 0x4000B008, to 1 */
elessair 0:f269e3021894 77 obj->pwmReg->PWM_DISABLE = 0x1;
elessair 0:f269e3021894 78 }
elessair 0:f269e3021894 79
elessair 0:f269e3021894 80 /** Set the output duty-cycle in range <0.0f, 1.0f>
elessair 0:f269e3021894 81 *
elessair 0:f269e3021894 82 * Value 0.0f represents 0 percentage, 1.0f represents 100 percent.
elessair 0:f269e3021894 83 * @param obj The pwmout object
elessair 0:f269e3021894 84 * @param percent The floating-point percentage number
elessair 0:f269e3021894 85 */
elessair 0:f269e3021894 86 void pwmout_write(pwmout_t *obj, float percent)
elessair 0:f269e3021894 87 {
elessair 0:f269e3021894 88 if (percent == 0.0) {
elessair 0:f269e3021894 89 obj->pwmReg->DUTYCYCLE = 0x00;
elessair 0:f269e3021894 90 } else if (percent == 1.0) {
elessair 0:f269e3021894 91 obj->pwmReg->DUTYCYCLE = 0xFF;
elessair 0:f269e3021894 92 } else {
elessair 0:f269e3021894 93 /* Write the duty cycle config register 0x4000B000, with the value passed on */
elessair 0:f269e3021894 94 /* ((percent * 255) + 1) is the duty cycle. Plus 1 is for accounting for round off errors; like a ceil function */
elessair 0:f269e3021894 95 obj->pwmReg->DUTYCYCLE = (uint8_t)((percent * 255) + 1);
elessair 0:f269e3021894 96 }
elessair 0:f269e3021894 97 }
elessair 0:f269e3021894 98
elessair 0:f269e3021894 99 /** Read the current float-point output duty-cycle
elessair 0:f269e3021894 100 *
elessair 0:f269e3021894 101 * @param obj The pwmout object
elessair 0:f269e3021894 102 * @return A floating-point output duty-cycle
elessair 0:f269e3021894 103 */
elessair 0:f269e3021894 104 float pwmout_read(pwmout_t *obj)
elessair 0:f269e3021894 105 {
elessair 0:f269e3021894 106 float retVal = 0.0;
elessair 0:f269e3021894 107 float dc = 0.0;
elessair 0:f269e3021894 108
elessair 0:f269e3021894 109 /* Read out the value of duty cycle register 0x4000B000 and return as a percent */
elessair 0:f269e3021894 110 /* Read value / 255 is the percent returned */
elessair 0:f269e3021894 111 dc = obj->pwmReg->DUTYCYCLE;
elessair 0:f269e3021894 112 retVal = dc/ (float)255;
elessair 0:f269e3021894 113
elessair 0:f269e3021894 114 return(retVal);
elessair 0:f269e3021894 115 }
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 /** Set the PWM period specified in seconds, keeping the duty cycle the same
elessair 0:f269e3021894 118 *
elessair 0:f269e3021894 119 * Periods smaller than microseconds (the lowest resolution) are set to zero.
elessair 0:f269e3021894 120 * @param obj The pwmout object
elessair 0:f269e3021894 121 * @param seconds The floating-point seconds period
elessair 0:f269e3021894 122 */
elessair 0:f269e3021894 123 void pwmout_period(pwmout_t *obj, float seconds)
elessair 0:f269e3021894 124 {
elessair 0:f269e3021894 125 /* Cannot be configured, prescaler is either 256 or 4096 */
elessair 0:f269e3021894 126 return;
elessair 0:f269e3021894 127 }
elessair 0:f269e3021894 128
elessair 0:f269e3021894 129 /** Set the PWM period specified in miliseconds, keeping the duty cycle the same
elessair 0:f269e3021894 130 *
elessair 0:f269e3021894 131 * @param obj The pwmout object
elessair 0:f269e3021894 132 * @param ms The milisecond period
elessair 0:f269e3021894 133 */
elessair 0:f269e3021894 134 void pwmout_period_ms(pwmout_t *obj, int ms)
elessair 0:f269e3021894 135 {
elessair 0:f269e3021894 136 /* Cannot be configured, prescaler is either 256 or 4096 */
elessair 0:f269e3021894 137 return;
elessair 0:f269e3021894 138 }
elessair 0:f269e3021894 139
elessair 0:f269e3021894 140 /** Set the PWM period specified in microseconds, keeping the duty cycle the same
elessair 0:f269e3021894 141 *
elessair 0:f269e3021894 142 * @param obj The pwmout object
elessair 0:f269e3021894 143 * @param us The microsecond period
elessair 0:f269e3021894 144 */
elessair 0:f269e3021894 145 void pwmout_period_us(pwmout_t *obj, int us)
elessair 0:f269e3021894 146 {
elessair 0:f269e3021894 147 /* Cannot be configured, prescaler is either 256 or 4096 */
elessair 0:f269e3021894 148 return;
elessair 0:f269e3021894 149 }
elessair 0:f269e3021894 150
elessair 0:f269e3021894 151 /** Set the PWM pulsewidth specified in seconds, keeping the period the same.
elessair 0:f269e3021894 152 *
elessair 0:f269e3021894 153 * @param obj The pwmout object
elessair 0:f269e3021894 154 * @param seconds The floating-point pulsewidth in seconds
elessair 0:f269e3021894 155 */
elessair 0:f269e3021894 156 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
elessair 0:f269e3021894 157 {
elessair 0:f269e3021894 158 /* Pulse width can never be in seconds since the period
elessair 0:f269e3021894 159 * itself is limited to either 8uSec or 128uSec
elessair 0:f269e3021894 160 */
elessair 0:f269e3021894 161 return;
elessair 0:f269e3021894 162 }
elessair 0:f269e3021894 163
elessair 0:f269e3021894 164 /** Set the PWM pulsewidth specified in miliseconds, keeping the period the same.
elessair 0:f269e3021894 165 *
elessair 0:f269e3021894 166 * @param obj The pwmout object
elessair 0:f269e3021894 167 * @param ms The floating-point pulsewidth in miliseconds
elessair 0:f269e3021894 168 */
elessair 0:f269e3021894 169 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
elessair 0:f269e3021894 170 {
elessair 0:f269e3021894 171
elessair 0:f269e3021894 172 /* Pulse width can never be in seconds since the period
elessair 0:f269e3021894 173 * itself is limited to either 8uSec or 128uSec
elessair 0:f269e3021894 174 */
elessair 0:f269e3021894 175 return;
elessair 0:f269e3021894 176 }
elessair 0:f269e3021894 177
elessair 0:f269e3021894 178 /** Set the PWM pulsewidth specified in microseconds, keeping the period the same.
elessair 0:f269e3021894 179 *
elessair 0:f269e3021894 180 * @param obj The pwmout object
elessair 0:f269e3021894 181 * @param us The floating-point pulsewidth in microseconds
elessair 0:f269e3021894 182 */
elessair 0:f269e3021894 183 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
elessair 0:f269e3021894 184 {
elessair 0:f269e3021894 185 int pulseWidth = 0;
elessair 0:f269e3021894 186
elessair 0:f269e3021894 187 /* Check if the uSec value is greater than 128uSec, if so reject */
elessair 0:f269e3021894 188 if (us > 128) {
elessair 0:f269e3021894 189 return;
elessair 0:f269e3021894 190 }
elessair 0:f269e3021894 191 /* If pulsewidth is less than 128uSec, set the prescaler to 4096
elessair 0:f269e3021894 192 * by enabling prescale register 0x4000B00C to 1 */
elessair 0:f269e3021894 193 obj->pwmReg->PRESCALE_ENABLE.WORD = 0x1;
elessair 0:f269e3021894 194
elessair 0:f269e3021894 195 /* Calculate the duty cycle based on the width of the pulse */
elessair 0:f269e3021894 196 /* ((255 * us) / 128) + 1 = duty cycle */
elessair 0:f269e3021894 197 pulseWidth = (int)((float)(255 * us)/(float)128) + 1;
elessair 0:f269e3021894 198 if (us == 0) {
elessair 0:f269e3021894 199 obj->pwmReg->DUTYCYCLE = 0x0;
elessair 0:f269e3021894 200 } else if (us == 128) {
elessair 0:f269e3021894 201 obj->pwmReg->DUTYCYCLE = 0xFF;
elessair 0:f269e3021894 202 } else {
elessair 0:f269e3021894 203 obj->pwmReg->DUTYCYCLE = (uint8_t)pulseWidth;
elessair 0:f269e3021894 204 }
elessair 0:f269e3021894 205 }
elessair 0:f269e3021894 206
elessair 0:f269e3021894 207 /**@}*/
elessair 0:f269e3021894 208
elessair 0:f269e3021894 209 #endif // DEVICE_PWMOUT