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 15KB

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