| Digital Power Starter Kit 3 Firmware dsPIC33C Boost Converter Voltage Mode Control Example |

p33c_adc.c
1 /*LICENSE *****************************************************************************************
2 *
3 * Software License Agreement
4 *
5 * Copyright (R) 2012 Microchip Technology Inc. All rights reserved. Microchip licenses to you the
6 * right to use, modify, copy and distribute Software only when embedded on a Microchip
7 * microcontroller or digital signal controller, which is integrated into your product or third
8 * party product (pursuant to the sublicense terms in the accompanying license agreement).
9 *
10 * You should refer to the license agreement accompanying this Software for additional information
11 * regarding your rights and obligations.
12 *
13 * SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR
14 * IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT
15 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
16 * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
17 * OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT
18 * LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS
19 * OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY
20 * THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
21 *
22 * ***********************************************************************************************/
23
24 // Include Header Files
25 #include "p33c_adc.h"
26
37 volatile uint16_t adcc_usage=0; // Private variable tracking the ADC cores in use while
38 // ADC inputs and the module gets initialized
39
52 volatile uint16_t ADC_Module_PowerUp(void)
53 {
54 volatile uint16_t fres=1;
55
56 #ifdef PMDCON
57 _PMDLOCK = 1; // Peripheral Module Disable-bits (1=can be set, 0=cannot be set) in software
58 #endif
59 #if defined (_ABGMD)
60 _ABGMD = 0; // Turn on power to analog bandgap reference
61 fres &= (1-_ABGMD);
62 #endif
63 #if defined (_ADCMD)
64 _ADCMD = 0; // Turn on power to ADC module
65 fres &= (1-_ADCMD);
66 #elif defined (_ADC1MD)
67 _ADC1MD = 0; // Turn on power to ADC module
68 fres &= (1-_ADC1MD);
69 #endif
70 #ifdef PMDCON
71 _PMDLOCK = 0; // Peripheral Module Disable-bits (1=can be set, 0=cannot be set) in software
72 #endif
73
74 return(fres);
75
76 }
77
90 volatile uint16_t ADC_Module_PowerDown(void)
91 {
92 volatile uint16_t fres=1;
93
94 Nop(); // No-Operation Instructions required to ensure proper register access
95 Nop(); // DO NOT REMOVE
96 Nop(); // *******************************************************************
97
98 #ifdef PMDCON
99 _PMDLOCK = 1; // Peripheral Module Disable-bits (1=can be set, 0=cannot be set) in software
100 #endif
101 #if defined (_ABGMD)
102 _ABGMD = 1; // Turn off power to analog bandgap reference
103 fres &= (_ABGMD);
104 #endif
105 #if defined (_ADCMD)
106 _ADCMD = 1; // Turn off power to PWM channel #1
107 fres &= (_ADCMD);
108 #elif defined (_ADC1MD)
109 _ADC1MD = 1; // Turn off power to PWM channel #1
110 fres &= (_ADC1MD);
111 #else
112 fres = 0;
113 #endif
114 #ifdef PMDCON
115 _PMDLOCK = 0; // Peripheral Module Disable-bits (1=can be set, 0=cannot be set) in software
116 #endif
117 return(fres);
118
119 }
120
133 volatile uint16_t ADC_Module_Initialize( volatile HSADC_ADMODCFG_t adc_cfg )
134 {
135 volatile uint16_t fres = 1;
136
137 // Ensure ADC module is powered up before registers are written
138 fres &= ADC_Module_PowerUp();
139
140 // Reset all ADC configuration registers to defaults
141 fres &= ADC_Module_Reset();
142
143 // Setting ADC configuration block #1 according to user settings.
144 // Please note:
145 // ADC ENABLE is ALWAYS masked out!
146 // The ADC has to be enabled later during the configuration process.
147
148 _ADON = ADCON1_ADON_DISABLED; // Always disable the ADC converter peripheral while being configured
149 _ADSIDL = adc_cfg.config.adsidl; // Set ADC Stop in Idle Mode bit
150
151 _REFSEL = adc_cfg.refcfg.refsel; // ADC Reference Voltage Selection bits
152 _REFCIE = adc_cfg.refcfg.refcie; // Band Gap and Reference Voltage Ready Common Interrupt Enable bit
153 _REFERCIE = adc_cfg.refcfg.refercie; // Band Gap or Reference Voltage Error Common Interrupt Enable bit
154 _WARMTIME = adc_cfg.config.warmtime;
155
156 _FORM = adc_cfg.config.form; // Set Fractional Data Output Format bit
157 _EIEN = adc_cfg.config.eien; // Set Early Interrupts Enable bit
158 ADCON2Lbits.PTGEN = adc_cfg.config.ptgen; // Set External Conversion Request Interface bit
159
160 _CNVCHSEL = adc_cfg.swtrig.cnvchsel; // Channel Number Selection for Software Individual Channel Conversion Trigger bits
161 _SUSPEND = adc_cfg.swtrig.suspend; // All ADC Core Triggers Disable bit
162 _SUSPCIE = adc_cfg.swtrig.suspcie; // Suspend All ADC Cores Common Interrupt Enable bit
163
164 ADCON3Hbits.CLKSEL = adc_cfg.cores.clksel; // Set ADC Module Clock Source Selection bits
165 ADCON3Hbits.CLKDIV = adc_cfg.cores.clkdiv; // Set ADC Module Clock Source Divider bits
166
167 _SHRADCS = adc_cfg.cores.shared_core.adcs; // Shared ADC Core Input Clock Divider bits
168 _SHRRES = adc_cfg.cores.shared_core.res; // Shared ADC Core Resolution Selection bits
169 _SHRSAMC = adc_cfg.cores.shared_core.samc; // Shared ADC Core Sample Time Selection bits
170 _SHREISEL = adc_cfg.cores.shared_core.eisel; // Shared Core Early Interrupt Time Selection bits
171
172 #if defined (ADCORE0L)
173 ADCORE0Hbits.ADCS = adc_cfg.cores.core0.adcs; // Dedicated ADC Core x Input Clock Divider bits
174 ADCORE0Hbits.RES = adc_cfg.cores.core0.res; // Dedicated ADC Core x Resolution Selection bits
175 ADCORE0Hbits.EISEL = adc_cfg.cores.core0.eisel; // Dedicated ADC Core x Early Interrupt Time Selection bits
176 ADCORE0Lbits.SAMC = adc_cfg.cores.core0.samc; // Dedicated ADC Core x Conversion Delay Selection bits
177 ADCON4Lbits.SAMC0EN = adc_cfg.cores.core0.samc_en; // Dedicated ADC Core x Conversion Delay Enable bit
178 #endif
179 #if defined (ADCORE1L)
180 ADCORE1Hbits.ADCS = adc_cfg.cores.core1.adcs; // Dedicated ADC Core x Input Clock Divider bits
181 ADCORE1Hbits.RES = adc_cfg.cores.core1.res; // Dedicated ADC Core x Resolution Selection bits
182 ADCORE1Hbits.EISEL = adc_cfg.cores.core1.eisel; // Dedicated ADC Core x Early Interrupt Time Selection bits
183 ADCORE1Lbits.SAMC = adc_cfg.cores.core1.samc; // Dedicated ADC Core x Conversion Delay Selection bits
184 ADCON4Lbits.SAMC0EN = adc_cfg.cores.core1.samc_en; // Dedicated ADC Core x Conversion Delay Enable bit
185 #endif
186 #if defined (ADCORE2L)
187 ADCORE2Hbits.ADCS = adc_cfg.cores.core2.adcs; // Dedicated ADC Core x Input Clock Divider bits
188 ADCORE2Hbits.RES = adc_cfg.cores.core2.res; // Dedicated ADC Core x Resolution Selection bits
189 ADCORE2Hbits.EISEL = adc_cfg.cores.core2.eisel; // Dedicated ADC Core x Early Interrupt Time Selection bits
190 ADCORE2Lbits.SAMC = adc_cfg.cores.core2.samc; // Dedicated ADC Core x Conversion Delay Selection bits
191 ADCON4Lbits.SAMC0EN = adc_cfg.cores.core2.samc_en; // Dedicated ADC Core x Conversion Delay Enable bit
192 #endif
193
194
195 // Return 1=success, 0=failure
196 return(fres);
197
198 }
199
200
213 volatile uint16_t ADC_ADInput_Initialize( volatile HSADC_ADCANCFG_t adin_cfg ) {
214
215 volatile uint16_t fres = 1;
216
217 // Check if given analog input number is available
218 if(adin_cfg.ad_input > ADC_ANINPUT_COUNT) { return(0); }
219
220 // Track ADC cores in use
221 adcc_usage |= (0x0001 << adin_cfg.config.core_index);
222
223 // Set AD input mode (differential or single ended) and
224 // Conversion data output format (signed/unsigned)
225 fres &= ADC_ADInput_SetMode(adin_cfg);
226
227 // Set interrupt enable and early interrupt enable
228 fres &= ADC_ADInput_SetInterrupt(adin_cfg);
229
230 // Set interrupt trigger mode (level/edge)
231 fres &= ADC_ADInput_SetTriggerMode(adin_cfg);
232
233 // Set interrupt trigger source
234 fres &= ADC_ADInput_SetTriggerSource(adin_cfg);
235
236
237 return(fres);
238
239 }
240
253 volatile uint16_t ADC_Module_Enable(void)
254 {
255 volatile uint16_t fres=1;
256 volatile uint16_t i=0;
257 volatile uint16_t adcore_check=0;
258
259 _ADON = ADC_ON; // Enable ADC module
260 fres &= _ADON; // Check if ADC module is enabled
261
262 // Enable all ADC cores
263 for (i=0; i<ADC_CORE_COUNT; i++) { // Check which of the ADC cores need to be enabled
264 adcore_check = (adcc_usage & (0x0001 << i)); // User ADC Core tracking variable to identify active cores
265 if (adcore_check)
266 { fres &= ADC_Core_PowerUp(i); } // enable active ADC core
267 }
268
269 return(fres);
270
271 }
272
285 volatile uint16_t ADC_Module_Disable(void)
286 {
287
288 ADCON1Lbits.ADON = ADC_OFF; // Disable ADC module
289 return(1 - ADCON1Lbits.ADON);
290
291 }
292
305 volatile uint16_t ADC_Module_Reset(void) {
306
307 /* ToDo: Add register contents check after WRITE */
308
309 // Reset all ADC configuration registers to defaults
310
311 ADCON1Lbits.ADON = ADC_OFF; // Disable ADC
312
313 ADCON1L = REG_ADCON1L_RESET; // Disable and reset ADC configuration register 1 low
314 ADCON1H = REG_ADCON1H_RESET; // Disable and reset ADC configuration register 1 high
315 ADCON2L = REG_ADCON2L_RESET; // Disable and reset ADC configuration register 2 low
316 ADCON2H = REG_ADCON2H_RESET; // Disable and reset ADC configuration register 2 high
317 ADCON3L = REG_ADCON3L_RESET; // Disable and reset ADC configuration register 3 low
318 ADCON3H = REG_ADCON3H_RESET; // Disable and reset ADC configuration register 3 high
319 #if defined (ADCON4L)
320 ADCON4L = REG_ADCON4L_RESET; // Disable and reset ADC configuration register 4 low
321 #endif
322 #if defined (ADCON4H)
323 ADCON4H = REG_ADCON4H_RESET; // Disable and reset ADC configuration register 4 high
324 #endif
325 ADCON5L = REG_ADCON5L_RESET; // Disable and reset ADC configuration register 5 low
326 ADCON5H = REG_ADCON5H_RESET; // Disable and reset ADC configuration register 5 high
327
328 // Reset registers for ADC input channels and sub-modules
329 ADMOD0L = REG_ADMOD0L_RESET; // Disable and reset ADC INPUT MODE CONTROL REGISTER 0 LOW
330 ADMOD0H = REG_ADMOD0H_RESET; // Disable and reset ADC INPUT MODE CONTROL REGISTER 0 HIGH
331 ADMOD1L = REG_ADMOD1L_RESET; // Disable and reset ADC INPUT MODE CONTROL REGISTER 1 LOW
332 #ifdef ADMOD1H
333 ADMOD1H = REG_ADMOD1H_RESET; // Disable and reset ADC INPUT MODE CONTROL REGISTER 1 HIGH
334 #endif
335 ADIEL = REG_ADIEL_RESET; // Disable and reset ADC INTERRUPT ENABLE REGISTER LOW
336 ADIEH = REG_ADIEH_RESET; // Disable and reset ADC INTERRUPT ENABLE REGISTER HIGH
337 ADSTATL = REG_ADSTATL_RESET; // Disable and reset ADC DATA READY STATUS REGISTER LOW
338 ADSTATH = REG_ADSTATH_RESET; // Disable and reset ADC DATA READY STATUS REGISTER HIGH
339 ADEIEL = REG_ADEIEL_RESET; // Disable and reset ADC EARLY INTERRUPT ENABLE REGISTER LOW
340 ADEIEH = REG_ADEIEH_RESET; // Disable and reset ADC EARLY INTERRUPT ENABLE REGISTER HIGH
341 ADEISTATL = REG_ADEISTATL_RESET; // Disable and reset ADC EARLY INTERRUPT STATUS REGISTER LOW
342 ADEISTATH = REG_ADEISTATH_RESET; // Disable and reset ADC EARLY INTERRUPT STATUS REGISTER HIGH
343
344 ADLVLTRGL = REG_ADLVLTRGL_RESET; // Disable and reset ADC LEVEL-SENSITIVE TRIGGER CONTROL REGISTER LOW
345 ADLVLTRGH = REG_ADLVLTRGH_RESET; // Disable and reset ADC LEVEL-SENSITIVE TRIGGER CONTROL REGISTER HIGH
346
347 // Reset ADC core usage tracking variable
348 adcc_usage = 0;
349
350 return(1);
351 }
352
372 volatile uint16_t ADC_Core_CheckReady(void)
373 {
374 volatile uint16_t fres = 1;
375 volatile uint16_t timeout = 0;
376 volatile uint16_t rdy_compare = 0;
377 volatile uint16_t reg_buf = 0;
378
379 /* ToDo: Add register contents check after WRITE */
380
381 fres &= _REFRDY; // Check if Band Gap reference is running and ready
382 fres &= (1-_REFERR); // Check if Band Gap reference indicating error
383
384 reg_buf = (ADCON5L & 0x00FF); // Capture enabled and powered ADC core bits
385 rdy_compare = ((reg_buf << 8) | reg_buf); // Set filter mask for ADC CORE READY bits
386
387 while( (ADCON5L != rdy_compare) && (timeout++ < 0xFFFE) );
388 if(timeout == 0xFFFF) { fres = 0; }
389
390 return(fres);
391 }
392
415 volatile uint16_t ADC_Core_PowerUp(volatile uint16_t index)
416 {
417 volatile uint16_t fres=1;
418 volatile uint16_t *regptr;
419 volatile uint16_t reg_buf=0;
420 volatile uint16_t timeout=0;
421
422 /* ToDo: Add register contents check after WRITE */
423
424 if (index >= ADC_CORE_COUNT) return(0);
425
426 regptr = (volatile uint16_t *)&ADCON5L;
427
428 // Power on ADC core x
429 if(index == ADC_SHARED_CORE_INDEX) {
430 // Shared Core Power Setting is located in Bit #7, while all others are
431 // enumerated on Bits #0 = dedicated core #0, #1 = dedicated core #1, etc
432 reg_buf = (REG_ADCON5L_SHRPWR_ON & REG_ADCON5L_VALID_DATA_WRITE_MSK);
433
434 }
435 else {
436 // Dedicated core power on enable bits are set based on the index/bit position
437 reg_buf = ((0x0001 << index) & REG_ADCON5L_VALID_DATA_WRITE_MSK);
438 }
439
440 if(!(*regptr & reg_buf)) // if bit hasn't been set yet...
441 { *regptr |= reg_buf; } // write to register
442 fres &= (volatile bool)((*regptr & reg_buf) == reg_buf);
443
444 // Check READY status of powered-up ADC core
445 reg_buf <<= 8; // Shift selected bit up into the high-word of ADCON5L for the status check
446 while(!(ADCON5L & reg_buf) && (timeout++ < 0xFFFE) );
447 if(timeout == 0xFFFF) return(0);
448
449 // Set pointer onto ADC core enable register ADCON3H
450 regptr = (volatile uint16_t *)&ADCON3H;
451
452 // Power on ADC core x
453 if(index == ADC_SHARED_CORE_INDEX) {
454 // Shared Core Power Setting is located in Bit #7, while all others are
455 // enumerated on Bits #0 = dedicated core #0, #1 = dedicated core #1, etc
456 reg_buf = (REG_ADCON3H_SHREN_ENABLED & REG_ADCON3H_VALID_DATA_WRITE_MSK);
457
458 }
459 else {
460 // Dedicated core power on enable bits are set based on the index/bit position
461 reg_buf = ((0x0001 << index) & REG_ADCON3H_VALID_DATA_WRITE_MSK);
462 }
463
464 if(!(*regptr & reg_buf)) // if bit hasn't been set yet...
465 { *regptr |= reg_buf; } // write to register
466 fres &= (volatile bool)((*regptr & reg_buf) == reg_buf);
467
468 return(fres);
469
470 }
471
491 volatile uint16_t ADC_ADInput_SetTriggerSource(volatile HSADC_ADCANCFG_t adin_cfg)
492 {
493 volatile uint16_t fres = 1;
494 volatile uint8_t *regptr;
495
496 // Check if given ADC input index is within available range
497 if (adin_cfg.ad_input >= ADC_ANINPUT_COUNT) return(0);
498
499 // Determine register set offset
500 regptr = (volatile uint8_t *)&ADTRIG0L; // get register block base address
501 regptr += (volatile uint8_t)adin_cfg.ad_input; // add offset
502 *regptr = (volatile uint8_t)adin_cfg.config.trigger_source;
503
504 // Check if WRITE operation was successful
505 fres &= (volatile bool)((*regptr == (volatile uint8_t)adin_cfg.config.trigger_source));
506
507 return(1);
508 }
509
527 volatile uint16_t ADC_ADInput_SetInterrupt(volatile HSADC_ADCANCFG_t adin_cfg)
528 {
529 volatile uint16_t fres = 1;
530 volatile uint16_t ad_idx = 0;
531 volatile uint16_t reg_val = 0;
532
533 /* ToDo: Add register contents check after WRITE */
534
535 if (adin_cfg.ad_input >= ADC_ANINPUT_COUNT)
536 return(0);
537
538 ad_idx = (volatile uint16_t)adin_cfg.ad_input;
539
540 if (ad_idx<16) {
541
542 // Setting the Early Interrupt Enable Bit
543 reg_val = (volatile uint16_t)adin_cfg.config.early_interrupt_enable;
544 reg_val <<= ad_idx;
545 ADEIEL |= (reg_val & REG_ADEIEL_VALID_DATA_MSK);
546 fres &= (volatile bool)((ADEIEL & reg_val) == reg_val);
547
548 // Setting the Interrupt Enable Bit
549 reg_val = (volatile uint16_t)adin_cfg.config.interrupt_enable;
550 reg_val <<= ad_idx;
551 ADIEL |= (reg_val & REG_ADIEL_VALID_DATA_MSK);
552 fres &= (volatile bool)((ADIEL & reg_val) == reg_val);
553
554 }
555 else {
556
557 ad_idx -= 16; // Shift analog input channel bit back to position zero
558
559 #ifdef ADEIEH
560 // Setting the Early Interrupt Enable Bit
561 reg_val = (volatile uint16_t)adin_cfg.config.early_interrupt_enable;
562 reg_val <<= ad_idx;
563 reg_val &= REG_ADEIEH_VALID_DATA_MSK;
564 ADEIEH |= reg_val;
565 fres &= (volatile bool)((ADEIEH & reg_val) == reg_val);
566
567 // Setting the Interrupt Enable Bit
568 reg_val = (volatile uint16_t)adin_cfg.config.interrupt_enable;
569 reg_val <<= ad_idx;
570 ADIEH |= (reg_val & REG_ADIEH_VALID_DATA_MSK);
571 fres &= (volatile bool)((ADIEH & reg_val) == reg_val);
572
573 #else
574 return(0);
575 #endif
576 }
577
578
579 return(fres);
580
581 }
582
602 volatile uint16_t ADC_ADInput_SetTriggerMode(volatile HSADC_ADCANCFG_t adin_cfg)
603 {
604 volatile uint16_t fres = 1;
605 volatile uint16_t regval = 0;
606 volatile uint16_t ad_idx = 0;
607
608 // Check if channel number exists
609 if (adin_cfg.ad_input >= ADC_ANINPUT_COUNT) return(0);
610
611 ad_idx = adin_cfg.ad_input; // Copy analog input number
612
613 // Map bit on right register (HIGH or LOW)
614 if (ad_idx<16) {
615 // Setting the Trigger Mode Bit
616 regval = (((volatile uint16_t)adin_cfg.config.trigger_mode) << ad_idx);
617 ADLVLTRGL |= (regval & REG_ADSTATL_VALID_DATA_MSK);
618 fres &= (volatile bool)((ADLVLTRGL & regval) == regval); // Check if bit has been set
619 }
620 else {
621
622 #ifdef ADLVLTRGH
623 ad_idx -= 16; // Scale ANx-number down into single register field
624 regval = (((volatile uint16_t)adin_cfg.config.trigger_mode) << ad_idx);
625 ADLVLTRGH |= (regval & REG_ADSTATH_VALID_DATA_MSK);
626 fres &= (volatile bool)((ADLVLTRGH & regval) == regval); // Check if bit has been set
627 #else
628 return(0); // Return ERROR if register does not exists
629 #endif
630 }
631
632 // Return Success/Error bit
633 return(fres);
634
635 }
636
663 volatile uint16_t ADC_ADInput_SetMode(volatile HSADC_ADCANCFG_t adin_cfg)
664 {
665 volatile uint16_t fres = 1;
666 volatile uint16_t ad_idx=0;
667 volatile uint16_t regval = 0;
668
669 // Check if channel number exists
670 if (adin_cfg.ad_input >= ADC_ANINPUT_COUNT)
671 return(0);
672
673 ad_idx = adin_cfg.ad_input; // Copy analog input channel number
674
675 // Build dual-bit value of settings
676 regval = (volatile uint16_t)adin_cfg.config.input_mode;
677 regval <<= 1;
678 regval |= (volatile uint16_t)adin_cfg.config.data_mode;
679
680 // Map bit on right register (HIGH or LOW)
681 if (adin_cfg.ad_input<8) {
682 // Setting the analog input mode of channel 0 to 7
683 ad_idx <<= 1; // Multiply index by 2
684 regval <<= ad_idx; // Shift bits up to channel index
685 ADMOD0L |= (regval & REG_ADMOD0L_VALID_DATA_MSK); // write value into register
686 fres &= (volatile bool)((ADMOD0L & regval) == regval); // Check if bit has been set
687 }
688 else if (adin_cfg.ad_input<16) {
689 // Setting the analog input mode of channel 8 to 15
690 ad_idx -= 8; // Scale ANx-number down into single register field
691 ad_idx <<= 1; // Multiply index by 2
692 regval <<= ad_idx; // Shift bits up to channel index
693 ADMOD0H |= (regval & REG_ADMOD0H_VALID_DATA_MSK); // write value into register
694 fres &= (volatile bool)((ADMOD0H & regval) == regval); // Check if bit has been set
695 }
696 else if (adin_cfg.ad_input<24) {
697 // Setting the analog input mode of channel 16 to 23
698 ad_idx -= 16; // Scale ANx-number down into single register field
699 ad_idx <<= 1; // Multiply index by 2
700 regval <<= ad_idx; // Shift bits up to channel index
701 ADMOD1L |= (regval & REG_ADMOD1L_VALID_DATA_MSK); // write value into register
702 fres &= (volatile bool)((ADMOD1L & regval) == regval); // Check if bit has been set
703 }
704 else {
705
706 #if defined (ADMOD1H)
707 // Setting the analog input mode of channel 24 to 31
708 ad_idx -= 24; // Scale ANx-number down into single register field
709 ad_idx <<= 1; // Multiply index by 2
710 regval <<= ad_idx; // Shift bits up to channel index
711 ADMOD1H |= (regval & REG_ADMOD1H_VALID_DATA_MSK); // write value into register
712 fres &= (volatile bool)((ADMOD1H & regval) == regval); // Check if bit has been set
713
714 #else
715 fres = 0; // Return ERROR if register does not exists
716 #endif
717 }
718
719
720 // Return Success/Error bit
721 return(fres);
722
723 }
724
725
726
743 volatile uint16_t ADC_ADComp_Initialize(volatile uint16_t index, volatile HSADC_ADCMP_CONFIG_t adcmp_cfg)
744 {
745
746 volatile uint16_t fres = 1;
747 volatile uint16_t *regptr16;
748 volatile uint16_t reg_offset = 0;
749 volatile uint16_t reg_value = 0;
750
751
752 if (index >= (ADC_ADCMP_COUNT-1)) return(0); // Check if analog input number is valid
753
754 // ADC Comparator Configuration
755 reg_offset = (index) * ((volatile uint16_t)&ADCMP1CON - (volatile uint16_t)&ADCMP0CON); // Get register offset
756 regptr16 = (volatile uint16_t *)&ADCMP0CON + reg_offset; // Set digital comparator configuration value
757 *regptr16 = (adcmp_cfg.ADCMPxCON.value & REG_ADCMPxCON_VALID_DATA_WR_MSK); // Write digital comparator value
758 fres &= ((*regptr16 & REG_ADCMPxCON_VALID_DATA_RD_MSK) == (adcmp_cfg.ADCMPxCON.value & REG_ADCMPxCON_VALID_DATA_WR_MSK)); // Test if written value matches parameter
759
760 // Lower Threshold Compare Value
761 reg_offset = (index) * ((volatile uint16_t)&ADCMP1LO - (volatile uint16_t)&ADCMP0LO); // Get register offset
762 regptr16 = (volatile uint16_t *)&ADCMP0LO + reg_offset; // Get lower threshold value
763 *regptr16 = (adcmp_cfg.ADCMPxLO & REG_ADCMPxLO_VALID_DATA_MSK); // Write lower threshold value
764 fres &= ((*regptr16 & REG_ADCMPxLO_VALID_DATA_MSK) == (adcmp_cfg.ADCMPxLO & REG_ADCMPxLO_VALID_DATA_MSK)); // Test if written value matches parameter
765
766 // Upper Threshold Compare Value
767 reg_offset = (index) * ((volatile uint16_t)&ADCMP1HI - (volatile uint16_t)&ADCMP0HI); // Get register offset
768 regptr16 = (volatile uint16_t *)&ADCMP0HI + reg_offset; // Get upper threshold value
769 *regptr16 = (adcmp_cfg.ADCMPxHI & REG_ADCMPxHI_VALID_DATA_MSK); // Write upper threshold value
770 fres &= ((*regptr16 & REG_ADCMPxHI_VALID_DATA_MSK) == (adcmp_cfg.ADCMPxHI & REG_ADCMPxHI_VALID_DATA_MSK)); // Test if written value matches parameter
771
772
773 // Capture ANx input number as source for comparison (this bit is automatically set and doesn't require to be set by the user)
774 reg_value = adcmp_cfg.ADCMPxCON.bits.chnl; // Read ANx input number as comparison source
775
776 if (reg_value < 16) {
777
778 // Enabling the corresponding analog input comparator input
779 reg_offset = (index) * ((volatile uint16_t)&ADCMP1ENL - (volatile uint16_t)&ADCMP0ENL); // Get register offset
780 regptr16 = (volatile uint16_t *)&ADCMP0ENL + reg_offset; // Get upper threshold value
781 *regptr16 = ((1 << reg_value) & REG_ADCMPxENH_VALID_DATA_MSK); // Write input channel enable bit
782
783 }
784 else if (reg_value < 32) {
785
786 #ifdef ADCMP0ENH
787 reg_value -= 16; // "Scale" analog input number 16-31 into register
788
789 // Enabling the corresponding analog input comparator input
790 reg_offset = (index) * ((volatile uint16_t)&ADCMP1ENH - (volatile uint16_t)&ADCMP0ENH); // Get register offset
791 regptr16 = (volatile uint16_t *)&ADCMP0ENH + reg_offset; // Get upper threshold value
792 *regptr16 = ((1 << reg_value) & REG_ADCMPxENH_VALID_DATA_MSK); // Write input channel enable bit
793 #else
794 return(0);
795 #endif
796 }
797 else { return(0); }
798
799 // Check if Analog Input Comparator Enable has been set correctly
800 fres &= (volatile bool)(*regptr16 & (1 << reg_value)); // Test if written value matches parameter
801
802 return(fres);
803
804 }
805
806
827 volatile uint16_t ADC_ADFilter_Initialize(volatile uint16_t index, volatile HSADC_ADFLT_CONFIG_t adflt_cfg) {
828
829 volatile uint16_t fres = 1;
830 volatile uint16_t *regptr16;
831 volatile uint16_t reg_offset = 0;
832
833
834 // Check if analog input number is valid
835 if (index >= (ADC_ADFL_COUNT-1))
836 return(0);
837
838 // ADC Comparator Configuration
839 reg_offset = (index) * ((volatile uint16_t)&ADFL1CON - (volatile uint16_t)&ADFL0CON); // Get register offset
840 regptr16 = (volatile uint16_t *)&ADFL0CON + reg_offset; // Set digital comparator configuration value
841 *regptr16 = (adflt_cfg.ADFLxCON.value & REG_ADFLxCON_VALID_DATA_WR_MSK); // Write digital comparator value
842 fres &= ((*regptr16 & REG_ADFLxCON_VALID_DATA_RD_MSK) == (adflt_cfg.ADFLxCON.value & REG_ADFLxCON_VALID_DATA_WR_MSK)); // Test if written value matches parameter
843
844 // Lower Threshold Compare Value
845 reg_offset = (index) * ((volatile uint16_t)&ADFL1DAT - (volatile uint16_t)&ADFL0DAT); // Get register offset
846 regptr16 = (volatile uint16_t *)&ADFL0DAT + reg_offset; // Get lower threshold value
847 *regptr16 = (adflt_cfg.ADFLxDAT & REG_ADFLxDAT_VALID_DATA_MSK); // Write lower threshold value
848 fres &= ((*regptr16 & REG_ADFLxDAT_VALID_DATA_MSK) == (adflt_cfg.ADFLxDAT & REG_ADFLxDAT_VALID_DATA_MSK)); // Test if written value matches parameter
849
850
851 return(fres);
852
853 }
854
855
856
857 // EOF