/*This file is prepared for Doxygen automatic documentation generation.*/
//! \file *********************************************************************
//!
//! \brief This file contains internal oscillator calibration drivers
//!
//! - Compiler:           IAR EWAVR and GNU GCC for AVR
//! - Supported devices:  ATmega32U4
//!
//! \author               Atmel Corporation: http://www.atmel.com \n
//!                       Support and FAQ: http://support.atmel.no/
//!
//! ***************************************************************************

/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
 *
 * 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
 * AVR 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.
 */

//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "cal_inter_rc.h"
#include "lib_mcu/temp_sensor/temp_sensor.h"
#include "lib_mcu/flash/flash_drv.h"
#include "lib_mcu/adc/adc_drv.h"

//_____ M A C R O S ________________________________________________________


//_____ P R I V A T E    D E C L A R A T I O N _____________________________


//_____ D E F I N I T I O N ________________________________________________


//_____ D E C L A R A T I O N ______________________________________________

U8 osc_cal_25_3v;
U8 osc_cal_85_3v;
U8 osc_cal_25_5v;
U8 offset;
U16 temp_sensor_25;
U16 temp_sensor_85;
U8 n_step;
U8 period;
U16 temp_value;

//! This function get the calibration values
//!
//! @param
//!
void get_cal_values(void)
{
  U8 temp_sensor_25_lo;
  U8 temp_sensor_25_hi;
  U8 temp_sensor_85_lo;
  U8 temp_sensor_85_hi;
  osc_cal_25_3v = flash_read_sig(0x01);
  osc_cal_85_3v = flash_read_sig(0x03);
  osc_cal_25_5v = flash_read_sig(0x05);
  temp_sensor_25_lo = flash_read_sig(0x38);
  temp_sensor_25_hi = flash_read_sig(0x39);
  temp_sensor_85_lo = flash_read_sig(0x3A);
  temp_sensor_85_hi = flash_read_sig(0x3B);
  temp_sensor_25 = (temp_sensor_25_hi << 8) + temp_sensor_25_lo;
  temp_sensor_85 = (temp_sensor_85_hi << 8) + temp_sensor_85_lo;
  offset = (osc_cal_25_5v) - (osc_cal_25_3v);
  n_step = osc_cal_25_3v - osc_cal_85_3v;
  period = (temp_sensor_85 - temp_sensor_25)/n_step;
}

//! This function update the OSCCAL value following the temperature and the voltage
//!
//! @param enum vcc: vcc_5 or vcc_3
//!
void calibrate_inter_osc(enum vcc v)
{
  U8 osc_cal;
  get_cal_values();
  osc_cal = osc_cal_25_3v;
  temp_value = get_temp_sensor_val();

   if(temp_value < temp_sensor_25)
   {
     for (U16 t = temp_sensor_25; t>0; t-=period)
        {
          osc_cal++;
          if(t<temp_value)
            break;
        }
   }
     else if(temp_value >= temp_sensor_85)
     osc_cal = osc_cal_85_3v;
      else if(temp_value > temp_sensor_25)
      { for (U16 t = temp_sensor_25; t<temp_sensor_85; t+=(2*period))
        {
          osc_cal--;
          if(t>temp_value)
            break;
        }
      }
  if(vcc_3)
  {
   OSCCAL = osc_cal;
  }
 else OSCCAL = osc_cal + offset;

}






