/**
  * @brief  Get the calibration factor.
  * @param  hadc: ADC handle.
  * @param  SingleDiff: This parameter can be only:
  *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
  * @retval Calibration value.
  */
uint32_t HAL_ADCEx_Calibration_GetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
{
  /* Check the parameters */
  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); 
  
  /* Return the ADC calibration value */ 
  return ((hadc->Instance->CALFACT) & 0x0000007F);
}
/**
  * @brief  Set the calibration factor to overwrite automatic conversion result.
  *         ADC must be enabled and no conversion is ongoing.
  * @param  hadc: ADC handle
  * @param  SingleDiff: This parameter can be only:
  *           @arg ADC_SINGLE_ENDED: Channel in mode input single ended.
  * @param  CalibrationFactor: Calibration factor (coded on 7 bits maximum)
  * @retval HAL state
  */
HAL_StatusTypeDef HAL_ADCEx_Calibration_SetValue(ADC_HandleTypeDef* hadc, uint32_t SingleDiff, uint32_t CalibrationFactor)
{
  HAL_StatusTypeDef tmp_hal_status = HAL_OK;
  
  /* Check the parameters */
  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); 
  assert_param(IS_ADC_CALFACT(CalibrationFactor)); 
  
  /* Process locked */
  __HAL_LOCK(hadc);
  
  /* Verification of hardware constraints before modifying the calibration    */
  /* factors register: ADC must be enabled, no conversion on going.           */
  if ( (ADC_IS_ENABLE(hadc) != RESET)                            &&
       (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)  )
  {
    /* Set the selected ADC calibration value */ 
    hadc->Instance->CALFACT &= ~ADC_CALFACT_CALFACT;
    hadc->Instance->CALFACT |= CalibrationFactor;
  }
  else
  {
    /* Update ADC state machine to error */
    SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
    /* Update ADC state machine to error */
    SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
    
    /* Update ADC state machine to error */
    tmp_hal_status = HAL_ERROR;
  }
  
  /* Process unlocked */
  __HAL_UNLOCK(hadc);
  
  /* Return function status */
  return tmp_hal_status;
}
/**
  * @brief  Start an automatic calibration
  * @param  hadc: pointer to a ADC_HandleTypeDef structure that contains
  *         the configuration information for the specified ADC.
  * @param  SingleDiff: Selection of single-ended or differential input
  *          This parameter can be only of the following values:
  *            @arg ADC_SINGLE_ENDED: Channel in mode input single ended
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff)
{
  uint32_t tickstart = 0;
  
  /* Check the parameters */
  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
  assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff));

  /* Process locked */
  __HAL_LOCK(hadc);
   
  /* Disable the ADC (if not already disabled) */
  if (__HAL_ADC_IS_ENABLED(hadc) != RESET )
  {
    /* Check if conditions to disable the ADC are fulfilled */
    if (__HAL_ADC_DISABLING_CONDITIONS(hadc) != RESET)
    {
      __HAL_ADC_DISABLE(hadc);    
    }
    else  
    {
      hadc->State= HAL_ADC_STATE_ERROR;
      
      /* Process unlocked */
      __HAL_UNLOCK(hadc);
      
      return HAL_ERROR;
    }   
    
    /* Wait for ADC effectively disabled */
    /* Get timeout */
    tickstart = HAL_GetTick();  

    /* Wait for disabling completion */
    while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADEN))
    {
      /* Check for the Timeout */
      if(ADC_DISABLE_TIMEOUT != HAL_MAX_DELAY)
      {
        if((HAL_GetTick() - tickstart ) > ADC_DISABLE_TIMEOUT)
        {
          hadc->State= HAL_ADC_STATE_TIMEOUT;
          
          /* Process unlocked */
          __HAL_UNLOCK(hadc);
          
          return HAL_TIMEOUT;
        }
      }
    }  
  }

  /* Start ADC calibration */
  hadc->Instance->CR |= ADC_CR_ADCAL;

  /* Get timeout */
  tickstart = HAL_GetTick(); 

  /* Wait for calibration completion */
  while(HAL_IS_BIT_SET(hadc->Instance->CR, ADC_CR_ADCAL))
  {
    /* Check for the Timeout */
    if(ADC_CALIBRATION_TIMEOUT != HAL_MAX_DELAY)
    {
      if((HAL_GetTick() - tickstart ) > ADC_CALIBRATION_TIMEOUT)
      {
        hadc->State= HAL_ADC_STATE_TIMEOUT;
        
        /* Process unlocked */
        __HAL_UNLOCK(hadc);
        
        return HAL_TIMEOUT;
      }
    }
  }  
  
  /* Process unlocked */
  __HAL_UNLOCK(hadc);
  
  /* Return function status */
  return HAL_OK;
  
}