uC chip interface arduino  0.9.0
A interface for async and neuromrphic IC testing
Loading...
Searching...
No Matches
core_intervaltimer_samd21.cpp
Go to the documentation of this file.
1/*
2 This file is part of the Firmware project to interface with small Async or Neuromorphic chips
3 Copyright (C) 2023 Ole Richter - University of Groningen
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
19#if defined(ARDUINO_ARCH_SAMD)
20// hardcoded to 48MHz should check via F_CPU flag
22#include "core_ring_buffer.h"
23
24callfunction_t IntervalTimer::_TC5_callfunc = NULL;
25callfunction_t IntervalTimer::_TC4_callfunc = NULL;
26//TcCount16* IntervalTimer::TC[INTERVALTIMER_MAX_TIMERS] = {(TcCount16*) &(TC4->COUNT32),(TcCount16*) &(TC5->COUNT32)};
27bool IntervalTimer::counter_active[INTERVALTIMER_MAX_TIMERS] = {};
28
29
30bool IntervalTimer::begin(callfunction_t callback, uint32_t usec) volatile {
31 if (usec < 1431655765U) last_period = usec;
32 else {
33 // bigger range can be implemented by choosing scaling factors, @TODO on demand
34 // @todo replace source header with timer config once implemented for PWM/analog sampling
36 return false;
37 }
38 if (counter_id >= INTERVALTIMER_MAX_TIMERS){
39 noInterrupts();
40 counter_id = 0;
41 while (counter_id < INTERVALTIMER_MAX_TIMERS && counter_active[counter_id]){
42 counter_id++;
43 }
44 if (counter_id >= INTERVALTIMER_MAX_TIMERS){
45 interrupts();
46 return false;
47 }
48 counter_active[counter_id] = true;
49 interrupts();
50 }
51
52 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0
53 GCLK_CLKCTRL_ID_TC4_TC5 | // GCLK0 output to TC4, TC5
54 GCLK_CLKCTRL_GEN_GCLK0; // Select GCLK0 at CPU Speed
55
56
57 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for sync
58
59 uint32_t period = last_period*3;
60 switch (counter_id){
61 case 0:
62 TC4->COUNT32.CC[0].reg = period; // Set the TC CC0 register to stop value
63 while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
64 // set ISR
65 _TC4_callfunc = callback;
66 NVIC_DisableIRQ(TC4_IRQn);
67 NVIC_ClearPendingIRQ(TC4_IRQn);
68 NVIC_SetPriority(TC4_IRQn, last_priority); // Set Nested Vector Interrupt Controller priority
69 NVIC_EnableIRQ(TC4_IRQn);
70 TC4->COUNT32.INTENSET.bit.OVF = 1; // Enable overflow interrupt
71
72 TC4->COUNT32.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock
73 TC_CTRLA_WAVEGEN_MFRQ | // Mode to match frequency (MFRQ)
74 TC_CTRLA_PRESCALER_DIV16 | // Set prescaler to 16 , for 0.333us
75 TC_CTRLA_MODE_COUNT32; // Mode to 32-bit
76
77 while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
78
79 TC4->COUNT32.CTRLA.bit.ENABLE = 1; // Enable
80 while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
81 break;
82 case 1:
83 TC5->COUNT32.CC[0].reg = period; // Set the TC CC0 register to stop value
84
85 while (TC5->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
86
87 _TC5_callfunc = callback;
88 NVIC_DisableIRQ(TC5_IRQn);
89 NVIC_ClearPendingIRQ(TC5_IRQn);
90 NVIC_SetPriority(TC5_IRQn, last_priority); // Set Nested Vector Interrupt Controller priority
91 NVIC_EnableIRQ(TC5_IRQn);
92
93 TC5->COUNT32.INTENSET.bit.OVF = 1; // Enable overflow interrupt
94
95 TC5->COUNT32.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock
96 TC_CTRLA_WAVEGEN_MFRQ | // Mode to match frequency (MFRQ)
97 TC_CTRLA_PRESCALER_DIV16 | // Set prescaler to 16 , for 0.333us
98 TC_CTRLA_MODE_COUNT32; // Mode to 32-bit
99
100 while (TC5->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
101
102 TC5->COUNT32.CTRLA.bit.ENABLE = 1; // Enable
103 while (TC5->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
104 break;
105 }
106 return true;
107}
108
109void IntervalTimer::update(uint32_t usec) volatile{
110 if (usec < 21845U) last_period = usec;
111 else {
112 // bigger range can be implemented by choosing scaling factors, @TODO on demand
113 // @todo replace source header with timer config once implemented for PWM/analog sampling
115 return;
116 }
117 switch(counter_id){
118 case 0:
119 begin(_TC4_callfunc,last_period);
120 break;
121 case 1:
122 begin(_TC5_callfunc,last_period);
123 break;
124 default:
125 return;
126 }
127}
128void IntervalTimer::end() volatile {
129 if (counter_id < INTERVALTIMER_MAX_TIMERS){
130 switch (counter_id){
131 case 0:
132 TC4->COUNT32.CTRLA.bit.ENABLE = 0; // Disable
133 while (TC4->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
134 counter_id=INTERVALTIMER_MAX_TIMERS;
135 break;
136 case 1:
137 TC5->COUNT32.CTRLA.bit.ENABLE = 0; // Disable
138 while (TC5->COUNT32.STATUS.bit.SYNCBUSY); // Wait for sync
139 counter_id=INTERVALTIMER_MAX_TIMERS;
140 break;
141 }
142
143 }
144}
145void IntervalTimer::priority(uint8_t priority) volatile {
146 if (priority > 3) {
147 last_priority = priority;
148 //NVIC_SetPriority(EIC_IRQn, 2);
149 }
150 else last_priority = priority;
151 update(last_period);
152}
153
154void TC4_Handler()
155{
156 TC4->COUNT32.INTFLAG.bit.OVF = 1; // Clear OVF flag
157 if (IntervalTimer::_TC4_callfunc != NULL) IntervalTimer::_TC4_callfunc();
158 //if (TC4->COUNT32.INTFLAG.bit.OVF && TC4->COUNT32.INTENSET.bit.OVF) {
159 //TC4->COUNT32.INTFLAG.bit.OVF = 1; // Clear OVF flag
160 //}
161}
162
163void TC5_Handler()
164{
165 TC5->COUNT32.INTFLAG.bit.OVF = 1; // Clear OVF flag
166 if (IntervalTimer::_TC5_callfunc != NULL) IntervalTimer::_TC5_callfunc();
167 //if (TC5->COUNT32.INTFLAG.bit.OVF && TC5->COUNT32.INTENSET.bit.OVF){
168 //TC5->COUNT32.INTFLAG.bit.OVF = 1; // Clear OVF flag
169 //}
170}
171#endif
void error_message(uint8_t error_header, uint8_t source_header, uint32_t value, uint8_t sub_source_header)
@ OUT_ERROR
Definition: datatypes.h:522
@ OUT_ERROR_CONFIGURATION_OUT_OF_BOUNDS
Definition: datatypes.h:579