/*******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2014 Freescale Semiconductor, Inc.
* ALL RIGHTS RESERVED.
*
****************************************************************************//*!
*
* @file    etpu_tg.c
*
* @author  Milan Brejl [r54529]
*
* @version 1.0
*
* @date    17-Mar-2014
*
* @brief   This file contains API for using the eTPU function
*          Tooth Generator (TG).
*
****************************************************************************//*!
*
* @mainpage
*
* The eTPU TG APIs @ref etpu_tg.c/.h includes API functions for eTPU
* function Tooth Generator, used to generate Crank & Cam patterns.
*
* Each instance of the TG eTPU function controls two eTPU channels.
*
* Features:
* - Selectable polarity of the output signals.
* - The crank tooth pattern is defined by
*   - number of teeth between two gaps (@ref teeth_till_gap),
*   - number of missing teeth in one gap (@ref teeth_in_gap) and
*   - number of teeth per one engine cycle (@ref teeth_per_cycle).
* - The crank tooth pattern including an additional tooth is not supported.
* - The cam pattern is defined by the initial cam signal polarity and an array
*   of cam transitions. The position of each transition is defined by the 
*   corresponding crank tooth number.
* - The engine speed is defined by tooth_period_target and an exponential
*   acceleration/deceleration speed profile given by accel_ratio.
* - The crank signal generation can be disabled/enabled at any time.
* - The TG operation can be monitored using TG state variables
*   tooth_counter_cycle and tooth_period_actual.
* - No channel interrupt is generated by TG.
*
*******************************************************************************/
/*******************************************************************************
* Includes
*******************************************************************************/
#include "etpu_tg.h"     /* private header file */
#include "etpu_util.h"    /* utility routines for working with the eTPU */

/*******************************************************************************
* Global variables
*******************************************************************************/
extern uint32_t fs_etpu_data_ram_start;
extern uint32_t fs_etpu_data_ram_ext;

/*******************************************************************************
* FUNCTION: fs_etpu_tg_init
****************************************************************************//*!
* @brief   This function initializes eTPU channels to run TG function.
*
* @note    The following actions are performed in order:
*          -# Use user-defined CPBA or allocate new eTPU DATA RAM
*          -# Write chan config registers and FM bits
*          -# Write channel parameters
*          -# Write HSR
*          -# Set channel priority
*
* @param   *p_tg_instance - This is a pointer to the instance structure
*            @ref tg_instance_t.
* @param   *p_tg_config - This is a pointer to the structure of configuration
*            parameters @ref tg_config_t.
*
* @return  Error codes that can be returned are:
*          - @ref FS_ETPU_ERROR_MALLOC - eTPU DATA RAM memory allocation error
*          - @ref FS_ETPU_ERROR_NONE - No error
*
* @warning This function does not configure the pins, only the eTPU channels.
*******************************************************************************/
uint32_t fs_etpu_tg_init(
  struct tg_instance_t *p_tg_instance,
  struct tg_config_t   *p_tg_config)
{
  uint8_t  chan_num_crank;
  uint8_t  chan_num_cam;
  uint8_t  priority;
  uint8_t  cam_edge_count;
  uint8_t  *p_cam_edge_tooth;
  uint32_t *cpba;
  uint8_t  *cpba8_cam_edge_tooth;
  uint8_t  i;

  chan_num_crank   = p_tg_instance->chan_num_crank;
  chan_num_cam     = p_tg_instance->chan_num_cam;
  priority         = p_tg_instance->priority;
  cam_edge_count   = p_tg_instance->cam_edge_count;
  p_cam_edge_tooth = (uint8_t*)p_tg_instance->p_cam_edge_tooth;
  cpba             = p_tg_instance->cpba;
  cpba8_cam_edge_tooth = p_tg_instance->cpba8_cam_edge_tooth;

  /* Use user-defined CPBA or allocate new eTPU DATA RAM */
  if(cpba == 0)
  {
    cpba = fs_etpu_malloc(FS_ETPU_TG_NUM_PARMS);
    if(cpba == 0)
    {
      return(FS_ETPU_ERROR_MALLOC);
    }
    else
    {
      p_tg_instance->cpba = cpba;
    }
  }

  /* Use user-defined Cam-edge-tooth array or allocate new eTPU DATA RAM */
  if(cpba8_cam_edge_tooth == 0)
  {
    cpba8_cam_edge_tooth = (uint8_t*)fs_etpu_malloc(cam_edge_count);
    if(cpba8_cam_edge_tooth == 0)
    {
      return(FS_ETPU_ERROR_MALLOC);
    }
    else
    {
      p_tg_instance->cpba8_cam_edge_tooth = cpba8_cam_edge_tooth;
    }
  }

  /* Write chan config registers and FM bits */
  eTPU->CHAN[chan_num_crank].CR.R =
       (FS_ETPU_TG_TABLE_SELECT << 24) +
       (FS_ETPU_TG_FUNCTION_NUMBER << 16) +
       (((uint32_t)cpba - fs_etpu_data_ram_start) >> 3);
  eTPU->CHAN[chan_num_cam].CR.R = eTPU->CHAN[chan_num_crank].CR.R;
  eTPU->CHAN[chan_num_crank].SCR.R =
       (uint32_t)p_tg_instance->polarity_crank + FS_ETPU_TG_FM1_CRANK;
  eTPU->CHAN[chan_num_cam].SCR.R =
       (uint32_t)p_tg_instance->polarity_cam + FS_ETPU_TG_FM1_CAM;

  /* Write channel parameters */
  /* 24-bit */
  *(cpba + ((FS_ETPU_TG_OFFSET_TOOTH_TCR1_TIME     - 1)>>2)) = 0;
  *(cpba + ((FS_ETPU_TG_OFFSET_TOOTH_PERIOD_ACTUAL - 1)>>2)) = p_tg_config->tooth_period_target;
  *(cpba + ((FS_ETPU_TG_OFFSET_TOOTH_PERIOD_TARGET - 1)>>2)) = p_tg_config->tooth_period_target;
  *(cpba + ((FS_ETPU_TG_OFFSET_ACCEL_RATIO         - 1)>>2)) = p_tg_config->accel_ratio;
  *(cpba + ((FS_ETPU_TG_OFFSET_P_CAM_TOOTH_FIRST   - 1)>>2)) = (uint32_t)cpba8_cam_edge_tooth - fs_etpu_data_ram_start;
  *(cpba + ((FS_ETPU_TG_OFFSET_P_CAM_TOOTH         - 1)>>2)) = 0;
  /* 8-bit */
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TEETH_TILL_GAP     ) = p_tg_instance->teeth_till_gap;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TEETH_IN_GAP       ) = p_tg_instance->teeth_in_gap;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TEETH_PER_CYCLE    ) = p_tg_instance->teeth_per_cycle;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TOOTH_COUNTER_GAP  ) = 0;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TOOTH_COUNTER_CYCLE) = 0;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_CAM_CHAN           ) = chan_num_cam;
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_GENERATION_DISABLE ) = p_tg_config->generation_disable;

  /* Write array of Cam-edge teeth */
  for(i=0; i<cam_edge_count; i++)
  {
    *cpba8_cam_edge_tooth++ = *p_cam_edge_tooth++;
  }

  /* Write HSR */
  eTPU->CHAN[chan_num_crank].HSRR.R = FS_ETPU_TG_HSR_INIT;
  eTPU->CHAN[chan_num_cam].HSRR.R   = FS_ETPU_TG_HSR_INIT;

  /* Set channel priority */
  fs_etpu_enable(chan_num_crank, priority);
  fs_etpu_enable(chan_num_cam, priority);

  return(FS_ETPU_ERROR_NONE);
}

/*******************************************************************************
* FUNCTION: fs_etpu_tg_config
****************************************************************************//*!
* @brief   This function changes the TG configuration.
*
* @note    The following actions are performed in order:
*          -# Write FM bits
*
* @param   *p_tg_instance - This is a pointer to the instance structure
*            @ref tg_instance_t.
* @param   *p_tg_config - This is a pointer to the structure of configuration
*            parameters @ref tg_config_t.
*
* @return  Error codes that can be returned are:
*          - @ref FS_ETPU_ERROR_NONE - No error
*
*******************************************************************************/
uint32_t fs_etpu_tg_config(
  struct tg_instance_t *p_tg_instance,
  struct tg_config_t   *p_tg_config)
{
  uint32_t *cpba;
  uint32_t *cpbae;

  cpba = p_tg_instance->cpba;
  cpbae = cpba + (0x4000 >> 2); /* sign-extended memory area */

  /* Write channel parameters */
  /* 24-bit - use cpbae to prevent from overwriting bits 31:24 */
  *(cpbae + ((FS_ETPU_TG_OFFSET_TOOTH_PERIOD_TARGET - 1)>>2)) = p_tg_config->tooth_period_target;
  *(cpbae + ((FS_ETPU_TG_OFFSET_ACCEL_RATIO         - 1)>>2)) = p_tg_config->accel_ratio;
  /* 8-bit */
  *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_GENERATION_DISABLE   ) = p_tg_config->generation_disable;

  return(FS_ETPU_ERROR_NONE);
}

/*******************************************************************************
* FUNCTION: fs_etpu_tg_get_states
****************************************************************************//*!
* @brief   This function reads state parameter values of the TG function.
*
* @note    The following actions are performed in order:
*          -# Read output parameter values from eTPU DATA RAM
*          -# Clear TG error flags in eTPU DATA RAM
*
* @param   *p_tg_instance - This is a pointer to the instance structure
*            @ref tg_instance_t.
* @param   *p_tg_states - This is a pointer to the structure of states
*            @ref tg_states_t.
*
* @return  Error codes that can be returned are:
*          - @ref FS_ETPU_ERROR_NONE - No error
*
*******************************************************************************/
uint32_t fs_etpu_tg_get_states(
  struct tg_instance_t *p_tg_instance,
  struct tg_states_t   *p_tg_states)
{
  uint32_t *cpba;
  uint32_t *cpbae;

  cpba = p_tg_instance->cpba;
  cpbae = cpba + (0x4000 >> 2); /* sign-extended memory area */

  /* Read channel parameters */
  p_tg_states->tooth_counter_cycle =
      *((uint8_t*)cpba + FS_ETPU_TG_OFFSET_TOOTH_COUNTER_CYCLE);

  p_tg_states->tooth_period_actual =
      *(cpbae + ((FS_ETPU_TG_OFFSET_TOOTH_PERIOD_ACTUAL - 1)>>2));

  return(FS_ETPU_ERROR_NONE);
}



/*******************************************************************************
 *
 * Copyright:
 *  Freescale Semiconductor, INC. All Rights Reserved.
 *  You are hereby granted a copyright license to use, modify, and
 *  distribute the SOFTWARE so long as this entire notice is
 *  retained without alteration in any modified and/or redistributed
 *  versions, and that such modified versions are clearly identified
 *  as such. No licenses are granted by implication, estoppel or
 *  otherwise under any patents or trademarks of Freescale
 *  Semiconductor, Inc. This software is provided on an "AS IS"
 *  basis and without warranty.
 *
 *  To the maximum extent permitted by applicable law, Freescale
 *  Semiconductor DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
 *  INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
 *  PARTICULAR PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
 *  REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
 *  AND ANY ACCOMPANYING WRITTEN MATERIALS.
 *
 *  To the maximum extent permitted by applicable law, IN NO EVENT
 *  SHALL Freescale Semiconductor BE LIABLE FOR ANY DAMAGES WHATSOEVER
 *  (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
 *  BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER
 *  PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
 *
 *  Freescale Semiconductor assumes no responsibility for the
 *  maintenance and support of this software
 ******************************************************************************/
/*******************************************************************************
 *
 * REVISION HISTORY:
 *
 * FILE OWNER: Milan Brejl [r54529]
 *
 * Revision 1.0  2014/03/17  r54529
 * Minor comment and formating improvements.
 * Ready for eTPU Engine Control Library release 1.0.
 *
 * Revision 0.4  2013/10/22  r54529
 * generation_disable switch added.
 *
 * Revision 0.3  2013/07/24  r54529
 * Separate initial polarity for Crank and Cam.
 *
 * Revision 0.2  2013/06/20  r54529
 * Acceleration/deceleration added.
 *
 * Revision 0.1  2012/11/28  r54529
 * Initial version of file.
 ******************************************************************************/