From a58a524d4c7e58d03a0fa3698f09fb17985a70bc Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 31 Mar 2011 10:21:52 +0000 Subject: Improvements to the PWM driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2853 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/pwm.h | 107 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 13 deletions(-) (limited to 'os/hal/include') diff --git a/os/hal/include/pwm.h b/os/hal/include/pwm.h index e63478ca3..7181054e4 100644 --- a/os/hal/include/pwm.h +++ b/os/hal/include/pwm.h @@ -57,13 +57,16 @@ typedef enum { } pwmstate_t; /** - * @brief PWM logic mode. + * @brief Type of a structure representing a PWM driver. */ -typedef enum { - PWM_OUTPUT_DISABLED = 0, /**< Output not driven, callback only. */ - PWM_OUTPUT_ACTIVE_HIGH = 1, /**< Idle is logic level 0. */ - PWM_OUTPUT_ACTIVE_LOW = 2 /**< Idle is logic level 1. */ -} pwmmode_t; +typedef struct PWMDriver PWMDriver; + +/** + * @brief PWM notification callback type. + * + * @param[in] pwmp pointer to a @p PWMDriver object + */ +typedef void (*pwmcallback_t)(PWMDriver *pwmp); #include "pwm_lld.h" @@ -71,13 +74,87 @@ typedef enum { /* Driver macros. */ /*===========================================================================*/ +/** + * @brief Converts from fraction to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify tenths of thousandth but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] denominator denominator of the fraction + * @param[in] numerator numerator of the fraction + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \ + ((uint16_t)((((uint32_t)(pwmp)->period) * \ + (uint32_t)(numerator)) / (uint32_t)(denominator))) + +/** + * @brief Converts from degrees to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify hundredths of degrees but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] degrees degrees as an integer between 0 and 36000 + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \ + PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees) + +/** + * @brief Converts from percentage to pulse width. + * @note Be careful with rounding errors, this is integer math not magic. + * You can specify tenths of thousandth but make sure you have the + * proper hardware resolution by carefully choosing the clock source + * and prescaler settings, see @p PWM_COMPUTE_PSC. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] percentage percentage as an integer between 0 and 10000 + * @return The pulse width to be passed to @p pwmEnableChannel(). + * + * @api + */ +#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \ + PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage) + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @post Any active channel is disabled by this function and must be + * activated explicitly using @p pwmEnableChannel(). + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @iclass + */ +#define pwmChangePeriodI(pwmp, period) { \ + (pwmp)->period = (period); \ + pwm_lld_change_period(pwmp, period); \ +} + /** * @brief Enables a PWM channel. - * @details Programs (or reprograms) a PWM channel. - * @note This function has to be invoked from a lock zone. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). * * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) * @param[in] width PWM pulse width as clock pulses number * * @iclass @@ -86,13 +163,16 @@ typedef enum { pwm_lld_enable_channel(pwmp, channel, width) /** - * @brief Disables a PWM channel. - * @details The channel is disabled and its output line returned to the + * @brief Disables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the * idle state. - * @note This function has to be invoked from a lock zone. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). * * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) * * @iclass */ @@ -110,6 +190,7 @@ extern "C" { void pwmObjectInit(PWMDriver *pwmp); void pwmStart(PWMDriver *pwmp, const PWMConfig *config); void pwmStop(PWMDriver *pwmp); + void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period); void pwmEnableChannel(PWMDriver *pwmp, pwmchannel_t channel, pwmcnt_t width); -- cgit v1.2.3