PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1722 lines
52KB

  1. /* Teensy 4.x, 3.x, LC ADC library
  2. * https://github.com/pedvide/ADC
  3. * Copyright (c) 2020 Pedro Villanueva
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining
  6. * a copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sublicense, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  20. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  21. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. */
  25. /* ADC_Module.cpp: Implements the fuctions of a Teensy 3.x, LC ADC module
  26. *
  27. */
  28. #include "ADC_Module.h"
  29. // include the internal reference
  30. #ifdef ADC_USE_INTERNAL_VREF
  31. #include <VREF.h>
  32. #endif
  33. /* Constructor
  34. * Point the registers to the correct ADC module
  35. * Copy the correct channel2sc1a
  36. * Call init
  37. */
  38. ADC_Module::ADC_Module(uint8_t ADC_number,
  39. const uint8_t *const a_channel2sc1a,
  40. #if ADC_DIFF_PAIRS > 0
  41. const ADC_NLIST *const a_diff_table,
  42. #endif
  43. ADC_REGS_t &a_adc_regs) : ADC_num(ADC_number), channel2sc1a(a_channel2sc1a)
  44. #if ADC_DIFF_PAIRS > 0
  45. ,
  46. diff_table(a_diff_table)
  47. #endif
  48. ,
  49. adc_regs(a_adc_regs)
  50. #ifdef ADC_USE_PDB
  51. ,
  52. PDB0_CHnC1(ADC_num ? PDB0_CH1C1 : PDB0_CH0C1)
  53. #endif
  54. #if defined(ADC_TEENSY_4)
  55. ,
  56. XBAR_IN(ADC_num ? XBARA1_IN_QTIMER4_TIMER3 : XBARA1_IN_QTIMER4_TIMER0), XBAR_OUT(ADC_num ? XBARA1_OUT_ADC_ETC_TRIG10 : XBARA1_OUT_ADC_ETC_TRIG00), QTIMER4_INDEX(ADC_num ? 3 : 0), ADC_ETC_TRIGGER_INDEX(ADC_num ? 4 : 0), IRQ_ADC(ADC_num ? IRQ_NUMBER_t::IRQ_ADC2 : IRQ_NUMBER_t::IRQ_ADC1)
  57. #elif defined(ADC_DUAL_ADCS)
  58. // IRQ_ADC0 and IRQ_ADC1 aren't consecutive in Teensy 3.6
  59. // fix by SB, https://github.com/pedvide/ADC/issues/19
  60. ,
  61. IRQ_ADC(ADC_num ? IRQ_NUMBER_t::IRQ_ADC1 : IRQ_NUMBER_t::IRQ_ADC0)
  62. #else
  63. ,
  64. IRQ_ADC(IRQ_NUMBER_t::IRQ_ADC0)
  65. #endif
  66. {
  67. // call our init
  68. analog_init();
  69. }
  70. /* Initialize stuff:
  71. * - Switch on clock
  72. * - Clear all fail flags
  73. * - Internal reference (default: external vcc)
  74. * - Mux between a and b channels (b channels)
  75. * - Calibrate with 32 averages and low speed
  76. * - When first calibration is done it sets:
  77. * - Resolution (default: 10 bits)
  78. * - Conversion speed and sampling time (both set to medium speed)
  79. * - Averaging (set to 4)
  80. */
  81. void ADC_Module::analog_init()
  82. {
  83. startClock();
  84. // default settings:
  85. /*
  86. - 10 bits resolution
  87. - 4 averages
  88. - vcc reference
  89. - no interrupts
  90. - pga gain=1
  91. - conversion speed = medium
  92. - sampling speed = medium
  93. initiate to 0 (or 1) so the corresponding functions change it to the correct value
  94. */
  95. analog_res_bits = 0;
  96. analog_max_val = 0;
  97. analog_num_average = 0;
  98. analog_reference_internal = ADC_REF_SOURCE::REF_NONE;
  99. #ifdef ADC_USE_PGA
  100. pga_value = 1;
  101. #endif
  102. interrupts_enabled = false;
  103. #ifdef ADC_TEENSY_4
  104. // overwrite old values if a new conversion ends
  105. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_OVWREN);
  106. // this is the only option for Teensy 3.x and LC
  107. #endif
  108. conversion_speed = ADC_CONVERSION_SPEED::HIGH_SPEED; // set to something different from line 139 so it gets changed there
  109. sampling_speed = ADC_SAMPLING_SPEED::VERY_HIGH_SPEED;
  110. calibrating = 0;
  111. fail_flag = ADC_ERROR::CLEAR; // clear all errors
  112. num_measurements = 0;
  113. // select b channels
  114. #ifdef ADC_TEENSY_4
  115. // T4 has no a or b channels
  116. #else
  117. // ADC_CFG2_muxsel = 1;
  118. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_MUXSEL);
  119. #endif
  120. // set reference to vcc
  121. setReference(ADC_REFERENCE::REF_3V3);
  122. // set resolution to 10
  123. setResolution(10);
  124. // the first calibration will use 32 averages and lowest speed,
  125. // when this calibration is over the averages and speed will be set to default by wait_for_cal and init_calib will be cleared.
  126. init_calib = 1;
  127. setAveraging(32);
  128. setConversionSpeed(ADC_CONVERSION_SPEED::LOW_SPEED);
  129. setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);
  130. // begin init calibration
  131. calibrate();
  132. }
  133. // starts calibration
  134. void ADC_Module::calibrate()
  135. {
  136. __disable_irq();
  137. calibrating = 1;
  138. #ifdef ADC_TEENSY_4
  139. atomic::clearBitFlag(adc_regs.GC, ADC_GC_CAL);
  140. atomic::setBitFlag(adc_regs.GS, ADC_GS_CALF);
  141. atomic::setBitFlag(adc_regs.GC, ADC_GC_CAL);
  142. #else
  143. // ADC_SC3_cal = 0; // stop possible previous calibration
  144. atomic::clearBitFlag(adc_regs.SC3, ADC_SC3_CAL);
  145. // ADC_SC3_calf = 1; // clear possible previous error
  146. atomic::setBitFlag(adc_regs.SC3, ADC_SC3_CALF);
  147. // ADC_SC3_cal = 1; // start calibration
  148. atomic::setBitFlag(adc_regs.SC3, ADC_SC3_CAL);
  149. #endif
  150. __enable_irq();
  151. }
  152. /* Waits until calibration is finished and writes the corresponding registers
  153. *
  154. */
  155. void ADC_Module::wait_for_cal(void)
  156. {
  157. // wait for calibration to finish
  158. #ifdef ADC_TEENSY_4
  159. while (atomic::getBitFlag(adc_regs.GC, ADC_GC_CAL))
  160. { // Bit ADC_GC_CAL in register GC cleared when calib. finishes.
  161. yield();
  162. }
  163. if (atomic::getBitFlag(adc_regs.GS, ADC_GS_CALF))
  164. { // calibration failed
  165. fail_flag |= ADC_ERROR::CALIB; // the user should know and recalibrate manually
  166. }
  167. #else
  168. while (atomic::getBitFlag(adc_regs.SC3, ADC_SC3_CAL))
  169. { // Bit ADC_SC3_CAL in register ADC0_SC3 cleared when calib. finishes.
  170. yield();
  171. }
  172. if (atomic::getBitFlag(adc_regs.SC3, ADC_SC3_CALF))
  173. { // calibration failed
  174. fail_flag |= ADC_ERROR::CALIB; // the user should know and recalibrate manually
  175. }
  176. #endif
  177. // set calibrated values to registers
  178. #ifdef ADC_TEENSY_4
  179. // T4 does not require anything else for calibration
  180. #else
  181. __disable_irq();
  182. uint16_t sum;
  183. if (calibrating)
  184. {
  185. sum = adc_regs.CLPS + adc_regs.CLP4 + adc_regs.CLP3 + adc_regs.CLP2 + adc_regs.CLP1 + adc_regs.CLP0;
  186. sum = (sum / 2) | 0x8000;
  187. adc_regs.PG = sum;
  188. sum = adc_regs.CLMS + adc_regs.CLM4 + adc_regs.CLM3 + adc_regs.CLM2 + adc_regs.CLM1 + adc_regs.CLM0;
  189. sum = (sum / 2) | 0x8000;
  190. adc_regs.MG = sum;
  191. }
  192. __enable_irq();
  193. #endif
  194. calibrating = 0;
  195. // the first calibration uses 32 averages and lowest speed,
  196. // when this calibration is over, set the averages and speed to default.
  197. if (init_calib)
  198. {
  199. // set conversion speed to medium
  200. setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
  201. // set sampling speed to medium
  202. setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED);
  203. // number of averages to 4
  204. setAveraging(4);
  205. init_calib = 0; // clear
  206. }
  207. }
  208. //! Starts the calibration sequence, waits until it's done and writes the results
  209. /** Usually it's not necessary to call this function directly, but do it if the "environment" changed
  210. * significantly since the program was started.
  211. */
  212. void ADC_Module::recalibrate()
  213. {
  214. calibrate();
  215. wait_for_cal();
  216. }
  217. /////////////// METHODS TO SET/GET SETTINGS OF THE ADC ////////////////////
  218. /* Set the voltage reference you prefer, default is 3.3V
  219. * It needs to recalibrate
  220. * Use ADC_REF_3V3, ADC_REF_1V2 (not for Teensy LC) or ADC_REF_EXT
  221. */
  222. void ADC_Module::setReference(ADC_REFERENCE type)
  223. {
  224. ADC_REF_SOURCE ref_type = static_cast<ADC_REF_SOURCE>(type); // cast to source type, that is, either internal or default
  225. if (analog_reference_internal == ref_type)
  226. { // don't need to change anything
  227. return;
  228. }
  229. if (ref_type == ADC_REF_SOURCE::REF_ALT)
  230. { // 1.2V ref for Teensy 3.x, 3.3 VDD for Teensy LC
  231. // internal reference requested
  232. #ifdef ADC_USE_INTERNAL_VREF
  233. VREF::start(); // enable VREF if Teensy 3.x
  234. #endif
  235. analog_reference_internal = ADC_REF_SOURCE::REF_ALT;
  236. #ifdef ADC_TEENSY_4
  237. // No REF_ALT for T4
  238. #else
  239. // *ADC_SC2_ref = 1; // uses bitband: atomic
  240. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_REFSEL(1));
  241. #endif
  242. }
  243. else if (ref_type == ADC_REF_SOURCE::REF_DEFAULT)
  244. { // ext ref for all Teensys, vcc also for Teensy 3.x
  245. // vcc or external reference requested
  246. #ifdef ADC_USE_INTERNAL_VREF
  247. VREF::stop(); // disable 1.2V reference source when using the external ref (p. 102, 3.7.1.7)
  248. #endif
  249. analog_reference_internal = ADC_REF_SOURCE::REF_DEFAULT;
  250. #ifdef ADC_TEENSY_4
  251. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_REFSEL(3));
  252. #else
  253. // *ADC_SC2_ref = 0; // uses bitband: atomic
  254. atomic::clearBitFlag(adc_regs.SC2, ADC_SC2_REFSEL(1));
  255. #endif
  256. }
  257. calibrate();
  258. }
  259. /* Change the resolution of the measurement
  260. * For single-ended measurements: 8, 10, 12 or 16 bits.
  261. * For differential measurements: 9, 11, 13 or 16 bits.
  262. * If you want something in between (11 bits single-ended for example) select the inmediate higher
  263. * and shift the result one to the right.
  264. *
  265. * It doesn't recalibrate
  266. */
  267. void ADC_Module::setResolution(uint8_t bits)
  268. {
  269. if (analog_res_bits == bits)
  270. {
  271. return;
  272. }
  273. uint8_t config;
  274. if (calibrating)
  275. wait_for_cal();
  276. if (bits <= 9)
  277. {
  278. config = 8;
  279. }
  280. else if (bits <= 11)
  281. {
  282. config = 10;
  283. #ifdef ADC_TEENSY_4
  284. }
  285. else if (bits > 11)
  286. {
  287. config = 12;
  288. #else
  289. }
  290. else if (bits <= 13)
  291. {
  292. config = 12;
  293. }
  294. else if (bits > 13)
  295. {
  296. config = 16;
  297. #endif
  298. }
  299. else
  300. {
  301. config = 8; // default to 8 bits
  302. }
  303. // conversion resolution
  304. // single-ended 8 bits is the same as differential 9 bits, etc.
  305. if ((config == 8) || (config == 9))
  306. {
  307. #ifdef ADC_TEENSY_4
  308. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_MODE(3));
  309. #else
  310. // *ADC_CFG1_mode1 = 0;
  311. // *ADC_CFG1_mode0 = 0;
  312. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_MODE(3));
  313. #endif
  314. analog_max_val = 255; // diff mode 9 bits has 1 bit for sign, so max value is the same as single 8 bits
  315. }
  316. else if ((config == 10) || (config == 11))
  317. {
  318. #ifdef ADC_TEENSY_4
  319. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_MODE(3), ADC_CFG_MODE(1));
  320. #else
  321. // *ADC_CFG1_mode1 = 1;
  322. // *ADC_CFG1_mode0 = 0;
  323. atomic::changeBitFlag(adc_regs.CFG1, ADC_CFG1_MODE(3), ADC_CFG1_MODE(2));
  324. #endif
  325. analog_max_val = 1023;
  326. }
  327. else if ((config == 12) || (config == 13))
  328. {
  329. #ifdef ADC_TEENSY_4
  330. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_MODE(3), ADC_CFG_MODE(2));
  331. #else
  332. // *ADC_CFG1_mode1 = 0;
  333. // *ADC_CFG1_mode0 = 1;
  334. atomic::changeBitFlag(adc_regs.CFG1, ADC_CFG1_MODE(3), ADC_CFG1_MODE(1));
  335. #endif
  336. analog_max_val = 4095;
  337. }
  338. else
  339. {
  340. #ifdef ADC_TEENSY_4
  341. // Impossible for T4
  342. #else
  343. // *ADC_CFG1_mode1 = 1;
  344. // *ADC_CFG1_mode0 = 1;
  345. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_MODE(3));
  346. #endif
  347. analog_max_val = 65535;
  348. }
  349. analog_res_bits = config;
  350. // no recalibration is needed when changing the resolution, p. 619
  351. }
  352. /* Returns the resolution of the ADC
  353. *
  354. */
  355. uint8_t ADC_Module::getResolution()
  356. {
  357. return analog_res_bits;
  358. }
  359. /* Returns the maximum value for a measurement, that is: 2^resolution-1
  360. *
  361. */
  362. uint32_t ADC_Module::getMaxValue()
  363. {
  364. return analog_max_val;
  365. }
  366. // Sets the conversion speed
  367. /* Increase the sampling speed for low impedance sources, decrease it for higher impedance ones.
  368. * \param speed can be any of the ADC_SAMPLING_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED, HIGH_SPEED or VERY_HIGH_SPEED.
  369. *
  370. * VERY_LOW_SPEED is the lowest possible sampling speed (+24 ADCK).
  371. * LOW_SPEED adds +16 ADCK.
  372. * MED_SPEED adds +10 ADCK.
  373. * HIGH_SPEED adds +6 ADCK.
  374. * VERY_HIGH_SPEED is the highest possible sampling speed (0 ADCK added).
  375. */
  376. void ADC_Module::setConversionSpeed(ADC_CONVERSION_SPEED speed)
  377. {
  378. if (speed == conversion_speed)
  379. { // no change
  380. return;
  381. }
  382. //if (calibrating) wait_for_cal();
  383. bool is_adack = false;
  384. uint32_t ADC_CFG1_speed = 0; // store the clock and divisor (set to 0 to avoid warnings)
  385. switch (speed)
  386. {
  387. // normal bus clock
  388. #ifndef ADC_TEENSY_4
  389. case ADC_CONVERSION_SPEED::VERY_LOW_SPEED:
  390. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  391. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  392. // ADC_CFG1_speed = ADC_CFG1_VERY_LOW_SPEED;
  393. ADC_CFG1_speed = get_CFG_VERY_LOW_SPEED(ADC_F_BUS);
  394. break;
  395. #endif
  396. case ADC_CONVERSION_SPEED::LOW_SPEED:
  397. #ifdef ADC_TEENSY_4
  398. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADHSC);
  399. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADLPC);
  400. #else
  401. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  402. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  403. #endif
  404. // ADC_CFG1_speed = ADC_CFG1_LOW_SPEED;
  405. ADC_CFG1_speed = get_CFG_LOW_SPEED(ADC_F_BUS);
  406. break;
  407. case ADC_CONVERSION_SPEED::MED_SPEED:
  408. #ifdef ADC_TEENSY_4
  409. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADHSC);
  410. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLPC);
  411. #else
  412. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  413. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  414. #endif
  415. ADC_CFG1_speed = get_CFG_MEDIUM_SPEED(ADC_F_BUS);
  416. break;
  417. #ifndef ADC_TEENSY_4
  418. case ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS:
  419. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  420. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  421. // ADC_CFG1_speed = ADC_CFG1_HI_SPEED_16_BITS;
  422. ADC_CFG1_speed = get_CFG_HI_SPEED_16_BITS(ADC_F_BUS);
  423. break;
  424. #endif
  425. case ADC_CONVERSION_SPEED::HIGH_SPEED:
  426. #ifdef ADC_TEENSY_4
  427. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADHSC);
  428. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLPC);
  429. #else
  430. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  431. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  432. #endif
  433. ADC_CFG1_speed = get_CFG_HIGH_SPEED(ADC_F_BUS);
  434. break;
  435. #ifndef ADC_TEENSY_4
  436. case ADC_CONVERSION_SPEED::VERY_HIGH_SPEED:
  437. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  438. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  439. // ADC_CFG1_speed = ADC_CFG1_VERY_HIGH_SPEED;
  440. ADC_CFG1_speed = get_CFG_VERY_HIGH_SPEED(ADC_F_BUS);
  441. break;
  442. #endif
  443. // adack - async clock source, independent of the bus clock
  444. #ifdef ADC_TEENSY_4 // fADK = 10 or 20 MHz
  445. case ADC_CONVERSION_SPEED::ADACK_10:
  446. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADHSC);
  447. is_adack = true;
  448. break;
  449. case ADC_CONVERSION_SPEED::ADACK_20:
  450. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADHSC);
  451. is_adack = true;
  452. break;
  453. #else // fADK = 2.4, 4.0, 5.2 or 6.2 MHz
  454. case ADC_CONVERSION_SPEED::ADACK_2_4:
  455. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  456. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  457. is_adack = true;
  458. break;
  459. case ADC_CONVERSION_SPEED::ADACK_4_0:
  460. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  461. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  462. is_adack = true;
  463. break;
  464. case ADC_CONVERSION_SPEED::ADACK_5_2:
  465. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  466. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  467. is_adack = true;
  468. break;
  469. case ADC_CONVERSION_SPEED::ADACK_6_2:
  470. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADHSC);
  471. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLPC);
  472. is_adack = true;
  473. break;
  474. #endif
  475. default:
  476. fail_flag |= ADC_ERROR::OTHER;
  477. return;
  478. }
  479. if (is_adack)
  480. {
  481. // async clock source, independent of the bus clock
  482. #ifdef ADC_TEENSY_4
  483. atomic::setBitFlag(adc_regs.GC, ADC_GC_ADACKEN); // enable ADACK (takes max 5us to be ready)
  484. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADICLK(3)); // select ADACK as clock source
  485. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADIV(3)); // select no dividers
  486. #else
  487. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADACKEN);
  488. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADICLK(3));
  489. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADIV(3));
  490. #endif
  491. }
  492. else
  493. {
  494. // normal bus clock used - disable the internal asynchronous clock
  495. // total speed can be: bus, bus/2, bus/4, bus/8 or bus/16.
  496. #ifdef ADC_TEENSY_4
  497. atomic::clearBitFlag(adc_regs.GC, ADC_GC_ADACKEN); // disable async
  498. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADICLK(3), ADC_CFG1_speed & ADC_CFG_ADICLK(3)); // bus or bus/2
  499. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADIV(3), ADC_CFG1_speed & ADC_CFG_ADIV(3)); // divisor for the clock source
  500. #else
  501. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADACKEN);
  502. atomic::changeBitFlag(adc_regs.CFG1, ADC_CFG1_ADICLK(3), ADC_CFG1_speed & ADC_CFG1_ADICLK(3));
  503. atomic::changeBitFlag(adc_regs.CFG1, ADC_CFG1_ADIV(3), ADC_CFG1_speed & ADC_CFG1_ADIV(3));
  504. #endif
  505. }
  506. conversion_speed = speed;
  507. calibrate();
  508. }
  509. // Sets the sampling speed
  510. /* Increase the sampling speed for low impedance sources, decrease it for higher impedance ones.
  511. * \param speed can be any of the ADC_SAMPLING_SPEED enum: VERY_LOW_SPEED, LOW_SPEED, MED_SPEED, HIGH_SPEED or VERY_HIGH_SPEED.
  512. *
  513. * VERY_LOW_SPEED is the lowest possible sampling speed (+24 ADCK).
  514. * LOW_SPEED adds +16 ADCK.
  515. * MED_SPEED adds +10 ADCK.
  516. * HIGH_SPEED adds +6 ADCK.
  517. * VERY_HIGH_SPEED is the highest possible sampling speed (0 ADCK added).
  518. */
  519. void ADC_Module::setSamplingSpeed(ADC_SAMPLING_SPEED speed)
  520. {
  521. if (calibrating)
  522. wait_for_cal();
  523. switch (speed)
  524. {
  525. #ifdef ADC_TEENSY_4
  526. case ADC_SAMPLING_SPEED::VERY_LOW_SPEED:
  527. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time enable
  528. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(3));
  529. break;
  530. case ADC_SAMPLING_SPEED::LOW_SPEED:
  531. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time enable
  532. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(2));
  533. break;
  534. case ADC_SAMPLING_SPEED::LOW_MED_SPEED:
  535. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time enable
  536. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(1));
  537. break;
  538. case ADC_SAMPLING_SPEED::MED_SPEED:
  539. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time enable
  540. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(0));
  541. break;
  542. case ADC_SAMPLING_SPEED::MED_HIGH_SPEED:
  543. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time disabled
  544. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(3));
  545. break;
  546. case ADC_SAMPLING_SPEED::HIGH_SPEED:
  547. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time disabled
  548. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(2));
  549. break;
  550. case ADC_SAMPLING_SPEED::HIGH_VERY_HIGH_SPEED:
  551. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time disabled
  552. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(1));
  553. break;
  554. case ADC_SAMPLING_SPEED::VERY_HIGH_SPEED:
  555. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_ADLSMP); // long sampling time disabled
  556. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_ADSTS(3), ADC_CFG_ADSTS(0));
  557. break;
  558. #else
  559. case ADC_SAMPLING_SPEED::VERY_LOW_SPEED:
  560. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLSMP); // long sampling time enable
  561. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_ADLSTS(3)); // maximum sampling time (+24 ADCK)
  562. break;
  563. case ADC_SAMPLING_SPEED::LOW_SPEED:
  564. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLSMP); // long sampling time enable
  565. atomic::changeBitFlag(adc_regs.CFG2, ADC_CFG2_ADLSTS(3), ADC_CFG2_ADLSTS(1)); // high sampling time (+16 ADCK)
  566. break;
  567. case ADC_SAMPLING_SPEED::MED_SPEED:
  568. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLSMP); // long sampling time enable
  569. atomic::changeBitFlag(adc_regs.CFG2, ADC_CFG2_ADLSTS(3), ADC_CFG2_ADLSTS(2)); // medium sampling time (+10 ADCK)
  570. break;
  571. case ADC_SAMPLING_SPEED::HIGH_SPEED:
  572. atomic::setBitFlag(adc_regs.CFG1, ADC_CFG1_ADLSMP); // long sampling time enable
  573. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_ADLSTS(3)); // low sampling time (+6 ADCK)
  574. break;
  575. case ADC_SAMPLING_SPEED::VERY_HIGH_SPEED:
  576. atomic::clearBitFlag(adc_regs.CFG1, ADC_CFG1_ADLSMP); // shortest sampling time
  577. break;
  578. #endif
  579. }
  580. sampling_speed = speed;
  581. }
  582. /* Set the number of averages: 0, 4, 8, 16 or 32.
  583. *
  584. */
  585. void ADC_Module::setAveraging(uint8_t num)
  586. {
  587. if (calibrating)
  588. wait_for_cal();
  589. if (num <= 1)
  590. {
  591. num = 0;
  592. // ADC_SC3_avge = 0;
  593. #ifdef ADC_TEENSY_4
  594. atomic::clearBitFlag(adc_regs.GC, ADC_GC_AVGE);
  595. #else
  596. atomic::clearBitFlag(adc_regs.SC3, ADC_SC3_AVGE);
  597. #endif
  598. }
  599. else
  600. {
  601. // ADC_SC3_avge = 1;
  602. #ifdef ADC_TEENSY_4
  603. atomic::setBitFlag(adc_regs.GC, ADC_GC_AVGE);
  604. #else
  605. atomic::setBitFlag(adc_regs.SC3, ADC_SC3_AVGE);
  606. #endif
  607. if (num <= 4)
  608. {
  609. num = 4;
  610. // ADC_SC3_avgs0 = 0;
  611. // ADC_SC3_avgs1 = 0;
  612. #ifdef ADC_TEENSY_4
  613. atomic::clearBitFlag(adc_regs.CFG, ADC_CFG_AVGS(3));
  614. #else
  615. atomic::clearBitFlag(adc_regs.SC3, ADC_SC3_AVGS(3));
  616. #endif
  617. }
  618. else if (num <= 8)
  619. {
  620. num = 8;
  621. // ADC_SC3_avgs0 = 1;
  622. // ADC_SC3_avgs1 = 0;
  623. #ifdef ADC_TEENSY_4
  624. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_AVGS(3), ADC_CFG_AVGS(1));
  625. #else
  626. atomic::changeBitFlag(adc_regs.SC3, ADC_SC3_AVGS(3), ADC_SC3_AVGS(1));
  627. #endif
  628. }
  629. else if (num <= 16)
  630. {
  631. num = 16;
  632. // ADC_SC3_avgs0 = 0;
  633. // ADC_SC3_avgs1 = 1;
  634. #ifdef ADC_TEENSY_4
  635. atomic::changeBitFlag(adc_regs.CFG, ADC_CFG_AVGS(3), ADC_CFG_AVGS(2));
  636. #else
  637. atomic::changeBitFlag(adc_regs.SC3, ADC_SC3_AVGS(3), ADC_SC3_AVGS(2));
  638. #endif
  639. }
  640. else
  641. {
  642. num = 32;
  643. // ADC_SC3_avgs0 = 1;
  644. // ADC_SC3_avgs1 = 1;
  645. #ifdef ADC_TEENSY_4
  646. atomic::setBitFlag(adc_regs.CFG, ADC_CFG_AVGS(3));
  647. #else
  648. atomic::setBitFlag(adc_regs.SC3, ADC_SC3_AVGS(3));
  649. #endif
  650. }
  651. }
  652. analog_num_average = num;
  653. }
  654. /* Enable interrupts: An ADC Interrupt will be raised when the conversion is completed
  655. * (including hardware averages and if the comparison (if any) is true).
  656. */
  657. void ADC_Module::enableInterrupts(void (*isr)(void), uint8_t priority)
  658. {
  659. if (calibrating)
  660. wait_for_cal();
  661. // ADC_SC1A_aien = 1;
  662. #ifdef ADC_TEENSY_4
  663. atomic::setBitFlag(adc_regs.HC0, ADC_HC_AIEN);
  664. interrupts_enabled = true;
  665. #else
  666. atomic::setBitFlag(adc_regs.SC1A, ADC_SC1_AIEN);
  667. #endif
  668. attachInterruptVector(IRQ_ADC, isr);
  669. NVIC_SET_PRIORITY(IRQ_ADC, priority);
  670. NVIC_ENABLE_IRQ(IRQ_ADC);
  671. }
  672. /* Disable interrupts
  673. *
  674. */
  675. void ADC_Module::disableInterrupts()
  676. {
  677. // ADC_SC1A_aien = 0;
  678. #ifdef ADC_TEENSY_4
  679. atomic::clearBitFlag(adc_regs.HC0, ADC_HC_AIEN);
  680. interrupts_enabled = false;
  681. #else
  682. atomic::clearBitFlag(adc_regs.SC1A, ADC_SC1_AIEN);
  683. #endif
  684. NVIC_DISABLE_IRQ(IRQ_ADC);
  685. }
  686. #ifdef ADC_USE_DMA
  687. /* Enable DMA request: An ADC DMA request will be raised when the conversion is completed
  688. * (including hardware averages and if the comparison (if any) is true).
  689. */
  690. void ADC_Module::enableDMA()
  691. {
  692. if (calibrating)
  693. wait_for_cal();
  694. // ADC_SC2_dma = 1;
  695. #ifdef ADC_TEENSY_4
  696. atomic::setBitFlag(adc_regs.GC, ADC_GC_DMAEN);
  697. #else
  698. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_DMAEN);
  699. #endif
  700. }
  701. /* Disable ADC DMA request
  702. *
  703. */
  704. void ADC_Module::disableDMA()
  705. {
  706. // ADC_SC2_dma = 0;
  707. #ifdef ADC_TEENSY_4
  708. atomic::clearBitFlag(adc_regs.GC, ADC_GC_DMAEN);
  709. #else
  710. atomic::clearBitFlag(adc_regs.SC2, ADC_SC2_DMAEN);
  711. #endif
  712. }
  713. #endif
  714. /* Enable the compare function: A conversion will be completed only when the ADC value
  715. * is >= compValue (greaterThan=1) or < compValue (greaterThan=0)
  716. * Call it after changing the resolution
  717. * Use with interrupts or poll conversion completion with isADC_Complete()
  718. */
  719. void ADC_Module::enableCompare(int16_t compValue, bool greaterThan)
  720. {
  721. if (calibrating)
  722. wait_for_cal(); // if we modify the adc's registers when calibrating, it will fail
  723. // ADC_SC2_cfe = 1; // enable compare
  724. // ADC_SC2_cfgt = (int32_t)greaterThan; // greater or less than?
  725. #ifdef ADC_TEENSY_4
  726. atomic::setBitFlag(adc_regs.GC, ADC_GC_ACFE);
  727. atomic::changeBitFlag(adc_regs.GC, ADC_GC_ACFGT, ADC_GC_ACFGT * greaterThan);
  728. adc_regs.CV = ADC_CV_CV1(compValue);
  729. #else
  730. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_ACFE);
  731. atomic::changeBitFlag(adc_regs.SC2, ADC_SC2_ACFGT, ADC_SC2_ACFGT * greaterThan);
  732. adc_regs.CV1 = (int16_t)compValue; // comp value
  733. #endif
  734. }
  735. /* Enable the compare function: A conversion will be completed only when the ADC value
  736. * is inside (insideRange=1) or outside (=0) the range given by (lowerLimit, upperLimit),
  737. * including (inclusive=1) the limits or not (inclusive=0).
  738. * See Table 31-78, p. 617 of the freescale manual.
  739. * Call it after changing the resolution
  740. */
  741. void ADC_Module::enableCompareRange(int16_t lowerLimit, int16_t upperLimit, bool insideRange, bool inclusive)
  742. {
  743. if (calibrating)
  744. wait_for_cal(); // if we modify the adc's registers when calibrating, it will fail
  745. // ADC_SC2_cfe = 1; // enable compare
  746. // ADC_SC2_cren = 1; // enable compare range
  747. #ifdef ADC_TEENSY_4
  748. atomic::setBitFlag(adc_regs.GC, ADC_GC_ACFE);
  749. atomic::setBitFlag(adc_regs.GC, ADC_GC_ACREN);
  750. #else
  751. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_ACFE);
  752. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_ACREN);
  753. #endif
  754. if (insideRange && inclusive)
  755. { // True if value is inside the range, including the limits. CV1 <= CV2 and ACFGT=1
  756. // ADC_SC2_cfgt = 1;
  757. #ifdef ADC_TEENSY_4
  758. atomic::setBitFlag(adc_regs.GC, ADC_GC_ACFGT);
  759. adc_regs.CV = ADC_CV_CV1(lowerLimit) | ADC_CV_CV2(upperLimit);
  760. #else
  761. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_ACFGT);
  762. adc_regs.CV1 = (int16_t)lowerLimit;
  763. adc_regs.CV2 = (int16_t)upperLimit;
  764. #endif
  765. }
  766. else if (insideRange && !inclusive)
  767. { // True if value is inside the range, excluding the limits. CV1 > CV2 and ACFGT=0
  768. // ADC_SC2_cfgt = 0;
  769. #ifdef ADC_TEENSY_4
  770. atomic::clearBitFlag(adc_regs.GC, ADC_GC_ACFGT);
  771. adc_regs.CV = ADC_CV_CV2(lowerLimit) | ADC_CV_CV1(upperLimit);
  772. #else
  773. atomic::clearBitFlag(adc_regs.SC2, ADC_SC2_ACFGT);
  774. adc_regs.CV2 = (int16_t)lowerLimit;
  775. adc_regs.CV1 = (int16_t)upperLimit;
  776. #endif
  777. }
  778. else if (!insideRange && inclusive)
  779. { // True if value is outside of range or is equal to either limit. CV1 > CV2 and ACFGT=1
  780. // ADC_SC2_cfgt = 1;
  781. #ifdef ADC_TEENSY_4
  782. atomic::setBitFlag(adc_regs.GC, ADC_GC_ACFGT);
  783. adc_regs.CV = ADC_CV_CV2(lowerLimit) | ADC_CV_CV1(upperLimit);
  784. #else
  785. atomic::setBitFlag(adc_regs.SC2, ADC_SC2_ACFGT);
  786. adc_regs.CV2 = (int16_t)lowerLimit;
  787. adc_regs.CV1 = (int16_t)upperLimit;
  788. #endif
  789. }
  790. else if (!insideRange && !inclusive)
  791. { // True if value is outside of range and not equal to either limit. CV1 > CV2 and ACFGT=0
  792. // ADC_SC2_cfgt = 0;
  793. #ifdef ADC_TEENSY_4
  794. atomic::clearBitFlag(adc_regs.GC, ADC_GC_ACFGT);
  795. adc_regs.CV = ADC_CV_CV1(lowerLimit) | ADC_CV_CV2(upperLimit);
  796. #else
  797. atomic::clearBitFlag(adc_regs.SC2, ADC_SC2_ACFGT);
  798. adc_regs.CV1 = (int16_t)lowerLimit;
  799. adc_regs.CV2 = (int16_t)upperLimit;
  800. #endif
  801. }
  802. }
  803. /* Disable the compare function
  804. *
  805. */
  806. void ADC_Module::disableCompare()
  807. {
  808. // ADC_SC2_cfe = 0;
  809. #ifdef ADC_TEENSY_4
  810. atomic::clearBitFlag(adc_regs.GC, ADC_GC_ACFE);
  811. #else
  812. atomic::clearBitFlag(adc_regs.SC2, ADC_SC2_ACFE);
  813. #endif
  814. }
  815. #ifdef ADC_USE_PGA
  816. /* Enables the PGA and sets the gain
  817. * Use only for signals lower than 1.2 V
  818. * \param gain can be 1, 2, 4, 8, 16 32 or 64
  819. *
  820. */
  821. void ADC_Module::enablePGA(uint8_t gain)
  822. {
  823. if (calibrating)
  824. wait_for_cal();
  825. uint8_t setting;
  826. if (gain <= 1)
  827. {
  828. setting = 0;
  829. }
  830. else if (gain <= 2)
  831. {
  832. setting = 1;
  833. }
  834. else if (gain <= 4)
  835. {
  836. setting = 2;
  837. }
  838. else if (gain <= 8)
  839. {
  840. setting = 3;
  841. }
  842. else if (gain <= 16)
  843. {
  844. setting = 4;
  845. }
  846. else if (gain <= 32)
  847. {
  848. setting = 5;
  849. }
  850. else
  851. { // 64
  852. setting = 6;
  853. }
  854. adc_regs.PGA = ADC_PGA_PGAEN | ADC_PGA_PGAG(setting);
  855. pga_value = 1 << setting;
  856. }
  857. /* Returns the PGA level
  858. * PGA level = from 0 to 64
  859. */
  860. uint8_t ADC_Module::getPGA()
  861. {
  862. return pga_value;
  863. }
  864. //! Disable PGA
  865. void ADC_Module::disablePGA()
  866. {
  867. // ADC_PGA_pgaen = 0;
  868. atomic::clearBitFlag(adc_regs.PGA, ADC_PGA_PGAEN);
  869. pga_value = 1;
  870. }
  871. #endif
  872. //////////////// INFORMATION ABOUT VALID PINS //////////////////
  873. // check whether the pin is a valid analog pin
  874. bool ADC_Module::checkPin(uint8_t pin)
  875. {
  876. if (pin > ADC_MAX_PIN)
  877. {
  878. return false; // all others are invalid
  879. }
  880. // translate pin number to SC1A number, that also contains MUX a or b info.
  881. const uint8_t sc1a_pin = channel2sc1a[pin];
  882. // check for valid pin
  883. if ((sc1a_pin & ADC_SC1A_CHANNELS) == ADC_SC1A_PIN_INVALID)
  884. {
  885. return false; // all others are invalid
  886. }
  887. return true;
  888. }
  889. #if ADC_DIFF_PAIRS > 0
  890. // check whether the pins are a valid analog differential pins (including PGA if enabled)
  891. bool ADC_Module::checkDifferentialPins(uint8_t pinP, uint8_t pinN)
  892. {
  893. if (pinP > ADC_MAX_PIN)
  894. {
  895. return false; // all others are invalid
  896. }
  897. // translate pinP number to SC1A number, to make sure it's differential
  898. uint8_t sc1a_pin = channel2sc1a[pinP];
  899. if (!(sc1a_pin & ADC_SC1A_PIN_DIFF))
  900. {
  901. return false; // all others are invalid
  902. }
  903. // get SC1A number, also whether it can do PGA
  904. sc1a_pin = getDifferentialPair(pinP);
  905. // the pair can't be measured with this ADC
  906. if ((sc1a_pin & ADC_SC1A_CHANNELS) == ADC_SC1A_PIN_INVALID)
  907. {
  908. return false; // all others are invalid
  909. }
  910. #ifdef ADC_USE_PGA
  911. // check if PGA is enabled, and whether the pin has access to it in this ADC module
  912. if (isPGAEnabled() && !(sc1a_pin & ADC_SC1A_PIN_PGA))
  913. {
  914. return false;
  915. }
  916. #endif // ADC_USE_PGA
  917. return true;
  918. }
  919. #endif
  920. //////////////// HELPER METHODS FOR CONVERSION /////////////////
  921. // Starts a single-ended conversion on the pin (sets the mux correctly)
  922. // Doesn't do any of the checks on the pin
  923. // It doesn't change the continuous conversion bit
  924. void ADC_Module::startReadFast(uint8_t pin)
  925. {
  926. // translate pin number to SC1A number, that also contains MUX a or b info.
  927. const uint8_t sc1a_pin = channel2sc1a[pin];
  928. #ifdef ADC_TEENSY_4
  929. // Teensy 4 has no a or b channels
  930. #else
  931. if (sc1a_pin & ADC_SC1A_PIN_MUX)
  932. { // mux a
  933. atomic::clearBitFlag(adc_regs.CFG2, ADC_CFG2_MUXSEL);
  934. }
  935. else
  936. { // mux b
  937. atomic::setBitFlag(adc_regs.CFG2, ADC_CFG2_MUXSEL);
  938. }
  939. #endif
  940. // select pin for single-ended mode and start conversion, enable interrupts if requested
  941. __disable_irq();
  942. #ifdef ADC_TEENSY_4
  943. adc_regs.HC0 = (sc1a_pin & ADC_SC1A_CHANNELS) + interrupts_enabled * ADC_HC_AIEN;
  944. #else
  945. adc_regs.SC1A = (sc1a_pin & ADC_SC1A_CHANNELS) + atomic::getBitFlag(adc_regs.SC1A, ADC_SC1_AIEN) * ADC_SC1_AIEN;
  946. #endif
  947. __enable_irq();
  948. }
  949. #if ADC_DIFF_PAIRS > 0
  950. // Starts a differential conversion on the pair of pins
  951. // Doesn't do any of the checks on the pins
  952. // It doesn't change the continuous conversion bit
  953. void ADC_Module::startDifferentialFast(uint8_t pinP, uint8_t pinN)
  954. {
  955. // get SC1A number
  956. uint8_t sc1a_pin = getDifferentialPair(pinP);
  957. #ifdef ADC_USE_PGA
  958. // check if PGA is enabled
  959. if (isPGAEnabled())
  960. {
  961. sc1a_pin = 0x2; // PGA always uses DAD2
  962. }
  963. #endif // ADC_USE_PGA
  964. __disable_irq();
  965. adc_regs.SC1A = ADC_SC1_DIFF + (sc1a_pin & ADC_SC1A_CHANNELS) + atomic::getBitFlag(adc_regs.SC1A, ADC_SC1_AIEN) * ADC_SC1_AIEN;
  966. __enable_irq();
  967. }
  968. #endif
  969. //////////////// BLOCKING CONVERSION METHODS //////////////////
  970. /*
  971. This methods are implemented like this:
  972. 1. Check that the pin is correct
  973. 2. if calibrating, wait for it to finish before modifiying any ADC register
  974. 3. Check if we're interrupting a measurement, if so store the settings.
  975. 4. Disable continuous conversion mode and start the current measurement
  976. 5. Wait until it's done, and check whether the comparison (if any) was succesful.
  977. 6. Get the result.
  978. 7. If step 3. is true, restore the previous ADC settings
  979. */
  980. /* Reads the analog value of the pin.
  981. * It waits until the value is read and then returns the result.
  982. * If a comparison has been set up and fails, it will return ADC_ERROR_VALUE.
  983. * Set the resolution, number of averages and voltage reference using the appropriate functions.
  984. */
  985. int ADC_Module::analogRead(uint8_t pin)
  986. {
  987. //digitalWriteFast(LED_BUILTIN, HIGH);
  988. // check whether the pin is correct
  989. if (!checkPin(pin))
  990. {
  991. fail_flag |= ADC_ERROR::WRONG_PIN;
  992. return ADC_ERROR_VALUE;
  993. }
  994. // increase the counter of measurements
  995. num_measurements++;
  996. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  997. if (calibrating)
  998. wait_for_cal();
  999. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  1000. // check if we are interrupting a measurement, store setting if so.
  1001. // vars to save the current state of the ADC in case it's in use
  1002. ADC_Config old_config = {};
  1003. const uint8_t wasADCInUse = isConverting(); // is the ADC running now?
  1004. if (wasADCInUse)
  1005. { // this means we're interrupting a conversion
  1006. // save the current conversion config, we don't want any other interrupts messing up the configs
  1007. __disable_irq();
  1008. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
  1009. saveConfig(&old_config);
  1010. __enable_irq();
  1011. }
  1012. // no continuous mode
  1013. singleMode();
  1014. startReadFast(pin); // start single read
  1015. // wait for the ADC to finish
  1016. while (isConverting())
  1017. {
  1018. yield();
  1019. }
  1020. // it's done, check if the comparison (if any) was true
  1021. int32_t result;
  1022. __disable_irq(); // make sure nothing interrupts this part
  1023. if (isComplete())
  1024. { // conversion succeded
  1025. result = (uint16_t)readSingle();
  1026. }
  1027. else
  1028. { // comparison was false
  1029. fail_flag |= ADC_ERROR::COMPARISON;
  1030. result = ADC_ERROR_VALUE;
  1031. }
  1032. __enable_irq();
  1033. // if we interrupted a conversion, set it again
  1034. if (wasADCInUse)
  1035. {
  1036. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
  1037. __disable_irq();
  1038. loadConfig(&old_config);
  1039. __enable_irq();
  1040. }
  1041. num_measurements--;
  1042. return result;
  1043. } // analogRead
  1044. #if ADC_DIFF_PAIRS > 0
  1045. /* Reads the differential analog value of two pins (pinP - pinN)
  1046. * It waits until the value is read and then returns the result
  1047. * If a comparison has been set up and fails, it will return ADC_ERROR_DIFF_VALUE
  1048. * Set the resolution, number of averages and voltage reference using the appropriate functions
  1049. */
  1050. int ADC_Module::analogReadDifferential(uint8_t pinP, uint8_t pinN)
  1051. {
  1052. if (!checkDifferentialPins(pinP, pinN))
  1053. {
  1054. fail_flag |= ADC_ERROR::WRONG_PIN;
  1055. return ADC_ERROR_VALUE; // all others are invalid
  1056. }
  1057. // increase the counter of measurements
  1058. num_measurements++;
  1059. // check for calibration before setting channels,
  1060. // because conversion will start as soon as we write to adc_regs.SC1A
  1061. if (calibrating)
  1062. wait_for_cal();
  1063. uint8_t res = getResolution();
  1064. // vars to saved the current state of the ADC in case it's in use
  1065. ADC_Config old_config = {};
  1066. uint8_t wasADCInUse = isConverting(); // is the ADC running now?
  1067. if (wasADCInUse)
  1068. { // this means we're interrupting a conversion
  1069. // save the current conversion config, we don't want any other interrupts messing up the configs
  1070. __disable_irq();
  1071. saveConfig(&old_config);
  1072. __enable_irq();
  1073. }
  1074. // no continuous mode
  1075. singleMode();
  1076. startDifferentialFast(pinP, pinN); // start conversion
  1077. // wait for the ADC to finish
  1078. while (isConverting())
  1079. {
  1080. yield();
  1081. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
  1082. }
  1083. // it's done, check if the comparison (if any) was true
  1084. int32_t result;
  1085. __disable_irq(); // make sure nothing interrupts this part
  1086. if (isComplete())
  1087. { // conversion succeded
  1088. result = (int16_t)(int32_t)readSingle(); // cast to 32 bits
  1089. if (res == 16)
  1090. { // 16 bit differential is actually 15 bit + 1 bit sign
  1091. result *= 2; // multiply by 2 as if it were really 16 bits, so that getMaxValue gives a correct value.
  1092. }
  1093. }
  1094. else
  1095. { // comparison was false
  1096. result = ADC_ERROR_VALUE;
  1097. fail_flag |= ADC_ERROR::COMPARISON;
  1098. }
  1099. __enable_irq();
  1100. // if we interrupted a conversion, set it again
  1101. if (wasADCInUse)
  1102. {
  1103. __disable_irq();
  1104. loadConfig(&old_config);
  1105. __enable_irq();
  1106. }
  1107. num_measurements--;
  1108. return result;
  1109. } // analogReadDifferential
  1110. #endif
  1111. /////////////// NON-BLOCKING CONVERSION METHODS //////////////
  1112. /*
  1113. This methods are implemented like this:
  1114. 1. Check that the pin is correct
  1115. 2. if calibrating, wait for it to finish before modifiying any ADC register
  1116. 3. Check if we're interrupting a measurement, if so store the settings (in a member of the class, so it can be accessed).
  1117. 4. Disable continuous conversion mode and start the current measurement
  1118. The fast methods only do step 4.
  1119. */
  1120. /* Starts an analog measurement on the pin.
  1121. * It returns inmediately, read value with readSingle().
  1122. * If the pin is incorrect it returns false.
  1123. */
  1124. bool ADC_Module::startSingleRead(uint8_t pin)
  1125. {
  1126. // check whether the pin is correct
  1127. if (!checkPin(pin))
  1128. {
  1129. fail_flag |= ADC_ERROR::WRONG_PIN;
  1130. return false;
  1131. }
  1132. if (calibrating)
  1133. wait_for_cal();
  1134. // save the current state of the ADC in case it's in use
  1135. adcWasInUse = isConverting(); // is the ADC running now?
  1136. if (adcWasInUse)
  1137. { // this means we're interrupting a conversion
  1138. // save the current conversion config, the adc isr will restore the adc
  1139. __disable_irq();
  1140. saveConfig(&adc_config);
  1141. __enable_irq();
  1142. }
  1143. // no continuous mode
  1144. singleMode();
  1145. // start measurement
  1146. startReadFast(pin);
  1147. return true;
  1148. }
  1149. #if ADC_DIFF_PAIRS > 0
  1150. /* Start a differential conversion between two pins (pinP - pinN).
  1151. * It returns inmediately, get value with readSingle().
  1152. * Incorrect pins will return false.
  1153. * Set the resolution, number of averages and voltage reference using the appropriate functions
  1154. */
  1155. bool ADC_Module::startSingleDifferential(uint8_t pinP, uint8_t pinN)
  1156. {
  1157. if (!checkDifferentialPins(pinP, pinN))
  1158. {
  1159. fail_flag |= ADC_ERROR::WRONG_PIN;
  1160. return false; // all others are invalid
  1161. }
  1162. // check for calibration before setting channels,
  1163. // because conversion will start as soon as we write to adc_regs.SC1A
  1164. if (calibrating)
  1165. wait_for_cal();
  1166. // vars to saved the current state of the ADC in case it's in use
  1167. adcWasInUse = isConverting(); // is the ADC running now?
  1168. if (adcWasInUse)
  1169. { // this means we're interrupting a conversion
  1170. // save the current conversion config, we don't want any other interrupts messing up the configs
  1171. __disable_irq();
  1172. saveConfig(&adc_config);
  1173. __enable_irq();
  1174. }
  1175. // no continuous mode
  1176. singleMode();
  1177. // start the conversion
  1178. startDifferentialFast(pinP, pinN);
  1179. return true;
  1180. }
  1181. #endif
  1182. ///////////// CONTINUOUS CONVERSION METHODS ////////////
  1183. /*
  1184. This methods are implemented like this:
  1185. 1. Check that the pin is correct
  1186. 2. If calibrating, wait for it to finish before modifiying any ADC register
  1187. 4. Enable continuous conversion mode and start the current measurement
  1188. */
  1189. /* Starts continuous conversion on the pin
  1190. * It returns as soon as the ADC is set, use analogReadContinuous() to read the values
  1191. * Set the resolution, number of averages and voltage reference using the appropriate functions BEFORE calling this function
  1192. */
  1193. bool ADC_Module::startContinuous(uint8_t pin)
  1194. {
  1195. // check whether the pin is correct
  1196. if (!checkPin(pin))
  1197. {
  1198. fail_flag |= ADC_ERROR::WRONG_PIN;
  1199. return false;
  1200. }
  1201. // check for calibration before setting channels,
  1202. if (calibrating)
  1203. wait_for_cal();
  1204. // increase the counter of measurements
  1205. num_measurements++;
  1206. // set continuous conversion flag
  1207. continuousMode();
  1208. startReadFast(pin);
  1209. return true;
  1210. }
  1211. #if ADC_DIFF_PAIRS > 0
  1212. /* Starts continuous and differential conversion between the pins (pinP-pinN)
  1213. * It returns as soon as the ADC is set, use analogReadContinuous() to read the value
  1214. * Set the resolution, number of averages and voltage reference using the appropriate functions BEFORE calling this function
  1215. */
  1216. bool ADC_Module::startContinuousDifferential(uint8_t pinP, uint8_t pinN)
  1217. {
  1218. if (!checkDifferentialPins(pinP, pinN))
  1219. {
  1220. fail_flag |= ADC_ERROR::WRONG_PIN;
  1221. return false; // all others are invalid
  1222. }
  1223. // increase the counter of measurements
  1224. num_measurements++;
  1225. // check for calibration before setting channels,
  1226. // because conversion will start as soon as we write to adc_regs.SC1A
  1227. if (calibrating)
  1228. wait_for_cal();
  1229. // save the current state of the ADC in case it's in use
  1230. uint8_t wasADCInUse = isConverting(); // is the ADC running now?
  1231. if (wasADCInUse)
  1232. { // this means we're interrupting a conversion
  1233. // save the current conversion config, we don't want any other interrupts messing up the configs
  1234. __disable_irq();
  1235. saveConfig(&adc_config);
  1236. __enable_irq();
  1237. }
  1238. // set continuous mode
  1239. continuousMode();
  1240. // start conversions
  1241. startDifferentialFast(pinP, pinN);
  1242. return true;
  1243. }
  1244. #endif
  1245. /* Stops continuous conversion
  1246. */
  1247. void ADC_Module::stopContinuous()
  1248. {
  1249. // set channel select to all 1's (31) to stop it.
  1250. #ifdef ADC_TEENSY_4
  1251. adc_regs.HC0 = ADC_SC1A_PIN_INVALID + interrupts_enabled * ADC_HC_AIEN;
  1252. #else
  1253. adc_regs.SC1A = ADC_SC1A_PIN_INVALID + atomic::getBitFlag(adc_regs.SC1A, ADC_SC1_AIEN) * ADC_SC1_AIEN;
  1254. #endif
  1255. // decrease the counter of measurements (unless it's 0)
  1256. if (num_measurements > 0)
  1257. {
  1258. num_measurements--;
  1259. }
  1260. return;
  1261. }
  1262. //////////// FREQUENCY METHODS ////////
  1263. //////////// PDB ////////////////
  1264. #ifdef ADC_USE_PDB
  1265. // frequency in Hz
  1266. void ADC_Module::startPDB(uint32_t freq)
  1267. {
  1268. if (!(SIM_SCGC6 & SIM_SCGC6_PDB))
  1269. { // setup PDB
  1270. SIM_SCGC6 |= SIM_SCGC6_PDB; // enable pdb clock
  1271. }
  1272. if (freq > ADC_F_BUS)
  1273. return; // too high
  1274. if (freq < 1)
  1275. return; // too low
  1276. // mod will have to be a 16 bit value
  1277. // we detect if it's higher than 0xFFFF and scale it back accordingly.
  1278. uint32_t mod = (ADC_F_BUS / freq);
  1279. uint8_t prescaler = 0; // from 0 to 7: factor of 1, 2, 4, 8, 16, 32, 64 or 128
  1280. uint8_t mult = 0; // from 0 to 3, factor of 1, 10, 20 or 40
  1281. // if mod is too high we need to use prescaler and mult to bring it down to a 16 bit number
  1282. const uint32_t min_level = 0xFFFF;
  1283. if (mod > min_level)
  1284. {
  1285. if (mod < 2 * min_level)
  1286. {
  1287. prescaler = 1;
  1288. }
  1289. else if (mod < 4 * min_level)
  1290. {
  1291. prescaler = 2;
  1292. }
  1293. else if (mod < 8 * min_level)
  1294. {
  1295. prescaler = 3;
  1296. }
  1297. else if (mod < 10 * min_level)
  1298. {
  1299. mult = 1;
  1300. }
  1301. else if (mod < 16 * min_level)
  1302. {
  1303. prescaler = 4;
  1304. }
  1305. else if (mod < 20 * min_level)
  1306. {
  1307. mult = 2;
  1308. }
  1309. else if (mod < 32 * min_level)
  1310. {
  1311. prescaler = 5;
  1312. }
  1313. else if (mod < 40 * min_level)
  1314. {
  1315. mult = 3;
  1316. }
  1317. else if (mod < 64 * min_level)
  1318. {
  1319. prescaler = 6;
  1320. }
  1321. else if (mod < 128 * min_level)
  1322. {
  1323. prescaler = 7;
  1324. }
  1325. else if (mod < 160 * min_level)
  1326. { // 16*10
  1327. prescaler = 4;
  1328. mult = 1;
  1329. }
  1330. else if (mod < 320 * min_level)
  1331. { // 16*20
  1332. prescaler = 4;
  1333. mult = 2;
  1334. }
  1335. else if (mod < 640 * min_level)
  1336. { // 16*40
  1337. prescaler = 4;
  1338. mult = 3;
  1339. }
  1340. else if (mod < 1280 * min_level)
  1341. { // 32*40
  1342. prescaler = 5;
  1343. mult = 3;
  1344. }
  1345. else if (mod < 2560 * min_level)
  1346. { // 64*40
  1347. prescaler = 6;
  1348. mult = 3;
  1349. }
  1350. else if (mod < 5120 * min_level)
  1351. { // 128*40
  1352. prescaler = 7;
  1353. mult = 3;
  1354. }
  1355. else
  1356. { // frequency too low
  1357. return;
  1358. }
  1359. mod >>= prescaler;
  1360. if (mult > 0)
  1361. {
  1362. mod /= 10;
  1363. mod >>= (mult - 1);
  1364. }
  1365. }
  1366. setHardwareTrigger(); // trigger ADC with hardware
  1367. // software trigger enable PDB PDB interrupt continuous mode load immediately
  1368. constexpr uint32_t ADC_PDB_CONFIG = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDMOD(0);
  1369. constexpr uint32_t PDB_CHnC1_TOS_1 = 0x0100;
  1370. constexpr uint32_t PDB_CHnC1_EN_1 = 0x01;
  1371. PDB0_IDLY = 1; // the pdb interrupt happens when IDLY is equal to CNT+1
  1372. PDB0_MOD = (uint16_t)(mod - 1);
  1373. PDB0_SC = ADC_PDB_CONFIG | PDB_SC_PRESCALER(prescaler) | PDB_SC_MULT(mult) | PDB_SC_LDOK; // load all new values
  1374. PDB0_SC = ADC_PDB_CONFIG | PDB_SC_PRESCALER(prescaler) | PDB_SC_MULT(mult) | PDB_SC_SWTRIG; // start the counter!
  1375. PDB0_CHnC1 = PDB_CHnC1_TOS_1 | PDB_CHnC1_EN_1; // enable pretrigger 0 (SC1A)
  1376. //NVIC_ENABLE_IRQ(IRQ_PDB);
  1377. }
  1378. void ADC_Module::stopPDB()
  1379. {
  1380. if (!(SIM_SCGC6 & SIM_SCGC6_PDB))
  1381. { // if PDB clock wasn't on, return
  1382. setSoftwareTrigger();
  1383. return;
  1384. }
  1385. PDB0_SC = 0;
  1386. setSoftwareTrigger();
  1387. //NVIC_DISABLE_IRQ(IRQ_PDB);
  1388. }
  1389. //! Return the PDB's frequency
  1390. uint32_t ADC_Module::getPDBFrequency()
  1391. {
  1392. const uint32_t mod = (uint32_t)PDB0_MOD;
  1393. const uint8_t prescaler = (PDB0_SC & 0x7000) >> 12;
  1394. const uint8_t mult = (PDB0_SC & 0xC) >> 2;
  1395. const uint32_t freq = uint32_t((mod + 1) << (prescaler)) * uint32_t((mult == 0) ? 1 : 10 << (mult - 1));
  1396. return ADC_F_BUS / freq;
  1397. }
  1398. #endif
  1399. #ifdef ADC_USE_QUAD_TIMER
  1400. // TODO: Add support for Teensy 3.x Quad timer
  1401. #if defined(ADC_TEENSY_4) // only supported by Teensy 4...
  1402. // try to use some teensy core functions...
  1403. // mainly out of pwm.c
  1404. extern "C"
  1405. {
  1406. extern void xbar_connect(unsigned int input, unsigned int output);
  1407. extern void quadtimer_init(IMXRT_TMR_t *p);
  1408. extern void quadtimerWrite(IMXRT_TMR_t *p, unsigned int submodule, uint16_t val);
  1409. extern void quadtimerFrequency(IMXRT_TMR_t *p, unsigned int submodule, float frequency);
  1410. }
  1411. void ADC_Module::startQuadTimer(uint32_t freq)
  1412. {
  1413. // First lets setup the XBAR
  1414. CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //turn clock on for xbara1
  1415. xbar_connect(XBAR_IN, XBAR_OUT);
  1416. // Update the ADC
  1417. uint8_t adc_pin_channel = adc_regs.HC0 & 0x1f; // remember the trigger that was set
  1418. setHardwareTrigger(); // set the hardware trigger
  1419. adc_regs.HC0 = (adc_regs.HC0 & ~0x1f) | 16; // ADC_ETC channel remember other states...
  1420. singleMode(); // make sure continuous is turned off as you want the trigger to di it.
  1421. // setup adc_etc - BUGBUG have not used the preset values yet.
  1422. if (IMXRT_ADC_ETC.CTRL & ADC_ETC_CTRL_SOFTRST)
  1423. { // SOFTRST
  1424. // Soft reset
  1425. atomic::clearBitFlag(IMXRT_ADC_ETC.CTRL, ADC_ETC_CTRL_SOFTRST);
  1426. delay(5); // give some time to be sure it is init
  1427. }
  1428. if (ADC_num == 0)
  1429. { // BUGBUG - in real code, should probably know we init ADC or not..
  1430. IMXRT_ADC_ETC.CTRL |=
  1431. (ADC_ETC_CTRL_TSC_BYPASS | ADC_ETC_CTRL_DMA_MODE_SEL | ADC_ETC_CTRL_TRIG_ENABLE(1 << ADC_ETC_TRIGGER_INDEX)); // 0x40000001; // start with trigger 0
  1432. IMXRT_ADC_ETC.TRIG[ADC_ETC_TRIGGER_INDEX].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(0); // chainlength -1 only us
  1433. IMXRT_ADC_ETC.TRIG[ADC_ETC_TRIGGER_INDEX].CHAIN_1_0 =
  1434. ADC_ETC_TRIG_CHAIN_IE0(1) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
  1435. | ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel);
  1436. if (interrupts_enabled)
  1437. {
  1438. // Not sure yet?
  1439. }
  1440. if (adc_regs.GC & ADC_GC_DMAEN)
  1441. {
  1442. IMXRT_ADC_ETC.DMA_CTRL |= ADC_ETC_DMA_CTRL_TRIQ_ENABLE(ADC_ETC_TRIGGER_INDEX);
  1443. }
  1444. }
  1445. else
  1446. {
  1447. // This is our second one... Try second trigger?
  1448. // Remove the BYPASS?
  1449. IMXRT_ADC_ETC.CTRL &= ~(ADC_ETC_CTRL_TSC_BYPASS); // 0x40000001; // start with trigger 0
  1450. IMXRT_ADC_ETC.CTRL |= ADC_ETC_CTRL_DMA_MODE_SEL | ADC_ETC_CTRL_TRIG_ENABLE(1 << ADC_ETC_TRIGGER_INDEX); // Add trigger
  1451. IMXRT_ADC_ETC.TRIG[ADC_ETC_TRIGGER_INDEX].CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(0); // chainlength -1 only us
  1452. IMXRT_ADC_ETC.TRIG[ADC_ETC_TRIGGER_INDEX].CHAIN_1_0 =
  1453. ADC_ETC_TRIG_CHAIN_IE0(1) /*| ADC_ETC_TRIG_CHAIN_B2B0 */
  1454. | ADC_ETC_TRIG_CHAIN_HWTS0(1) | ADC_ETC_TRIG_CHAIN_CSEL0(adc_pin_channel);
  1455. if (adc_regs.GC & ADC_GC_DMAEN)
  1456. {
  1457. IMXRT_ADC_ETC.DMA_CTRL |= ADC_ETC_DMA_CTRL_TRIQ_ENABLE(ADC_ETC_TRIGGER_INDEX);
  1458. }
  1459. }
  1460. // Now init the QTimer.
  1461. // Extracted from quadtimer_init in pwm.c but only the one channel...
  1462. // Maybe see if we have to do this every time we call this. But how often is that?
  1463. IMXRT_TMR4.CH[QTIMER4_INDEX].CTRL = 0; // stop timer
  1464. IMXRT_TMR4.CH[QTIMER4_INDEX].CNTR = 0;
  1465. IMXRT_TMR4.CH[QTIMER4_INDEX].SCTRL = TMR_SCTRL_OEN | TMR_SCTRL_OPS | TMR_SCTRL_VAL | TMR_SCTRL_FORCE;
  1466. IMXRT_TMR4.CH[QTIMER4_INDEX].CSCTRL = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_ALT_LOAD;
  1467. // COMP must be less than LOAD - otherwise output is always low
  1468. IMXRT_TMR4.CH[QTIMER4_INDEX].LOAD = 24000; // low time (65537 - x) -
  1469. IMXRT_TMR4.CH[QTIMER4_INDEX].COMP1 = 0; // high time (0 = always low, max = LOAD-1)
  1470. IMXRT_TMR4.CH[QTIMER4_INDEX].CMPLD1 = 0;
  1471. IMXRT_TMR4.CH[QTIMER4_INDEX].CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) |
  1472. TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(6);
  1473. quadtimerFrequency(&IMXRT_TMR4, QTIMER4_INDEX, freq);
  1474. quadtimerWrite(&IMXRT_TMR4, QTIMER4_INDEX, 5);
  1475. }
  1476. //! Stop the PDB
  1477. void ADC_Module::stopQuadTimer()
  1478. {
  1479. quadtimerWrite(&IMXRT_TMR4, QTIMER4_INDEX, 0);
  1480. setSoftwareTrigger();
  1481. }
  1482. //! Return the PDB's frequency
  1483. uint32_t ADC_Module::getQuadTimerFrequency()
  1484. {
  1485. // Can I reverse the calculations of quad timer set frequency?
  1486. uint32_t high = IMXRT_TMR4.CH[QTIMER4_INDEX].CMPLD1;
  1487. uint32_t low = 65537 - IMXRT_TMR4.CH[QTIMER4_INDEX].LOAD;
  1488. uint32_t highPlusLow = high + low; //
  1489. if (highPlusLow == 0)
  1490. return 0; //
  1491. uint8_t pcs = (IMXRT_TMR4.CH[QTIMER4_INDEX].CTRL >> 9) & 0x7;
  1492. uint32_t freq = (F_BUS_ACTUAL >> pcs) / highPlusLow;
  1493. //Serial.printf("ADC_Module::getTimerFrequency H:%u L:%u H+L=%u pcs:%u freq:%u\n", high, low, highPlusLow, pcs, freq);
  1494. return freq;
  1495. }
  1496. #endif // Teensy 4
  1497. #endif // ADC_USE_QUAD_TIMER