/******************************************************************************
 *
 * Freescale Semiconductor Inc.
 * (c) Copyright 2004-2013 Freescale Semiconductor, Inc.
 * ALL RIGHTS RESERVED.
 *
 ******************************************************************************
 *
 * THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
 * IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS 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.
 *
 **************************************************************************//*!
 *
 * @file dac.c
 *
 * @author  
 *
 * @version 1.0
 *
 * @date Feb-09-2013
 *
 * @brief DAC functions for Kinetis microcontrollers
 *
 *****************************************************************************/

/*****************************************************************************
 * Header files
 ****************************************************************************/
#include "derivative.h"
#include "dac.h"
#include "nvic.h"

/*****************************************************************************
 * Globals
 ****************************************************************************/
unsigned char gu8DacIrqFlag = 0;

/*****************************************************************************
 * Functions
 ****************************************************************************/

/****************************************************************************
 * 
 * @function: vfnDacInit
 * 
 * @description: Initialize DAC using the parameters specified in tDAC_CONFIG DacCfg structure
 * 
 * @inputs:
 * 
 * -tDAC_CONFIG DacCfg	tDAC type structure containing all the configuration parameters
 * 						(see dac_kinetis.h for more information)
 * 
 * @outputs:
 * 
 * @warnings:
 * 
 ***************************************************************************/

void vfnDacInit(tDAC DacCfg)
{
	if(DacCfg.DacModule == DAC0)
	{
		SIM_SCGC2 |= SIM_SCGC2_DAC0_MASK;
		u8NvicEnableIrq((INT_DAC0 - 16));
	}
	
        #if defined(DAC1_PRESENT)
	if(DacCfg.DacModule == DAC1)
	{
		SIM_SCGC2 |= SIM_SCGC2_DAC1_MASK;
		u8NvicEnableIrq((INT_DAC1 - 16));
	}
        #endif
	
	DAC_C0_REG(DacCfg.DacModule) = DacCfg.u8DacRefvTrigPowermode;
	DAC_C0_REG(DacCfg.DacModule) |= DacCfg.u8DacIntEn;
	
	DAC_C1_REG(DacCfg.DacModule) = DacCfg.u8DacDmaBufferenBuffermode;
	
	if(DacCfg.u8DacIntEn & DAC_WATERMARK_INT)
	{
		DAC_C1_REG(DacCfg.DacModule)|= DacCfg.u8DacBufferWms;
	}
	
	if(DacCfg.u8DacBufferUp != 0)
			DAC_C2_REG(DacCfg.DacModule) = DacCfg.u8DacBufferUp;
	
	DAC_C0_REG(DacCfg.DacModule) |= DAC_C0_DACEN_MASK;
}

/******************************************************************************/

/****************************************************************************
 * 
 * @function: u8DacLoadVal
 * 
 * @description: Load a 12-bit value to an specified DAC_DAT register (DAC buffer)
 * 
 * @inputs:
 * 
 * -DAC_MemMapPtr Module: DAC module to modify (i.e. DAC0)
 * 
 * -unsigned short u16Value: Value to load. Maximum value = 0x0FFF
 * 
 * -unsigned char u8Index: Index of the DAC_DAT register where u16Value will be loaded. Maximum value = 15
 * 
 * @outputs:
 * 
 * -unsigned char: Error status (DAC_OK or DAC_ERR)
 * 
 * @warnings:
 * 
 ***************************************************************************/
unsigned char u8DacLoadVal(DAC_MemMapPtr Module, unsigned short u16Value, unsigned char u8Index)
{
	if(u8Index > 15)
		return DAC_ERR;
	
	if(u16Value > 4095)
		return DAC_ERR;
	
	DAC_DATL_REG(Module,u8Index) = ((unsigned char)(u16Value & 0x00FFu));
	DAC_DATH_REG(Module,u8Index) = ((unsigned char)((u16Value & 0xFF00u) >> 0x08u));
	
	return DAC_OK;
}

/******************************************************************************/

/****************************************************************************
 * 
 * @function: u8DacLoadBuff
 * 
 * @description: Load an array containing 12-bits values to a DAC module buffer (DAC_DAT)
 * 
 * @inputs:
 * 
 * -DAC_MemMapPtr Module: DAC module to modify (i.e. DAC0)
 * 
 * -unsigned short* pBuffer: Pointer to the first member of the array to load
 * 
 * -unsigned char u8Size: Size of the array to load
 * 
 * @outputs:
 * 
 * -unsigned char: DAC error status (DAC_OK or DAC_ERR)
 * 
 * @warnings:
 * 
 * -This function uses u8DacLoadVal function. The limitations of this function
 * must be considered (Max data value = 0x0FFF, Max buffer size = 16)
 * 
 ***************************************************************************/
unsigned char u8DacLoadBuff (DAC_MemMapPtr Module, unsigned short* pBuffer, unsigned char u8Size)
{
	unsigned char u8ErrReport;
	unsigned char u8Index;
	
	if(u8Size > 16)
		return DAC_ERR;
	
	for(u8Index = 0; u8Index < u8Size; u8Index++)
	{
		u8ErrReport = u8DacLoadVal(Module, *pBuffer, u8Index);
		pBuffer++;
		
		if(u8ErrReport == DAC_ERR)
			return DAC_ERR;
	}
	
	return DAC_OK;
}

/*******************************************************************************/

/****************************************************************************
 * 
 * @function: vfnDacSwTrigger
 * 
 * @description: Performs a software trigger on a selected DAC module
 * 
 * @inputs:
 * 
 * -DAC_MemMapPtr Module: DAC module where the software trigger will be performed (i.e. DAC0)
 * 
 * @outputs:
 * 
 * @warnings:
 * 
 ***************************************************************************/
void vfnDacSwTrigger(DAC_MemMapPtr Module)
{
	DAC_C0_REG(Module) |= DAC_C0_DACSWTRG_MASK;
}

/******************************************************************************/

/****************************************************************************
 * 
 * @function: vfnDacDeinit
 * 
 * @description: Deinitializes a DAC module
 * 
 * @inputs:
 * 
 * -DAC_MemMapPtr Module: DAC module to deinitialize (i.e. DAC0)
 * 
 * @outputs:
 * 
 * @warnings:
 * 
 ***************************************************************************/
void vfnDacDeinit(DAC_MemMapPtr Module)
{
	if(Module == DAC0)
		SIM_SCGC2 |= SIM_SCGC2_DAC0_MASK;

        #if defined(DAC1_PRESENT)
	if(Module == DAC1)
		SIM_SCGC2 |= SIM_SCGC2_DAC1_MASK;
        #endif
	
	DAC_C0_REG(Module) = 0x00u;
	DAC_C1_REG(Module) = 0x00u;
	DAC_C2_REG(Module) = 0x0Fu;
	
	if(Module == DAC0)
	{
		SIM_SCGC2 &= ~SIM_SCGC2_DAC0_MASK;
		u8NvicDisableIrq(INT_DAC0 - 16);
	}
	#if defined(DAC1_PRESENT)	
	if(Module == DAC1)
	{
		SIM_SCGC2 &= ~SIM_SCGC2_DAC1_MASK;
		u8NvicDisableIrq(INT_DAC1 - 16);
	}
        #endif
}

/****************************************************************************
 * 
 * @function: vfnDac0Isr
 * 
 * @description: Interrupt service routine for DAC0
 * 
 * @inputs:
 * 
 * @outputs:
 * 
 * @warnings: Function must be in the RAM interrupt vector table prior use
 * 
 ***************************************************************************/
void vfnDac0Isr (void)
{
	unsigned char u8DacStatus;
	
	u8DacStatus = DAC0_SR;		//Read DAC status register
	DAC0_SR = 0x00u;			//Clear all flags in DAC status register
	
	if(u8DacStatus & DAC_SR_DACBFRPBF_MASK)
		{
			// Check for DAC0 pointer bottom IRQ. If asserted, sets flag
			DAC0_BFRPB_EVENT;
		}
	
	if(u8DacStatus & DAC_SR_DACBFRPTF_MASK)
		{
		// Check for DAC0 pointer top IRQ. If asserted, sets flag
			DAC0_BFRPT_EVENT;
		}
	
	if(u8DacStatus & DAC_SR_DACBFWMF_MASK)
		{
		// Check for DAC0 watermark IRQ. If asserted, sets flag
			DAC0_BFWM_EVENT;
		}
}


#if defined(DAC1_BASE_PTR)
/****************************************************************************
 * 
 * @function: vfnDac1Isr
 * 
 * @description: Interrupt service routine for DAC1
 * 
 * @inputs:
 * 
 * @outputs:
 * 
 * @warnings: Function must be in the RAM interrupt vector table prior use
 * 
 ***************************************************************************/
void vfnDac1Isr (void)
{
	unsigned char u8DacStatus;
	
	u8DacStatus = DAC1_SR;		//Read DAC status register
	DAC1_SR = 0x00u;			//Clear all flags in DAC status register
	
	if(u8DacStatus & DAC_SR_DACBFRPBF_MASK)
		{
			// Check for DAC1 pointer bottom IRQ. If asserted, sets flag
			DAC1_BFRPB_EVENT;
		}
	
	if(u8DacStatus & DAC_SR_DACBFRPTF_MASK)
		{
		// Check for DAC1 pointer top IRQ. If asserted, sets flag
			DAC1_BFRPT_EVENT;
		}
	
	if(u8DacStatus & DAC_SR_DACBFWMF_MASK)
		{
		// Check for DAC1 watermark IRQ. If asserted, sets flag
			DAC1_BFWM_EVENT;
		}
}
#endif

