DIY Auto-Correlator 1.0
Auto-Correlator Card implementation using Teensy 4.x microcontrollers.
qtmr1.hpp
Go to the documentation of this file.
1#pragma once
2#include "errors.hpp"
3
4#define _TMR1_CONTROLLER_CH_ 0
5
8{
9private:
10 static constexpr bool Singleton_flag = false;
11public:
12
13 //0
16 {
17 static_assert((_TMR1_CONTROLLER_CH_ <= 2 && _TMR1_CONTROLLER_CH_ >= 0),
18 "TMR1Controller: CHID is invalid (try <= 2).");
19 //_assert_(!Singleton_flag, "TMR1Controller: The resource is already constructed."); //Assert Singleton
20 }
21
22 //1
24 void start() __attribute__((always_inline))
25 {
26 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CTRL |= TMR_CTRL_CM(1); //Set (001)
27 }
28
29 //2
31 void stop() __attribute__((always_inline))
32 {
33 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CTRL |= TMR_CTRL_CM(0); //Set (000)
34 }
35
36 //3
38 void reset() __attribute__((always_inline))
39 {
40 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CNTR = 0; //Reset Counter to 0.
41 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CAPT = 0; //Reset Capture Register
42 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL &= ~TMR_SCTRL_IEF; //Write zero to the Input Edge Flag
43 }
44
45 //4
48 {
49 return (IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CAPT);
50 }
51
52
53 //5
56 {
57 return (this->is_overflow() * 65535) + (this->get_capture_val());
58 }
59
60
61 //6
63 bool is_overflow() __attribute__((always_inline))
64 {
65 return ((IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL & TMR_SCTRL_TOF) != 0);
66 }
67
68
69 //7
70 /*Input Edge Flag - This bit is set when CAPTMODE is enabled and a proper input transition occurs (on an input selected as a secondary count source) while the count mode does not equal 000. This bit is cleared by writing a zero to this bit position. This bit can also be cleared automatically by a read of CAPT when DMA[IEFDE] is set.*/
71
72 /* @brief Clear `Input Edge Flag` - which indicates a Capture Event. */
73 void clear_input_edge_flag() __attribute__((always_inline))
74 {
75 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL &= ~TMR_SCTRL_IEF; //Unset
76 }
77
78
79 //8
80 /* @brief Clears the overflow flag. */
81 void clear_overflow_flag() __attribute__((always_inline))
82 {
83 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL &= ~TMR_SCTRL_TOF; //Unset
84 }
85
86
87 //9
90 int get_ttl_input_pin() __attribute__((always_inline))
91 {
92 #if _TMR1_CONTROLLER_CH_ == 0
93 return 10; //Assigned to CH0
94 #elif _TMR1_CONTROLLER_CH_ == 1
95 return 12; //Assigned to CH1
96 #elif _TMR1_CONTROLLER_CH_ == 2
97 return 11; //Assigned to CH2
98 #elif _TMR1_CONTROLLER_CH_ == 3
99 static_assert(false, "This Channel has no IO Pin");
100 return SAFE_INPUT_DUMP_PIN;
101 #endif
102 }
103
104
105 //10
106 /* @brief Initalise the counter and set registers for counting. */
107 void init() __attribute__((always_inline))
108 {
109
110 //A. Control Register setup → TMR1_CTRL1 (16-bit register) ----------------------------------------------------------
111
112 //0. Un-set the whole register that sets Counting mode as "No operation" → 0 [Disable Timer] (3 bit field)
113 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CTRL = 0;
114
115
116 //2. Set Primary Count Source as "Counter #_TMR1_CONTROLLER_CH_ input pin"
117 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CTRL |= TMR_CTRL_PCS(_TMR1_CONTROLLER_CH_);
118
119 //3. Set Secondary Count Source "CAPTURE SIGNAL PIN" to _TMR1_CONTROLLER_CH_ + 1 → The pin of the next successive channel.
120 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CTRL |= TMR_CTRL_SCS(_TMR1_CONTROLLER_CH_ + 1);
121
122 //→ Rest of the Bitfields are set to zero (those modes are the required modes.
123
124
125 //Timer Channel Status and Control Register
126 //B. (TMR1_SCTRL1) Register (16-Bit) -------------------------------------------
127
128 //0. Set Everything to zero
129 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL = 0;
130
131 //1. These bits specify the operation of the capture register as well as the operation of the input edge flag. The input source is the secondary count source. "01 Load capture register on rising edge (when IPS=0) or falling edge (when IPS=1) of input"
132 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].SCTRL |= TMR_SCTRL_CAPTURE_MODE(1);
133
134 //OEN Output Enable (Output Pin Mode selection) - {0-Input-SCS, 1-OFLAG output}
135
136 //Set the Next channel's external pin as an input pin (unset)
137 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_ + 1].SCTRL &= TMR_SCTRL_OEN;
138
139
140 //C. TMR1_CSCTRL1 Timer Channel Comparator Status and Control Register ----------------------------------------------------------------------
141
142 //0. Reset Register
143 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CSCTRL = 0;
144
145 //1. Reload on Capture - This bit enables the capture function to cause the counter to be reloaded from the LOAD register. → 1 Reload the counter on a capture event.
146 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CSCTRL |= TMR_CSCTRL_ROC; //Set Bit
147
148
149 //D. Timer Channel Input Filter Register (TMR1_FILT1) -----------------------------------------------------
150
151 //1. → Zero values disables input filtering.
152 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].FILT = 0;
153
154 //E. Timer Channel DMA Enable Register (TMRx_DMAn) ---------------------------------------------------
155
156 //Input Edge Flag DMA Enable
157 //1. Setting this bit enables DMA read requests for CAPT when SCTRL[IEF] is set. This also unsets the SCTRL[IEF] automatically.
158 //IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].DMA |= TMR_DMA_IEFDE; // ATTENTION
159
160
161 //F. TMR1_LOAD1 -> Timer Channel Load Register -----------------------------------------------
162 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].LOAD = 0; //Set value to zero (For upcounting)
163
164
165 //G. Timer Channel Counter Register (TMR1_CNTR1) -------------------------------------------------
166 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CNTR = 0; //Set value to zero (For upcounting)
167
168 //H. Timer Channel Capture Register (TMR1_CAPT1) ------------------------------------------------
169 IMXRT_TMR1.CH[_TMR1_CONTROLLER_CH_].CAPT = 0; //Reset
170
171
172 //I. Timer Channel Enable Register (TMR1_ENBL) -----------------------------------------------
173
174 //1. Setting the corresponding Bits enables the corresponding channels
175 IMXRT_TMR1.ENBL |= (1 << _TMR1_CONTROLLER_CH_);
176
177 asm volatile ("dsb");
178
179 } //End of init()
180
181
182 //11
185 void init_pins() __attribute__((always_inline))
186 {
187 #if _TMR1_CONTROLLER_CH_ == 0
188 IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 = 1; //Assign IOPAD for CH0
189 IOMUXC_GPR_GPR6 |= IOMUXC_GPR_GPR6_QTIMER1_TRM1_INPUT_SEL; //Set CH1 input to XBAR
190 #elif _TMR1_CONTROLLER_CH_ == 1
191 IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 1; //Assign IOPAD for CH1
192 IOMUXC_GPR_GPR6 |= IOMUXC_GPR_GPR6_QTIMER1_TRM2_INPUT_SEL; //Set CH2 input to XBAR
193 #elif _TMR1_CONTROLLER_CH_ == 2
194 IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 1; //Assign IOPAD to CH2
195 IOMUXC_GPR_GPR6 |= IOMUXC_GPR_GPR6_QTIMER1_TRM3_INPUT_SEL; //Set CH3 input to XBAR
196 #elif _TMR1_CONTROLLER_CH_ == 3
197 static_assert(false, "This Channel has no IO Pin");
198 #endif
199
200 asm volatile ("dsb");
201 }
202
203 //12
206 unsigned int get_xbar_out_pin() __attribute__((always_inline))
207 {
208 #if _TMR1_CONTROLLER_CH_ == 0
209 return 87; //Return CH1's pin
210 #elif _TMR1_CONTROLLER_CH_ == 1
211 return 88; //Return CH2's pin
212 #elif _TMR1_CONTROLLER_CH_ == 2
213 return 89; //Return CH3's pin
214 #elif _TMR1_CONTROLLER_CH_ == 3
215 static_assert(false, "This Channel does not have an assigned capture pin. ");
216 return 133; //Any out-pin greater than 132 is invalid and ignored.
217 #endif
218 }
219
220
221 //13 → Use with caution
225 {
226 #if _TMR1_CONTROLLER_CH_ == 0
227 return 12; //Assigned to CH1
228 #elif _TMR1_CONTROLLER_CH_ == 1
229 return 11; //Assigned to CH2
230 #elif _TMR1_CONTROLLER_CH_ == 2
231 return 10; //Assigned to CH0
232 #elif _TMR1_CONTROLLER_CH_ == 3
233 static_assert(false, "This Channel has no TTL Pin");
234 return SAFE_INPUT_DUMP_PIN;
235 #endif
236 }
237
238
239 //14
242 void static timers_freeze() __attribute__((always_inline))
243 {
244 IOMUXC_GPR_GPR2 |= IOMUXC_GPR_GPR2_QTIMER1_TMR_CNTS_FREEZE; //Set Bit
245 }
246
247
248 //15
251 void static timers_anti_freeze() __attribute__((always_inline))
252 {
253 IOMUXC_GPR_GPR2 &= ~IOMUXC_GPR_GPR2_QTIMER1_TMR_CNTS_FREEZE; //Unset Bit
254 }
255
256};
257
Templated interface for Quad Timer 1 channels for Gate Counting. The module uses the macro _TMR1_CONT...
Definition: qtmr1.hpp:8
bool is_overflow() __attribute__((always_inline))
Returns the overflow status of the Counter. Reads the TOF - Timer Overflow Flag.
Definition: qtmr1.hpp:63
int get_ttl_input_pin() __attribute__((always_inline))
Returns the pin number on which the TTL input must be connected.
Definition: qtmr1.hpp:90
void init_pins() __attribute__((always_inline))
Sets the Primary and Secondary inputs for Capture Mode, routed through XBAR. Reference XBAR and IOMUX...
Definition: qtmr1.hpp:185
counter_t get_capture_double_range() __attribute__((flatten
Returns a value that has range (2 X 2**n - 1). This is done by checking the overflow flag.
counter_t get_capture_val() __attribute__((always_inline))
Reads and returns the Capture Register.
Definition: qtmr1.hpp:47
int get_extern_capture_signal_pin()
Returns the pin number on which the capture signal must be connected.
Definition: qtmr1.hpp:224
static constexpr bool Singleton_flag
Singleton template.
Definition: qtmr1.hpp:10
unsigned int get_xbar_out_pin() __attribute__((always_inline))
Returns the corresponding XBAR Output Pin to use for routing the Capture Signal. Reference Manual Pag...
Definition: qtmr1.hpp:206
void start() __attribute__((always_inline))
Starts up-counting from the set counter value.
Definition: qtmr1.hpp:24
void clear_overflow_flag() __attribute__((always_inline))
Definition: qtmr1.hpp:81
static void timers_freeze() __attribute__((always_inline))
Reset Counter and output flags. Reference Manual Page 332.
Definition: qtmr1.hpp:242
void clear_input_edge_flag() __attribute__((always_inline))
Definition: qtmr1.hpp:73
static void timers_anti_freeze() __attribute__((always_inline))
Enable counting normally. Reference Manual Page 332.
Definition: qtmr1.hpp:251
counter_t always_inline
Definition: qtmr1.hpp:56
void reset() __attribute__((always_inline))
Resets the counter to zero. It also cleares the capture register and unsets the Input Edge Flag.
Definition: qtmr1.hpp:38
TMR1Controller()
Default Constructor that assers if the user constructed object with a valid TMR1_CONTROLLER_CH,...
Definition: qtmr1.hpp:15
void init() __attribute__((always_inline))
Definition: qtmr1.hpp:107
void stop() __attribute__((always_inline))
Stops counting and freezes the current counter value.
Definition: qtmr1.hpp:31
const int SAFE_INPUT_DUMP_PIN
Definition: pins.hpp:14
#define _TMR1_CONTROLLER_CH_
Definition: qtmr1.hpp:4
uint32_t counter_t
Data type received from the pulse counter. It is the fundamental type used for representing series da...
Definition: types.hpp:7