text: /**
   * \file
   *
   * \brief Analog-Front-End Controller driver for SAM.
   *
   * Copyright (c) 2013 Atmel Corporation. All rights reserved.
   *
   * \asf_license_start
   *
   * \page License
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice,
   *    this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   *
   * 3. The name of Atmel may not be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * 4. This software may only be redistributed and used in connection with an
   *    Atmel microcontroller product.
   *
   * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
   * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   *
   * \asf_license_stop
   *
   */
  
  #ifndef AFEC_H_INCLUDED
  #define AFEC_H_INCLUDED
  
  #include "compiler.h"
  #include "status_codes.h"
  
  /** Definitions for AFEC resolution */
  enum afec_resolution {
  	AFEC_10_BITS = AFEC_EMR_RES_LOW_RES,       /* AFEC 10-bit resolution */
  	AFEC_12_BITS = AFEC_EMR_RES_NO_AVERAGE,    /* AFEC 12-bit resolution */
  	AFEC_13_BITS = AFEC_EMR_RES_OSR4,          /* AFEC 13-bit resolution */
  	AFEC_14_BITS = AFEC_EMR_RES_OSR16,         /* AFEC 14-bit resolution */
  	AFEC_15_BITS = AFEC_EMR_RES_OSR64,         /* AFEC 15-bit resolution */
  	AFEC_16_BITS = AFEC_EMR_RES_OSR256         /* AFEC 16-bit resolution */
  };
  
  /** Definitions for AFEC power mode */
  enum afec_power_mode {
  	/* AFEC core on and reference voltage circuitry on */
  	AFEC_POWER_MODE_0 = 0,
  	/* AFEC core off and reference voltage circuitry on */
  	AFEC_POWER_MODE_1,
  	/* AFEC core off and reference voltage circuitry off */
  	AFEC_POWER_MODE_2
  };
  
  /** Definitions for AFEC trigger */
  enum afec_trigger {
  	/* Starting a conversion is only possible by software. */
  	AFEC_TRIG_SW = AFEC_MR_TRGEN_DIS,
  	/* External trigger */
  	AFEC_TRIG_EXT = AFEC_MR_TRGSEL_AFEC_TRIG0 | AFEC_MR_TRGEN,
  	/* TIO Output of the Timer Counter Channel 0 */
  	AFEC_TRIG_TIO_CH_0 = AFEC_MR_TRGSEL_AFEC_TRIG1 | AFEC_MR_TRGEN,
  	/* TIO Output of the Timer Counter Channel 1 */
  	AFEC_TRIG_TIO_CH_1 = AFEC_MR_TRGSEL_AFEC_TRIG2 | AFEC_MR_TRGEN,
  	/* TIO Output of the Timer Counter Channel 2 */
  	AFEC_TRIG_TIO_CH_2 = AFEC_MR_TRGSEL_AFEC_TRIG3 | AFEC_MR_TRGEN,
  	/* PWM Event Line 0 */
  	AFEC_TRIG_PWM_EVENT_LINE_0 = AFEC_MR_TRGSEL_AFEC_TRIG4 | AFEC_MR_TRGEN,
  	/* PWM Event Line 1 */
  	AFEC_TRIG_PWM_EVENT_LINE_1 = AFEC_MR_TRGSEL_AFEC_TRIG5 | AFEC_MR_TRGEN,
  	/* Freerun mode conversion. */
  	AFEC_TRIG_FREERUN = 0xFF,
  };
  
  #if defined __SAM4E8C__  || defined __SAM4E16C__
  /** Definitions for AFEC channel number */
  enum afec_channel_num {
  	AFEC_CHANNEL_0 = 0,
  	AFEC_CHANNEL_1,
  	AFEC_CHANNEL_2,
  	AFEC_CHANNEL_3,
  	AFEC_CHANNEL_4,
  	AFEC_CHANNEL_5,
  	AFEC_TEMPERATURE_SENSOR = 15,
  	AFEC_CHANNEL_ALL = 0x803F,
  } ;
  #elif defined __SAM4E8E__  || defined __SAM4E16E__
  /** Definitions for AFEC channel number */
  enum afec_channel_num {
  	AFEC_CHANNEL_0 = 0,
  	AFEC_CHANNEL_1,
  	AFEC_CHANNEL_2,
  	AFEC_CHANNEL_3,
  	AFEC_CHANNEL_4,
  	AFEC_CHANNEL_5,
  	AFEC_CHANNEL_6,
  	AFEC_CHANNEL_7,
  	AFEC_CHANNEL_8,
  	AFEC_CHANNEL_9,
  	AFEC_CHANNEL_10,
  	AFEC_CHANNEL_11,
  	AFEC_CHANNEL_12,
  	AFEC_CHANNEL_13,
  	AFEC_CHANNEL_14,
  	AFEC_TEMPERATURE_SENSOR,
  	AFEC_CHANNEL_ALL = 0xFFFF,
  } ;
  #endif
  
  /** Definitions for AFEC gain value */
  enum afec_gainvalue {
  	AFEC_GAINVALUE_0 = 0,
  	AFEC_GAINVALUE_1 = 1,
  	AFEC_GAINVALUE_2 = 2,
  	AFEC_GAINVALUE_3 = 3
  };
  
  /** Definitions for AFEC Start Up Time */
  enum afec_startup_time {
  	AFEC_STARTUP_TIME_0 = AFEC_MR_STARTUP_SUT0,
  	AFEC_STARTUP_TIME_1 = AFEC_MR_STARTUP_SUT8,
  	AFEC_STARTUP_TIME_2 = AFEC_MR_STARTUP_SUT16,
  	AFEC_STARTUP_TIME_3 = AFEC_MR_STARTUP_SUT24,
  	AFEC_STARTUP_TIME_4 = AFEC_MR_STARTUP_SUT64,
  	AFEC_STARTUP_TIME_5 = AFEC_MR_STARTUP_SUT80,
  	AFEC_STARTUP_TIME_6 = AFEC_MR_STARTUP_SUT96,
  	AFEC_STARTUP_TIME_7 = AFEC_MR_STARTUP_SUT112,
  	AFEC_STARTUP_TIME_8 = AFEC_MR_STARTUP_SUT512,
  	AFEC_STARTUP_TIME_9 = AFEC_MR_STARTUP_SUT576,
  	AFEC_STARTUP_TIME_10 = AFEC_MR_STARTUP_SUT640,
  	AFEC_STARTUP_TIME_11 = AFEC_MR_STARTUP_SUT704,
  	AFEC_STARTUP_TIME_12 = AFEC_MR_STARTUP_SUT768,
  	AFEC_STARTUP_TIME_13 = AFEC_MR_STARTUP_SUT832,
  	AFEC_STARTUP_TIME_14 = AFEC_MR_STARTUP_SUT896,
  	AFEC_STARTUP_TIME_15 = AFEC_MR_STARTUP_SUT960
  };
  
  /** Definitions for AFEC analog settling time */
  enum afec_settling_time {
  	AFEC_SETTLING_TIME_0 = AFEC_MR_SETTLING_AST3,
  	AFEC_SETTLING_TIME_1 = AFEC_MR_SETTLING_AST5,
  	AFEC_SETTLING_TIME_2 = AFEC_MR_SETTLING_AST9,
  	AFEC_SETTLING_TIME_3 = AFEC_MR_SETTLING_AST17
  };
  
  /** Definitions for Comparison Mode */
  enum afec_cmp_mode {
  	AFEC_CMP_MODE_0 = AFEC_EMR_CMPMODE_LOW,
  	AFEC_CMP_MODE_1 = AFEC_EMR_CMPMODE_HIGH,
  	AFEC_CMP_MODE_2 = AFEC_EMR_CMPMODE_IN,
  	AFEC_CMP_MODE_3 = AFEC_EMR_CMPMODE_OUT
  };
  
  /** Definitions for Temperature Comparison Mode */
  enum afec_temp_cmp_mode {
  	AFEC_TEMP_CMP_MODE_0 = AFEC_TEMPMR_TEMPCMPMOD_LOW,
  	AFEC_TEMP_CMP_MODE_1 = AFEC_TEMPMR_TEMPCMPMOD_HIGH,
  	AFEC_TEMP_CMP_MODE_2 = AFEC_TEMPMR_TEMPCMPMOD_IN,
  	AFEC_TEMP_CMP_MODE_3 = AFEC_TEMPMR_TEMPCMPMOD_OUT
  };
  
  /**
   * \brief Analog-Front-End Controller configuration structure.
   *
   * Configuration structure for a Analog-Front-End Controller instance.
   * This structure could be initialized by the \ref afec_get_config_defaults()
   * function before being modified by the user application.
   */
  struct afec_config {
  	/** Resolution */
  	enum afec_resolution resolution;
  	/** Master Clock */
  	uint32_t mck;
  	/** AFEC Clock */
  	uint32_t afec_clock;
  	/** Start Up Time */
  	enum afec_startup_time startup_time;
  	/** Analog Settling Time = (settling_time + 1) / AFEC clock */
  	enum afec_settling_time settling_time;
  	/** Tracking Time = tracktim / AFEC clock */
  	uint8_t tracktim;
  	/** Transfer Period = (transfer * 2 + 3) / AFEC clock */
  	uint8_t transfer;
  	/** Analog Change */
  	bool anach;
  	/** Use Sequence Enable */
  	bool useq;
  	/** TAG of AFE_LDCR register */
  	bool tag;
  	/** Single Trigger Mode */
  	bool stm;
  	/** AFE Bias Current Control */
  	uint8_t ibctl;
  };
  
  /** AFEC channel configuration structure.*/
  struct afec_ch_config {
  	/** Differential Mode */
  	bool diff;
  	/** Gain Value */
  	enum afec_gainvalue gain;
  };
  
  /** AFEC Temperature Sensor configuration structure.*/
  struct afec_temp_sensor_config {
  	/** RTC Trigger mode */
  	bool rctc;
  	/** Temperature Comparison Mode */
  	enum afec_temp_cmp_mode mode;
  	/** Temperature Low Threshold */
  	uint16_t low_threshold;
  	/** Temperature High Threshold */
  	uint16_t high_threshold;
  };
  
  #if defined __SAM4E8C__  || defined __SAM4E16C__
  /** AFEC interrupt source type */
  enum afec_interrupt_source {
  	AFEC_INTERRUPT_EOC_0 = 0,
  	AFEC_INTERRUPT_EOC_1,
  	AFEC_INTERRUPT_EOC_2,
  	AFEC_INTERRUPT_EOC_3,
  	AFEC_INTERRUPT_EOC_4,
  	AFEC_INTERRUPT_EOC_5,
  	AFEC_INTERRUPT_EOC_15,
  	AFEC_INTERRUPT_DATA_READY,
  	AFEC_INTERRUPT_OVERRUN_ERROR,
  	AFEC_INTERRUPT_COMP_ERROR,
  	AFEC_INTERRUPT_END_RXBUF,
  	AFEC_INTERRUPT_RXBUF_FULL,
  	AFEC_INTERRUPT_TEMP_CHANGE,
  	AFEC_INTERRUPT_END_CAL,
  	_AFEC_NUM_OF_INTERRUPT_SOURCE,
  	AFEC_INTERRUPT_ALL = 0xFFFFFFFF,
  };
  #elif defined __SAM4E8E__  || defined __SAM4E16E__
  /** AFEC interrupt source type */
  enum afec_interrupt_source {
  	AFEC_INTERRUPT_EOC_0 = 0,
  	AFEC_INTERRUPT_EOC_1,
  	AFEC_INTERRUPT_EOC_2,
  	AFEC_INTERRUPT_EOC_3,
  	AFEC_INTERRUPT_EOC_4,
  	AFEC_INTERRUPT_EOC_5,
  	AFEC_INTERRUPT_EOC_6,
  	AFEC_INTERRUPT_EOC_7,
  	AFEC_INTERRUPT_EOC_8,
  	AFEC_INTERRUPT_EOC_9,
  	AFEC_INTERRUPT_EOC_10,
  	AFEC_INTERRUPT_EOC_11,
  	AFEC_INTERRUPT_EOC_12,
  	AFEC_INTERRUPT_EOC_13,
  	AFEC_INTERRUPT_EOC_14,
  	AFEC_INTERRUPT_EOC_15,
  	AFEC_INTERRUPT_DATA_READY,
  	AFEC_INTERRUPT_OVERRUN_ERROR,
  	AFEC_INTERRUPT_COMP_ERROR,
  	AFEC_INTERRUPT_END_RXBUF,
  	AFEC_INTERRUPT_RXBUF_FULL,
  	AFEC_INTERRUPT_TEMP_CHANGE,
  	AFEC_INTERRUPT_END_CAL,
  	_AFEC_NUM_OF_INTERRUPT_SOURCE,
  	AFEC_INTERRUPT_ALL = 0xFFFFFFFF,
  };
  #endif
  
  typedef void (*afec_callback_t)(void);
  
  void afec_get_config_defaults(struct afec_config *const cfg);
  void afec_ch_get_config_defaults(struct afec_ch_config *const cfg);
  void afec_temp_sensor_get_config_defaults(
  		struct afec_temp_sensor_config *const cfg);
  enum status_code afec_init(Afec *const afec, struct afec_config *const config);
  void afec_temp_sensor_set_config(Afec *const afec,
  		struct afec_temp_sensor_config *config);
  void afec_ch_set_config(Afec *const afec, const enum afec_channel_num channel,
  		struct afec_ch_config *config);
  void afec_configure_sequence(Afec *const afec,
  		const enum afec_channel_num ch_list[], const uint8_t uc_num);
  void afec_enable(Afec *const afec);
  void afec_disable(Afec *const afec);
  void afec_set_callback(Afec *const afec, enum afec_interrupt_source source,
  		afec_callback_t callback, uint8_t irq_level);
  
  /**
   * \internal
   * \brief AFEC channel sanity check
   *
   * \param afec  Base address of the AFEC.
   * \param channel  AFEC channel number.
   *
   */
  static inline void afec_ch_sanity_check(Afec *const afec,
  		const enum afec_channel_num channel)
  {
  	if (afec == AFEC0) {
  	#if defined __SAM4E8C__  || defined __SAM4E16C__
  		Assert((channel < NB_CH_AFE0) || (channel == AFEC_TEMPERATURE_SENSOR));
  	#elif defined __SAM4E8E__  || defined __SAM4E16E__
  		Assert(channel < NB_CH_AFE0);
  	#endif
  	} else if (afec == AFEC1) {
  		Assert(channel < NB_CH_AFE1);
  	}
  	UNUSED(channel);
  }
  
  /**
   * \brief Configure conversion trigger and free run mode.
   *
   * \param afec  Base address of the AFEC.
   * \param trigger Conversion trigger.
   *
   */
  static inline void afec_set_trigger(Afec *const afec,
  		const enum afec_trigger trigger)
  {
  	uint32_t reg;
  
  	reg = afec->AFEC_MR;
  
  	if (trigger == AFEC_TRIG_FREERUN) {
  		reg |= AFEC_MR_FREERUN_ON;
  	} else {
  		reg &= ~(AFEC_MR_TRGSEL_Msk | AFEC_MR_TRGEN | AFEC_MR_FREERUN_ON);
  		reg |= trigger;
  	}
  
  	afec->AFEC_MR = reg;
  }
  
  /**
   * \brief Configure conversion resolution.
   *
   * \param afec  Base address of the AFEC.
   * \param res Conversion resolution.
   *
   */
  static inline void afec_set_resolution(Afec *const afec,
  		const enum afec_resolution res)
  {
  	uint32_t reg;
  
  	reg = afec->AFEC_EMR;
  
  	reg &= ~AFEC_EMR_RES_Msk;
  	reg |= res;
  
  	afec->AFEC_EMR = reg;
  }
  
  void afec_set_comparison_mode(Afec *const afec,
  		const enum afec_cmp_mode mode, const enum afec_channel_num channel,
  		uint8_t cmp_filter);
  
  /**
   * \brief Get comparison mode.
   *
   * \param afec  Base address of the AFEC.
   *
   * \retval Compare mode value.
   */
  static inline enum afec_cmp_mode afec_get_comparison_mode(Afec *const afec)
  {
  	return (enum afec_cmp_mode)(afec->AFEC_EMR & AFEC_EMR_CMPMODE_Msk);
  }
  
  /**
   * \brief Configure AFEC compare window.
   *
   * \param afec  Base address of the AFEC.
   * \param us_low_threshold Low threshold of compare window.
   * \param us_high_threshold High threshold of compare window.
   */
  static inline void afec_set_comparison_window(Afec *const afec,
  		const uint16_t us_low_threshold, const uint16_t us_high_threshold)
  {
  	afec->AFEC_CWR = AFEC_CWR_LOWTHRES(us_low_threshold) |
  			AFEC_CWR_HIGHTHRES(us_high_threshold);
  }
  
  /**
   * \brief Enable or disable write protection of AFEC registers.
   *
   * \param afec  Base address of the AFEC.
   * \param is_enable 1 to enable, 0 to disable.
   */
  static inline void afec_set_writeprotect(Afec *const afec,
  		const bool is_enable)
  {
  	if (is_enable) {
  		afec->AFEC_WPMR = AFEC_WPMR_WPEN | AFEC_WPMR_WPKEY_ADC;
  	} else {
  		afec->AFEC_WPMR &= ~AFEC_WPMR_WPEN;
  		afec->AFEC_WPMR |= AFEC_WPMR_WPKEY_ADC;
  	}
  }
  
  /**
   * \brief Indicate write protect status.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return 0 if the peripheral is not protected, or 16-bit write protect
   * violation source.
   */
  static inline uint32_t afec_get_writeprotect_status(Afec *const afec)
  {
  	return (afec->AFEC_WPSR & AFEC_WPSR_WPVS) ?
  			(afec->AFEC_WPSR & AFEC_WPMR_WPKEY_Msk) : 0;
  }
  
  /**
   * \brief Get AFEC overrun error status.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return AFEC overrun error status.
   */
  static inline uint32_t afec_get_overrun_status(Afec *const afec)
  {
  	return afec->AFEC_OVER;
  }
  
  /**
   * \brief Start analog-to-digital conversion.
   *
   * \note If one of the hardware event is selected as AFEC trigger,
   * this function can NOT start analog to digital conversion.
   *
   * \param afec  Base address of the AFEC.
   */
  static inline void afec_start_software_conversion(Afec *const afec)
  {
  	afec->AFEC_CR = AFEC_CR_START;
  }
  
  void afec_set_power_mode(Afec *const afec,
  		const enum afec_power_mode mode);
  
  /**
   * \brief Enable the specified AFEC channel.
   *
   * \param afec  Base address of the AFEC.
   * \param afec_ch AFEC channel number.
   */
  static inline void afec_channel_enable(Afec *const afec,
  		const enum afec_channel_num afec_ch)
  {
  	if (afec_ch != AFEC_CHANNEL_ALL) {
  		afec_ch_sanity_check(afec, afec_ch);
  	}
  
  	afec->AFEC_CHER = (afec_ch == AFEC_CHANNEL_ALL) ?
  			AFEC_CHANNEL_ALL : 1 << afec_ch;
  }
  
  /**
   * \brief Disable the specified AFEC channel.
   *
   * \param afec  Base address of the AFEC.
   * \param afec_ch AFEC channel number.
   */
  static inline void afec_channel_disable(Afec *const afec,
  		const enum afec_channel_num afec_ch)
  {
  	if (afec_ch != AFEC_CHANNEL_ALL) {
  		afec_ch_sanity_check(afec, afec_ch);
  	}
  
  	afec->AFEC_CHDR = (afec_ch == AFEC_CHANNEL_ALL) ?
  			AFEC_CHANNEL_ALL : 1 << afec_ch;
  }
  
  /**
   * \brief Get the AFEC channel status.
   *
   * \param afec  Base address of the AFEC.
   * \param afec_ch AFEC channel number.
   *
   * \retval 1 if channel is enabled.
   * \retval 0 if channel is disabled.
   */
  static inline uint32_t afec_channel_get_status(Afec *const afec,
  		const enum afec_channel_num afec_ch)
  {
  	afec_ch_sanity_check(afec, afec_ch);
  
  	return afec->AFEC_CHSR & (1 << afec_ch);
  }
  
  /**
   * \brief Read the Converted Data of the selected channel.
   *
   * \param afec  Base address of the AFEC.
   * \param afec_ch AFEC channel number.
   *
   * \return AFEC converted value of the selected channel.
   */
  static inline uint32_t afec_channel_get_value(Afec *const afec,
  		enum afec_channel_num afec_ch)
  {
  	afec_ch_sanity_check(afec, afec_ch);
  
  	afec->AFEC_CSELR = afec_ch;
  	return afec->AFEC_CDR;
  }
  
  /**
   * \brief Set analog offset to be used for channel CSEL.
   *
   * \param afec  Base address of the AFEC.
   * \param afec_ch AFEC channel number.
   * \param aoffset  Analog offset value.
   */
  static inline void afec_channel_set_analog_offset(Afec *const afec,
  		enum afec_channel_num afec_ch, uint16_t aoffset)
  {
  	afec_ch_sanity_check(afec, afec_ch);
  
  	afec->AFEC_CSELR = afec_ch;
  	afec->AFEC_COCR = (aoffset & AFEC_COCR_AOFF_Msk);
  }
  
  /**
   * \brief Get the Last Data Converted.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return AFEC latest converted value.
   */
  static inline uint32_t afec_get_latest_value(Afec *const afec)
  {
  	return afec->AFEC_LCDR & AFEC_LCDR_LDATA_Msk;
  }
  
  /**
   * \brief Get the Last Converted Channel Number.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return AFEC Last Converted Channel Number.
   */
  static inline uint32_t afec_get_latest_chan_num(Afec *const afec)
  {
  	return (afec->AFEC_LCDR & AFEC_LCDR_CHNB_Msk) >> AFEC_LCDR_CHNB_Pos;
  }
  
  void afec_enable_interrupt(Afec *const afec,
  		enum afec_interrupt_source interrupt_source);
  
  void afec_disable_interrupt(Afec *const afec,
  		enum afec_interrupt_source interrupt_source);
  
  /**
   * \brief Get AFEC interrupt status.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return The interrupt status value.
   */
  static inline uint32_t afec_get_interrupt_status(Afec *const afec)
  {
  	return afec->AFEC_ISR;
  }
  
  /**
   * \brief Get AFEC interrupt mask.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return The interrupt mask value.
   */
  static inline uint32_t afec_get_interrupt_mask(Afec *const afec)
  {
  	return afec->AFEC_IMR;
  }
  
  /**
   * \brief Get PDC registers base address.
   *
   * \param afec  Base address of the AFEC.
   *
   * \return AFEC PDC register base address.
   */
  static inline Pdc *afec_get_pdc_base(Afec *const afec)
  {
  	Pdc *p_pdc_base = NULL;
  
  #ifdef PDC_AFEC0
  	if (afec == AFEC0) {
  		p_pdc_base = PDC_AFEC0;
  	}
  #endif
  
  #ifdef PDC_AFEC1
  	else if (afec == AFEC1) {
  		p_pdc_base = PDC_AFEC1;
  	}
  #endif
  
  	return p_pdc_base;
  }
  
  /**
   * \brief Launch an automatic calibration of the AFEC on next sequence.
   *
   * \param afec  Base address of the AFEC.
   *
   * \retval STATUS_OK  An automatic calibration is launched.
   * \retval STATUS_ERR_BUSY  Automatic calibration can not be launched because
   *         the AFEC is in freerun mode.
   */
  static inline enum status_code afec_start_calibration(Afec *const afec)
  {
  	uint32_t reg;
  
  	reg = afec->AFEC_CHSR;
  	afec->AFEC_CDOR = reg;
  
  	if ((afec->AFEC_MR & AFEC_MR_FREERUN) == AFEC_MR_FREERUN_ON) {
  		return STATUS_ERR_BUSY;
  	}
  	afec->AFEC_CR = AFEC_CR_AUTOCAL;
  	return STATUS_OK;
  }
  
  /**
   * \page sam_afec_quickstart Quickstart guide for SAM AFEC driver
   *
   * This is the quickstart guide for the \ref sam_drivers_afec_group
   * "SAM AFEC driver" with step-by-step instructions on how to configure and use
   * the driver in a selection of use cases.
   *
   * The use cases contain several code fragments. The code fragments in the
   * steps for setup can be copied into a custom initialization function, while
   * the steps for usage can be copied into, e.g., the main application function.
   *
   * \section afec_basic_use_case Basic use case
   * In this basic use case, the AFEC module and single channel are configured for:
   * - 12 -bit resolution
   * - AFEC clock frequency is 6MHz
   * - Start Up Time is 64 periods AFEC clock
   * - Analog Settling Time is 3 periods of AFEC clock
   * - Tracking Time is 3 periods of AFEC clock
   * - Transfer Period is 5 periods AFEC clock
   * - Allows different analog settings for each channel
   * - The controller converts channels in a simple numeric order
   * - Appends the channel number to the conversion result in AFE_LDCR register
   * - Only a Single Trigger is required to get an averaged value
   * - AFE Bias Current Control value is 1
   * - Software triggering of conversions
   * - Single channel measurement
   * - AFEC_CHANNEL_5 of AFEC0 as input
   *
   * \subsection sam_afec_quickstart_prereq Prerequisites
   * -# \ref sysclk_group "System Clock Management (Sysclock)"
   *
   * \section afec_basic_use_case_setup Setup steps
   * \subsection afec_basic_use_case_setup_code Example code
   * Add to application C-file:
   * \code
   *  afec_enable(AFEC0);
   *  afec_get_config_defaults(&afec_cfg);
   *  afec_init(AFEC0, &afec_cfg);
   *  afec_set_trigger(AFEC0, AFEC_TRIG_SW);
   *  afec_channel_enable(AFEC0, AFEC_CHANNEL_5);
   * \endcode
   *
   * \subsection afec_basic_use_case_setup_flow Workflow
   * -# Enable AFEC Module:
   *   - \code afec_enable(AFEC0); \endcode
   * -# Get the AFEC default configurations:
   *   - \code afec_get_config_defaults(&afec_cfg); \endcode
   * -# Initialize the AFEC Module:
   *   - \code  afec_init(AFEC0, &afec_cfg); \endcode
   * -# Configure conversion trigger and free run mode:
   *   - \code afec_set_trigger(AFEC0, AFEC_TRIG_SW); \endcode
   * -# Enable Channel:
   *   - \code afec_channel_enable(AFEC0, AFEC_CHANNEL_5); \endcode
   *
   * \section afec_basic_use_case_usage Usage steps
   * \subsection afec_basic_use_case_usage_code Example code
   * Add to, e.g., main loop in application C-file:
   * \code
   *  afec_start_software_conversion(AFEC0);
   *  while (afec_get_interrupt_status(AFEC0) & (1 << AFEC_CHANNEL_5));
   *  uint32_t result = afec_channel_get_value(AFEC0, AFEC_CHANNEL_5);
   * \endcode
   *
   * \subsection afec_basic_use_case_usage_flow Workflow
   * -# Start AFEC conversion on channel:
   *   - \code afec_start_software_conversion(AFEC0); \endcode
   * -# Wait for the conversion over:
   *   - \code while (afec_get_interrupt_status(AFEC0) & (1 << AFEC_CHANNEL_5));
   *     \endcode
   * -# Get the conversion result:
   *   - \code uint32_t result = afec_channel_get_value(AFEC0, AFEC_CHANNEL_5);
   *     \endcode
   */
  #endif /* AFEC_H_INCLUDED */
  