The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.
Dependents: hello SerialTestv11 SerialTestv12 Sierpinski ... more
mbed 2
This is the mbed 2 library. If you'd like to learn about Mbed OS please see the mbed-os docs.
Diff: TARGET_SAMD21G18A/TOOLCHAIN_ARM_STD/tc.h
- Revision:
- 171:3a7713b1edbc
- Parent:
- 111:4336505e4b1c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_SAMD21G18A/TOOLCHAIN_ARM_STD/tc.h Thu Nov 08 11:45:42 2018 +0000 @@ -0,0 +1,1764 @@ +/** + * \file + * + * \brief SAM TC - Timer Counter Driver + * + * Copyright (C) 2013-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * 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. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef TC_H_INCLUDED +#define TC_H_INCLUDED + +/** + * \defgroup asfdoc_sam0_tc_group SAM Timer/Counter Driver (TC) + * + * This driver for Atmel® | SMART SAM devices provides an interface for the configuration + * and management of the timer modules within the device, for waveform + * generation and timing operations. The following driver API modes are covered + * by this manual: + * + * - Polled APIs + * \if TC_CALLBACK_MODE + * - Callback APIs + * \endif + * + * + * The following peripherals are used by this module: + * - TC (Timer/Counter) + * + * The following devices can use this module: + * - Atmel | SMART SAM D20/D21 + * - Atmel | SMART SAM R21 + * - Atmel | SMART SAM D10/D11 + * - Atmel | SMART SAM L21 + * - Atmel | SMART SAM DAx + * - Atmel | SMART SAM C20/C21 + * + * The outline of this documentation is as follows: + * - \ref asfdoc_sam0_tc_prerequisites + * - \ref asfdoc_sam0_tc_module_overview + * - \ref asfdoc_sam0_tc_special_considerations + * - \ref asfdoc_sam0_tc_extra_info + * - \ref asfdoc_sam0_tc_examples + * - \ref asfdoc_sam0_tc_api_overview + * + * + * \section asfdoc_sam0_tc_prerequisites Prerequisites + * + * There are no prerequisites for this module. + * + * + * \section asfdoc_sam0_tc_module_overview Module Overview + * + * The Timer/Counter (TC) module provides a set of timing and counting related + * functionality, such as the generation of periodic waveforms, the capturing + * of a periodic waveform's frequency/duty cycle, and software timekeeping for + * periodic operations. TC modules can be configured to use an 8-, 16-, or + * 32-bit counter size. + * + * This TC module for the SAM is capable of the following functions: + * + * - Generation of PWM signals + * - Generation of timestamps for events + * - General time counting + * - Waveform period capture + * - Waveform frequency capture + * + * \ref asfdoc_sam0_tc_block_diagram "The diagram below" shows the overview + * of the TC module design. + * + * \anchor asfdoc_sam0_tc_block_diagram + * \image html overview.svg "Basic Overview of the TC Module" + * + * + * \subsection asfdoc_sam0_tc_features Driver Feature Macro Definition + * <table> + * <tr> + * <th>Driver Feature Macro</th> + * <th>Supported devices</th> + * </tr> + * <tr> + * <td>FEATURE_TC_DOUBLE_BUFFERED</td> + * <td>SAML21/C20/C21</td> + * </tr> + * <tr> + * <td>FEATURE_TC_SYNCBUSY_SCHEME_VERSION_2</td> + * <td>SAML21/C20/C21</td> + * </tr> + * <tr> + * <td>FEATURE_TC_STAMP_PW_CAPTURE</td> + * <td>SAML21/C20/C21</td> + * </tr> + * <tr> + * <td>FEATURE_TC_READ_SYNC</td> + * <td>SAML21/C20/C21</td> + * </tr> + * <tr> + * <td>FEATURE_TC_IO_CAPTURE</td> + * <td>SAML21/C20/C21</td> + * </tr> + * <tr> + * <td>FEATURE_TC_GENERATE_DMA_TRIGGER</td> + * <td>SAML21</td> + * </tr> + * </table> + * \note The specific features are only available in the driver when the + * selected device supports those features. + * + * \subsection asfdoc_sam0_tc_module_overview_func_desc Functional Description + * Independent of the configured counter size, each TC module can be set up + * in one of two different modes; capture and compare. + * + * In capture mode, the counter value is stored when a configurable event + * occurs. This mode can be used to generate timestamps used in event capture, + * or it can be used for the measurement of a periodic input signal's + * frequency/duty cycle. + * + * In compare mode, the counter value is compared against one or more of the + * configured channel compare values. When the counter value coincides with a + * compare value an action can be taken automatically by the module, such as + * generating an output event or toggling a pin when used for frequency or PWM + * signal generation. + * + * \note The connection of events between modules requires the use of the + * \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)" + * to route output event of one module to the input event of another. + * For more information on event routing, refer to the event driver + * documentation. + * + * \subsection asfdoc_sam0_tc_module_overview_tc_size Timer/Counter Size + * Each timer module can be configured in one of three different counter + * sizes; 8-, 16-, and 32-bit. The size of the counter determines the maximum + * value it can count to before an overflow occurs and the count is reset back + * to zero. \ref asfdoc_sam0_tc_count_size_vs_top "The table below" shows the + * maximum values for each of the possible counter sizes. + * + * \anchor asfdoc_sam0_tc_count_size_vs_top + * <table> + * <caption>Timer Counter Sizes and Their Maximum Count Values</caption> + * <tr> + * <th>Counter size</th> + * <th>Max. (hexadecimal)</th> + * <th>Max. (decimal)</th> + * </tr> + * <tr> + * <td>8-bit</td> + * <td>0xFF</td> + * <td>255</td> + * </tr> + * <tr> + * <td>16-bit</td> + * <td>0xFFFF</td> + * <td>65,535</td> + * </tr> + * <tr> + * <td>32-bit</td> + * <td>0xFFFFFFFF</td> + * <td>4,294,967,295</td> + * </tr> + * </table> + * + * When using the counter in 16- or 32-bit count mode, Compare Capture + * register 0 (CC0) is used to store the period value when running in PWM + * generation match mode. + * + * When using 32-bit counter size, two 16-bit counters are chained together + * in a cascade formation. Except in SAM D10/D11, Even numbered TC modules + * (e.g. TC0, TC2) can be configured as 32-bit counters. The odd numbered + * counters will act as slaves to the even numbered masters, and will not + * be reconfigurable until the master timer is disabled. The pairing of timer + * modules for 32-bit mode is shown in \ref asfdoc_sam0_tc_module_ms_pairs + * "the table below". + * + * \anchor asfdoc_sam0_tc_module_ms_pairs + * <table> + * <caption>TC Master and Slave Module Pairings</caption> + * <tr> + * <th>Master TC Module</th> + * <th>Slave TC Module</th> + * </tr> + * <tr> + * <td>TC0</td> + * <td>TC1</td> + * </tr> + * <tr> + * <td>TC2</td> + * <td>TC3</td> + * </tr> + * <tr> + * <td>...</td> + * <td>...</td> + * </tr> + * <tr> + * <td>TCn-1</td> + * <td>TCn</td> + * </tr> + * </table> + * + * In SAMD10/D11, odd numbered TC modules (e.g. TC1) can be configured as 32-bit + * counters. The even numbered(e.g. TC2) counters will act as slaves to the odd + * numbered masters. + * + * \subsection asfdoc_sam0_tc_module_overview_clock Clock Settings + * + * \subsubsection asfdoc_sam0_tc_module_overview_clock_selection Clock Selection + * Each TC peripheral is clocked asynchronously to the system clock by a GCLK + * (Generic Clock) channel. The GCLK channel connects to any of the GCLK + * generators. The GCLK generators are configured to use one of the available + * clock sources on the system such as internal oscillator, external crystals, + * etc. see the \ref asfdoc_sam0_system_clock_group "Generic Clock driver" + *for + * more information. + * + * \subsubsection asfdoc_sam0_tc_module_overview_clock_prescaler Prescaler + * Each TC module in the SAM has its own individual clock prescaler, which + * can be used to divide the input clock frequency used in the counter. This + * prescaler only scales the clock used to provide clock pulses for the counter + * to count, and does not affect the digital register interface portion of + * the module, thus the timer registers will synchronize to the raw GCLK + * frequency input to the module. + * + * As a result of this, when selecting a GCLK frequency and timer prescaler + * value the user application should consider both the timer resolution + * required and the synchronization frequency, to avoid lengthy + * synchronization times of the module if a very slow GCLK frequency is fed + * into the TC module. It is preferable to use a higher module GCLK frequency + * as the input to the timer, and prescale this down as much as possible to + * obtain a suitable counter frequency in latency-sensitive applications. + * + * \subsubsection asfdoc_sam0_tc_module_overview_clock_reloading Reloading + * Timer modules also contain a configurable reload action, used when a + * re-trigger event occurs. Examples of a re-trigger event are the counter + * reaching the maximum value when counting up, or when an event from the event + * system tells the counter to re-trigger. The reload action determines if the + * prescaler should be reset, and when this should happen. The counter will + * always be reloaded with the value it is set to start counting from. The user + * can choose between three different reload actions, described in + * \ref asfdoc_sam0_tc_module_reload_act "the table below". + * + * \anchor asfdoc_sam0_tc_module_reload_act + * <table> + * <caption>TC Module Reload Actions</caption> + * <tr> + * <th>Reload action</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>\ref TC_RELOAD_ACTION_GCLK </td> + * <td>Reload TC counter value on next GCLK cycle. Leave prescaler + * as-is.</td> + * </tr> + * <tr> + * <td>\ref TC_RELOAD_ACTION_PRESC </td> + * <td>Reloads TC counter value on next prescaler clock. Leave prescaler + * as-is.</td> + * </tr> + * <tr> + * <td> \ref TC_RELOAD_ACTION_RESYNC </td> + * <td>Reload TC counter value on next GCLK cycle. Clear prescaler to + * zero.</td> + * </tr> + * </table> + * + * The reload action to use will depend on the specific application being + * implemented. One example is when an external trigger for a reload occurs; if + * the TC uses the prescaler, the counter in the prescaler should not have a + * value between zero and the division factor. The TC counter and the counter + * in the prescaler should both start at zero. When the counter is set to + * re-trigger when it reaches the maximum value on the other hand, this is not the + * right option to use. In such a case it would be better if the prescaler is + * left unaltered when the re-trigger happens, letting the counter reset on the + * next GCLK cycle. + * + * \subsection asfdoc_sam0_tc_module_overview_compare_match Compare Match Operations + * In compare match operation, Compare/Capture registers are used in comparison + * with the counter value. When the timer's count value matches the value of a + * compare channel, a user defined action can be taken. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_timer Basic Timer + * + * A Basic Timer is a simple application where compare match operations is used + * to determine when a specific period has elapsed. In Basic Timer operations, + * one or more values in the module's Compare/Capture registers are used to + * specify the time (as a number of prescaled GCLK cycles) when an action should + * be taken by the microcontroller. This can be an Interrupt Service Routine + * (ISR), event generator via the event system, or a software flag that is + * polled via the user application. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_wg Waveform Generation + * + * Waveform generation enables the TC module to generate square waves, or if + * combined with an external passive low-pass filter; analog waveforms. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_wg_pwm Waveform Generation - PWM + * + * Pulse width modulation is a form of waveform generation and a signalling + * technique that can be useful in many situations. When PWM mode is used, + * a digital pulse train with a configurable frequency and duty cycle can be + * generated by the TC module and output to a GPIO pin of the device. + * + * Often PWM is used to communicate a control or information parameter to an + * external circuit or component. Differing impedances of the source generator + * and sink receiver circuits is less of an issue when using PWM compared to + * using an analog voltage value, as noise will not generally affect the + * signal's integrity to a meaningful extent. + * + * \ref asfdoc_sam0_tc_module_pwm_normal_diag "The figure below" illustrates + * operations and different states of the counter and its output when running + * the counter in PWM normal mode. As can be seen, the TOP value is unchanged + * and is set to MAX. The compare match value is changed at several points to + * illustrate the resulting waveform output changes. The PWM output is set to + * normal (i.e. non-inverted) output mode. + * + * \anchor asfdoc_sam0_tc_module_pwm_normal_diag + * \image html pwm_normal_ex.svg "Example of PWM in Normal Mode, and Different Counter Operations" + * + * + * In \ref asfdoc_sam0_tc_module_pwm_match_diag "the figure below", the + * counter is set to generate PWM in Match mode. The PWM output is inverted via + * the appropriate configuration option in the TC driver configuration + * structure. In this example, the counter value is changed once, but the + * compare match value is kept unchanged. As can be seen, it is possible to + * change the TOP value when running in PWM match mode. + * + * \anchor asfdoc_sam0_tc_module_pwm_match_diag + * \image html pwm_match_ex.svg "Example of PWM in Match Mode, and Different Counter Operations" + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_wg_freq Waveform Generation - Frequency + * + * Frequency Generation mode is in many ways identical to PWM + * generation. However, in Frequency Generation a toggle only occurs + * on the output when a match on a capture channels occurs. When the + * match is made, the timer value is reset, resulting in a variable + * frequency square wave with a fixed 50% duty cycle. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_capt Capture Operations + * + * In capture operations, any event from the event system or a pin change can + * trigger a capture of the counter value. This captured counter value can be + * used as a timestamp for the event, or it can be used in frequency and pulse + * width capture. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_capt_event_capture Capture Operations - Event + * + * Event capture is a simple use of the capture functionality, + * designed to create timestamps for specific events. When the TC + * module's input capture pin is externally toggled, the current timer + * count value is copied into a buffered register which can then be + * read out by the user application. + * + * Note that when performing any capture operation, there is a risk that the + * counter reaches its top value (MAX) when counting up, or the bottom value + * (zero) when counting down, before the capture event occurs. This can distort + * the result, making event timestamps to appear shorter than reality; the + * user application should check for timer overflow when reading a capture + * result in order to detect this situation and perform an appropriate + * adjustment. + * + * Before checking for a new capture, \ref TC_STATUS_COUNT_OVERFLOW + * should be checked. The response to an overflow error is left to the user + * application, however it may be necessary to clear both the capture overflow + * flag and the capture flag upon each capture reading. + * + * \subsubsection asfdoc_sam0_tc_module_overview_compare_match_capt_pwc Capture Operations - Pulse Width + * + * Pulse Width Capture mode makes it possible to measure the pulse width and + * period of PWM signals. This mode uses two capture channels of the counter. + * This means that the counter module used for Pulse Width Capture can not be + * used for any other purpose. There are two modes for pulse width capture; + * Pulse Width Period (PWP) and Period Pulse Width (PPW). In PWP mode, capture + * channel 0 is used for storing the pulse width and capture channel 1 stores + * the observed period. While in PPW mode, the roles of the two capture channels + * is reversed. + * + * As in the above example it is necessary to poll on interrupt flags to see + * if a new capture has happened and check that a capture overflow error has + * not occurred. + * + * \subsection asfdoc_sam0_tc_module_overview_oneshot One-shot Mode + * + * TC modules can be configured into a one-shot mode. When configured in this + * manner, starting the timer will cause it to count until the next overflow + * or underflow condition before automatically halting, waiting to be manually + * triggered by the user application software or an event signal from the event + * system. + * + * \subsubsection asfdoc_sam0_tc_module_overview_inversion Wave Generation Output Inversion + * + * The output of the wave generation can be inverted by hardware if desired, + * resulting in the logically inverted value being output to the configured + * device GPIO pin. + * + * + * \section asfdoc_sam0_tc_special_considerations Special Considerations + * + * The number of capture compare registers in each TC module is dependent on + * the specific SAM device being used, and in some cases the counter size. + * + * The maximum amount of capture compare registers available in any SAM + * device is two when running in 32-bit mode and four in 8- and 16-bit modes. + * + * + * \section asfdoc_sam0_tc_extra_info Extra Information + * + * For extra information, see \ref asfdoc_sam0_tc_extra. This includes: + * - \ref asfdoc_sam0_tc_extra_acronyms + * - \ref asfdoc_sam0_tc_extra_dependencies + * - \ref asfdoc_sam0_tc_extra_errata + * - \ref asfdoc_sam0_tc_extra_history + * + * + * \section asfdoc_sam0_tc_examples Examples + * + * For a list of examples related to this driver, see + * \ref asfdoc_sam0_tc_exqsg. + * + * \section asfdoc_sam0_tc_api_overview API Overview + * @{ + */ + +#include <compiler.h> +#include <clock.h> +#include <gclk.h> +#include <pinmux.h> + +/** + * Define port features set according to different device family + * @{ +*/ +#if (SAML21) || (SAMC20) || (SAMC21) || defined(__DOXYGEN__) +/** TC double buffered. */ +# define FEATURE_TC_DOUBLE_BUFFERED +/** SYNCBUSY scheme version 2. */ +# define FEATURE_TC_SYNCBUSY_SCHEME_VERSION_2 +/** TC time stamp capture and pulse width capture. */ +# define FEATURE_TC_STAMP_PW_CAPTURE +/** Read synchronization of COUNT. */ +# define FEATURE_TC_READ_SYNC +/** IO pin edge capture. */ +# define FEATURE_TC_IO_CAPTURE +/** Generate DMA triggers. */ +# define FEATURE_TC_GENERATE_DMA_TRIGGER +#endif +/*@}*/ + +#if !defined(__DOXYGEN__) +#if SAMD20 || SAML21 || SAMC20 || SAMC21 +# define TC_INSTANCE_OFFSET 0 +#endif +#if SAMD21 || SAMR21 || SAMDA1 +# define TC_INSTANCE_OFFSET 3 +#endif +#if SAMD10 || SAMD11 +# define TC_INSTANCE_OFFSET 1 +#endif + +#if SAMD20 +# define NUMBER_OF_COMPARE_CAPTURE_CHANNELS TC0_CC8_NUM +#elif SAML21 || SAMC20 || SAMC21 +# define NUMBER_OF_COMPARE_CAPTURE_CHANNELS TC0_CC_NUM +#elif SAMD10 || SAMD11 +# define NUMBER_OF_COMPARE_CAPTURE_CHANNELS TC1_CC8_NUM +#else +# define NUMBER_OF_COMPARE_CAPTURE_CHANNELS TC3_CC8_NUM +/* Same number for 8-, 16- and 32-bit TC and all TC instances */ +#endif + +/** TC Instance MAX ID Number. */ +#if SAMD20E || SAMD21G || SAMD21E || SAMR21 +#define TC_INST_MAX_ID 5 +#elif SAML21 || SAMC20 || SAMC21 +#define TC_INST_MAX_ID 4 +#elif SAMD10 || SAMD11 +#define TC_INST_MAX_ID 2 +#else +#define TC_INST_MAX_ID 7 +#endif + +#endif + +#if TC_ASYNC == true +# include <system_interrupt.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if TC_ASYNC == true +/** Enum for the possible callback types for the TC module. */ +enum tc_callback { + /** Callback for TC overflow. */ + TC_CALLBACK_OVERFLOW, + /** Callback for capture overflow error. */ + TC_CALLBACK_ERROR, + /** Callback for capture compare channel 0. */ + TC_CALLBACK_CC_CHANNEL0, + /** Callback for capture compare channel 1. */ + TC_CALLBACK_CC_CHANNEL1, +# if !defined(__DOXYGEN__) + /** Number of available callbacks. */ + TC_CALLBACK_N, +# endif +}; +#endif + +/** + * \name Module Status Flags + * + * TC status flags, returned by \ref tc_get_status() and cleared by + * \ref tc_clear_status(). + * + * @{ + */ + +/** Timer channel 0 has matched against its compare value, or has captured a + * new value. + */ +#define TC_STATUS_CHANNEL_0_MATCH (1UL << 0) + +/** Timer channel 1 has matched against its compare value, or has captured a + * new value. + */ +#define TC_STATUS_CHANNEL_1_MATCH (1UL << 1) + +/** Timer register synchronization has completed, and the synchronized count + * value may be read. + */ +#define TC_STATUS_SYNC_READY (1UL << 2) + +/** A new value was captured before the previous value was read, resulting in + * lost data. + */ +#define TC_STATUS_CAPTURE_OVERFLOW (1UL << 3) + +/** The timer count value has overflowed from its maximum value to its minimum + * when counting upward, or from its minimum value to its maximum when + * counting downward. + */ +#define TC_STATUS_COUNT_OVERFLOW (1UL << 4) + +#ifdef FEATURE_TC_DOUBLE_BUFFERED +/** Channel 0 compare or capture buffer valid. */ +#define TC_STATUS_CHN0_BUFFER_VALID (1UL << 5) +/** Channel 1 compare or capture buffer valid. */ +#define TC_STATUS_CHN1_BUFFER_VALID (1UL << 6) +/** Period buffer valid. */ +#define TC_STATUS_PERIOD_BUFFER_VALID (1UL << 7) +#endif +/** @} */ + +/** + * \brief Index of the compare capture channels. + * + * This enum is used to specify which capture/compare channel to do + * operations on. + */ +enum tc_compare_capture_channel { + /** Index of compare capture channel 0. */ + TC_COMPARE_CAPTURE_CHANNEL_0, + /** Index of compare capture channel 1. */ + TC_COMPARE_CAPTURE_CHANNEL_1, +}; + +/** TC wave generation mode. */ +#if SAML21 || SAMC20 || SAMC21 +#define TC_WAVE_GENERATION_NORMAL_FREQ_MODE TC_WAVE_WAVEGEN_NFRQ +#define TC_WAVE_GENERATION_MATCH_FREQ_MODE TC_WAVE_WAVEGEN_MFRQ +#define TC_WAVE_GENERATION_NORMAL_PWM_MODE TC_WAVE_WAVEGEN_NPWM +#define TC_WAVE_GENERATION_MATCH_PWM_MODE TC_WAVE_WAVEGEN_MPWM +#else +#define TC_WAVE_GENERATION_NORMAL_FREQ_MODE TC_CTRLA_WAVEGEN_NFRQ +#define TC_WAVE_GENERATION_MATCH_FREQ_MODE TC_CTRLA_WAVEGEN_MFRQ +#define TC_WAVE_GENERATION_NORMAL_PWM_MODE TC_CTRLA_WAVEGEN_NPWM +#define TC_WAVE_GENERATION_MATCH_PWM_MODE TC_CTRLA_WAVEGEN_MPWM +#endif + +/** + * \brief TC wave generation mode enum. + * + * This enum is used to select which mode to run the wave + * generation in. + * + */ +enum tc_wave_generation { + /** Top is maximum, except in 8-bit counter size where it is the PER + * register. + */ + TC_WAVE_GENERATION_NORMAL_FREQ = TC_WAVE_GENERATION_NORMAL_FREQ_MODE, + + /** Top is CC0, except in 8-bit counter size where it is the PER + * register. + */ + TC_WAVE_GENERATION_MATCH_FREQ = TC_WAVE_GENERATION_MATCH_FREQ_MODE, + + /** Top is maximum, except in 8-bit counter size where it is the PER + * register. + */ + TC_WAVE_GENERATION_NORMAL_PWM = TC_WAVE_GENERATION_NORMAL_PWM_MODE, + + /** Top is CC0, except in 8-bit counter size where it is the PER + * register. + */ + TC_WAVE_GENERATION_MATCH_PWM = TC_WAVE_GENERATION_MATCH_PWM_MODE, +}; + +/** + * \brief Specifies if the counter is 8-, 16-, or 32-bit. + * + * This enum specifies the maximum value it is possible to count to. + */ +enum tc_counter_size { + /** The counter's maximum value is 0xFF, the period register is + * available to be used as top value. + */ + TC_COUNTER_SIZE_8BIT = TC_CTRLA_MODE_COUNT8, + + /** The counter's maximum value is 0xFFFF. There is no separate + * period register, to modify top one of the capture compare + * registers has to be used. This limits the amount of + * available channels. + */ + TC_COUNTER_SIZE_16BIT = TC_CTRLA_MODE_COUNT16, + + /** The counter's maximum value is 0xFFFFFFFF. There is no separate + * period register, to modify top one of the capture compare + * registers has to be used. This limits the amount of + * available channels. + */ + TC_COUNTER_SIZE_32BIT = TC_CTRLA_MODE_COUNT32, +}; + +/** + * \brief TC Counter reload action enum. + * + * This enum specify how the counter and prescaler should reload. + */ +enum tc_reload_action { + /** The counter is reloaded/reset on the next GCLK and starts + * counting on the prescaler clock. + */ + TC_RELOAD_ACTION_GCLK = TC_CTRLA_PRESCSYNC_GCLK, + + /** The counter is reloaded/reset on the next prescaler clock. + */ + TC_RELOAD_ACTION_PRESC = TC_CTRLA_PRESCSYNC_PRESC, + + /** The counter is reloaded/reset on the next GCLK, and the + * prescaler is restarted as well. + */ + TC_RELOAD_ACTION_RESYNC = TC_CTRLA_PRESCSYNC_RESYNC, +}; + +/** + * \brief TC clock prescaler values. + * + * This enum is used to choose the clock prescaler + * configuration. The prescaler divides the clock frequency of the TC + * module to make the counter count slower. + */ +enum tc_clock_prescaler { + /** Divide clock by 1. */ + TC_CLOCK_PRESCALER_DIV1 = TC_CTRLA_PRESCALER(0), + /** Divide clock by 2. */ + TC_CLOCK_PRESCALER_DIV2 = TC_CTRLA_PRESCALER(1), + /** Divide clock by 4. */ + TC_CLOCK_PRESCALER_DIV4 = TC_CTRLA_PRESCALER(2), + /** Divide clock by 8. */ + TC_CLOCK_PRESCALER_DIV8 = TC_CTRLA_PRESCALER(3), + /** Divide clock by 16. */ + TC_CLOCK_PRESCALER_DIV16 = TC_CTRLA_PRESCALER(4), + /** Divide clock by 64. */ + TC_CLOCK_PRESCALER_DIV64 = TC_CTRLA_PRESCALER(5), + /** Divide clock by 256. */ + TC_CLOCK_PRESCALER_DIV256 = TC_CTRLA_PRESCALER(6), + /** Divide clock by 1024. */ + TC_CLOCK_PRESCALER_DIV1024 = TC_CTRLA_PRESCALER(7), +}; + +/** + * \brief TC module count direction. + * + * Timer/Counter count direction. + */ +enum tc_count_direction { + /** Timer should count upward from zero to MAX. */ + TC_COUNT_DIRECTION_UP, + + /** Timer should count downward to zero from MAX. */ + TC_COUNT_DIRECTION_DOWN, +}; + +/** Waveform inversion mode. */ +#if SAML21 || SAMC20 || SAMC21 +#define TC_WAVEFORM_INVERT_CC0_MODE TC_DRVCTRL_INVEN(1) +#define TC_WAVEFORM_INVERT_CC1_MODE TC_DRVCTRL_INVEN(2) +#else +#define TC_WAVEFORM_INVERT_CC0_MODE TC_CTRLC_INVEN(1) +#define TC_WAVEFORM_INVERT_CC1_MODE TC_CTRLC_INVEN(2) +#endif + +/** + * \brief Waveform inversion mode. + * + * Output waveform inversion mode. + */ +enum tc_waveform_invert_output { + /** No inversion of the waveform output. */ + TC_WAVEFORM_INVERT_OUTPUT_NONE = 0, + /** Invert output from compare channel 0. */ + TC_WAVEFORM_INVERT_OUTPUT_CHANNEL_0 = TC_WAVEFORM_INVERT_CC0_MODE, + /** Invert output from compare channel 1. */ + TC_WAVEFORM_INVERT_OUTPUT_CHANNEL_1 = TC_WAVEFORM_INVERT_CC1_MODE, +}; + +/** + * \brief Action to perform when the TC module is triggered by an event. + * + * Event action to perform when the module is triggered by an event. + */ +enum tc_event_action { + /** No event action. */ + TC_EVENT_ACTION_OFF = TC_EVCTRL_EVACT_OFF, + /** Re-trigger on event. */ + TC_EVENT_ACTION_RETRIGGER = TC_EVCTRL_EVACT_RETRIGGER, + /** Increment counter on event. */ + TC_EVENT_ACTION_INCREMENT_COUNTER = TC_EVCTRL_EVACT_COUNT, + /** Start counter on event. */ + TC_EVENT_ACTION_START = TC_EVCTRL_EVACT_START, + + /** Store period in capture register 0, pulse width in capture + * register 1. + */ + TC_EVENT_ACTION_PPW = TC_EVCTRL_EVACT_PPW, + + /** Store pulse width in capture register 0, period in capture + * register 1. + */ + TC_EVENT_ACTION_PWP = TC_EVCTRL_EVACT_PWP, +#ifdef FEATURE_TC_STAMP_PW_CAPTURE + /** Time stamp capture. */ + TC_EVENT_ACTION_STAMP = TC_EVCTRL_EVACT_STAMP, + /** Pulse width capture. */ + TC_EVENT_ACTION_PW = TC_EVCTRL_EVACT_PW, +#endif +}; + +/** + * \brief TC event enable/disable structure. + * + * Event flags for the \ref tc_enable_events() and \ref tc_disable_events(). + */ +struct tc_events { + /** Generate an output event on a compare channel match. */ + bool generate_event_on_compare_channel + [NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; + /** Generate an output event on counter overflow. */ + bool generate_event_on_overflow; + /** Perform the configured event action when an incoming event is signalled. */ + bool on_event_perform_action; + /** Specifies if the input event source is inverted, when used in PWP or + * PPW event action modes. + */ + bool invert_event_input; + /** Specifies which event to trigger if an event is triggered. */ + enum tc_event_action event_action; +}; + +/** + * \brief Configuration struct for TC module in 8-bit size counter mode. + */ +struct tc_8bit_config { + /** Initial timer count value. */ + uint8_t value; + /** Where to count to or from depending on the direction on the counter. */ + uint8_t period; + /** Value to be used for compare match on each channel. */ + uint8_t compare_capture_channel[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; +}; + +/** + * \brief Configuration struct for TC module in 16-bit size counter mode. + */ +struct tc_16bit_config { + /** Initial timer count value. */ + uint16_t value; + /** Value to be used for compare match on each channel. */ + uint16_t compare_capture_channel[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; +}; + +/** + * \brief Configuration struct for TC module in 32-bit size counter mode. + */ +struct tc_32bit_config { + /** Initial timer count value. */ + uint32_t value; + /** Value to be used for compare match on each channel. */ + uint32_t compare_capture_channel[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; +}; + +/** + * \brief Configuration struct for TC module in 32-bit size counter mode. + */ +struct tc_pwm_channel { + /** When \c true, PWM output for the given channel is enabled. */ + bool enabled; + /** Specifies pin output for each channel. */ + uint32_t pin_out; + /** Specifies MUX setting for each output channel pin. */ + uint32_t pin_mux; +}; + +/** + * \brief TC configuration structure. + * + * Configuration struct for a TC instance. This structure should be + * initialized by the \ref tc_get_config_defaults function before being + * modified by the user application. + */ +struct tc_config { + /** GCLK generator used to clock the peripheral. */ + enum gclk_generator clock_source; + + /** When \c true the module is enabled during standby. */ + bool run_in_standby; +#if (SAML21) || (SAMC20) || (SAMC21) + /** Run on demand. */ + bool on_demand; +#endif + /** Specifies either 8-, 16-, or 32-bit counter size. */ + enum tc_counter_size counter_size; + /** Specifies the prescaler value for GCLK_TC. */ + enum tc_clock_prescaler clock_prescaler; + /** Specifies which waveform generation mode to use. */ + enum tc_wave_generation wave_generation; + + /** Specifies the reload or reset time of the counter and prescaler + * resynchronization on a re-trigger event for the TC. + */ + enum tc_reload_action reload_action; + + /** Specifies which channel(s) to invert the waveform on. + For SAML21/C20/C21, it's also used to invert IO input pin. */ + uint8_t waveform_invert_output; + + /** Specifies which channel(s) to enable channel capture + * operation on. + */ + bool enable_capture_on_channel[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; +#ifdef FEATURE_TC_IO_CAPTURE + /** Specifies which channel(s) to enable I/O capture + * operation on. + */ + bool enable_capture_on_IO[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; +#endif + + /** When \c true, one-shot will stop the TC on next hardware or software + * re-trigger event or overflow/underflow. + */ + bool oneshot; + + /** Specifies the direction for the TC to count. */ + enum tc_count_direction count_direction; + + /** Specifies the PWM channel for TC. */ + struct tc_pwm_channel pwm_channel[NUMBER_OF_COMPARE_CAPTURE_CHANNELS]; + + /** Access the different counter size settings though this configuration member. */ + union { + /** Struct for 8-bit specific timer configuration. */ + struct tc_8bit_config counter_8_bit; + /** Struct for 16-bit specific timer configuration. */ + struct tc_16bit_config counter_16_bit; + /** Struct for 32-bit specific timer configuration. */ + struct tc_32bit_config counter_32_bit; + }; + +#ifdef FEATURE_TC_DOUBLE_BUFFERED + /** Set to \c true to enable double buffering write. When enabled any write + * through \ref tc_set_top_value(), \ref tc_set_compare_value() and + * will direct to the buffer register as buffered + * value, and the buffered value will be committed to effective register + * on UPDATE condition, if update is not locked. + */ + bool double_buffering_enabled; +#endif +}; + +#if TC_ASYNC == true +/* Forward Declaration for the device instance. */ +struct tc_module; + +/* Type of the callback functions. */ +typedef void (*tc_callback_t)(struct tc_module *const module); +#endif + +/** + * \brief TC software device instance structure. + * + * TC software instance structure, used to retain software state information + * of an associated hardware module instance. + * + * \note The fields of this structure should not be altered by the user + * application; they are reserved for module-internal use only. + */ +struct tc_module { +#if !defined(__DOXYGEN__) + /** Hardware module pointer of the associated Timer/Counter peripheral. */ + Tc *hw; + + /** Size of the initialized Timer/Counter module configuration. */ + enum tc_counter_size counter_size; +# if TC_ASYNC == true + /** Array of callbacks. */ + tc_callback_t callback[TC_CALLBACK_N]; + /** Bit mask for callbacks registered. */ + uint8_t register_callback_mask; + /** Bit mask for callbacks enabled. */ + uint8_t enable_callback_mask; +# endif +#ifdef FEATURE_TC_DOUBLE_BUFFERED + /** Set to \c true to enable double buffering write. */ + bool double_buffering_enabled; +#endif +#endif +}; + +#if !defined(__DOXYGEN__) +uint8_t _tc_get_inst_index( + Tc *const hw); +#endif + +/** + * \name Driver Initialization and Configuration + * @{ + */ + +/** + * \brief Determines if the hardware module(s) are currently synchronizing to + *the bus. + * + * Checks to see if the underlying hardware peripheral module(s) are currently + * synchronizing across multiple clock domains to the hardware bus. This + * function can be used to delay further operations on a module until such time + * that it is ready, to prevent blocking delays for synchronization in the + * user application. + * + * \param[in] module_inst Pointer to the software module instance struct + * + * \return Synchronization status of the underlying hardware module(s). + * + * \retval false If the module has completed synchronization + * \retval true If the module synchronization is ongoing + */ +static inline bool tc_is_syncing( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + +#if (SAML21) || (SAMC20) || (SAMC21) + return (tc_module->SYNCBUSY.reg); +#else + return (tc_module->STATUS.reg & TC_STATUS_SYNCBUSY); +#endif +} + +/** + * \brief Initializes config with predefined default values. + * + * This function will initialize a given TC configuration structure to + * a set of known default values. This function should be called on + * any new instance of the configuration structures before being + * modified by the user application. + * + * The default configuration is as follows: + * \li GCLK generator 0 (GCLK main) clock source + * \li 16-bit counter size on the counter + * \li No prescaler + * \li Normal frequency wave generation + * \li GCLK reload action + * \li Don't run in standby + * \li Don't run on demand for SAML21/C20/C21 + * \li No inversion of waveform output + * \li No capture enabled + * \li No I/O capture enabled for SAML21/C20/C21 + * \li No event input enabled + * \li Count upward + * \li Don't perform one-shot operations + * \li No event action + * \li No channel 0 PWM output + * \li No channel 1 PWM output + * \li Counter starts on 0 + * \li Capture compare channel 0 set to 0 + * \li Capture compare channel 1 set to 0 + * \li No PWM pin output enabled + * \li Pin and MUX configuration not set + * \li Double buffer disabled (if have this feature) + * + * \param[out] config Pointer to a TC module configuration structure to set + */ +static inline void tc_get_config_defaults( + struct tc_config *const config) +{ + /* Sanity check arguments */ + Assert(config); + + /* Write default config to config struct */ + config->clock_source = GCLK_GENERATOR_0; + config->counter_size = TC_COUNTER_SIZE_16BIT; + config->clock_prescaler = TC_CLOCK_PRESCALER_DIV1; + config->wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ; + config->reload_action = TC_RELOAD_ACTION_GCLK; + config->run_in_standby = false; +#if (SAML21) || (SAMC20) || (SAMC21) + config->on_demand = false; +#endif + config->waveform_invert_output = TC_WAVEFORM_INVERT_OUTPUT_NONE; + config->enable_capture_on_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = false; + config->enable_capture_on_channel[TC_COMPARE_CAPTURE_CHANNEL_1] = false; +#ifdef FEATURE_TC_IO_CAPTURE + config->enable_capture_on_IO[TC_COMPARE_CAPTURE_CHANNEL_0] = false; + config->enable_capture_on_IO[TC_COMPARE_CAPTURE_CHANNEL_1] = false; +#endif + + config->count_direction = TC_COUNT_DIRECTION_UP; + config->oneshot = false; + + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_0].enabled = false; + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_0].pin_out = 0; + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_0].pin_mux = 0; + + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].enabled = false; + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_out = 0; + config->pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_mux = 0; + + config->counter_16_bit.value = 0x0000; + config->counter_16_bit.compare_capture_channel\ + [TC_COMPARE_CAPTURE_CHANNEL_0] = 0x0000; + config->counter_16_bit.compare_capture_channel\ + [TC_COMPARE_CAPTURE_CHANNEL_1] = 0x0000; +#ifdef FEATURE_TC_DOUBLE_BUFFERED + config->double_buffering_enabled = false; +#endif + +} + +enum status_code tc_init( + struct tc_module *const module_inst, + Tc *const hw, + const struct tc_config *const config); + +/** @} */ + +/** + * \name Event Management + * @{ + */ + +/** + * \brief Enables a TC module event input or output. + * + * Enables one or more input or output events to or from the TC module. + * See \ref tc_events for a list of events this module supports. + * + * \note Events cannot be altered while the module is enabled. + * + * \param[in] module_inst Pointer to the software module instance struct + * \param[in] events Struct containing flags of events to enable + */ +static inline void tc_enable_events( + struct tc_module *const module_inst, + struct tc_events *const events) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + Assert(events); + + Tc *const tc_module = module_inst->hw; + + uint32_t event_mask = 0; + + if (events->invert_event_input == true) { + event_mask |= TC_EVCTRL_TCINV; + } + + if (events->on_event_perform_action == true) { + event_mask |= TC_EVCTRL_TCEI; + } + + if (events->generate_event_on_overflow == true) { + event_mask |= TC_EVCTRL_OVFEO; + } + + for (uint8_t i = 0; i < NUMBER_OF_COMPARE_CAPTURE_CHANNELS; i++) { + if (events->generate_event_on_compare_channel[i] == true) { + event_mask |= (TC_EVCTRL_MCEO(1) << i); + } + } + + tc_module->COUNT8.EVCTRL.reg |= event_mask | events->event_action; +} + +/** + * \brief Disables a TC module event input or output. + * + * Disables one or more input or output events to or from the TC module. + * See \ref tc_events for a list of events this module supports. + * + * \note Events cannot be altered while the module is enabled. + * + * \param[in] module_inst Pointer to the software module instance struct + * \param[in] events Struct containing flags of events to disable + */ +static inline void tc_disable_events( + struct tc_module *const module_inst, + struct tc_events *const events) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + Assert(events); + + Tc *const tc_module = module_inst->hw; + + uint32_t event_mask = 0; + + if (events->invert_event_input == true) { + event_mask |= TC_EVCTRL_TCINV; + } + + if (events->on_event_perform_action == true) { + event_mask |= TC_EVCTRL_TCEI; + } + + if (events->generate_event_on_overflow == true) { + event_mask |= TC_EVCTRL_OVFEO; + } + + for (uint8_t i = 0; i < NUMBER_OF_COMPARE_CAPTURE_CHANNELS; i++) { + if (events->generate_event_on_compare_channel[i] == true) { + event_mask |= (TC_EVCTRL_MCEO(1) << i); + } + } + + tc_module->COUNT8.EVCTRL.reg &= ~event_mask; +} + +/** @} */ + +/** + * \name Enable/Disable/Reset + * @{ + */ + +enum status_code tc_reset( + const struct tc_module *const module_inst); + +/** + * \brief Enable the TC module. + * + * Enables a TC module that has been previously initialized. The counter will + * start when the counter is enabled. + * + * \note When the counter is configured to re-trigger on an event, the counter + * will not start until the start function is used. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_enable( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Enable TC module */ + tc_module->CTRLA.reg |= TC_CTRLA_ENABLE; +} + +/** + * \brief Disables the TC module. + * + * Disables a TC module and stops the counter. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_disable( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Disable TC module */ + tc_module->CTRLA.reg &= ~TC_CTRLA_ENABLE; +} + +/** @} */ + +/** + * \name Get/Set Count Value + * @{ + */ + +uint32_t tc_get_count_value( + const struct tc_module *const module_inst); + +enum status_code tc_set_count_value( + const struct tc_module *const module_inst, + const uint32_t count); + +/** @} */ + +/** + * \name Start/Stop Counter + * @{ + */ + +/** + * \brief Stops the counter. + * + * This function will stop the counter. When the counter is stopped + * the value in the count value is set to 0 if the counter was + * counting up, or maximum if the counter was counting + * down when stopped. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_stop_counter( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_STOP_Val); +} + +/** + * \brief Starts the counter. + * + * Starts or restarts an initialized TC module's counter. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_start_counter( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Make certain that there are no conflicting commands in the register */ + tc_module->CTRLBCLR.reg = TC_CTRLBCLR_CMD_NONE; + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_RETRIGGER_Val); +} + +/** @} */ + +#ifdef FEATURE_TC_DOUBLE_BUFFERED +/** + * \name Double Buffering + * @{ + */ + +/** + * \brief Update double buffer. + * + * Update double buffer. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_update_double_buffer( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Make certain that there are no conflicting commands in the register */ + tc_module->CTRLBCLR.reg = TC_CTRLBCLR_CMD_NONE; + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_UPDATE_Val); +} +/** @} */ +#endif + +#ifdef FEATURE_TC_READ_SYNC +/** + * \name Count Read Synchronization + * @{ + */ + +/** + * \brief Read synchronization of COUNT. + * + * Read synchronization of COUNT. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_sync_read_count( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Make certain that there are no conflicting commands in the register */ + tc_module->CTRLBCLR.reg = TC_CTRLBCLR_CMD_NONE; + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_READSYNC_Val); +} +/** @} */ +#endif + +#ifdef FEATURE_TC_GENERATE_DMA_TRIGGER +/** + * \name Generate TC DMA Triggers command + * @{ + */ + +/** + * \brief TC DMA Trigger. + * + * TC DMA trigger command. + * + * \param[in] module_inst Pointer to the software module instance struct + */ +static inline void tc_dma_trigger_command( + const struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + + /* Make certain that there are no conflicting commands in the register */ + tc_module->CTRLBCLR.reg = TC_CTRLBCLR_CMD_NONE; + + while (tc_is_syncing(module_inst)) { + /* Wait for sync */ + } + +#if SAML21 + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_DMATRG_Val); +#endif +#if (SAMC20) || (SAMC21) + /* Write command to execute */ + tc_module->CTRLBSET.reg = TC_CTRLBSET_CMD(TC_CTRLBSET_CMD_DMAOS_Val); +#endif +} +/** @} */ +#endif + +/** + * \name Get Capture Set Compare + * @{ + */ + +uint32_t tc_get_capture_value( + const struct tc_module *const module_inst, + const enum tc_compare_capture_channel channel_index); + +enum status_code tc_set_compare_value( + const struct tc_module *const module_inst, + const enum tc_compare_capture_channel channel_index, + const uint32_t compare_value); + +/** @} */ + +/** + * \name Set Top Value + * @{ + */ + +enum status_code tc_set_top_value( + const struct tc_module *const module_inst, + const uint32_t top_value); + +/** @} */ + +/** + * \name Status Management + * @{ + */ + +/** + * \brief Retrieves the current module status. + * + * Retrieves the status of the module, giving overall state information. + * + * \param[in] module_inst Pointer to the TC software instance struct + * + * \return Bitmask of \c TC_STATUS_* flags. + * + * \retval TC_STATUS_CHANNEL_0_MATCH Timer channel 0 compare/capture match + * \retval TC_STATUS_CHANNEL_1_MATCH Timer channel 1 compare/capture match + * \retval TC_STATUS_SYNC_READY Timer read synchronization has completed + * \retval TC_STATUS_CAPTURE_OVERFLOW Timer capture data has overflowed + * \retval TC_STATUS_COUNT_OVERFLOW Timer count value has overflowed + * \retval TC_STATUS_CHN0_BUFFER_VALID Timer count channel 0 compare/capture buffer valid + * \retval TC_STATUS_CHN1_BUFFER_VALID Timer count channel 1 compare/capture buffer valid + * \retval TC_STATUS_PERIOD_BUFFER_VALID Timer count period buffer valid + */ +static inline uint32_t tc_get_status( + struct tc_module *const module_inst) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + uint32_t int_flags = tc_module->INTFLAG.reg; + + uint32_t status_flags = 0; + + /* Check for TC channel 0 match */ + if (int_flags & TC_INTFLAG_MC(1)) { + status_flags |= TC_STATUS_CHANNEL_0_MATCH; + } + + /* Check for TC channel 1 match */ + if (int_flags & TC_INTFLAG_MC(2)) { + status_flags |= TC_STATUS_CHANNEL_1_MATCH; + } + +#if !defined(FEATURE_TC_SYNCBUSY_SCHEME_VERSION_2) + /* Check for TC read synchronization ready */ + if (int_flags & TC_INTFLAG_SYNCRDY) { + status_flags |= TC_STATUS_SYNC_READY; + } +#endif + + /* Check for TC capture overflow */ + if (int_flags & TC_INTFLAG_ERR) { + status_flags |= TC_STATUS_CAPTURE_OVERFLOW; + } + + /* Check for TC count overflow */ + if (int_flags & TC_INTFLAG_OVF) { + status_flags |= TC_STATUS_COUNT_OVERFLOW; + } +#ifdef FEATURE_TC_DOUBLE_BUFFERED + uint8_t double_buffer_valid_status = tc_module->STATUS.reg; + + /* Check channel 0 compare or capture buffer valid */ + if (double_buffer_valid_status & TC_STATUS_CCBUFV0) { + status_flags |= TC_STATUS_CHN0_BUFFER_VALID; + } + /* Check channel 0 compare or capture buffer valid */ + if (double_buffer_valid_status & TC_STATUS_CCBUFV1) { + status_flags |= TC_STATUS_CHN1_BUFFER_VALID; + } + /* Check period buffer valid */ + if (double_buffer_valid_status & TC_STATUS_PERBUFV) { + status_flags |= TC_STATUS_PERIOD_BUFFER_VALID; + } +#endif + + return status_flags; +} + +/** + * \brief Clears a module status flag. + * + * Clears the given status flag of the module. + * + * \param[in] module_inst Pointer to the TC software instance struct + * \param[in] status_flags Bitmask of \c TC_STATUS_* flags to clear + */ +static inline void tc_clear_status( + struct tc_module *const module_inst, + const uint32_t status_flags) +{ + /* Sanity check arguments */ + Assert(module_inst); + Assert(module_inst->hw); + + /* Get a pointer to the module's hardware instance */ + TcCount8 *const tc_module = &(module_inst->hw->COUNT8); + + uint32_t int_flags = 0; + + /* Check for TC channel 0 match */ + if (status_flags & TC_STATUS_CHANNEL_0_MATCH) { + int_flags |= TC_INTFLAG_MC(1); + } + + /* Check for TC channel 1 match */ + if (status_flags & TC_STATUS_CHANNEL_1_MATCH) { + int_flags |= TC_INTFLAG_MC(2); + } + +#if !defined(FEATURE_TC_SYNCBUSY_SCHEME_VERSION_2) + /* Check for TC read synchronization ready */ + if (status_flags & TC_STATUS_SYNC_READY) { + int_flags |= TC_INTFLAG_SYNCRDY; + } +#endif + + /* Check for TC capture overflow */ + if (status_flags & TC_STATUS_CAPTURE_OVERFLOW) { + int_flags |= TC_INTFLAG_ERR; + } + + /* Check for TC count overflow */ + if (status_flags & TC_STATUS_COUNT_OVERFLOW) { + int_flags |= TC_INTFLAG_OVF; + } + + /* Clear interrupt flag */ + tc_module->INTFLAG.reg = int_flags; +} + +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** + * \page asfdoc_sam0_tc_extra Extra Information for TC Driver + * + * \section asfdoc_sam0_tc_extra_acronyms Acronyms + * The table below presents the acronyms used in this module: + * + * <table> + * <tr> + * <th>Acronym</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>DMA</td> + * <td>Direct Memory Access</td> + * </tr> + * <tr> + * <td>TC</td> + * <td>Timer Counter</td> + * </tr> + * <tr> + * <td>PWM</td> + * <td>Pulse Width Modulation</td> + * </tr> + * <tr> + * <td>PWP</td> + * <td>Pulse Width Period</td> + * </tr> + * <tr> + * <td>PPW</td> + * <td>Period Pulse Width</td> + * </tr> + * </table> + * + * + * \section asfdoc_sam0_tc_extra_dependencies Dependencies + * This driver has the following dependencies: + * + * - \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver" + * + * + * \section asfdoc_sam0_tc_extra_errata Errata + * There are no errata related to this driver. + * + * + * \section asfdoc_sam0_tc_extra_history Module History + * An overview of the module history is presented in the table below, with + * details on the enhancements and fixes made to the module since its first + * release. The current version of this corresponds to the newest version in + * the table. + * + * <table> + * <tr> + * <th>Changelog</th> + * </tr> + * <tr> + * <td>Added support for SAMD21 and do some modifications as below: + * \li Clean up in the configuration structure, the counter size + * setting specific registers is accessed through the counter_8_bit, + * counter_16_bit and counter_32_bit structures + * \li All event related settings moved into the tc_event structure </td> + * </tr> + * <tr> + * <td>Added automatic digital clock interface enable for the slave TC + * module when a timer is initialized in 32-bit mode</td> + * </tr> + * <tr> + * <td>Initial Release</td> + * </tr> + * </table> + */ + +/** + * \page asfdoc_sam0_tc_exqsg Examples for TC Driver + * + * This is a list of the available Quick Start guides (QSGs) and example + * applications for \ref asfdoc_sam0_tc_group. QSGs are simple examples with + * step-by-step instructions to configure and use this driver in a selection of + * use cases. Note that QSGs can be compiled as a standalone application or be + * added to the user application. + * + * - \subpage asfdoc_sam0_tc_basic_use_case + * - \subpage asfdoc_sam0_tc_macth_freq_use_case + * \if TC_CALLBACK_MODE + * - \subpage asfdoc_sam0_tc_timer_use_case + * - \subpage asfdoc_sam0_tc_callback_use_case + * \endif + * - \subpage asfdoc_sam0_tc_dma_use_case + * + * \page asfdoc_sam0_tc_document_revision_history Document Revision History + * + * <table> + * <tr> + * <th>Doc. Rev.</td> + * <th>Date</td> + * <th>Comments</td> + * </tr> + * <tr> + * <td>F</td> + * <td>12/2014</td> + * <td>Added support for SAMC21.</td> + * </tr> + * <tr> + * <td>E</td> + * <td>04/2015</td> + * <td>Added support for SAML21 and SAMDAx.</td> + * </tr> + * <tr> + * <td>D</td> + * <td>12/2014</td> + * <td>Added timer use case. + * Added support for SAMR21 and SAMD10/D11.</td> + * </tr> + * <tr> + * <td>C</td> + * <td>01/2014</td> + * <td>Added support for SAMD21.</td> + * </tr> + * <tr> + * <td>B</td> + * <td>06/2013</td> + * <td>Corrected documentation typos.</td> + * </tr> + * <tr> + * <td>A</td> + * <td>06/2013</td> + * <td>Initial release</td> + * </tr> + * </table> + */ + +#endif /* TC_H_INCLUDED */