SWM050: Adds the timer peripheral and updates the README.
This commit is contained in:
parent
7daa6f15bf
commit
f06a1ca958
@ -18,6 +18,7 @@ Currently (at least partly) supported microcontrollers:
|
|||||||
- EFM32 Gecko series (only core support)
|
- EFM32 Gecko series (only core support)
|
||||||
- Freescale Vybrid VF6xx
|
- Freescale Vybrid VF6xx
|
||||||
- Qorvo (formerly ActiveSemi) PAC55XX
|
- Qorvo (formerly ActiveSemi) PAC55XX
|
||||||
|
- Synwit SWM050
|
||||||
|
|
||||||
The library is written completely from scratch based on the vendor datasheets,
|
The library is written completely from scratch based on the vendor datasheets,
|
||||||
programming manuals, and application notes. The code is meant to be used
|
programming manuals, and application notes. The code is meant to be used
|
||||||
|
233
include/libopencm3/swm050/timer.h
Normal file
233
include/libopencm3/swm050/timer.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/** @defgroup timer_defines Timer Defines
|
||||||
|
*
|
||||||
|
* @brief <b>Defined Constants and Types for the SWM050 Timer</b>
|
||||||
|
*
|
||||||
|
* @ingroup SWM050_defines
|
||||||
|
*
|
||||||
|
* LGPL License Terms @ref lgpl_license
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**@{*/
|
||||||
|
#ifndef LIBOPENCM3_TIMER_H
|
||||||
|
#define LIBOPENCM3_TIMER_H
|
||||||
|
#include <libopencm3/cm3/common.h>
|
||||||
|
#include <libopencm3/swm050/memorymap.h>
|
||||||
|
|
||||||
|
/* Timer select */
|
||||||
|
/** @defgroup timer_select Timer Select
|
||||||
|
@{*/
|
||||||
|
#define TIMER_SE0 TIMER_SE0_BASE
|
||||||
|
#define TIMER_SE1 TIMER_SE1_BASE
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer level definitions */
|
||||||
|
/** @defgroup timer_level Timer Level
|
||||||
|
@{*/
|
||||||
|
enum timer_level {
|
||||||
|
TIMER_LEVEL_LOW,
|
||||||
|
TIMER_LEVEL_HIGH
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer edge mode definitions */
|
||||||
|
/** @defgroup timer_edge_modes Timer Edge Modes
|
||||||
|
@{*/
|
||||||
|
enum timer_edge_modes {
|
||||||
|
/* Trigger on rising edge */
|
||||||
|
TIMER_EDGE_RISING,
|
||||||
|
/* Trigger on falling edge */
|
||||||
|
TIMER_EDGE_FALLING
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer operation mode definitions */
|
||||||
|
/** @defgroup timer_operation_modes Timer Operation Modes
|
||||||
|
@{*/
|
||||||
|
enum timer_operation_modes {
|
||||||
|
TIMER_MODE_COUNTER,
|
||||||
|
TIMER_MODE_PWM,
|
||||||
|
TIMER_MODE_PULSE_CAPTURE,
|
||||||
|
TIMER_MODE_DUTY_CYCLE_CAPTURE
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer clock source definitions */
|
||||||
|
/** @defgroup timer_clk_src Timer Clock Source
|
||||||
|
@{*/
|
||||||
|
enum timer_clk_src {
|
||||||
|
TIMER_CLK_INTERNAL,
|
||||||
|
TIMER_CLK_EXTERNAL
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer interrupt mask definitions */
|
||||||
|
/** @defgroup timer_int_masked Timer Interrupt Mask
|
||||||
|
@{*/
|
||||||
|
enum timer_int_masked {
|
||||||
|
TIMER_UNMASKED,
|
||||||
|
TIMER_MASKED
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer loop mode definitions */
|
||||||
|
/** @defgroup timer_loop_modes Timer Loop Modes
|
||||||
|
@{*/
|
||||||
|
enum timer_loop_modes {
|
||||||
|
TIMER_LOOP_MODE,
|
||||||
|
TIMER_SINGLE_MODE
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer output mode definitions */
|
||||||
|
/** @defgroup timer_output_modes Timer Output Modes
|
||||||
|
@{*/
|
||||||
|
enum timer_output_modes {
|
||||||
|
TIMER_OUTPUT_NONE,
|
||||||
|
TIMER_OUTPUT_INVERT,
|
||||||
|
TIMER_OUTPUT_HIGH,
|
||||||
|
TIMER_OUTPUT_LOW
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer PWM period definitions */
|
||||||
|
/** @defgroup timer_pwm_period Timer PWM Periods
|
||||||
|
@{*/
|
||||||
|
enum timer_pwm_period {
|
||||||
|
TIMER_PERIOD_0,
|
||||||
|
TIMER_PERIOD_1
|
||||||
|
};
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer clock divider mask */
|
||||||
|
/** @defgroup timer_div_mask Timer Clock Divider Mask
|
||||||
|
@{*/
|
||||||
|
#define TIMER_DIV_MASK (0x3F << 16)
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer operation mode mask */
|
||||||
|
/** @defgroup timer_operation_mask Timer Operation Mode Mask
|
||||||
|
@{*/
|
||||||
|
#define TIMER_OPER_MODE_MASK (0x3 << 4)
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer output mode mask */
|
||||||
|
/** @defgroup timer_output_mask Timer Output Mode Mask
|
||||||
|
@{*/
|
||||||
|
#define TIMER_OUTP_MODE_MASK (0x3 << 12)
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer subregisters */
|
||||||
|
/** @defgroup timer_subregisters Timer Subregisters
|
||||||
|
@{*/
|
||||||
|
#define TIMER_CTRL_EN 1
|
||||||
|
/** Clock source selection */
|
||||||
|
#define TIMER_CTRL_OSCMOD (1 << 8)
|
||||||
|
/** Valid edge selection */
|
||||||
|
#define TIMER_CTRL_TMOD (1 << 16)
|
||||||
|
/** Loop mode selection */
|
||||||
|
#define TIMER_CTRL_LMOD (1 << 28)
|
||||||
|
/** Interrupt mask */
|
||||||
|
#define TIMER_INTCTL_INTMSK (1 << 1)
|
||||||
|
/** Interrupt enable */
|
||||||
|
#define TIMER_INTCTL_INTEN 1
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
/* Timer registers */
|
||||||
|
/** @defgroup timer_registers Timer Registers
|
||||||
|
@{*/
|
||||||
|
/** Timer control register */
|
||||||
|
#define TIMER_CTRL(x) MMIO32(x + 0x0)
|
||||||
|
/** The target value(s). Treated as uint32_t in counter mode (0), and as 2
|
||||||
|
uint16_t values in PWM mode (1) */
|
||||||
|
#define TIMER_TARVAL(x) MMIO32(x + 0x4)
|
||||||
|
/** Current count value in modes 0, 2, and 3 */
|
||||||
|
#define TIMER_CURVAL(x) MMIO32(x + 0x8)
|
||||||
|
/** Cycle width in mode 3 */
|
||||||
|
#define TIMER_CAPW(x) MMIO32(x + 0xC)
|
||||||
|
/** Pulse width in modes 2 and 3 */
|
||||||
|
#define TIMER_CAPLH(x) MMIO32(x + 0x10)
|
||||||
|
/** PWM state in mode 1 */
|
||||||
|
#define TIMER_MOD2LF(x) MMIO32(x + 0x14)
|
||||||
|
/** Timer output pin value */
|
||||||
|
#define TIMER_OUTPVAL(x) MMIO32(x + 0x80)
|
||||||
|
/** Interrupt enable and mask */
|
||||||
|
#define TIMER_INTCTL(x) MMIO32(x + 0x84)
|
||||||
|
/** Interrupt status before masking */
|
||||||
|
#define TIMER_INTSTAT(x) MMIO32(x + 0x88)
|
||||||
|
/** Interrupt status after masking */
|
||||||
|
#define TIMER_INTMSKSTAT(x) MMIO32(x + 0x8C)
|
||||||
|
/** Interrupt overflow; 1 if interrupt occurs again without being cleared */
|
||||||
|
#define TIMER_INTFLAG(x) MMIO32(x + 0x90)
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
BEGIN_DECLS
|
||||||
|
|
||||||
|
void timer_counter_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode,
|
||||||
|
enum timer_clk_src clk_src,
|
||||||
|
enum timer_output_modes output_mode,
|
||||||
|
enum timer_level output_level,
|
||||||
|
uint32_t target);
|
||||||
|
|
||||||
|
void timer_pwm_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_clk_src clk_src,
|
||||||
|
enum timer_level output_level,
|
||||||
|
uint16_t target1,
|
||||||
|
uint16_t target2);
|
||||||
|
|
||||||
|
void timer_pulse_capture_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode);
|
||||||
|
|
||||||
|
void timer_duty_cycle_capture_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode);
|
||||||
|
|
||||||
|
void timer_clock_div(uint8_t div);
|
||||||
|
void timer_enable(uint32_t timer, bool en);
|
||||||
|
void timer_clock_enable(uint32_t timer, bool en);
|
||||||
|
void timer_operation_mode(uint32_t timer, enum timer_operation_modes mode);
|
||||||
|
void timer_output_mode(uint32_t timer, enum timer_output_modes mode);
|
||||||
|
void timer_output_level(uint32_t timer, enum timer_level level);
|
||||||
|
void timer_edge_mode(uint32_t timer, enum timer_edge_modes mode);
|
||||||
|
void timer_loop_mode(uint32_t timer, enum timer_loop_modes mode);
|
||||||
|
void timer_clock_source(uint32_t timer, enum timer_clk_src src);
|
||||||
|
void timer_counter_target_value(uint32_t timer, uint32_t target);
|
||||||
|
void timer_pwm_target_value(uint32_t timer, uint16_t period0, uint16_t period1);
|
||||||
|
void timer_int_enable(uint32_t timer, bool en);
|
||||||
|
void timer_int_mask(uint32_t timer, enum timer_int_masked masked);
|
||||||
|
uint32_t timer_get_current_value(uint32_t timer);
|
||||||
|
uint32_t timer_get_cycle_width(uint32_t timer);
|
||||||
|
uint32_t timer_get_pulse_width(uint32_t timer);
|
||||||
|
enum timer_pwm_period timer_get_pwm_period(uint32_t timer);
|
||||||
|
bool timer_int_status(uint32_t timer);
|
||||||
|
bool timer_int_raw_status(uint32_t timer);
|
||||||
|
bool timer_int_overflow_status(uint32_t timer);
|
||||||
|
|
||||||
|
END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/**@}*/
|
@ -38,6 +38,7 @@ OBJS += flash.o
|
|||||||
OBJS += gpio.o
|
OBJS += gpio.o
|
||||||
OBJS += pwr.o
|
OBJS += pwr.o
|
||||||
OBJS += syscon.o
|
OBJS += syscon.o
|
||||||
|
OBJS += timer.o
|
||||||
OBJS += wdt.o
|
OBJS += wdt.o
|
||||||
VPATH += ../cm3
|
VPATH += ../cm3
|
||||||
|
|
||||||
|
455
lib/swm050/timer.c
Normal file
455
lib/swm050/timer.c
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
/** @defgroup timer_file Timer peripheral API
|
||||||
|
* @brief SWM050 Timer API.
|
||||||
|
* @ingroup peripheral_apis
|
||||||
|
* LGPL License Terms @ref lgpl_license
|
||||||
|
* @author @htmlonly © @endhtmlonly 2020
|
||||||
|
* Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**@{*/
|
||||||
|
#include <libopencm3/swm050/timer.h>
|
||||||
|
#include <libopencm3/swm050/sysctl.h>
|
||||||
|
#include <libopencm3/swm050/syscon.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function for timer setup.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param timer_int_en Passed to @ref timer_int_enable()
|
||||||
|
* @param op_mode Passed to @ref timer_operation_mode()
|
||||||
|
* @param edge_mode Passed to @ref timer_edge_mode()
|
||||||
|
* @param loop_mode Passed to @ref timer_loop_mode()
|
||||||
|
* @param clk_src Passed to @ref timer_clock_source()
|
||||||
|
* @param output_mode Passed to @ref timer_output_mode()
|
||||||
|
* @param output_level Passed to @ref timer_output_level()
|
||||||
|
*/
|
||||||
|
static void timer_setup_internal(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_operation_modes op_mode,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode,
|
||||||
|
enum timer_clk_src clk_src,
|
||||||
|
enum timer_output_modes output_mode,
|
||||||
|
enum timer_level output_level)
|
||||||
|
{
|
||||||
|
timer_enable(timer, false);
|
||||||
|
|
||||||
|
/* Conserve power by shutting off the unneeded clock */
|
||||||
|
timer_clock_enable(timer, (clk_src == TIMER_CLK_INTERNAL));
|
||||||
|
|
||||||
|
timer_loop_mode(timer, loop_mode);
|
||||||
|
timer_output_mode(timer, output_mode);
|
||||||
|
timer_output_level(timer, output_level);
|
||||||
|
timer_clock_source(timer, clk_src);
|
||||||
|
timer_operation_mode(timer, op_mode);
|
||||||
|
timer_edge_mode(timer, edge_mode);
|
||||||
|
timer_int_enable(timer, timer_int_en);
|
||||||
|
timer_int_mask(timer, TIMER_UNMASKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the timer in counter mode.
|
||||||
|
* @note Call @ref timer_enable() when you are ready to start the timer.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @note If interrupts are enabled here, the interrupt should also be enabled
|
||||||
|
* using the NVIC before enabling the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param timer_int_en Passed to @ref timer_int_enable()
|
||||||
|
* @param edge_mode Passed to @ref timer_edge_mode()
|
||||||
|
* @param loop_mode Passed to @ref timer_loop_mode()
|
||||||
|
* @param clk_src Passed to @ref timer_clock_source()
|
||||||
|
* @param output_mode Passed to @ref timer_output_mode()
|
||||||
|
* @param output_level Passed to @ref timer_output_level()
|
||||||
|
*/
|
||||||
|
void timer_counter_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode,
|
||||||
|
enum timer_clk_src clk_src,
|
||||||
|
enum timer_output_modes output_mode,
|
||||||
|
enum timer_level output_level,
|
||||||
|
uint32_t target)
|
||||||
|
{
|
||||||
|
timer_setup_internal(timer, timer_int_en, TIMER_MODE_COUNTER, edge_mode,
|
||||||
|
loop_mode, clk_src, output_mode, output_level);
|
||||||
|
timer_counter_target_value(timer, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the timer in PWM mode.
|
||||||
|
* @note Call @ref timer_enable() when you are ready to start the timer.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @note If interrupts are enabled here, the interrupt should also be enabled
|
||||||
|
* using the NVIC before enabling the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param timer_int_en Passed to @ref timer_int_enable()
|
||||||
|
* @param edge_mode Passed to @ref timer_edge_mode()
|
||||||
|
* @param loop_mode Passed to @ref timer_loop_mode()
|
||||||
|
* @param clk_src Passed to @ref timer_clock_source()
|
||||||
|
* @param output_mode Passed to @ref timer_output_mode()
|
||||||
|
* @param output_level Passed to @ref timer_output_level()
|
||||||
|
* @param period0 Passed to @ref timer_pwm_target_value()
|
||||||
|
* @param period1 Passed to @ref timer_pwm_target_value()
|
||||||
|
*/
|
||||||
|
void timer_pwm_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_clk_src clk_src,
|
||||||
|
enum timer_level output_level,
|
||||||
|
uint16_t period0,
|
||||||
|
uint16_t period1)
|
||||||
|
{
|
||||||
|
timer_setup_internal(timer, timer_int_en, TIMER_MODE_PWM, edge_mode,
|
||||||
|
TIMER_LOOP_MODE, clk_src, TIMER_OUTPUT_NONE,
|
||||||
|
output_level);
|
||||||
|
timer_pwm_target_value(timer, period0, period1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the timer in pulse capture mode.
|
||||||
|
* @note Call @ref timer_enable() when you are ready to start the timer.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @note If interrupts are enabled here, the interrupt should also be enabled
|
||||||
|
* using the NVIC before enabling the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param timer_int_en Passed to @ref timer_int_enable()
|
||||||
|
* @param edge_mode Passed to @ref timer_edge_mode()
|
||||||
|
* @param loop_mode Passed to @ref timer_loop_mode()
|
||||||
|
*/
|
||||||
|
void timer_pulse_capture_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode)
|
||||||
|
{
|
||||||
|
timer_setup_internal(timer, timer_int_en, TIMER_MODE_PULSE_CAPTURE,
|
||||||
|
edge_mode, loop_mode, TIMER_CLK_INTERNAL,
|
||||||
|
TIMER_OUTPUT_NONE, TIMER_LEVEL_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the timer in duty cycle capture mode.
|
||||||
|
* @note Call @ref timer_enable() when you are ready to start the timer.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @note If interrupts are enabled here, the interrupt should also be enabled
|
||||||
|
* using the NVIC before enabling the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param timer_int_en Passed to @ref timer_int_enable()
|
||||||
|
* @param edge_mode Passed to @ref timer_edge_mode()
|
||||||
|
* @param loop_mode Passed to @ref timer_loop_mode()
|
||||||
|
*/
|
||||||
|
void timer_duty_cycle_capture_setup(uint32_t timer,
|
||||||
|
bool timer_int_en,
|
||||||
|
enum timer_edge_modes edge_mode,
|
||||||
|
enum timer_loop_modes loop_mode)
|
||||||
|
{
|
||||||
|
timer_setup_internal(timer, timer_int_en, TIMER_MODE_DUTY_CYCLE_CAPTURE,
|
||||||
|
edge_mode, loop_mode, TIMER_CLK_INTERNAL,
|
||||||
|
TIMER_OUTPUT_NONE, TIMER_LEVEL_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the timer clock divider, based off of the 18MHz oscillator
|
||||||
|
* @param div Timer clock divider. Only the 6 least-significant bits are used,
|
||||||
|
* Takes values from 0 to 63 (in reality the possible values are the even
|
||||||
|
* numbers from 2 to 62, as well as the number 1). Anything after the 6
|
||||||
|
* least-significant bits are stripped off of the value. If the value is 0,
|
||||||
|
* it will be treated as a 1. All odd values other than 1 are rounded down
|
||||||
|
* to the closest even value, due to the fact that all odd values are
|
||||||
|
* treated by the register as a 1, which would likely be unexpected. A
|
||||||
|
* value of 0 would also normally be treated as a 2, which would also be
|
||||||
|
* unexpected behavior.
|
||||||
|
*/
|
||||||
|
void timer_clock_div(uint8_t div)
|
||||||
|
{
|
||||||
|
/* If the value is 0 or 1, make it odd, meaning no divide. */
|
||||||
|
/* Otherwise, drop div to the closest even value. */
|
||||||
|
div = (div <= 1) ? 1 : (div & ~0x1);
|
||||||
|
SYSCTL_SYS_CFG_1 = (~TIMER_DIV_MASK & SYSCTL_SYS_CFG_1) | (div << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param en Enable or disable the timer
|
||||||
|
*/
|
||||||
|
void timer_enable(uint32_t timer, bool en)
|
||||||
|
{
|
||||||
|
if (en) {
|
||||||
|
TIMER_CTRL(timer) |= TIMER_CTRL_EN;
|
||||||
|
} else {
|
||||||
|
TIMER_CTRL(timer) &= ~TIMER_CTRL_EN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the timer's internal clock.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param en Enable or disable the internal clock
|
||||||
|
*/
|
||||||
|
void timer_clock_enable(uint32_t timer, bool en)
|
||||||
|
{
|
||||||
|
if (timer == TIMER_SE1) {
|
||||||
|
if (en) {
|
||||||
|
SYSCTL_SYS_CFG_1 |= SYSCTL_SYS_CFG_1_TIMERSE1;
|
||||||
|
} else {
|
||||||
|
SYSCTL_SYS_CFG_1 &= ~SYSCTL_SYS_CFG_1_TIMERSE1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (en) {
|
||||||
|
SYSCTL_SYS_CFG_1 |= SYSCTL_SYS_CFG_1_TIMERSE0;
|
||||||
|
} else {
|
||||||
|
SYSCTL_SYS_CFG_1 &= ~SYSCTL_SYS_CFG_1_TIMERSE0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the mode of operation.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param mode The mode of operation @ref timer_operation_modes
|
||||||
|
*/
|
||||||
|
void timer_operation_mode(uint32_t timer, enum timer_operation_modes mode)
|
||||||
|
{
|
||||||
|
mode = (mode << 4);
|
||||||
|
TIMER_CTRL(timer) = (~TIMER_OPER_MODE_MASK & TIMER_CTRL(timer)) | mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the output mode.
|
||||||
|
* Only used in counter mode.
|
||||||
|
* When done counting, the pin can be set to no output,
|
||||||
|
* to invert the current pin level, to set the pin high,
|
||||||
|
* or to set the pin low.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param mode The output mode @ref timer_output_modes
|
||||||
|
*/
|
||||||
|
void timer_output_mode(uint32_t timer, enum timer_output_modes mode)
|
||||||
|
{
|
||||||
|
mode = (mode << 12);
|
||||||
|
TIMER_CTRL(timer) = (~TIMER_OUTP_MODE_MASK & TIMER_CTRL(timer)) | mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the initial output level.
|
||||||
|
* Only used in counter and PWM modes.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param level The initial output level @ref timer_level
|
||||||
|
*/
|
||||||
|
void timer_output_level(uint32_t timer, enum timer_level level)
|
||||||
|
{
|
||||||
|
TIMER_OUTPVAL(timer) = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the edge mode.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param mode The edge mode @ref timer_edge_modes
|
||||||
|
*/
|
||||||
|
void timer_edge_mode(uint32_t timer, enum timer_edge_modes mode)
|
||||||
|
{
|
||||||
|
if (mode) {
|
||||||
|
TIMER_CTRL(timer) |= TIMER_CTRL_TMOD;
|
||||||
|
} else {
|
||||||
|
TIMER_CTRL(timer) &= ~TIMER_CTRL_TMOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the loop mode.
|
||||||
|
* This has no use in PWM mode.
|
||||||
|
* In loop mode with counter mode, the counter will constantly loop.
|
||||||
|
* In loop mode with the capture modes, the values will be captured
|
||||||
|
* again and again. In single mode, these operations happen only once.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param mode The loop mode @ref timer_loop_modes
|
||||||
|
*/
|
||||||
|
void timer_loop_mode(uint32_t timer, enum timer_loop_modes mode)
|
||||||
|
{
|
||||||
|
if (mode) {
|
||||||
|
TIMER_CTRL(timer) |= TIMER_CTRL_LMOD;
|
||||||
|
} else {
|
||||||
|
TIMER_CTRL(timer) &= ~TIMER_CTRL_LMOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the clock source for the timer.
|
||||||
|
* @note Be sure to set the alternate functions of the timer pins
|
||||||
|
* with @ref syscon_sel_af() and disable SWD on those pins
|
||||||
|
* with @ref syscon_sel_swd() as needed.
|
||||||
|
* @note If not using the internal clock, you can disable it
|
||||||
|
* with @ref timer_clock_enable() for power savings.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param src Select the internal or external clock source @ref timer_clk_src
|
||||||
|
*/
|
||||||
|
void timer_clock_source(uint32_t timer, enum timer_clk_src src)
|
||||||
|
{
|
||||||
|
if (src) {
|
||||||
|
TIMER_CTRL(timer) |= TIMER_CTRL_OSCMOD;
|
||||||
|
} else {
|
||||||
|
TIMER_CTRL(timer) &= ~TIMER_CTRL_OSCMOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the target values for counter mode.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param target The value to count up to
|
||||||
|
*/
|
||||||
|
void timer_counter_target_value(uint32_t timer, uint32_t target)
|
||||||
|
{
|
||||||
|
TIMER_TARVAL(timer) = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the target values for PWM mode.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param period0 length of period 0 in clock cycles. Whether
|
||||||
|
* it is high or low is set in @ref timer_output_level()
|
||||||
|
* @param period1 length of period 1
|
||||||
|
*/
|
||||||
|
void timer_pwm_target_value(uint32_t timer, uint16_t period0, uint16_t period1)
|
||||||
|
{
|
||||||
|
timer_counter_target_value(timer, (period1 << 16) | period0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable the interrupt.
|
||||||
|
* In counter mode, when the count has been completed,
|
||||||
|
* an interrupt is generated.
|
||||||
|
* In PWM mode, on a level change, an interupt is generated.
|
||||||
|
* In either capture mode, when a capture is complete,
|
||||||
|
* an interrupt is generated.
|
||||||
|
* @note If interrupts are enabled here, the interrupt should also be enabled
|
||||||
|
* using the NVIC before enabling the timer.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param en Enable or disable the interrupt
|
||||||
|
*/
|
||||||
|
void timer_int_enable(uint32_t timer, bool en)
|
||||||
|
{
|
||||||
|
if (en) {
|
||||||
|
TIMER_INTCTL(timer) |= TIMER_INTCTL_INTEN;
|
||||||
|
} else {
|
||||||
|
TIMER_INTCTL(timer) &= ~TIMER_INTCTL_INTEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the interrupt mask.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @param masked Whether or not to mask the interrupt @ref timer_int_masked
|
||||||
|
*/
|
||||||
|
void timer_int_mask(uint32_t timer, enum timer_int_masked masked)
|
||||||
|
{
|
||||||
|
if (masked) {
|
||||||
|
TIMER_INTCTL(timer) &= ~TIMER_INTCTL_INTMSK;
|
||||||
|
} else {
|
||||||
|
TIMER_INTCTL(timer) |= TIMER_INTCTL_INTMSK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current counter value, and clears the interrupt/interrupt overflow.
|
||||||
|
* If in PWM mode, this is only used for clearing the interrupt.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The current counter value
|
||||||
|
*/
|
||||||
|
uint32_t timer_get_current_value(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_CURVAL(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cycle width.
|
||||||
|
* Only used in duty cycle capture mode.
|
||||||
|
* @note See the datasheet for more concise diagrams.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The cycle width
|
||||||
|
*/
|
||||||
|
uint32_t timer_get_cycle_width(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_CAPW(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pulse width in pulse capture mode,
|
||||||
|
* or gets the period width in duty cycle capture mode.
|
||||||
|
* @note See the datasheet for more concise diagrams.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The pulse width
|
||||||
|
*/
|
||||||
|
uint32_t timer_get_pulse_width(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_CAPLH(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current output period in PWM mode.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The current output period @ref timer_pwm_period
|
||||||
|
*/
|
||||||
|
enum timer_pwm_period timer_get_pwm_period(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_MOD2LF(timer) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the interrupt status after masking.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The interrupt status after masking
|
||||||
|
*/
|
||||||
|
bool timer_int_status(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_INTMSKSTAT(timer) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the interrupt status before masking.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The interrupt status before masking
|
||||||
|
*/
|
||||||
|
bool timer_int_raw_status(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_INTSTAT(timer) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the interrupt overflow status.
|
||||||
|
* Overflow will occur if the interrupt has not been cleared when a second
|
||||||
|
* interrupt happens.
|
||||||
|
* @param timer Select timer @ref timer_select
|
||||||
|
* @return The interrupt overflow status
|
||||||
|
*/
|
||||||
|
bool timer_int_overflow_status(uint32_t timer)
|
||||||
|
{
|
||||||
|
return TIMER_INTFLAG(timer) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**@}*/
|
Loading…
x
Reference in New Issue
Block a user