d_timer.c
Go to the documentation of this file.
1 #include <asf.h>
2 #include <tc.h>
3 #include "d_timer.h"
4 #ifdef ENABLE_TC_WAVEFORM_INTERRUPT
5 #include "conf_interrupts.h"
6 #endif // ENABLE_TC_WAVEFORM_INTERRUPT
7 // #include "globals.h"
8 #include "misc/debug_gpio.h"
9 
10 #ifdef DEBUG
11 //#define TIMER_DEBUG
12 //#define TIMER_IO_DEBUG
13 #endif // DEBUG
14 
15 #ifdef TIMER_IO_DEBUG
16 #if (BOARD == SAME70_XPLAINED)
17 #define TIMER_PIN PIN_TC0_TIOA0
18 #elif (BOARD == USER_BOARD)
19 #define TIMER_PIN GPIO_8_PIN
20 #endif // BOARD
21 #endif // TIMER_IO_DEBUG
22 
23 // source based on example acquired from:
24 // https://github.com/avrxml/asf/blob/master/sam/drivers/tc/tc_capture_waveform_example
25 
26 
27 //----------------------------------------
28 // waveform mode
29 //----------------------------------------
30 // The last one is meaningless
31 static const uint32_t g_divisors[5] = { 2, 8, 32, 128, 0 };
32 static void (*g_wvf_callback)(void) = NULL;
33 static unsigned int g_wvf_channel;
34 
35 static void timer_io_enable(void)
36 {
37 #ifdef TIMER_IO_DEBUG
38 //#if (BOARD == SAME70_XPLAINED)
39 // ioport_set_pin_mode(PIN_TC0_TIOA0, PIN_TC0_TIOA0_MUX);
40 // ioport_disable_pin(PIN_TC0_TIOA0);
41 //#endif // BOARD
43  ioport_set_pin_level(TIMER_PIN, 0);
44 #endif // TIMER_IO_DEBUG
45 }
46 
47 
48 #ifdef ENABLE_TC_WAVEFORM_INTERRUPT
49 #ifdef TIMER_DEBUG
50 #include "d_time.h"
51 static uint32_t g_times[TC_SAMPLE_SENSORS_RATE_HZ+1];
52 
53 static inline void timer_report(void)
54 {
55  uint32_t k;
56  uint32_t sum = 0;
57  uint32_t diffs = 0;
58  uint32_t diff;
59 
60  for (k=1; k<TC_SAMPLE_SENSORS_RATE_HZ; k++)
61  {
62  if (g_times[k] > g_times[k-1])
63  {
64  sum += g_times[k] - g_times[k-1];
65  diffs++;
66  }
67  }
68  //printf("diffs=%04u sum=%u\r\n", (unsigned int)diffs, (unsigned int)sum);
69  printf("avg=%u us expected=%u us\r\n",
70  (unsigned int)((sum/TIME_TICKS_PER_US)/diffs),
71  (unsigned int)(1000000.0/(TC_SAMPLE_SENSORS_RATE_HZ*1.0)));
72  diff = g_times[TC_SAMPLE_SENSORS_RATE_HZ]-g_times[0];
73  printf("t0=%u t%d=%u diff=%u\r\n",
74  (unsigned int)g_times[0],
75  TC_SAMPLE_SENSORS_RATE_HZ,
76  (unsigned int)g_times[TC_SAMPLE_SENSORS_RATE_HZ],
77  (unsigned int)diff);
78 }
79 #endif // TIMER_DEBUG
80 
81 
82 static void timer_register_callback(void (*func)(void))
83 {
84  g_wvf_callback = func;
85 }
86 
87 
88 
90 {
92  {
96  if (g_wvf_callback)
97  (*g_wvf_callback)();
100  }
101 }
102 #endif // ENABLE_TC_WAVEFORM_INTERRUPT
103 
104 
105 void timer_waveform_init(unsigned int channel, void (*func)(void))
106 {
107  uint32_t ra, rc;
109 
110  g_wvf_channel = channel;
111  g_wvf_callback = func;
112 
113  timer_io_enable();
114 
115  // Configure the PMC to enable the TC module.
117 
118 #if SAMG55
119  // Enable PCK output
120  pmc_disable_pck(PMC_PCK_3);
121  pmc_switch_pck_to_mck(PMC_PCK_3, PMC_PCK_PRES(0));
122  pmc_enable_pck(PMC_PCK_3);
123 #endif // SAMG55
124 
125  // Init TC to waveform mode.
127  wvf.ul_intclock // Waveform Clock Selection
128  | TC_CMR_WAVE // Waveform mode is enabled
129  | TC_CMR_ACPA_SET // RA Compare Effect: set
130  | TC_CMR_ACPC_CLEAR // RC Compare Effect: clear
131  | TC_CMR_CPCTRG // UP mode with automatic trigger on RC Compare
132  );
133 
134  // Configure waveform frequency and duty cycle.
137  ra = (100 - wvf.us_dutycycle) * rc / 100;
139 
140 #ifdef ENABLE_TC_WAVEFORM_INTERRUPT
141  timer_register_callback(func);
148 #endif // ENABLE_TC_WAVEFORM_INTERRUPT
149 
150 #ifdef TIMER_DEBUG
151  printf("rc: %u, ra: %u\r\n", (unsigned int)rc, (unsigned int)ra);
152  printf("Start waveform: Frequency = %d Hz,Duty Cycle = %2d%%\n\r",
153  wvf.us_frequency, wvf.us_dutycycle);
154 #endif // TIMER_DEBUG
155 }
156 
157 
158 //----------------------------------------
159 // capture mode
160 //----------------------------------------
162 #ifdef ENABLE_TC_CAPTURE_INTERRUPT
163 static uint32_t g_captured;
164 extern void gps_sync_int_handler(int index, int addTimeSinceTrigger);
165 
166 
167 void TC_TIME_SYNC_HANDLER(void)
168 {
169  uint32_t status = tc_get_status(TC0, TC_TIME_SYNC_CHANNEL);
170 
171  if (status & TC_TIME_SYNC_IER_MASK)
172  {
173 #if 0
174  if (TC_CAPTURE_IER_MASK & TC_IER_LDRAS)
175  g_captured = tc_read_ra(TC0, TC_CAPTURE_CHANNEL);
176  else
177  g_captured = tc_read_cv(TC0, TC_CAPTURE_CHANNEL);
178 
179  if (!(g_nvmFlashCfg->sysCfgBits & SYS_CFG_BITS_DISABLE_LEDS) && g_sysParams.hStatus&HDW_STATUS_GPS_SATELLITE_RX)
180  {
181  LEDS_GPS_PULSE();
182  g_led.gps_timeMs = g_gpsTimeOfWeekMs;
183  }
184 #else
185  gps_sync_int_handler(0,1);
186 #endif // 0
187  }
188 }
189 #endif // ENABLE_TC_CAPTURE_INTERRUPT
190 
191 
193 {
194  if (!g_capture_initialized)
195  return -1;
196 
197 #ifdef ENABLE_TC_CAPTURE_INTERRUPT
198  tc_enable_interrupt(TC0, TC_TIME_SYNC_CHANNEL, TC_TIME_SYNC_IER_MASK);
199 #endif // ENABLE_TC_CAPTURE_INTERRUPT
201 
202  return 0;
203 }
204 
205 
207 {
208  if (!g_capture_initialized)
209  return -1;
210 
211 #ifdef ENABLE_TC_CAPTURE_INTERRUPT
212  tc_disable_interrupt(TC0, TC_TIME_SYNC_CHANNEL, TC_TIME_SYNC_IER_MASK);
213 #endif // ENABLE_TC_CAPTURE_INTERRUPT
215 
216  return 0;
217 }
218 
219 
221 {
222  if (g_capture_initialized)
223  return;
224 
225  // Configure the PMC to enable the TC module.
227 
228 #if SAMG55
229  // Enable PCK output
230  pmc_disable_pck(PMC_PCK_3);
231  pmc_switch_pck_to_mck(PMC_PCK_3, PMC_PCK_PRES(0));
232  pmc_enable_pck(PMC_PCK_3);
233 #endif // SAMG55
234 
235  // Init TC to capture mode.
237  TC_CMR_TCCLKS_TIMER_CLOCK2 // Clock Selection
238  | TC_CMR_LDRA_RISING // RA Loading: rising edge of TIOA
239  | TC_CMR_ABETRG // External Trigger: TIOA
240  | TC_CMR_ETRGEDG_RISING // External Trigger Edge: Rising edge
241  );
242 
243 #ifdef ENABLE_TC_CAPTURE_INTERRUPT
244  tc_disable_interrupt(TC0, TC_TIME_SYNC_CHANNEL, TC_TIME_SYNC_IER_MASK);
249  tc_enable_interrupt(TC0, TC_TIME_SYNC_CHANNEL, TC_TIME_SYNC_IER_MASK);
250 #endif // ENABLE_TC_CAPTURE_INTERRUPT
251 
253 
254  g_capture_initialized = 1;
255 }
256 
257 
258 uint32_t timer_captured(void)
259 {
260 #ifdef ENABLE_TC_CAPTURE_INTERRUPT
261  return g_captured;
262 #else
265 #endif // ENABLE_TC_CAPTURE_INTERRUPT
266 }
267 
268 
269 //----------------------------------------
270 // time timer
271 //----------------------------------------
272 static uint16_t g_rollover = 0;
273 
274 
275 void TC_TIME_HANDLER(void)
276 {
278  {
279  g_rollover++;
280  }
281 }
282 
283 
284 volatile uint64_t time_cv(void)
285 {
286  union
287  {
288  uint16_t u16[4];
289  uint64_t u64;
290  } ticks;
291 
292  ticks.u16[3] = g_rollover;
293  ticks.u16[2] = (uint16_t) tc_read_cv(TC3, 2);
294  ticks.u16[1] = (uint16_t) tc_read_cv(TC3, 1);
295  ticks.u16[0] = (uint16_t) tc_read_cv(TC3, 0);
296 
297  return ticks.u64;
298 }
299 
300 
301 static void time_channel_init(uint32_t channel, uint32_t intclock)
302 {
303  // Configure the PMC to enable the TC module.
305 
306  // Init TC to waveform mode.
307  tc_init(TC3, channel,
308  intclock // Waveform Clock Selection
309  | TC_CMR_WAVE // Waveform mode is enabled
310  | TC_CMR_WAVSEL_UP // WAVSEL = 00 without Trigger
311  | TC_CMR_ACPA_CLEAR // RA Compare Effect: clear
312  | TC_CMR_ACPC_SET // RC Compare Effect: set
313  | TC_CMR_CPCTRG // UP mode with automatic trigger on RC Compare
314  );
315 
316  // Configure waveform frequency and duty cycle.
317  tc_write_ra(TC3, channel, 0xFF);
318  tc_write_rc(TC3, channel, 0xFFFF);
319 }
320 
321 
322 void timer_time_init(void)
323 {
324 #ifdef ENABLE_TC_WAVEFORM_INTERRUPT
328 
330  TC_BMR_TC1XC1S_TIOA0 | // select TIOA0 as external clock signal for channel 1
331  TC_BMR_TC2XC2S_TIOA1); // select TIOA1 as external clock signal for channel 2
332 
333  // the last channel will generate an interrupt for rollover
340 
341  tc_start(TC3, 2);
342  tc_start(TC3, 1);
343  tc_start(TC3, 0);
344 
345  uint32_t previous_time = tc_read_cv(TC3, 0);
346  while (previous_time == tc_read_cv(TC3, 0));
347 #endif
348 }
static unsigned int g_wvf_channel
Definition: d_timer.c:33
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
static void timer_io_enable(void)
Definition: d_timer.c:35
uint32_t us_frequency
Definition: d_timer.h:47
static void ioport_set_pin_level(ioport_pin_t pin, bool level)
Set an IOPORT pin to a specified logical value.
Definition: ioport.h:275
void pmc_enable_pck(uint32_t ul_id)
Enable the specified programmable clock.
Definition: pmc.c:1020
#define TC0
(TC0 ) Base Address
Definition: same70j19.h:501
#define TC_CMR_TCCLKS_TIMER_CLOCK2
(TC_CMR) Clock selected: internal MCK/8 clock signal (from PMC)
void tc_stop(Tc *p_tc, uint32_t ul_channel)
Stop the TC clock on the specified channel.
Definition: tc.c:187
#define TC_CMR_TCCLKS_XC2
(TC_CMR) Clock selected: XC2
#define TC_CMR_ACPA_CLEAR
(TC_CMR) Clear
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
Set Interrupt Priority.
Definition: core_cm7.h:1766
#define TC_SAMPLE_SENSORS_RATE_HZ
Definition: d_timer.h:22
#define TC_IMR_CPCS
(TC_IMR) RC Compare
#define NULL
Definition: nm_bsp.h:52
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
static uint16_t g_rollover
Definition: d_timer.c:272
#define TC_IER_LDRAS
(TC_IER) RA Loading
static const uint32_t g_divisors[5]
Definition: d_timer.c:31
uint32_t tc_read_cv(Tc *p_tc, uint32_t ul_channel)
Read the counter value on the specified channel.
Definition: tc.c:207
#define TC_CMR_ETRGEDG_RISING
(TC_CMR) Rising edge
#define TC_CMR_WAVE
(TC_CMR) Waveform Mode
uint16_t us_dutycycle
Definition: d_timer.h:49
void tc_start(Tc *p_tc, uint32_t ul_channel)
Start the TC clock on the specified channel.
Definition: tc.c:169
void pmc_disable_pck(uint32_t ul_id)
Disable the specified programmable clock.
Definition: pmc.c:1030
#define TC_CMR_ACPC_CLEAR
(TC_CMR) Clear
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
Disable External Interrupt.
Definition: core_cm7.h:1696
#define TC_CMR_ACPA_SET
(TC_CMR) Set
void timer_time_init(void)
Definition: d_timer.c:322
#define TC_SAMPLE_SENSORS_ID
Definition: d_timer.h:19
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm7.h:1683
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
#define TC_CMR_WAVSEL_UP
(TC_CMR) UP mode without automatic trigger on RC Compare
#define printf(...)
Definition: evb_tasks.h:36
static int g_capture_initialized
Definition: d_timer.c:161
int timer_capture_disable(void)
Definition: d_timer.c:206
#define TC_TIME_SYNC_CHANNEL
Definition: d_timer.h:26
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
#define TC_CMR_CPCTRG
(TC_CMR) RC Compare Trigger Enable
void TC_TIME_HANDLER(void)
Definition: d_timer.c:275
#define TC_IER_CPCS
(TC_IER) RC Compare
static void(* g_wvf_callback)(void)
Definition: d_timer.c:32
#define TC_TIME_IRQn
Definition: d_timer.h:39
#define TC_CMR_LDRA_RISING
(TC_CMR) Rising edge of TIOA
volatile uint64_t time_cv(void)
Definition: d_timer.c:284
#define PMC_PCK_PRES(value)
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear Pending Interrupt.
Definition: core_cm7.h:1736
#define TC_TIME_CHANNEL
Definition: d_timer.h:37
#define TC_IDR_CPCS
(TC_IDR) RC Compare
#define TC_BMR_TC2XC2S_TIOA1
(TC_BMR) Signal connected to XC2: TIOA1
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
#define TC_BMR_TC1XC1S_TIOA0
(TC_BMR) Signal connected to XC1: TIOA0
static void time_channel_init(uint32_t channel, uint32_t intclock)
Definition: d_timer.c:301
uint32_t pmc_switch_pck_to_mck(uint32_t ul_id, uint32_t ul_pres)
Switch programmable clock source selection to mck.
Definition: pmc.c:1000
int timer_capture_enable(void)
Definition: d_timer.c:192
#define TC3
(TC3 ) Base Address
Definition: same70j19.h:515
static void ioport_set_pin_dir(ioport_pin_t pin, enum ioport_direction dir)
Set direction for a single IOPORT pin.
Definition: ioport.h:263
#define TC_TIME_SYNC_IRQn
Definition: d_timer.h:29
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
void timer_capture_init(void)
Definition: d_timer.c:220
#define TC_TIME_SYNC_HANDLER
Definition: d_timer.h:28
#define TC_SAMPLE_SENSORS_HANDLER
Definition: d_timer.h:20
#define INT_PRIORITY_TC
#define TIME_TICKS_PER_US
Definition: d_time.h:42
uint32_t timer_captured(void)
Definition: d_timer.c:258
static void sysclk_enable_peripheral_clock(uint32_t ul_id)
Enable a peripheral&#39;s clock.
Autogenerated API include file for the Atmel Software Framework (ASF)
void timer_waveform_init(unsigned int channel, void(*func)(void))
Definition: d_timer.c:105
#define TC_SAMPLE_SENSORS_CHANNEL
Definition: d_timer.h:18
void tc_set_block_mode(Tc *p_tc, uint32_t ul_blockmode)
Configure the TC Block mode.
Definition: tc.c:123
#define TC_CMR_ABETRG
(TC_CMR) TIOA or TIOB External Trigger Selection
#define TC_TIME_SYNC_IER_MASK
Definition: d_timer.h:30
#define TC_TIME_BASE_ID
Definition: d_timer.h:36
#define TC_CMR_ACPC_SET
(TC_CMR) Set
#define TC_SAMPLE_SENSORS_IRQn
Definition: d_timer.h:21
static uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module)
Retrieves the current rate in Hz of the Peripheral Bus clock attached to the specified peripheral...
#define TC_CMR_TCCLKS_XC1
(TC_CMR) Clock selected: XC1
uint32_t ul_intclock
Definition: d_timer.h:45
#define TC_TIME_SYNC_ID
Definition: d_timer.h:27


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