tc.c
Go to the documentation of this file.
1 
33 /*
34  * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35  */
36 
37 #include <assert.h>
38 #include "tc.h"
39 
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45 
46 
48 #ifndef TC_WPMR_WPKEY_PASSWD
49 #define TC_WPMR_WPKEY_PASSWD TC_WPMR_WPKEY((uint32_t)0x54494D)
50 #endif
51 
70 void tc_init(
71  Tc *p_tc,
72  uint32_t ul_channel,
73  uint32_t ul_mode)
74 {
75  TcChannel *tc_channel;
76 
77  /* Validate inputs. */
78  Assert(p_tc);
79  Assert(ul_channel <
80  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
81  tc_channel = p_tc->TC_CHANNEL + ul_channel;
82 
83  /* Disable TC clock. */
84  tc_channel->TC_CCR = TC_CCR_CLKDIS;
85 
86  /* Disable interrupts. */
87  tc_channel->TC_IDR = 0xFFFFFFFF;
88 
89  /* Clear status register. */
90  tc_channel->TC_SR;
91 
92  /* Set mode. */
93  tc_channel->TC_CMR = ul_mode;
94 }
95 
104  Tc *p_tc)
105 {
106  /* Validate inputs. */
107  Assert(p_tc);
108 
109  p_tc->TC_BCR = TC_BCR_SYNC;
110 }
111 
124  Tc *p_tc,
125  uint32_t ul_blockmode)
126 {
127  /* Validate inputs. */
128  Assert(p_tc);
129 
130  p_tc->TC_BMR = ul_blockmode;
131 }
132 
133 #if (!SAM3U) || defined(__DOXYGEN__)
134 
148  Tc *p_tc,
149  uint32_t ul_channel,
150  uint32_t ul_steppermode)
151 {
152  /* Validate inputs. */
153  Assert(p_tc);
154  Assert(ul_channel <
155  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
156 
157  p_tc->TC_CHANNEL[ul_channel].TC_SMMR = ul_steppermode;
158  return 0;
159 }
160 
161 #endif /* (!SAM3U) || defined(__DOXYGEN__) */
162 
169 void tc_start(
170  Tc *p_tc,
171  uint32_t ul_channel)
172 {
173  /* Validate inputs. */
174  Assert(p_tc);
175  Assert(ul_channel <
176  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
177 
178  p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
179 }
180 
187 void tc_stop(
188  Tc *p_tc,
189  uint32_t ul_channel)
190 {
191  /* Validate inputs. */
192  Assert(p_tc);
193  Assert(ul_channel <
194  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
195 
196  p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKDIS;
197 }
198 
207 uint32_t tc_read_cv(
208  Tc *p_tc,
209  uint32_t ul_channel)
210 {
211  /* Validate inputs. */
212  Assert(p_tc);
213  Assert(ul_channel <
214  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
215 
216  return p_tc->TC_CHANNEL[ul_channel].TC_CV;
217 }
218 
227 uint32_t tc_read_ra(
228  Tc *p_tc,
229  uint32_t ul_channel)
230 {
231  /* Validate inputs. */
232  Assert(p_tc);
233  Assert(ul_channel <
234  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
235 
236  return p_tc->TC_CHANNEL[ul_channel].TC_RA;
237 }
238 
247 uint32_t tc_read_rb(
248  Tc *p_tc,
249  uint32_t ul_channel)
250 {
251  /* Validate inputs. */
252  Assert(p_tc);
253  Assert(ul_channel <
254  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
255 
256  return p_tc->TC_CHANNEL[ul_channel].TC_RB;
257 }
258 
267 uint32_t tc_read_rc(
268  Tc *p_tc,
269  uint32_t ul_channel)
270 {
271  /* Validate inputs. */
272  Assert(p_tc);
273  Assert(ul_channel <
274  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
275 
276  return p_tc->TC_CHANNEL[ul_channel].TC_RC;
277 }
278 
287  Tc *p_tc,
288  uint32_t ul_channel,
289  uint32_t ul_value)
290 {
291  /* Validate inputs. */
292  Assert(p_tc);
293  Assert(ul_channel <
294  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
295 
296  p_tc->TC_CHANNEL[ul_channel].TC_RA = ul_value;
297 }
298 
307  Tc *p_tc,
308  uint32_t ul_channel,
309  uint32_t ul_value)
310 {
311  /* Validate inputs. */
312  Assert(p_tc);
313  Assert(ul_channel <
314  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
315 
316  p_tc->TC_CHANNEL[ul_channel].TC_RB = ul_value;
317 }
318 
327  Tc *p_tc,
328  uint32_t ul_channel,
329  uint32_t ul_value)
330 {
331  /* Validate inputs. */
332  Assert(p_tc);
333  Assert(ul_channel <
334  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
335 
336  p_tc->TC_CHANNEL[ul_channel].TC_RC = ul_value;
337 }
338 
363  Tc *p_tc,
364  uint32_t ul_channel,
365  uint32_t ul_sources)
366 {
367  TcChannel *tc_channel;
368 
369  /* Validate inputs. */
370  Assert(p_tc);
371  Assert(ul_channel <
372  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
373  tc_channel = p_tc->TC_CHANNEL + ul_channel;
374  tc_channel->TC_IER = ul_sources;
375 }
376 
401  Tc *p_tc,
402  uint32_t ul_channel,
403  uint32_t ul_sources)
404 {
405  TcChannel *tc_channel;
406 
407  /* Validate inputs. */
408  Assert(p_tc);
409  Assert(ul_channel <
410  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
411  tc_channel = p_tc->TC_CHANNEL + ul_channel;
412  tc_channel->TC_IDR = ul_sources;
413 }
414 
424  Tc *p_tc,
425  uint32_t ul_channel)
426 {
427  TcChannel *tc_channel;
428 
429  /* Validate inputs. */
430  Assert(p_tc);
431  Assert(ul_channel <
432  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
433  tc_channel = p_tc->TC_CHANNEL + ul_channel;
434  return tc_channel->TC_IMR;
435 }
436 
445 uint32_t tc_get_status(
446  Tc *p_tc,
447  uint32_t ul_channel)
448 {
449  TcChannel *tc_channel;
450 
451  /* Validate inputs. */
452  Assert(p_tc);
453  Assert(ul_channel <
454  (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
455 
456  tc_channel = p_tc->TC_CHANNEL + ul_channel;
457  return tc_channel->TC_SR;
458 }
459 
460 /* TC divisor used to find the lowest acceptable timer frequency */
461 #define TC_DIV_FACTOR 65536
462 
463 #if (!SAM4L) && !defined(__DOXYGEN__)
464 
465 #ifndef FREQ_SLOW_CLOCK_EXT
466 #define FREQ_SLOW_CLOCK_EXT 32768 /* External slow clock frequency (hz) */
467 #endif
468 
488  uint32_t ul_freq,
489  uint32_t ul_mck,
490  uint32_t *p_uldiv,
491  uint32_t *p_ultcclks,
492  uint32_t ul_boardmck)
493 {
494  const uint32_t divisors[5] = { 2, 8, 32, 128,
495  ul_boardmck / FREQ_SLOW_CLOCK_EXT };
496  uint32_t ul_index;
497  uint32_t ul_high, ul_low;
498 
499  /* Satisfy frequency bound. */
500  for (ul_index = 0;
501  ul_index < (sizeof(divisors) / sizeof(divisors[0]));
502  ul_index++) {
503  ul_high = ul_mck / divisors[ul_index];
504  ul_low = ul_high / TC_DIV_FACTOR;
505  if (ul_freq > ul_high) {
506  return 0;
507  } else if (ul_freq >= ul_low) {
508  break;
509  }
510  }
511  if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
512  return 0;
513  }
514 
515  /* Store results. */
516  if (p_uldiv) {
517  *p_uldiv = divisors[ul_index];
518  }
519 
520  if (p_ultcclks) {
521  *p_ultcclks = ul_index;
522  }
523 
524  return 1;
525 }
526 
527 #endif /* (!SAM4L) */
528 
529 #if (SAM4L) || defined(__DOXYGEN__)
530 
553 uint32_t tc_find_mck_divisor(
554  uint32_t ul_freq,
555  uint32_t ul_mck,
556  uint32_t *p_uldiv,
557  uint32_t *p_ultcclks,
558  uint32_t ul_boardmck)
559 {
560  const uint32_t divisors[5] = { 0, 2, 8, 32, 128};
561  uint32_t ul_index;
562  uint32_t ul_high, ul_low;
563 
564  UNUSED(ul_boardmck);
565 
566  /* Satisfy frequency bound. */
567  for (ul_index = 1;
568  ul_index < (sizeof(divisors) / sizeof(divisors[0]));
569  ul_index++) {
570  ul_high = ul_mck / divisors[ul_index];
571  ul_low = ul_high / TC_DIV_FACTOR;
572  if (ul_freq > ul_high) {
573  return 0;
574  } else if (ul_freq >= ul_low) {
575  break;
576  }
577  }
578  if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
579  return 0;
580  }
581 
582  /* Store results. */
583  if (p_uldiv) {
584  *p_uldiv = divisors[ul_index];
585  }
586 
587  if (p_ultcclks) {
588  *p_ultcclks = ul_index;
589  }
590 
591  return 1;
592 }
593 
594 #endif /* (SAM4L) || defined(__DOXYGEN__) */
595 
596 #if (!SAM4L && !SAMG) || defined(__DOXYGEN__)
597 
618  Tc *p_tc,
619  uint32_t ul_sources)
620 {
621  /* Validate inputs. */
622  Assert(p_tc);
623 
624  p_tc->TC_QIER = ul_sources;
625 }
626 
647  Tc *p_tc,
648  uint32_t ul_sources)
649 {
650  /* Validate inputs. */
651  Assert(p_tc);
652 
653  p_tc->TC_QIDR = ul_sources;
654 }
655 
666  Tc *p_tc)
667 {
668  /* Validate inputs. */
669  Assert(p_tc);
670 
671  return p_tc->TC_QIMR;
672 }
673 
684  Tc *p_tc)
685 {
686  /* Validate inputs. */
687  Assert(p_tc);
688 
689  return p_tc->TC_QISR;
690 }
691 
692 #endif /* (!SAM4L && !SAMG) || defined(__DOXYGEN__) */
693 
694 #if (!SAM3U) || defined(__DOXYGEN__)
695 
705  Tc *p_tc,
706  uint32_t ul_enable)
707 {
708  /* Validate inputs. */
709  Assert(p_tc);
710 
711  if (ul_enable) {
713  } else {
715  }
716 }
717 
718 #endif /* (!SAM3U) || defined(__DOXYGEN__) */
719 
720 #if SAM4L || defined(__DOXYGEN__)
721 
731 uint32_t tc_get_feature(
732  Tc *p_tc)
733 {
734  /* Validate inputs. */
735  Assert(p_tc);
736 
737  return p_tc->TC_FEATURES;
738 }
739 
749 uint32_t tc_get_version(
750  Tc *p_tc)
751 {
752  /* Validate inputs. */
753  Assert(p_tc);
754 
755  return p_tc->TC_VERSION;
756 }
757 
758 #endif /* SAM4L || defined(__DOXYGEN__) */
759 
761 
762 #ifdef __cplusplus
763 }
764 #endif
765 
766 
__O uint32_t TC_QIER
(Tc Offset: 0xC8) QDEC Interrupt Enable Register
void tc_write_rc(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register C (RC) on the selected channel.
Definition: tc.c:326
#define UNUSED(v)
Marking v as a unused parameter or value.
Definition: compiler.h:86
uint32_t tc_read_rb(Tc *p_tc, uint32_t ul_channel)
Read TC Register B (RB) on the specified channel.
Definition: tc.c:247
uint32_t tc_get_qdec_interrupt_mask(Tc *p_tc)
Read TC QDEC interrupt mask.
Definition: tc.c:665
void tc_disable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
Disable TC QDEC interrupts.
Definition: tc.c:646
void tc_set_writeprotect(Tc *p_tc, uint32_t ul_enable)
Enable or disable write protection of TC registers.
Definition: tc.c:704
void tc_stop(Tc *p_tc, uint32_t ul_channel)
Stop the TC clock on the specified channel.
Definition: tc.c:187
SAM Timer Counter (TC) driver.
void tc_disable_interrupt(Tc *p_tc, uint32_t ul_channel, uint32_t ul_sources)
Disable TC interrupts on the specified channel.
Definition: tc.c:400
__IO uint32_t TC_RA
(TcChannel Offset: 0x14) Register A
__I uint32_t TC_CV
(TcChannel Offset: 0x10) Counter Value
uint32_t tc_read_cv(Tc *p_tc, uint32_t ul_channel)
Read the counter value on the specified channel.
Definition: tc.c:207
__I uint32_t TC_QIMR
(Tc Offset: 0xD0) QDEC Interrupt Mask Register
__O uint32_t TC_QIDR
(Tc Offset: 0xCC) QDEC Interrupt Disable Register
void tc_write_rb(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register B (RB) on the specified channel.
Definition: tc.c:306
#define TC_DIV_FACTOR
Definition: tc.c:461
void tc_start(Tc *p_tc, uint32_t ul_channel)
Start the TC clock on the specified channel.
Definition: tc.c:169
void tc_sync_trigger(Tc *p_tc)
Asserts a SYNC signal to generate a software trigger on all channels.
Definition: tc.c:103
#define FREQ_SLOW_CLOCK_EXT
Definition: tc.c:466
TcChannel hardware registers.
__IO uint32_t TC_SMMR
(TcChannel Offset: 0x8) Stepper Motor Mode Register
void tc_init(Tc *p_tc, uint32_t ul_channel, uint32_t ul_mode)
Configure TC for timer, waveform generation, or capture.
Definition: tc.c:70
__I uint32_t TC_IMR
(TcChannel Offset: 0x2C) Interrupt Mask Register
__I uint32_t TC_SR
(TcChannel Offset: 0x20) Status Register
uint32_t tc_read_ra(Tc *p_tc, uint32_t ul_channel)
Read TC Register A (RA) on the specified channel.
Definition: tc.c:227
__IO uint32_t TC_BMR
(Tc Offset: 0xC4) Block Mode Register
uint32_t tc_get_interrupt_mask(Tc *p_tc, uint32_t ul_channel)
Read the TC interrupt mask for the specified channel.
Definition: tc.c:423
__O uint32_t TC_CCR
(TcChannel Offset: 0x0) Channel Control Register
__IO uint32_t TC_RC
(TcChannel Offset: 0x1C) Register C
#define TC_CCR_CLKDIS
(TC_CCR) Counter Clock Disable Command
uint32_t tc_get_status(Tc *p_tc, uint32_t ul_channel)
Get the current status for the specified TC channel.
Definition: tc.c:445
void tc_write_ra(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register A (RA) on the specified channel.
Definition: tc.c:286
__I uint32_t TC_QISR
(Tc Offset: 0xD4) QDEC Interrupt Status Register
TcChannel TC_CHANNEL[TCCHANNEL_NUMBER]
(Tc Offset: 0x0) channel = 0 .. 2
#define TC_BCR_SYNC
(TC_BCR) Synchro Command
uint32_t tc_find_mck_divisor(uint32_t ul_freq, uint32_t ul_mck, uint32_t *p_uldiv, uint32_t *p_ultcclks, uint32_t ul_boardmck)
Find the best MCK divisor.
Definition: tc.c:487
#define TC_WPMR_WPKEY_PASSWD
Definition: tc.c:49
uint32_t tc_read_rc(Tc *p_tc, uint32_t ul_channel)
Read TC Register C (RC) on the specified channel.
Definition: tc.c:267
__IO uint32_t TC_RB
(TcChannel Offset: 0x18) Register B
void tc_enable_interrupt(Tc *p_tc, uint32_t ul_channel, uint32_t ul_sources)
Enable the TC interrupts on the specified channel.
Definition: tc.c:362
__O uint32_t TC_IDR
(TcChannel Offset: 0x28) Interrupt Disable Register
__IO uint32_t TC_CMR
(TcChannel Offset: 0x4) Channel Mode Register
void tc_enable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
Enable TC QDEC interrupts.
Definition: tc.c:617
#define TC_CCR_SWTRG
(TC_CCR) Software Trigger Command
#define TC_WPMR_WPEN
(TC_WPMR) Write Protection Enable
__IO uint32_t TC_WPMR
(Tc Offset: 0xE4) Write Protection Mode Register
__O uint32_t TC_IER
(TcChannel Offset: 0x24) Interrupt Enable Register
uint32_t tc_get_qdec_interrupt_status(Tc *p_tc)
Get current TC QDEC interrupt status.
Definition: tc.c:683
__O uint32_t TC_BCR
(Tc Offset: 0xC0) Block Control Register
void tc_set_block_mode(Tc *p_tc, uint32_t ul_blockmode)
Configure the TC Block mode.
Definition: tc.c:123
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:196
#define TC_CCR_CLKEN
(TC_CCR) Counter Clock Enable Command
uint32_t tc_init_2bit_gray(Tc *p_tc, uint32_t ul_channel, uint32_t ul_steppermode)
Configure TC for 2-bit Gray Counter for Stepper Motor.
Definition: tc.c:147


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58