Digital Power Starter Kit 3 Firmware
dsPIC33C Buck 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