REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
mode.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
4
5#include <Arduino.h>
6#include <FlexIO_t4.h>
7
8#include <mode/counters.h>
9#include <mode/mode.h>
10#include <mode/teensy/mode.h>
11#include <utils/factorize.h>
12#include <utils/logging.h>
13
14bool mode::is_global_overload_active() {
15 // TODO: This is probably inverted.
16 return digitalReadFast(PIN_MODE_OVERLOAD);
17}
18
19void mode::ManualControl::init() {
20 digitalWriteFast(PIN_MODE_IC, HIGH);
21 digitalWriteFast(PIN_MODE_OP, HIGH);
22 pinMode(PIN_MODE_IC, OUTPUT);
23 pinMode(PIN_MODE_OP, OUTPUT);
24 digitalWriteFast(PIN_MODE_IC, HIGH);
25 digitalWriteFast(PIN_MODE_OP, HIGH);
26}
27
28void mode::ManualControl::to_ic() {
29 digitalWriteFast(PIN_MODE_OP, HIGH);
30 digitalWriteFast(PIN_MODE_IC, LOW);
31 mode::PerformanceCounter::get().to(mode::Mode::IC);
32}
33
34void mode::ManualControl::to_op() {
35 digitalWriteFast(PIN_MODE_IC, HIGH);
36 digitalWriteFast(PIN_MODE_OP, LOW);
37 mode::PerformanceCounter::get().to(mode::Mode::OP);
38}
39
40void mode::ManualControl::to_halt() {
41 digitalWriteFast(PIN_MODE_IC, HIGH);
42 digitalWriteFast(PIN_MODE_OP, HIGH);
43 mode::PerformanceCounter::get().to(mode::Mode::HALT);
44}
45
46void mode::RealManualControl::enable() {
50 }
51 }
52}
53
54void mode::RealManualControl::disable() {
58 } else {
59 // this should not happen.
60 }
61 }
62}
63
64void mode::RealManualControl::to_ic() {
65 enable();
68 } else {
69 mode::ManualControl::to_ic();
70 }
71}
72
73void mode::RealManualControl::to_op() {
74 enable();
77 } else {
78 mode::ManualControl::to_op();
79 }
80}
81
82void mode::RealManualControl::to_halt() {
83 enable();
86 } else {
87 mode::ManualControl::to_halt();
88 }
89}
90
91// storage and default values for static class members
92bool mode::FlexIOControl::_is_initialized = false;
93bool mode::FlexIOControl::_is_enabled = false;
94
95bool mode::FlexIOControl::init(unsigned long long ic_time_ns, unsigned long long op_time_ns,
96 mode::OnOverload on_overload, mode::OnExtHalt on_ext_halt,
97 SyncConfig sync_config) {
98
99 // Initialize and reset QTMR
102
103 // Get FlexIO handler for initialization
104 auto flexio = FlexIOHandler::flexIOHandler_list[2];
105
106 // Set clock settings
107 // For (3, 0, 0) the clock frequency is 480'000'000
108 flexio->setClockSettings(CLK_SEL, 1, 1);
109 auto CLK_FREQ = flexio->computeClockRate();
110 auto CLK_FREQ_MHz = CLK_FREQ / 1'000'000;
111 // Enable fast access?
112 // flexio->port().CTRL |= FLEXIO_CTRL_FASTACC;
113
114 //
115 // Configure IDLE and SYNC
116 //
117
118 if (!sync_config.enabled) {
119 flexio->port().TIMCTL[t_sync_clk] = 0;
120 flexio->port().TIMCFG[t_sync_clk] = 0;
121 flexio->port().TIMCMP[t_sync_clk] = 0;
122 flexio->port().SHIFTCTL[z_sync_match] = 0;
123 flexio->port().SHIFTCFG[z_sync_match] = 0;
124 flexio->port().SHIFTBUF[z_sync_match] = 0;
125 flexio->port().TIMCTL[t_sync_trigger] = 0;
126 flexio->port().TIMCFG[t_sync_trigger] = 0;
127 flexio->port().TIMCMP[t_sync_trigger] = 0;
128
129 flexio->port().SHIFTCTL[s_idle] = FLEXIO_SHIFTCTL_PINCFG(3) | FLEXIO_SHIFTCTL_SMOD_STATE;
130 flexio->port().SHIFTBUF[s_idle] = FLEXIO_STATE_SHIFTBUF(0b11111111, s_idle);
131 }else{
132 // Get internal FlexIO pins from external pins
133 uint8_t _sck_flex_pin = flexio->mapIOPinToFlexPin(PIN_SYNC_CLK);
134 if (_sck_flex_pin == 0xff)
135 return false;
136
137 // Configure a timer to track signal of PIN_SYNC_CLK
138 flexio->port().TIMCTL[t_sync_clk] = FLEXIO_TIMCTL_PINSEL(_sck_flex_pin) | FLEXIO_TIMCTL_TIMOD(1);
139 flexio->port().TIMCFG[t_sync_clk] = FLEXIO_TIMCFG_TIMOUT(1) | FLEXIO_TIMCFG_TIMDEC(2);
140 flexio->port().TIMCMP[t_sync_clk] = 0x0000'FF'00;
141
142 // Select a shifter for monitoring PIN_SYNC_ID
143 auto _flexio_pin_data_in = flexio->mapIOPinToFlexPin(PIN_SYNC_ID);
144 if (_flexio_pin_data_in == 0xff)
145 return false;
146 // Configure the shifter into continuous match mode, monitoring SYNC_CLK_ID
147 flexio->port().SHIFTCTL[z_sync_match] = FLEXIO_SHIFTCTL_TIMSEL(t_sync_clk) |
148 FLEXIO_SHIFTCTL_PINSEL(_flexio_pin_data_in) |
149 FLEXIO_SHIFTCTL_SMOD(0b101);
150 flexio->port().SHIFTCFG[z_sync_match] = 0;
151 // Set compare value in SHIFTBUF[31:16] and mask in SHIFTBUF[15:0] (1=mask, 0=no mask)
152 // flexio->port().SHIFTBUF[z_sync_match] = 0b00010101'00001111'00000000'00000000;
153 flexio->port().SHIFTBUFBIS[z_sync_match] = 0b00000000'00000000'11110000'00000000 | sync_config.id;
154
155 // Get a timer which is enabled when there is a match
156 // Configure timer
157 flexio->port().TIMCTL[t_sync_trigger] =
158 FLEXIO_TIMCTL_TRGSEL(4 * z_sync_match + 1) | FLEXIO_TIMCTL_TRGSRC | FLEXIO_TIMCTL_TIMOD(1);
159 flexio->port().TIMCFG[t_sync_trigger] = FLEXIO_TIMCFG_TIMDIS(2) | FLEXIO_TIMCFG_TIMENA(6);
160 flexio->port().TIMCMP[t_sync_trigger] = 0x0000'01'00;
161
162 flexio->port().SHIFTCTL[s_idle] =
163 FLEXIO_SHIFTCTL_TIMSEL(t_sync_trigger) | FLEXIO_SHIFTCTL_PINCFG(3) | FLEXIO_SHIFTCTL_SMOD_STATE;
164 flexio->port().SHIFTBUF[s_idle] = FLEXIO_STATE_SHIFTBUF(0b11111111, s_ic);
165 }
166 flexio->port().SHIFTCFG[s_idle] = 0;
167
168 //
169 // Configure state check timer
170 //
171
172 // Some states are changed not by timer triggers, but by continuously checking of the inputs
173 // Configure state change check timer as fast as possible
174 flexio->port().TIMCTL[t_state_check] = FLEXIO_TIMCTL_TIMOD(3);
175 flexio->port().TIMCFG[t_state_check] = FLEXIO_TIMCFG_TIMDIS(0) | FLEXIO_TIMCFG_TIMENA(0);
176 flexio->port().TIMCMP[t_state_check] = 0x0000'0001;
177
178 //
179 // Configure IC state
180 //
181
182 // Sanity check
183 if (ic_time_ns < 100) {
184 LOG_ERROR("FlexIOControl: ic_time_ns < 100 not implemented.");
185 return false;
186 }
187
188 // We split counting to two chained timers
189 auto factors = utils::factorize(ic_time_ns * CLK_FREQ_MHz / 1000);
190 if (factors.first >= 1 << 16 || factors.second >= 1 << 16) {
191 // Factor even is too big for two cascaded timers
192 LOG_ERROR("FlexIOControl: Requested ic_time_ns cannot be represented by 32bit.");
193 return false;
194 }
195
196 // Configure state timer
197 flexio->port().TIMCTL[t_ic] =
198 FLEXIO_TIMCTL_TRGSEL_STATE(s_ic) | FLEXIO_TIMCTL_TIMOD(3) | FLEXIO_TIMCTL_PINPOL;
199 flexio->port().TIMCFG[t_ic] = FLEXIO_TIMCFG_TIMRST(6) | FLEXIO_TIMCFG_TIMDIS(6) | FLEXIO_TIMCFG_TIMENA(6);
200 flexio->port().TIMCMP[t_ic] = factors.first - 1;
201 // Configure second timer
202 flexio->port().TIMCTL[t_ic_second] = FLEXIO_TIMCTL_TRGSEL(4 * t_ic + 3) | FLEXIO_TIMCTL_TRGSRC |
203 FLEXIO_TIMCTL_TIMOD(3) | FLEXIO_TIMCTL_PINCFG(3) |
204 FLEXIO_TIMCTL_PINSEL(17);
205 flexio->port().TIMCFG[t_ic_second] = FLEXIO_TIMCFG_TIMDEC(1) | FLEXIO_TIMCFG_TIMRST(0) |
206 FLEXIO_TIMCFG_TIMDIS(1) | FLEXIO_TIMCFG_TIMENA(1) |
207 FLEXIO_TIMCFG_TIMOUT(1);
208 flexio->port().TIMCMP[t_ic_second] = factors.second;
209 //}
210
211 // Configure state shifter
212 flexio->port().SHIFTCTL[s_ic] = FLEXIO_SHIFTCTL_TIMSEL(t_state_check) | FLEXIO_SHIFTCTL_PINCFG(3) |
213 FLEXIO_SHIFTCTL_PINSEL(15) | FLEXIO_SHIFTCTL_SMOD_STATE;
214 flexio->port().SHIFTCFG[s_ic] = 0;
215 flexio->port().SHIFTBUF[s_ic] =
216 FLEXIO_STATE_SHIFTBUF(0b11101111, s_ic, s_ic, s_ic, s_ic, s_op, s_op, s_op, s_op);
217
218 //
219 // Configure OP state.
220 //
221 // State changes are triggered continuously as fast as possible,
222 // but we only leave OP when the correct input is set.
223 //
224
225 // Sanity check
226 if (op_time_ns < 100) {
227 LOG_ERROR("FlexIOControl: op_time_ns < 100 not implemented.");
228 return false;
229 }
230
231 // Configure a timer to set an input pin high, signaling end of op_time
232 if (op_time_ns < 0xFFFFull * 1000ull / CLK_FREQ_MHz) {
233 // One 16bit timer is enough actually
234 flexio->port().TIMCTL[t_op] = FLEXIO_TIMCTL_TRGSEL_STATE(s_op) | FLEXIO_TIMCTL_TIMOD(3) |
235 FLEXIO_TIMCTL_PINCFG(3) | FLEXIO_TIMCTL_PINSEL(12);
236 flexio->port().TIMCFG[t_op] = FLEXIO_TIMCFG_TIMRST(6) | FLEXIO_TIMCFG_TIMDIS(0b110) |
237 FLEXIO_TIMCFG_TIMENA(6) | FLEXIO_TIMCFG_TIMOUT(1);
238 flexio->port().TIMCMP[t_op] = op_time_ns * CLK_FREQ_MHz / 1000;
239
240 // Reset second timer used when going towards higher op_times
241 flexio->port().TIMCTL[t_op_second] = 0;
242 flexio->port().TIMCFG[t_op_second] = 0;
243 flexio->port().TIMCMP[t_op_second] = 0;
244 } else {
245 // Configure first timer as pre-scaler
246 // But we want to pre-scale as much as possible, even though we then lose resolution
247 // But for op times in the range of seconds, we don't need microseconds resolution
248
249 auto factors = utils::factorize(op_time_ns * CLK_FREQ_MHz / 1000);
250 if (factors.first >= 1 << 16 || factors.second >= 1 << 16) {
251 // Factor is too big for two cascaded timers
252 LOG_ERROR("FlexIOControl: Requested op_time_ns cannot be represented by 32bit.");
253 return false;
254 }
255
256 flexio->port().TIMCTL[t_op] =
257 FLEXIO_TIMCTL_TRGSEL_STATE(s_op) | FLEXIO_TIMCTL_TIMOD(3) | FLEXIO_TIMCTL_PINPOL;
258 flexio->port().TIMCFG[t_op] =
259 FLEXIO_TIMCFG_TIMRST(6) | FLEXIO_TIMCFG_TIMDIS(0b110) | FLEXIO_TIMCFG_TIMENA(6);
260 flexio->port().TIMCMP[t_op] = factors.first - 1;
261 // Configure second timer for 32bit total
262 flexio->port().TIMCTL[t_op_second] = FLEXIO_TIMCTL_TRGSEL(4 * t_op + 3) | FLEXIO_TIMCTL_TRGSRC |
263 FLEXIO_TIMCTL_TIMOD(3) | FLEXIO_TIMCTL_PINCFG(3) |
264 FLEXIO_TIMCTL_PINSEL(12);
265 flexio->port().TIMCFG[t_op_second] = FLEXIO_TIMCFG_TIMDEC(1) | FLEXIO_TIMCFG_TIMRST(0) |
266 FLEXIO_TIMCFG_TIMDIS(1) | FLEXIO_TIMCFG_TIMENA(1) |
267 FLEXIO_TIMCFG_TIMOUT(1);
268 flexio->port().TIMCMP[t_op_second] = factors.second;
269 }
270
271 // Configure state shifter
272 flexio->port().SHIFTCTL[s_op] = FLEXIO_SHIFTCTL_TIMSEL(t_state_check) | FLEXIO_SHIFTCTL_PINCFG(3) |
273 FLEXIO_SHIFTCTL_PINSEL(10) | FLEXIO_SHIFTCTL_SMOD_STATE;
274 flexio->port().SHIFTCFG[s_op] = 0;
275 // Next state after OP depends on FlexIO inputs 10 (0 if overload), 11 (0 if exthalt), 12 (1 if op time over)
276 // Check with priority op-time-over > overload > ext halt
277 // Comments are t/T whether op-time-over, o/O whether overload active, e/E wether ext halt is true
278 uint8_t next_if_overload_and_exthalt = s_op, next_if_overload = s_op, next_if_exthalt = s_op;
279 switch (on_ext_halt) {
280 case OnExtHalt::IGNORE:
281 next_if_exthalt = s_op;
282 break;
283 case OnExtHalt::PAUSE_THEN_RESTART:
284 next_if_exthalt = s_exthalt;
285 break;
286 }
287 switch (on_overload) {
288 case OnOverload::IGNORE:
289 next_if_overload = s_op;
290 next_if_overload_and_exthalt = next_if_exthalt;
291 break;
292 case OnOverload::HALT:
293 next_if_overload = s_overload;
294 next_if_overload_and_exthalt = s_overload;
295 break;
296 }
297 flexio->port().SHIFTBUF[s_op] = FLEXIO_STATE_SHIFTBUF(0b11011111, // Inputs [12-11-10]
298 next_if_overload_and_exthalt, // [0-0-0] = [t-E-O]
299 next_if_exthalt, // [0-0-1] = [t-E-o]
300 next_if_overload, // [0-1-0] = [t-e-O]
301 s_op, // [0-1-1] = [t-e-o]
302 s_end, // [1-0-0] = [T-E-O]
303 s_end, // [1-0-1] = [T-E-o]
304 s_end, // [1-1-0] = [T-e-O]
305 s_end // [1-1-1] = [T-e-o]
306 );
307
308 //
309 // Configure END state.
310 //
311
312 flexio->port().SHIFTCTL[s_end] = FLEXIO_SHIFTCTL_PINCFG(3) | FLEXIO_SHIFTCTL_SMOD_STATE;
313 flexio->port().SHIFTCFG[s_end] = 0;
314 flexio->port().SHIFTBUF[s_end] = FLEXIO_STATE_SHIFTBUF(0b11111111, s_end);
315
316 //
317 // Configure OVERLOAD state.
318 //
319
320 flexio->port().SHIFTCTL[s_overload] = FLEXIO_SHIFTCTL_PINCFG(3) | FLEXIO_SHIFTCTL_SMOD_STATE;
321 flexio->port().SHIFTCFG[s_overload] = 0;
322 flexio->port().SHIFTBUF[s_overload] = FLEXIO_STATE_SHIFTBUF(0b11111111, s_overload);
323
324 //
325 // Configure EXT HALT state.
326 //
327
328 // EXT HALT is a paused state which resumes as soon as the signal is no longer active.
329 // But "resuming" is only partially correct, since the full op time is restarted.
330 // Thus, the OP state after EXT HALT runs for the full OP time, not just the remainder.
331 // This can be solved similarly to the ADC by gating a timer with the OP signal,
332 // but that requires additional connections on the PCB.
333 // For all currently envisioned EXT HALT applications (e.g. control-systems), this is okay.
334 flexio->port().SHIFTCTL[s_exthalt] = FLEXIO_SHIFTCTL_TIMSEL(t_state_check) | FLEXIO_SHIFTCTL_PINCFG(3) |
335 FLEXIO_SHIFTCTL_PINSEL(10) | FLEXIO_SHIFTCTL_SMOD_STATE;
336 flexio->port().SHIFTCFG[s_exthalt] = 0;
337 // When selecting next state based on inputs [12-11-10], ignore anything but EXT HALT (11).
338 flexio->port().SHIFTBUF[s_exthalt] =
339 FLEXIO_STATE_SHIFTBUF(0b11111111, s_exthalt, s_exthalt, s_op, s_op, s_exthalt, s_exthalt, s_op, s_op);
340
341 //
342 // Configure miscellaneous flexio stuff
343 //
344
345 // Put relevant pins into FlexIO mode
347 if (flexio->mapIOPinToFlexPin(pin) == 0xff) {
348 return false;
349 }
350 flexio->setIOPinToFlexMode(pin);
351 }
352
353 enable();
354 _is_initialized = true;
355 return true;
356}
357
359 auto flexio = FlexIOHandler::flexIOHandler_list[2];
360 flexio->port().CTRL &= ~FLEXIO_CTRL_FLEXEN;
361 _is_enabled = false;
362}
363
365 auto flexio = FlexIOHandler::flexIOHandler_list[2];
366 flexio->port().CTRL |= FLEXIO_CTRL_FLEXEN;
367 _is_enabled = true;
368}
369
371
373 auto flexio = FlexIOHandler::flexIOHandler_list[2];
374 flexio->port().SHIFTSTATE = s_idle;
375 mode::PerformanceCounter::get().to(mode::Mode::HALT);
376}
377
379 auto flexio = FlexIOHandler::flexIOHandler_list[2];
380 flexio->port().SHIFTSTATE = s_ic;
381 mode::PerformanceCounter::get().to(mode::Mode::IC);
382}
383
385 auto flexio = FlexIOHandler::flexIOHandler_list[2];
386 flexio->port().SHIFTSTATE = s_op;
387 mode::PerformanceCounter::get().to(mode::Mode::OP);
388}
389
391 auto flexio = FlexIOHandler::flexIOHandler_list[2];
392 flexio->port().SHIFTSTATE = s_exthalt;
393 mode::PerformanceCounter::get().to(mode::Mode::HALT);
394}
395
397 auto flexio = FlexIOHandler::flexIOHandler_list[2];
398 flexio->port().SHIFTSTATE = s_end;
399 mode::PerformanceCounter::get().to(mode::Mode::HALT);
400}
401
403 disable();
404 delayMicroseconds(1);
405 auto flexio = FlexIOHandler::flexIOHandler_list[2];
406 flexio->port().CTRL |= FLEXIO_CTRL_SWRST;
407 delayMicroseconds(1);
408 flexio->port().CTRL &= ~FLEXIO_CTRL_SWRST;
409 delayMicroseconds(1);
410}
411
413 while (!is_done()) {
414 }
415}
416
418 TMR1_CNTR1 = 0;
419 TMR1_CNTR2 = 0;
420}
421
423 CCM_CCGR6 |= CCM_CCGR6_QTIMER1(CCM_CCGR_ON);
424
425 // Configure timer 1 of first QTMR module to do input-gated counting
426 TMR1_CTRL1 = 0; // stop
427 TMR1_CNTR1 = 0; // reset counter
428 TMR1_SCTRL1 = 0;
429 TMR1_LOAD1 = 0;
430 TMR1_CSCTRL1 = 0;
431 TMR1_LOAD1 = 0; // start val after compare
432 TMR1_COMP11 = 0xffff; // count up to this val, interrupt, and start again
433 TMR1_CMPLD11 = 0xffff;
434 // Set CM=0 for now, enable later, select fastest clock with PCS, select gating signal with SCS
435 TMR1_CTRL1 = TMR_CTRL_CM(0) | TMR_CTRL_PCS(8) | TMR_CTRL_SCS(1);
436 // Invert secondary signal (gating when HIGH, counting when LOW)
437 TMR1_SCTRL1 = TMR_SCTRL_IPS;
438
439 // Configure timer 2 of first QTMR module to cascade from timer 1
440 TMR1_CTRL2 = 0;
441 TMR1_CNTR2 = 0; // reset counter
442 TMR1_SCTRL2 = 0;
443 TMR1_LOAD2 = 0;
444 TMR1_CSCTRL2 = 0;
445 TMR1_LOAD2 = 0; // start val after compare
446 TMR1_COMP12 = 0xffff; // count up to this val and start again
447 TMR1_CMPLD12 = 0xffff;
448 // Set CM=0 for now, enable later, select first timer with PCS
449 TMR1_CTRL2 = TMR_CTRL_CM(0) | TMR_CTRL_PCS(4 + 1);
450
451 // Put PIN_QTMR_OP_GATE in QTimer mode
452 *(portConfigRegister(PIN_QTMR_OP_GATE)) = 1; // ALT 1
453 // Enable timers in reverse order
454 TMR1_CTRL2 |= TMR_CTRL_CM(7);
455 TMR1_CTRL1 |= TMR_CTRL_CM(3);
456}
457
459 // TODO: This is currently measured, but of course it can be calculated
460 return (TMR1_CNTR2 * 0xFFFF + TMR1_CNTR1) * 671 / 100;
461}
462
464 auto flexio = FlexIOHandler::flexIOHandler_list[2];
465 return flexio->port().SHIFTSTATE == s_idle;
466}
467
469 auto flexio = FlexIOHandler::flexIOHandler_list[2];
470 return flexio->port().SHIFTSTATE == s_op;
471}
472
474 auto flexio = FlexIOHandler::flexIOHandler_list[2];
475 auto state = flexio->port().SHIFTSTATE;
476 return state == s_end or state == s_overload;
477}
478
480 auto flexio = FlexIOHandler::flexIOHandler_list[2];
481 return flexio->port().SHIFTSTATE == s_overload;
482}
483
485 auto flexio = FlexIOHandler::flexIOHandler_list[2];
486 return flexio->port().SHIFTSTATE == s_exthalt;
487}
static void to_exthalt()
Definition mode.cpp:390
static void disable()
Definition mode.cpp:358
static void to_end()
Definition mode.cpp:396
static void _reset_qtmr_op()
Definition mode.cpp:417
static bool is_op()
Definition mode.cpp:468
static bool is_idle()
Definition mode.cpp:463
static bool is_initialized()
Definition mode.h:88
static unsigned long long get_actual_op_time()
Definition mode.cpp:458
static bool is_done()
Definition mode.cpp:473
static void reset()
Definition mode.cpp:402
static bool is_enabled()
Definition mode.h:93
static void to_ic()
Definition mode.cpp:378
static void to_op()
Definition mode.cpp:384
static void delay_till_done()
Definition mode.cpp:412
static void force_start()
Definition mode.cpp:370
static void to_idle()
Definition mode.cpp:372
static bool is_overloaded()
Definition mode.cpp:479
static bool init(unsigned long long ic_time_ns, unsigned long long op_time_ns, mode::OnOverload on_overload=mode::OnOverload::HALT, mode::OnExtHalt on_ext_halt=mode::OnExtHalt::IGNORE, SyncConfig sync_config={})
Definition mode.cpp:95
static void enable()
Definition mode.cpp:364
static void _init_qtmr_op()
Definition mode.cpp:422
static bool is_exthalt()
Definition mode.cpp:484
constexpr uint8_t PIN_MODE_OP
Definition mode.h:17
constexpr uint8_t PIN_SYNC_CLK
Definition mode.h:20
constexpr uint8_t PIN_MODE_IC
Definition mode.h:16
constexpr uint8_t PIN_QTMR_OP_GATE
Definition mode.h:22
constexpr uint8_t PIN_MODE_EXTHALT
Definition mode.h:19
constexpr uint8_t PIN_MODE_OVERLOAD
Definition mode.h:18
constexpr uint8_t PIN_SYNC_ID
Definition mode.h:21