My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HAL.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /**
  2. * Marlin 3D Printer Firmware
  3. *
  4. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  5. * SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. *
  20. */
  21. #ifdef __SAMD51__
  22. #include "../../inc/MarlinConfig.h"
  23. #include <Adafruit_ZeroDMA.h>
  24. #include <wiring_private.h>
  25. #ifdef ADAFRUIT_GRAND_CENTRAL_M4
  26. #if USING_HW_SERIALUSB
  27. DefaultSerial1 MSerial0(false, Serial);
  28. #endif
  29. #if USING_HW_SERIAL0
  30. DefaultSerial2 MSerial1(false, Serial1);
  31. #endif
  32. #if USING_HW_SERIAL1
  33. DefaultSerial3 MSerial2(false, Serial2);
  34. #endif
  35. #if USING_HW_SERIAL2
  36. DefaultSerial4 MSerial3(false, Serial3);
  37. #endif
  38. #if USING_HW_SERIAL3
  39. DefaultSerial5 MSerial4(false, Serial4);
  40. #endif
  41. #endif
  42. // ------------------------
  43. // Local defines
  44. // ------------------------
  45. #define GET_TEMP_0_ADC() TERN(HAS_TEMP_ADC_0, PIN_TO_ADC(TEMP_0_PIN), -1)
  46. #define GET_TEMP_1_ADC() TERN(HAS_TEMP_ADC_1, PIN_TO_ADC(TEMP_1_PIN), -1)
  47. #define GET_TEMP_2_ADC() TERN(HAS_TEMP_ADC_2, PIN_TO_ADC(TEMP_2_PIN), -1)
  48. #define GET_TEMP_3_ADC() TERN(HAS_TEMP_ADC_3, PIN_TO_ADC(TEMP_3_PIN), -1)
  49. #define GET_TEMP_4_ADC() TERN(HAS_TEMP_ADC_4, PIN_TO_ADC(TEMP_4_PIN), -1)
  50. #define GET_TEMP_5_ADC() TERN(HAS_TEMP_ADC_5, PIN_TO_ADC(TEMP_5_PIN), -1)
  51. #define GET_TEMP_6_ADC() TERN(HAS_TEMP_ADC_6, PIN_TO_ADC(TEMP_6_PIN), -1)
  52. #define GET_TEMP_7_ADC() TERN(HAS_TEMP_ADC_7, PIN_TO_ADC(TEMP_7_PIN), -1)
  53. #define GET_PROBE_ADC() TERN(HAS_TEMP_PROBE, PIN_TO_ADC(TEMP_PROBE_PIN), -1)
  54. #define GET_BED_ADC() TERN(HAS_TEMP_ADC_BED, PIN_TO_ADC(TEMP_BED_PIN), -1)
  55. #define GET_CHAMBER_ADC() TERN(HAS_TEMP_ADC_CHAMBER, PIN_TO_ADC(TEMP_CHAMBER_PIN), -1)
  56. #define GET_COOLER_ADC() TERN(HAS_TEMP_ADC_COOLER, PIN_TO_ADC(TEMP_COOLER_PIN), -1)
  57. #define GET_FILAMENT_WIDTH_ADC() TERN(FILAMENT_WIDTH_SENSOR, PIN_TO_ADC(FILWIDTH_PIN), -1)
  58. #define GET_BUTTONS_ADC() TERN(HAS_ADC_BUTTONS, PIN_TO_ADC(ADC_KEYPAD_PIN), -1)
  59. #define IS_ADC_REQUIRED(n) ( \
  60. GET_TEMP_0_ADC() == n || GET_TEMP_1_ADC() == n || GET_TEMP_2_ADC() == n || GET_TEMP_3_ADC() == n \
  61. || GET_TEMP_4_ADC() == n || GET_TEMP_5_ADC() == n || GET_TEMP_6_ADC() == n || GET_TEMP_7_ADC() == n \
  62. || GET_PROBE_ADC() == n \
  63. || GET_BED_ADC() == n \
  64. || GET_CHAMBER_ADC() == n \
  65. || GET_COOLER_ADC() == n \
  66. || GET_FILAMENT_WIDTH_ADC() == n \
  67. || GET_BUTTONS_ADC() == n \
  68. )
  69. #if IS_ADC_REQUIRED(0)
  70. #define ADC0_IS_REQUIRED 1
  71. #define FIRST_ADC 0
  72. #else
  73. #define FIRST_ADC 1
  74. #endif
  75. #if IS_ADC_REQUIRED(1)
  76. #define ADC1_IS_REQUIRED 1
  77. #define LAST_ADC 1
  78. #else
  79. #define LAST_ADC 0
  80. #endif
  81. #if ADC0_IS_REQUIRED || ADC1_IS_REQUIRED
  82. #define ADC_IS_REQUIRED 1
  83. #define DMA_IS_REQUIRED 1
  84. #endif
  85. // ------------------------
  86. // Types
  87. // ------------------------
  88. #if DMA_IS_REQUIRED
  89. // Struct must be 32 bits aligned because of DMA accesses but fields needs to be 8 bits packed
  90. typedef struct __attribute__((aligned(4), packed)) {
  91. ADC_INPUTCTRL_Type INPUTCTRL;
  92. } HAL_DMA_DAC_Registers; // DMA transferred registers
  93. #endif
  94. // ------------------------
  95. // Private Variables
  96. // ------------------------
  97. uint16_t HAL_adc_result;
  98. #if ADC_IS_REQUIRED
  99. // Pins used by ADC inputs. Order must be ADC0 inputs first then ADC1
  100. const uint8_t adc_pins[] = {
  101. // ADC0 pins
  102. #if GET_TEMP_0_ADC() == 0
  103. TEMP_0_PIN,
  104. #endif
  105. #if GET_TEMP_1_ADC() == 0
  106. TEMP_1_PIN,
  107. #endif
  108. #if GET_TEMP_2_ADC() == 0
  109. TEMP_2_PIN,
  110. #endif
  111. #if GET_TEMP_3_ADC() == 0
  112. TEMP_3_PIN,
  113. #endif
  114. #if GET_TEMP_4_ADC() == 0
  115. TEMP_4_PIN,
  116. #endif
  117. #if GET_TEMP_5_ADC() == 0
  118. TEMP_5_PIN,
  119. #endif
  120. #if GET_TEMP_6_ADC() == 0
  121. TEMP_6_PIN,
  122. #endif
  123. #if GET_TEMP_7_ADC() == 0
  124. TEMP_7_PIN,
  125. #endif
  126. #if GET_PROBE_ADC() == 0
  127. TEMP_PROBE_PIN,
  128. #endif
  129. #if GET_BED_ADC() == 0
  130. TEMP_BED_PIN,
  131. #endif
  132. #if GET_CHAMBER_ADC() == 0
  133. TEMP_CHAMBER_PIN,
  134. #endif
  135. #if GET_COOLER_ADC() == 0
  136. TEMP_COOLER_PIN,
  137. #endif
  138. #if GET_FILAMENT_WIDTH_ADC() == 0
  139. FILWIDTH_PIN,
  140. #endif
  141. #if GET_BUTTONS_ADC() == 0
  142. ADC_KEYPAD_PIN,
  143. #endif
  144. // ADC1 pins
  145. #if GET_TEMP_0_ADC() == 1
  146. TEMP_0_PIN,
  147. #endif
  148. #if GET_TEMP_1_ADC() == 1
  149. TEMP_1_PIN,
  150. #endif
  151. #if GET_TEMP_2_ADC() == 1
  152. TEMP_2_PIN,
  153. #endif
  154. #if GET_TEMP_3_ADC() == 1
  155. TEMP_3_PIN,
  156. #endif
  157. #if GET_TEMP_4_ADC() == 1
  158. TEMP_4_PIN,
  159. #endif
  160. #if GET_TEMP_5_ADC() == 1
  161. TEMP_5_PIN,
  162. #endif
  163. #if GET_TEMP_6_ADC() == 1
  164. TEMP_6_PIN,
  165. #endif
  166. #if GET_TEMP_7_ADC() == 1
  167. TEMP_7_PIN,
  168. #endif
  169. #if GET_PROBE_ADC() == 1
  170. TEMP_PROBE_PIN,
  171. #endif
  172. #if GET_BED_ADC() == 1
  173. TEMP_BED_PIN,
  174. #endif
  175. #if GET_CHAMBER_ADC() == 1
  176. TEMP_CHAMBER_PIN,
  177. #endif
  178. #if GET_COOLER_ADC() == 1
  179. TEMP_COOLER_PIN,
  180. #endif
  181. #if GET_FILAMENT_WIDTH_ADC() == 1
  182. FILWIDTH_PIN,
  183. #endif
  184. #if GET_BUTTONS_ADC() == 1
  185. ADC_KEYPAD_PIN,
  186. #endif
  187. };
  188. uint16_t HAL_adc_results[COUNT(adc_pins)];
  189. #if ADC0_IS_REQUIRED
  190. Adafruit_ZeroDMA adc0DMAProgram,
  191. adc0DMARead;
  192. const HAL_DMA_DAC_Registers adc0_dma_regs_list[] = {
  193. #if GET_TEMP_0_ADC() == 0
  194. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  195. #endif
  196. #if GET_TEMP_1_ADC() == 0
  197. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  198. #endif
  199. #if GET_TEMP_2_ADC() == 0
  200. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  201. #endif
  202. #if GET_TEMP_3_ADC() == 0
  203. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  204. #endif
  205. #if GET_TEMP_4_ADC() == 0
  206. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  207. #endif
  208. #if GET_TEMP_5_ADC() == 0
  209. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  210. #endif
  211. #if GET_TEMP_6_ADC() == 0
  212. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  213. #endif
  214. #if GET_TEMP_7_ADC() == 0
  215. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  216. #endif
  217. #if GET_PROBE_ADC() == 0
  218. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  219. #endif
  220. #if GET_BED_ADC() == 0
  221. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  222. #endif
  223. #if GET_CHAMBER_ADC() == 0
  224. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  225. #endif
  226. #if GET_COOLER_ADC() == 0
  227. { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
  228. #endif
  229. #if GET_FILAMENT_WIDTH_ADC() == 0
  230. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  231. #endif
  232. #if GET_BUTTONS_ADC() == 0
  233. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  234. #endif
  235. };
  236. #define ADC0_AINCOUNT COUNT(adc0_dma_regs_list)
  237. #endif // ADC0_IS_REQUIRED
  238. #if ADC1_IS_REQUIRED
  239. Adafruit_ZeroDMA adc1DMAProgram,
  240. adc1DMARead;
  241. const HAL_DMA_DAC_Registers adc1_dma_regs_list[] = {
  242. #if GET_TEMP_0_ADC() == 1
  243. { PIN_TO_INPUTCTRL(TEMP_0_PIN) },
  244. #endif
  245. #if GET_TEMP_1_ADC() == 1
  246. { PIN_TO_INPUTCTRL(TEMP_1_PIN) },
  247. #endif
  248. #if GET_TEMP_2_ADC() == 1
  249. { PIN_TO_INPUTCTRL(TEMP_2_PIN) },
  250. #endif
  251. #if GET_TEMP_3_ADC() == 1
  252. { PIN_TO_INPUTCTRL(TEMP_3_PIN) },
  253. #endif
  254. #if GET_TEMP_4_ADC() == 1
  255. { PIN_TO_INPUTCTRL(TEMP_4_PIN) },
  256. #endif
  257. #if GET_TEMP_5_ADC() == 1
  258. { PIN_TO_INPUTCTRL(TEMP_5_PIN) },
  259. #endif
  260. #if GET_TEMP_6_ADC() == 1
  261. { PIN_TO_INPUTCTRL(TEMP_6_PIN) },
  262. #endif
  263. #if GET_TEMP_7_ADC() == 1
  264. { PIN_TO_INPUTCTRL(TEMP_7_PIN) },
  265. #endif
  266. #if GET_PROBE_ADC() == 1
  267. { PIN_TO_INPUTCTRL(TEMP_PROBE_PIN) },
  268. #endif
  269. #if GET_BED_ADC() == 1
  270. { PIN_TO_INPUTCTRL(TEMP_BED_PIN) },
  271. #endif
  272. #if GET_CHAMBER_ADC() == 1
  273. { PIN_TO_INPUTCTRL(TEMP_CHAMBER_PIN) },
  274. #endif
  275. #if GET_COOLER_ADC() == 1
  276. { PIN_TO_INPUTCTRL(TEMP_COOLER_PIN) },
  277. #endif
  278. #if GET_FILAMENT_WIDTH_ADC() == 1
  279. { PIN_TO_INPUTCTRL(FILWIDTH_PIN) },
  280. #endif
  281. #if GET_BUTTONS_ADC() == 1
  282. { PIN_TO_INPUTCTRL(ADC_KEYPAD_PIN) },
  283. #endif
  284. };
  285. #define ADC1_AINCOUNT COUNT(adc1_dma_regs_list)
  286. #endif // ADC1_IS_REQUIRED
  287. #endif // ADC_IS_REQUIRED
  288. // ------------------------
  289. // Private functions
  290. // ------------------------
  291. #if DMA_IS_REQUIRED
  292. void dma_init() {
  293. DmacDescriptor *descriptor;
  294. #if ADC0_IS_REQUIRED
  295. adc0DMAProgram.setTrigger(ADC0_DMAC_ID_SEQ);
  296. adc0DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  297. adc0DMAProgram.loop(true);
  298. if (adc0DMAProgram.allocate() == DMA_STATUS_OK) {
  299. descriptor = adc0DMAProgram.addDescriptor(
  300. (void *)adc0_dma_regs_list, // SRC
  301. (void *)&ADC0->DSEQDATA.reg, // DEST
  302. sizeof(adc0_dma_regs_list) / 4, // CNT
  303. DMA_BEAT_SIZE_WORD,
  304. true, // SRCINC
  305. false, // DSTINC
  306. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  307. DMA_STEPSEL_SRC // STEPSEL
  308. );
  309. if (descriptor)
  310. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  311. adc0DMAProgram.startJob();
  312. }
  313. adc0DMARead.setTrigger(ADC0_DMAC_ID_RESRDY);
  314. adc0DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  315. adc0DMARead.loop(true);
  316. if (adc0DMARead.allocate() == DMA_STATUS_OK) {
  317. adc0DMARead.addDescriptor(
  318. (void *)&ADC0->RESULT.reg, // SRC
  319. &HAL_adc_results, // DEST
  320. ADC0_AINCOUNT, // CNT
  321. DMA_BEAT_SIZE_HWORD,
  322. false, // SRCINC
  323. true, // DSTINC
  324. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  325. DMA_STEPSEL_DST // STEPSEL
  326. );
  327. adc0DMARead.startJob();
  328. }
  329. #endif
  330. #if ADC1_IS_REQUIRED
  331. adc1DMAProgram.setTrigger(ADC1_DMAC_ID_SEQ);
  332. adc1DMAProgram.setAction(DMA_TRIGGER_ACTON_BEAT);
  333. adc1DMAProgram.loop(true);
  334. if (adc1DMAProgram.allocate() == DMA_STATUS_OK) {
  335. descriptor = adc1DMAProgram.addDescriptor(
  336. (void *)adc1_dma_regs_list, // SRC
  337. (void *)&ADC1->DSEQDATA.reg, // DEST
  338. sizeof(adc1_dma_regs_list) / 4, // CNT
  339. DMA_BEAT_SIZE_WORD,
  340. true, // SRCINC
  341. false, // DSTINC
  342. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  343. DMA_STEPSEL_SRC // STEPSEL
  344. );
  345. if (descriptor)
  346. descriptor->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_BEAT;
  347. adc1DMAProgram.startJob();
  348. }
  349. adc1DMARead.setTrigger(ADC1_DMAC_ID_RESRDY);
  350. adc1DMARead.setAction(DMA_TRIGGER_ACTON_BEAT);
  351. adc1DMARead.loop(true);
  352. if (adc1DMARead.allocate() == DMA_STATUS_OK) {
  353. adc1DMARead.addDescriptor(
  354. (void *)&ADC1->RESULT.reg, // SRC
  355. &HAL_adc_results[ADC0_AINCOUNT], // DEST
  356. ADC1_AINCOUNT, // CNT
  357. DMA_BEAT_SIZE_HWORD,
  358. false, // SRCINC
  359. true, // DSTINC
  360. DMA_ADDRESS_INCREMENT_STEP_SIZE_1, // STEPSIZE
  361. DMA_STEPSEL_DST // STEPSEL
  362. );
  363. adc1DMARead.startJob();
  364. }
  365. #endif
  366. DMAC->PRICTRL0.bit.RRLVLEN0 = true; // Activate round robin for DMA channels required by ADCs
  367. }
  368. #endif // DMA_IS_REQUIRED
  369. // ------------------------
  370. // Public functions
  371. // ------------------------
  372. // HAL initialization task
  373. void HAL_init() {
  374. TERN_(DMA_IS_REQUIRED, dma_init());
  375. #if ENABLED(SDSUPPORT)
  376. #if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT)
  377. SET_INPUT_PULLUP(SD_DETECT_PIN);
  378. #endif
  379. OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
  380. #endif
  381. }
  382. // HAL idle task
  383. /*
  384. void HAL_idletask() {
  385. }
  386. */
  387. void HAL_clear_reset_source() { }
  388. #pragma push_macro("WDT")
  389. #undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
  390. uint8_t HAL_get_reset_source() {
  391. RSTC_RCAUSE_Type resetCause;
  392. resetCause.reg = REG_RSTC_RCAUSE;
  393. if (resetCause.bit.POR) return RST_POWER_ON;
  394. else if (resetCause.bit.EXT) return RST_EXTERNAL;
  395. else if (resetCause.bit.BODCORE || resetCause.bit.BODVDD) return RST_BROWN_OUT;
  396. else if (resetCause.bit.WDT) return RST_WATCHDOG;
  397. else if (resetCause.bit.SYST || resetCause.bit.NVM) return RST_SOFTWARE;
  398. else if (resetCause.bit.BACKUP) return RST_BACKUP;
  399. return 0;
  400. }
  401. #pragma pop_macro("WDT")
  402. void HAL_reboot() { NVIC_SystemReset(); }
  403. extern "C" {
  404. void * _sbrk(int incr);
  405. extern unsigned int __bss_end__; // end of bss section
  406. }
  407. // Return free memory between end of heap (or end bss) and whatever is current
  408. int freeMemory() {
  409. int free_memory, heap_end = (int)_sbrk(0);
  410. return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
  411. }
  412. // ------------------------
  413. // ADC
  414. // ------------------------
  415. void HAL_adc_init() {
  416. #if ADC_IS_REQUIRED
  417. memset(HAL_adc_results, 0xFF, sizeof(HAL_adc_results)); // Fill result with invalid values
  418. LOOP_L_N(pi, COUNT(adc_pins))
  419. pinPeripheral(adc_pins[pi], PIO_ANALOG);
  420. LOOP_S_LE_N(ai, FIRST_ADC, LAST_ADC) {
  421. Adc* adc = ((Adc*[])ADC_INSTS)[ai];
  422. // ADC clock setup
  423. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN = false;
  424. SYNC(GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  425. GCLK->PCHCTRL[ADC0_GCLK_ID + ai].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN; // 48MHz startup code programmed
  426. SYNC(!GCLK->PCHCTRL[ADC0_GCLK_ID + ai].bit.CHEN);
  427. adc->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV32_Val; // 1.5MHZ adc clock
  428. // ADC setup
  429. // Preloaded data (fixed for all ADC instances hence not loaded by DMA)
  430. adc->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; // VRefA pin
  431. SYNC(adc->SYNCBUSY.bit.REFCTRL);
  432. adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val; // ... ADC_CTRLB_RESSEL_16BIT_Val
  433. SYNC(adc->SYNCBUSY.bit.CTRLB);
  434. adc->SAMPCTRL.bit.SAMPLEN = (6 - 1); // Sampling clocks
  435. //adc->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(4); // 16 Accumulated conversions and shift 4 to get oversampled 12 bits result
  436. //SYNC(adc->SYNCBUSY.bit.AVGCTRL);
  437. // Registers loaded by DMA
  438. adc->DSEQCTRL.bit.INPUTCTRL = true;
  439. adc->DSEQCTRL.bit.AUTOSTART = true; // Start conversion after DMA sequence
  440. adc->CTRLA.bit.ENABLE = true; // Enable ADC
  441. SYNC(adc->SYNCBUSY.bit.ENABLE);
  442. }
  443. #endif // ADC_IS_REQUIRED
  444. }
  445. void HAL_adc_start_conversion(const uint8_t adc_pin) {
  446. #if ADC_IS_REQUIRED
  447. LOOP_L_N(pi, COUNT(adc_pins)) {
  448. if (adc_pin == adc_pins[pi]) {
  449. HAL_adc_result = HAL_adc_results[pi];
  450. return;
  451. }
  452. }
  453. #endif
  454. HAL_adc_result = 0xFFFF;
  455. }
  456. #endif // __SAMD51__