nes-proj/cpu/cc2538/dev/pwm.h
Benoît Thébaudeau 4a6e19ed38 cc2538: pwm: Automatically disable PM1+ if running
The peripheral core clocks of the PWM timers are gated in PM1+, so these
power modes must be disabled if a PWM timer is running. Use
lpm_register_peripheral() to handle this automatically and dynamically.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2015-12-13 02:39:55 +01:00

181 lines
8.1 KiB
C

/*
* Copyright (c) 2015, Zolertia - http://www.zolertia.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup cc2538
* @{
*
* \defgroup cc2538-pwm-driver CC2538 PWM driver
*
* Driver for the CC2538 PWM on GPTIMER
*
* The driver uses the timers A and B of the general purpose timers to create
* a PWM signal, allowing to set a duty cycle value from 1-100%. This
* implementation relies on having a peripheral clock of 16MHz, but it can be
* easily changed (see PWM_FREQ_MIN and PWM_FREQ_MAX values). The reason it is
* fixed to these frequencies is to have a consistent duty cycle
* implementation.
*
* Depending on the specific needs these limits can be changed to meet a given
* duty cycle and lower frequencies by using the prescaler (GPTIMER_TnPR).
*
* Running a PWM timer prevents the LPM driver from dropping to PM1+.
*
* @{
*
* \file
* Header file for the CC2538 PWM driver
*
* \author
* Javier Sanchez <jsanchez@zolertia.com>
* Antonio Lignan <alinan@zolertia.com>
*/
/*---------------------------------------------------------------------------*/
#ifndef PWM_H_
#define PWM_H_
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "dev/ioc.h"
#include "dev/gpio.h"
#include "dev/sys-ctrl.h"
/*---------------------------------------------------------------------------*/
/** \name PWM return values
* @{
*/
#define PWM_SUCCESS 0
#define PWM_ERROR (-1)
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PWM recommended values respect to peripheral clock frequency
* @{
*/
/* Roughly 244 Hz with a 16-MHz system clock, no prescaler */
#define PWM_SYS_16MHZ_NO_PRES_MIN 0xFFFF
#define PWM_SYS_16MHZ_NO_PRES_MIN_FREQ 244
/* Roughly 1 Hz with a 16-MHz system clock, to keep frequency parameter in Hz */
#define PWM_SYS_16MHZ_PRES_MIN 0x00F42400
#define PWM_SYS_16MHZ_PRES_MIN_FREQ 1
/* Yields 160 KHz at 16 MHz and allows down to 1% (integer) duty cycles */
#define PWM_SYS_16MHZ_NO_PRES_MAX 100
#define PWM_SYS_16MHZ_NO_PRES_MAX_FREQ 160000
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PWM driver definitions and configuration values
* @{
*/
#define PWM_TIMER_A 0
#define PWM_TIMER_B 1
#define PWM_TIMER_0 0
#define PWM_TIMER_1 1
#define PWM_TIMER_2 2
#define PWM_TIMER_3 3
#define PWM_TIMER_MIN PWM_TIMER_0
#define PWM_TIMER_MAX PWM_TIMER_3
#define PWM_SIGNAL_STRAIGHT 1
#define PWM_SIGNAL_INVERTED 0
#define PWM_OFF_WHEN_STOP 0
#define PWM_ON_WHEN_STOP 1
#define PWM_GPTIMER_CFG_SPLIT_MODE 0x04
#define PWM_DUTY_MAX 100
#define PWM_DUTY_MIN 0
#define PWM_FREQ_MIN PWM_SYS_16MHZ_PRES_MIN_FREQ
#define PWM_FREQ_MAX PWM_SYS_16MHZ_NO_PRES_MAX_FREQ
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PWM functions
* @{
*/
/** \brief Configures the general purpose timer in PWM mode
* \param freq PWM frequency (in Hz)
* \param duty PWM duty cycle (percentage in integers)
* \param timer General purpose timer to use [0-3]
* \param ab Select which timer to use (Timer A or B)
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*/
int8_t pwm_enable(uint32_t freq, uint8_t duty, uint8_t timer, uint8_t ab);
/*---------------------------------------------------------------------------*/
/** \brief Disables a previously PWM configured GPTn
* \param timer General purpose timer to disable [0-3]
* \param ab Select which timer to disable (Timer A or B)
* \param port Port number used as PWM to disable (set as input GPIO)
* \param pin Pin number used as PWM to disable (set as input GPIO)
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*
* This function disables a specific timer (A or B) and reset related registers
* to default values. The user must explicitely pass the port/pin number of
* the pin to disable as PWM and to be configured as input GPIO.
* The module clock is not disabled with this function
*/
int8_t pwm_disable(uint8_t timer, uint8_t ab, uint8_t port, uint8_t pin);
/*---------------------------------------------------------------------------*/
/** \brief Once configured, starts the PWM
* \param timer General purpose timer to start [0-3]
* \param ab Select which timer to start (Timer A or B)
* \param port Port number to use as PWM
* \param pin Pin number to use as PWM
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*/
int8_t pwm_start(uint8_t timer, uint8_t ab, uint8_t port, uint8_t pin);
/*---------------------------------------------------------------------------*/
/** \brief Halts the PWM in a given GPT/timer
* \param timer General purpose timer to stop [0-3]
* \param ab Select which timer to stop (Timer A or B)
* \param port Port of the gpio port mapped to the PWM to stop
* \param pin Pin of the gpio port mapped to the PWM to stop
* \param state State to leave the pin once stopped, on (1) or off (0)
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*/
int8_t pwm_stop(uint8_t timer, uint8_t ab, uint8_t port, uint8_t pin, uint8_t state);
/*---------------------------------------------------------------------------*/
/** \brief Sets the PWM duty cycle signal direction (high/low)
* \param timer General purpose timer [0-3]
* \param ab Select which timer to use (Timer A or B)
* \param dir Direction of the PWM signal, \c PWM_SIGNAL_INVERTED or
* \c PWM_SIGNAL_STRAIGHT
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*/
int8_t pwm_set_direction(uint8_t timer, uint8_t ab, uint8_t dir);
/*---------------------------------------------------------------------------*/
/** \brief Toggle the PWM signal direction (inverts the current duty cycle)
* \param timer General purpose timer to use [0-3]
* \param ab Select which timer to use (Timer A or B)
* \return \c PWM_SUCCESS if successful, else \c PWM_ERROR
*/
int8_t pwm_toggle_direction(uint8_t timer, uint8_t ab);
/*---------------------------------------------------------------------------*/
/** @} */
#endif /* PWM_H_ */
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/