]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/tc/tc.c
Rename DummyTCB_t to StaticTCB_t.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAME70_Xplained_AtmelStudio / src / ASF / sam / drivers / tc / tc.c
diff --git a/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/tc/tc.c b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/ASF/sam/drivers/tc/tc.c
new file mode 100644 (file)
index 0000000..e545b92
--- /dev/null
@@ -0,0 +1,776 @@
+/**\r
+ * \file\r
+ *\r
+ * \brief SAM Timer Counter (TC) driver.\r
+ *\r
+ * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+/*\r
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>\r
+ */\r
+\r
+#include <assert.h>\r
+#include "tc.h"\r
+\r
+/// @cond\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+#ifndef TC_WPMR_WPKEY_PASSWD\r
+#define TC_WPMR_WPKEY_PASSWD TC_WPMR_WPKEY((uint32_t)0x54494D)\r
+#endif\r
+\r
+/**\r
+ * \brief Configure TC for timer, waveform generation, or capture.\r
+ *\r
+ * \param[in,out] p_tc   Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to configure\r
+ * \param[in] ul_mode    Control mode register bitmask value to set\r
+ *\r
+ * \note For more information regarding <i>ul_mode</i> configuration refer to\r
+ * the section entitled "Channel Mode Register: Capture Mode" and/or section\r
+ * "Waveform Operating Mode" in the device-specific datasheet.\r
+ *\r
+ * \note If the TC is configured for waveform generation then the external event\r
+ * selection (EEVT) should only be set to TC_CMR_EEVT_TIOB, or the\r
+ * equivalent value of 0, if it really is the intention to use TIOB as an\r
+ * external event trigger. This is because this setting forces TIOB to be\r
+ * an input, even if the external event trigger has not been enabled with\r
+ * TC_CMR_ENETRG, and thus prevents normal operation of TIOB.\r
+ */\r
+void tc_init(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_mode)\r
+{\r
+       TcChannel *tc_channel;\r
+\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+       tc_channel = p_tc->TC_CHANNEL + ul_channel;\r
+\r
+       /*  Disable TC clock. */\r
+       tc_channel->TC_CCR = TC_CCR_CLKDIS;\r
+\r
+       /*  Disable interrupts. */\r
+       tc_channel->TC_IDR = 0xFFFFFFFF;\r
+\r
+       /*  Clear status register. */\r
+       tc_channel->TC_SR;\r
+\r
+       /*  Set mode. */\r
+       tc_channel->TC_CMR = ul_mode;\r
+}\r
+\r
+/**\r
+ * \brief Asserts a SYNC signal to generate a software trigger on\r
+ * all channels.\r
+ *\r
+ * \param[out] p_tc Module hardware register base address pointer\r
+ *\r
+ */\r
+void tc_sync_trigger(\r
+               Tc *p_tc)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       p_tc->TC_BCR = TC_BCR_SYNC;\r
+}\r
+\r
+/**\r
+ * \brief Configure the TC Block mode.\r
+ *\r
+ * \note The function tc_init() must be called prior to this one.\r
+ *\r
+ * \param[out] p_tc        Module hardware register base address pointer\r
+ * \param[in] ul_blockmode Block mode register value to set\r
+ *\r
+ * \note For more information regarding <i>ul_blockmode</i> configuration refer to\r
+ * the section  entitled "TC Block Mode Register" in the device-specific datasheet.\r
+ */\r
+void tc_set_block_mode(\r
+               Tc *p_tc,\r
+               uint32_t ul_blockmode)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       p_tc->TC_BMR = ul_blockmode;\r
+}\r
+\r
+#if (!SAM3U) || defined(__DOXYGEN__)\r
+\r
+/**\r
+ * \brief Configure TC for 2-bit Gray Counter for Stepper Motor.\r
+ * \note The function tc_init() must be called prior to this one.\r
+ *\r
+ * \note This function is not available on SAM3U devices.\r
+ *\r
+ * \param[out] p_tc          Module hardware register base address pointer\r
+ * \param[in] ul_channel     Channel to configure\r
+ * \param[in] ul_steppermode Stepper motor mode register value to set\r
+ *\r
+ * \return 0 for OK.\r
+ */\r
+uint32_t tc_init_2bit_gray(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_steppermode)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_SMMR = ul_steppermode;\r
+       return 0;\r
+}\r
+\r
+#endif /* (!SAM3U) || defined(__DOXYGEN__) */\r
+\r
+/**\r
+ * \brief Start the TC clock on the specified channel.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to configure\r
+ */\r
+void tc_start(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;\r
+}\r
+\r
+/**\r
+ * \brief Stop the TC clock on the specified channel.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to configure\r
+ */\r
+void tc_stop(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKDIS;\r
+}\r
+\r
+/**\r
+ * \brief Read the counter value on the specified channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to read\r
+ *\r
+ * \return The counter value.\r
+ */\r
+uint32_t tc_read_cv(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       return p_tc->TC_CHANNEL[ul_channel].TC_CV;\r
+}\r
+\r
+/**\r
+ * \brief Read TC Register A (RA) on the specified channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to read\r
+ *\r
+ * \return The TC Register A (RA) value.\r
+ */\r
+uint32_t tc_read_ra(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       return p_tc->TC_CHANNEL[ul_channel].TC_RA;\r
+}\r
+\r
+/**\r
+ * \brief Read TC Register B (RB) on the specified channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to read\r
+ *\r
+ * \return The TC Register B (RB) value.\r
+ */\r
+uint32_t tc_read_rb(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       return p_tc->TC_CHANNEL[ul_channel].TC_RB;\r
+}\r
+\r
+/**\r
+ * \brief Read TC Register C (RC) on the specified channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to read\r
+ *\r
+ * \return The Register C (RC) value.\r
+ */\r
+uint32_t tc_read_rc(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       return p_tc->TC_CHANNEL[ul_channel].TC_RC;\r
+}\r
+\r
+/**\r
+ * \brief Write to TC Register A (RA) on the specified channel.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to write\r
+ * \param[in] ul_value   Value to write\r
+ */\r
+void tc_write_ra(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_value)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_RA = ul_value;\r
+}\r
+\r
+/**\r
+ * \brief Write to TC Register B (RB) on the specified channel.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to write\r
+ * \param[in] ul_value   Value to write\r
+ */\r
+void tc_write_rb(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_value)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_RB = ul_value;\r
+}\r
+\r
+/**\r
+ * \brief Write to TC Register C (RC) on the selected channel.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to write\r
+ * \param[in] ul_value   Value to write\r
+ */\r
+void tc_write_rc(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_value)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+\r
+       p_tc->TC_CHANNEL[ul_channel].TC_RC = ul_value;\r
+}\r
+\r
+/**\r
+ * \brief Enable the TC interrupts on the specified channel.\r
+ *\r
+ * \param[in,out] p_tc   Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to configure\r
+ * \param[in] ul_sources Bitmask of interrupt sources\r
+ *\r
+ * Where the input parameter <i>ul_sources</i> can be one or more of the following:\r
+ * <table>\r
+ * <tr>\r
+ *    <th>Parameter Value</th>\r
+ *    <th>Description</th>\r
+ * </tr>\r
+ *     <tr><td>TC_IER_COVFS</td><td>Enables the Counter Overflow Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_LOVRS</td><td>Enables the Load Overrun Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_CPAS</td><td>Enables the RA Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_CPBS</td><td>Enables the RB Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_CPCS</td><td>Enables the RC Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_LDRAS</td><td>Enables the RA Load Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_LDRBS</td><td>Enables the RB Load Interrupt</td></tr>\r
+ *     <tr><td>TC_IER_ETRGS</td><td>Enables the External Trigger Interrupt</td></tr>\r
+ * </table>\r
+ */\r
+void tc_enable_interrupt(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_sources)\r
+{\r
+       TcChannel *tc_channel;\r
+\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+       tc_channel = p_tc->TC_CHANNEL + ul_channel;\r
+       tc_channel->TC_IER = ul_sources;\r
+}\r
+\r
+/**\r
+ * \brief Disable TC interrupts on the specified channel.\r
+ *\r
+ * \param[in,out] p_tc   Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to configure\r
+ * \param[in] ul_sources A bitmask of Interrupt sources\r
+ *\r
+ * Where the input parameter <i>ul_sources</i> can be one or more of the following:\r
+ * <table>\r
+ * <tr>\r
+ *    <th>Parameter Value</th>\r
+ *    <th>Description</th>\r
+ * </tr>\r
+ *     <tr><td>TC_IDR_COVFS</td><td>Disables the Counter Overflow Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_LOVRS</td><td>Disables the Load Overrun Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_CPAS</td><td>Disables the RA Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_CPBS</td><td>Disables the RB Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_CPCS</td><td>Disables the RC Compare Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_LDRAS</td><td>Disables the RA Load Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_LDRBS</td><td>Disables the RB Load Interrupt</td></tr>\r
+ *     <tr><td>TC_IDR_ETRGS</td><td>Disables the External Trigger Interrupt</td></tr>\r
+ * </table>\r
+ */\r
+void tc_disable_interrupt(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel,\r
+               uint32_t ul_sources)\r
+{\r
+       TcChannel *tc_channel;\r
+\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+       tc_channel = p_tc->TC_CHANNEL + ul_channel;\r
+       tc_channel->TC_IDR = ul_sources;\r
+}\r
+\r
+/**\r
+ * \brief Read the TC interrupt mask for the specified channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel to read\r
+ *\r
+ * \return The TC interrupt mask value.\r
+ */\r
+uint32_t tc_get_interrupt_mask(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       TcChannel *tc_channel;\r
+\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+       tc_channel = p_tc->TC_CHANNEL + ul_channel;\r
+       return tc_channel->TC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Get the current status for the specified TC channel.\r
+ *\r
+ * \param[in] p_tc       Module hardware register base address pointer\r
+ * \param[in] ul_channel Channel number\r
+ *\r
+ * \return The current TC status.\r
+ */\r
+uint32_t tc_get_status(\r
+               Tc *p_tc,\r
+               uint32_t ul_channel)\r
+{\r
+       TcChannel *tc_channel;\r
+\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       Assert(ul_channel <\r
+                       (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));\r
+                       \r
+       tc_channel = p_tc->TC_CHANNEL + ul_channel;\r
+       return tc_channel->TC_SR;\r
+}\r
+\r
+/* TC divisor used to find the lowest acceptable timer frequency */\r
+#define TC_DIV_FACTOR 65536\r
+\r
+#if (!SAM4L) && !defined(__DOXYGEN__)\r
+\r
+#ifndef FREQ_SLOW_CLOCK_EXT\r
+#define FREQ_SLOW_CLOCK_EXT 32768 /* External slow clock frequency (hz) */\r
+#endif\r
+\r
+/**\r
+ * \brief Find the best MCK divisor.\r
+ *\r
+ * Finds the best MCK divisor given the timer frequency and MCK. The result\r
+ * is guaranteed to satisfy the following equation:\r
+ * \code (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) \endcode\r
+ * With DIV being the lowest possible value, to maximize timing adjust resolution.\r
+ *\r
+ * \param[in] ul_freq     Desired timer frequency\r
+ * \param[in] ul_mck      Master clock frequency\r
+ * \param[out] p_uldiv    Divisor value\r
+ * \param[out] p_ultcclks TCCLKS field value for divisor\r
+ * \param[in] ul_boardmck Board clock frequency\r
+ *\r
+ * \return The divisor found status.\r
+ * \retval 0 No suitable divisor was found\r
+ * \retval 1 A divisor was found\r
+ */\r
+uint32_t tc_find_mck_divisor(\r
+               uint32_t ul_freq,\r
+               uint32_t ul_mck,\r
+               uint32_t *p_uldiv,\r
+               uint32_t *p_ultcclks,\r
+               uint32_t ul_boardmck)\r
+{\r
+       const uint32_t divisors[5] = { 2, 8, 32, 128,\r
+                       ul_boardmck / FREQ_SLOW_CLOCK_EXT };\r
+       uint32_t ul_index;\r
+       uint32_t ul_high, ul_low;\r
+\r
+       /*  Satisfy frequency bound. */\r
+       for (ul_index = 0;\r
+                       ul_index < (sizeof(divisors) / sizeof(divisors[0]));\r
+                       ul_index++) {\r
+               ul_high = ul_mck / divisors[ul_index];\r
+               ul_low  = ul_high / TC_DIV_FACTOR;\r
+               if (ul_freq > ul_high) {\r
+                       return 0;\r
+               } else if (ul_freq >= ul_low) {\r
+                       break;\r
+               }\r
+       }\r
+       if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {\r
+               return 0;\r
+       }\r
+\r
+       /*  Store results. */\r
+       if (p_uldiv) {\r
+               *p_uldiv = divisors[ul_index];\r
+       }\r
+\r
+       if (p_ultcclks) {\r
+               *p_ultcclks = ul_index;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+#endif /* (!SAM4L) */\r
+\r
+#if (SAM4L) || defined(__DOXYGEN__)\r
+/**\r
+ * \brief Find the best PBA/MCK divisor.\r
+ *\r
+ * <b>For SAM4L devices:</b> Finds the best PBA divisor given the timer\r
+ * frequency and PBA clock. The result is guaranteed to satisfy the following equation:\r
+ * \code  (ul_pbaclk / (2* DIV * 65536)) <= freq <= (ul_pbaclk / (2* DIV)) \endcode\r
+ * with DIV being the lowest possible value, to maximize timing adjust resolution.\r
+ *\r
+ * <b>For non SAM4L devices:</b> Finds the best MCK divisor given the timer frequency\r
+ * and MCK. The result is guaranteed to satisfy the following equation:\r
+ * \code (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) \endcode\r
+ * with DIV being the lowest possible value, to maximize timing adjust resolution.\r
+ *\r
+ * \param[in] ul_freq     Desired timer frequency\r
+ * \param[in] ul_mck      PBA clock frequency\r
+ * \param[out] p_uldiv    Divisor value\r
+ * \param[out] p_ultcclks TCCLKS field value for divisor\r
+ * \param[in] ul_boardmck Board clock frequency (set to 0 for SAM4L devices)\r
+ *\r
+ * \return The divisor found status.\r
+ * \retval 0 No suitable divisor was found\r
+ * \retval 1 A divisor was found\r
+ */\r
+uint32_t tc_find_mck_divisor(\r
+               uint32_t ul_freq,\r
+               uint32_t ul_mck,\r
+               uint32_t *p_uldiv,\r
+               uint32_t *p_ultcclks,\r
+               uint32_t ul_boardmck)\r
+{\r
+       const uint32_t divisors[5] = { 0, 2, 8, 32, 128};\r
+       uint32_t ul_index;\r
+       uint32_t ul_high, ul_low;\r
+\r
+       UNUSED(ul_boardmck);\r
+\r
+       /*  Satisfy frequency bound. */\r
+       for (ul_index = 1;\r
+                       ul_index < (sizeof(divisors) / sizeof(divisors[0]));\r
+                       ul_index++) {\r
+               ul_high = ul_mck / divisors[ul_index];\r
+               ul_low  = ul_high / TC_DIV_FACTOR;\r
+               if (ul_freq > ul_high) {\r
+                       return 0;\r
+               } else if (ul_freq >= ul_low) {\r
+                       break;\r
+               }\r
+       }\r
+       if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {\r
+               return 0;\r
+       }\r
+\r
+       /*  Store results. */\r
+       if (p_uldiv) {\r
+               *p_uldiv = divisors[ul_index];\r
+       }\r
+\r
+       if (p_ultcclks) {\r
+               *p_ultcclks = ul_index;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+#endif /* (SAM4L) || defined(__DOXYGEN__) */\r
+\r
+#if (!SAM4L && !SAMG) || defined(__DOXYGEN__)\r
+\r
+/**\r
+ * \brief Enable TC QDEC interrupts.\r
+ *\r
+ * \note This function is not available on SAM4L or SAMG devices.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_sources A bitmask of QDEC interrupts to be enabled\r
+ *\r
+ * Where the input parameter <i>ul_sources</i> can be one or more of the following:\r
+ * <table>\r
+ * <tr>\r
+ *    <th>Parameter Value</th>\r
+ *    <th>Description</th>\r
+ * </tr>\r
+ *     <tr><td>TC_QIER_IDX</td><td>Enable the rising edge detected on IDX input interrupt</td></tr>\r
+ *     <tr><td>TC_QIER_DIRCHG</td><td>Enable the change in rotation direction detected interrupt</td></tr>\r
+ *     <tr><td>TC_QIER_QERR</td><td>Enable the quadrature error detected on PHA/PHB interrupt</td></tr>\r
+ * </table>\r
+ */\r
+void tc_enable_qdec_interrupt(\r
+               Tc *p_tc,\r
+               uint32_t ul_sources)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       p_tc->TC_QIER = ul_sources;\r
+}\r
+\r
+/**\r
+ * \brief Disable TC QDEC interrupts.\r
+ *\r
+ * \note This function is not available on SAM4L or SAMG devices.\r
+ *\r
+ * \param[out] p_tc      Module hardware register base address pointer\r
+ * \param[in] ul_sources A bitmask of QDEC interrupts to be disabled\r
+ *\r
+ * Where the input parameter <i>ul_sources</i> can be one or more of the following:\r
+ * <table>\r
+ * <tr>\r
+ *    <th>Parameter Value</th>\r
+ *    <th>Description</th>\r
+ * </tr>\r
+ *     <tr><td>TC_QIDR_IDX</td><td>Disable the rising edge detected on IDX input interrupt</td></tr>\r
+ *     <tr><td>TC_QIDR_DIRCHG</td><td>Disable the change in rotation direction detected interrupt</td></tr>\r
+ *     <tr><td>TC_QIDR_QERR</td><td>Disable the quadrature error detected on PHA/PHB interrupt</td></tr>\r
+ * </table>\r
+ */\r
+void tc_disable_qdec_interrupt(\r
+               Tc *p_tc,\r
+               uint32_t ul_sources)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       p_tc->TC_QIDR = ul_sources;\r
+}\r
+\r
+/**\r
+ * \brief Read TC QDEC interrupt mask.\r
+ *\r
+ * \note This function is not available on SAM4L or SAMG devices.\r
+ *\r
+ * \param[in] p_tc Module hardware register base address pointer\r
+ *\r
+ * \return The QDEC interrupt mask value.\r
+ */\r
+uint32_t tc_get_qdec_interrupt_mask(\r
+               Tc *p_tc)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       return p_tc->TC_QIMR;\r
+}\r
+\r
+/**\r
+ * \brief Get current TC QDEC interrupt status.\r
+ *\r
+ * \note This function is not available on SAM4L or SAMG devices.\r
+ *\r
+ * \param[in] p_tc Module hardware register base address pointer\r
+ *\r
+ * \return The TC QDEC interrupt status.\r
+ */\r
+uint32_t tc_get_qdec_interrupt_status(\r
+               Tc *p_tc)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       return p_tc->TC_QISR;\r
+}\r
+\r
+#endif /* (!SAM4L && !SAMG) || defined(__DOXYGEN__) */\r
+\r
+#if (!SAM3U) || defined(__DOXYGEN__)\r
+\r
+/**\r
+ * \brief Enable or disable write protection of TC registers.\r
+ *\r
+ * \note This function is not available on SAM3U devices.\r
+ *\r
+ * \param[out] p_tc     Module hardware register base address pointer\r
+ * \param[in] ul_enable 1 to enable, 0 to disable\r
+ */\r
+void tc_set_writeprotect(\r
+               Tc *p_tc,\r
+               uint32_t ul_enable)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       if (ul_enable) {\r
+               p_tc->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN;\r
+       } else {\r
+               p_tc->TC_WPMR = TC_WPMR_WPKEY_PASSWD;\r
+       }\r
+}\r
+\r
+#endif /* (!SAM3U) || defined(__DOXYGEN__) */\r
+\r
+#if SAM4L || defined(__DOXYGEN__)\r
+\r
+/**\r
+ * \brief Indicate TC features.\r
+ *\r
+ * \note This function is only available on SAM4L devices.\r
+ *\r
+ * \param[in] p_tc Module hardware register base address pointer\r
+ *\r
+ * \return The TC FEATURES register contents.\r
+ */\r
+uint32_t tc_get_feature(\r
+               Tc *p_tc)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       return p_tc->TC_FEATURES;\r
+}\r
+\r
+/**\r
+ * \brief Indicate TC version.\r
+ *\r
+ * \note This function is only available on SAM4L devices.\r
+ *\r
+ * \param[in] p_tc Module hardware register base address pointer\r
+ *\r
+ * \return The TC VERSION register contents.\r
+ */\r
+uint32_t tc_get_version(\r
+               Tc *p_tc)\r
+{\r
+       /* Validate inputs. */\r
+       Assert(p_tc);\r
+       \r
+       return p_tc->TC_VERSION;\r
+}\r
+\r
+#endif /* SAM4L || defined(__DOXYGEN__) */\r
+\r
+/// @cond\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r