/******************************************************************************
* 
* Freescale Semiconductor Inc.
* (c) Copyright 2010 Freescale Semiconductor, Inc.
* ALL RIGHTS RESERVED.
*
***************************************************************************//*!
*
* @file     MC33937_routines.c
*
* @author   B15651
*
* @version  1.0.2.0
*
* @date     May-11-2010
*
* @brief    The MC33937 MOSFET pre-driver Init function file, with routines for
*           pre-driver setup and diagnostic.
*
*******************************************************************************
*
* Detailed Description of the file.
*
******************************************************************************/
 
/*! 
@if MC33937_GROUP
    @addtogroup MC33937_GROUP
@else
    @defgroup MC33937_GROUP   MC33937
@endif
*/ 


/*****************************************************************************
* External objects
******************************************************************************/
#include "MPC5554.h"
#include "siu_struct.h"
#include "typedefs.h"
#include "MC33937_routines.h"

uint8_t  bFcnStatusMC33937;
uint32_t TBL_REG;
/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          MC33937 pre-driver fault clear

@param[in,out]  *ptr

@return         void

@details        The function clears a portion of the fault latch corresponding \
                to MASK0 and MASK1 using lower four bits of commands. A 1 bit \
                clears the interrupt latch for that flag. INT remains asserted \
                if other unmasked faults are still present.

@note           

@warning
******************************************************************************/
void    MC33937_clear_fault(MC33937_SET_T *ptr)
{
    uint8_t help;

    // Disable MC33937 for operation
    GPIO_SIU.GPDO[ptr->EnPcrNb].B.PDO       = 0;
    if (ptr->DspiNb == 0)
    {
        // send CLINT0 command to clear known faults 0:3
        DSPI0_transmit_SPI_8(CLINT0_CMD, ptr, &help);
        // send CLINT1 command to clear known faults 4:7
        DSPI0_transmit_SPI_8(CLINT1_CMD, ptr, &help);
    }
    if (ptr->DspiNb == 1)
    {
        // send CLINT0 command to clear known faults 0:3
        DSPI1_transmit_SPI_8(CLINT0_CMD, ptr, &help);
        // send CLINT1 command to clear known faults 4:7
        DSPI1_transmit_SPI_8(CLINT1_CMD, ptr, &help);
    }
    if (ptr->DspiNb == 2)
    {
        // send CLINT0 command to clear known faults 0:3
        DSPI2_transmit_SPI_8(CLINT0_CMD, ptr, &help);
        // send CLINT1 command to clear known faults 4:7
        DSPI2_transmit_SPI_8(CLINT1_CMD, ptr, &help);
    }
    // Enable MC33937 for operation
    GPIO_SIU.GPDO[ptr->EnPcrNb].B.PDO        = 1;
}


/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          MC33937 pre-driver set Enable pin

@param[out]     void
@param[in]      void

@return         The MC33937_enable function returns nothing.

@details        The function sets enable inputs pin of MC33937 pre-driver ( \
                enable driver outputs). 


@note           This function is used to enable outputs of the MC33937

@warning
******************************************************************************/
void    MC33937_enable(MC33937_SET_T *ptr)
{
    // Enable MC33937 for operation
    GPIO_SIU.GPDO[ptr->EnPcrNb].B.PDO        = 1;
}


/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          Clear Enable pin of the MC33937 pre-driver.

@param[in,out]  *ptr

@return         void

@details        The function clear enable inputs of MC33937 pre-driver ( \
                disable driver outputs). The IC is in Standby mode.

@note           The IC is fully biased up and all functions are operating, the \
                output drivers actively turn off all of the external FETs \
                (after initialization). The SPI port is functional. Logic level\
                 outputs are driven with low impedance. SO is high impedance \
                unless CS is low. VDD, Charge Pump and VLS regulators are all \
                operating. The IC is ready to move to Enable Mode.

@warning
******************************************************************************/
void    MC33937_disable(MC33937_SET_T *ptr)
{
    // Disable MC33937 for operation
    GPIO_SIU.GPDO[ptr->EnPcrNb].B.PDO        = 0;
}

/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          Reset the MC33937 pre-driver.

@param[in,out]  *ptr

@return         void

@details        The function resets MC33937 pre-driver

@note

@warning
******************************************************************************/
void    MC33937_reset(MC33937_SET_T *ptr)
{
    // Disable MC33937 for operation
    GPIO_SIU.GPDO[ptr->RstPcrNb].B.PDO        = 0;
}

/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          Read the status registers of the MC33937 pre-driver.

@param[in,out]  *SetPtr

@return         void

@details        The function read status registers values of the MC33937 pre-driver.
                The actual values of the status registers are stored in SetPtr
                structure.

@note           

@warning
******************************************************************************/
void   MC33937_read_SR(MC33937_SET_T *SetPtr)
{
    uint8_t help;

    if (SetPtr->DspiNb == 0)
    {
        // send NULL0 command - ignore return value (previous command is unknown)
        DSPI0_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        // send NULL0 command - return value is status register 0 value
        DSPI0_transmit_SPI_8(STATUS1_CMD, SetPtr, &help);
        SetPtr->status.sr0.R    = help;
        // send NULL1 command - return value is status register 1 value
        DSPI0_transmit_SPI_8(STATUS2_CMD, SetPtr, &help);
        SetPtr->status.sr1.R    = help;
        // send NULL2 command - return value is status register 2 value
        DSPI0_transmit_SPI_8(STATUS3_CMD, SetPtr, &help);
        SetPtr->status.sr2.R    = help;
        // send NULL0 command - return value is status register 3 value
        DSPI0_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        SetPtr->status.sr3      = help;
    }
    if (SetPtr->DspiNb == 1)
    {
        // send NULL0 command - ignore return value (previous command is unknown)
        DSPI1_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        // send NULL0 command - return value is status register 0 value
        DSPI1_transmit_SPI_8(STATUS1_CMD, SetPtr, &help);
        SetPtr->status.sr0.R    = help;
        // send NULL1 command - return value is status register 1 value
        DSPI1_transmit_SPI_8(STATUS2_CMD, SetPtr, &help);
        SetPtr->status.sr1.R    = help;
        // send NULL2 command - return value is status register 2 value
        DSPI1_transmit_SPI_8(STATUS3_CMD, SetPtr, &help);
        SetPtr->status.sr2.R    = help;
        // send NULL0 command - return value is status register 3 value
        DSPI1_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        SetPtr->status.sr3      = help;
    }
    if (SetPtr->DspiNb == 2)
    {
        // send NULL0 command - ignore return value (previous command is unknown)
        DSPI2_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        // send NULL0 command - return value is status register 0 value
        DSPI2_transmit_SPI_8(STATUS1_CMD, SetPtr, &help);
        SetPtr->status.sr0.R    = help;
        // send NULL1 command - return value is status register 1 value
        DSPI2_transmit_SPI_8(STATUS2_CMD, SetPtr, &help);
        SetPtr->status.sr1.R    = help;
        // send NULL2 command - return value is status register 2 value
        DSPI2_transmit_SPI_8(STATUS3_CMD, SetPtr, &help);
        SetPtr->status.sr2.R    = help;
        // send NULL0 command - return value is status register 3 value
        DSPI2_transmit_SPI_8(STATUS0_CMD, SetPtr, &help);
        SetPtr->status.sr3      = help;
    }
}


/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          MC33937 pre-driver deadtime setup

@param[in,out]  *SetPtr

@return         void

@details        The function setup deadtime between top and bottom transistor
                of MC33937 pre-driver. Required deadtime value is stored in \
                structure item SetPtr->deadtime. The MC33937 real deadtime value \
                is stored in the SetPtr->Set_deadtime. The real deadtime value \
                corresponds to the value of the status register 3 multipied by \
                50ns.


@note           This function is included in the MC33937_config function

@warning
******************************************************************************/
void   MC33937_deadtime_setup(MC33937_SET_T *SetPtr)
{
    static  uint32_t    delay;
    static  uint8_t     help_sr0;

    // read TB actual value
    TBL_REG	= readFIT();
    delay	= TBL_REG + MC33937_POWER_UP_TIME;
    // wait 2ms for power supply voltage stabilization
    while(TBL_REG < delay)
    {
        TBL_REG	= readFIT();
    }

    // send command for setup deadtime
    DSPI0_transmit_SPI_8(DEADTIME_CMD, SetPtr, &help_sr0);

    DSPI0_transmit_SPI_8(STATUS3_CMD, SetPtr, &help_sr0);
    DSPI0_transmit_SPI_8(STATUS2_CMD, SetPtr, &help_sr0);

    // store deadtime in [ns]
    SetPtr->Set_deadtime        = help_sr0;
}


/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          MC33937 pre-driver configuration function.

@param[in,out]  *SetPtr

@return         void

@details        The function provide configuration of MC33937 pre-driver and
                setup deadtime between top and bottom transistor. Function uses
                PIT module and DSPI module.

@note           This function is used to configure MC33937

@warning
******************************************************************************/
void MC33937_config(MC33937_SET_T *SetPtr)
{
    static  uint32_t        delay;
    static  uint8_t         help_sr0;

    // remove /RST, EN1 and EN2 are still low -> VDD rise, init interrupt
    // handler, enable SPI C[10] to high
    GPIO_SIU.GPDO[SetPtr->RstPcrNb].B.PDO           = 1;

    // init TB counter to zero
	  initFIT();

	  // read TB actual value
	  TBL_REG	= readFIT();
	  delay	= TBL_REG + MC33937_POWER_UP_TIME;
    // wait 2ms for power supply voltage stabilization
	  while(TBL_REG < delay)
	  {
		    TBL_REG	= readFIT();
	  }

    // at first clear faults
    MC33937_clear_fault(SetPtr);
    // Initialize MASK register to mask unwanted interrupts
    // send MASK0 and MASK1 command to mask out unwanted interrupts
    DSPI0_transmit_SPI_8(SetPtr->mask0, SetPtr, &help_sr0);
    DSPI0_transmit_SPI_8(SetPtr->mask1, SetPtr, &help_sr0);

    // setup desired deadtime of MC33937 value is in [ns]
    MC33937_deadtime_setup(SetPtr);
    MC33937_clear_fault(SetPtr);
    // send MODE command with desired bits, and also the LOCK bit to prevent further mode changes
    DSPI0_transmit_SPI_8(SetPtr->mode, SetPtr, &help_sr0);
}

/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          Initialize time base timer on the core.

@param[in,out]  

@return         void

@details        The function setup registers values of the core TB timer.
                
@note           

@warning
******************************************************************************/
asm void initFIT(void) {
  li		r0, 0		       	/* Initialize time base to 0  */
  mttbu		r0					  
  mttbl		r0				
  lis	  	r0, 0x0000		  	/* Enable FIT interrupt and set	*/
  ori		r0, r0, 0x4000		/* FP=0, FPEXT=A for 0.7 sec timeout */
  mttcr		r0			
  li		r0, 0x4000		  	/* Enable Time Base and Decrementer (set TBEN) */
  mthid0	r0
}

/**************************************************************************//*!
@ingroup        MC33937_GROUP
@brief          Read actual time base timer register value on the core.

@param[in,out]  

@return         void

@details        The function read actual registers values of the core TB timer.
                
@note           

@warning
******************************************************************************/
uint32_t readFIT(void)
{
	asm("mftbl r3");
}
