/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  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.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR
 * 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    DM814x_i2cGpioExp.c
 *
 * \brief   I2C routines for DM814x EVM
 *
 * This file contains the routines for configuring and
 * accessing the I2C controller and slave devices.
 *
 * \author  0043
 *
 * \version 01a,13aug,2010 Created
 */

/*
 *====================
 * Includes
 *====================
 */
#include "DM814x_types.h"
#include "DM814x_i2c.h"
#include "DM814x_EVM.h"

#include "stdio.h"

/*
 *====================
 * Defines
 *====================
*/

/*
 *====================
 * Function implementations
 *====================
 */
 /** **************************************************************************
 * \n \brief Routine to Initialize the PCF8575 I2C based IO expander.
 *
 * This routine initialzes the I2C controller being used for the purpose and also
 * probes the I2C io expander. It returns success only if both the I2C controller
 * initialization succeeded as well as the Probe for the I2C GPIO expander is 
 * successful.
 *
 * \param u8I2cBusNum   [IN]    I2C Bus instance number [0, 1, 2, 3]
 * \param u8SlaveAddr   [IN]    I2C slave address of the IO Expander
 *
 * \return
 * \n      return SUCCESS for success  - Description 
 * \n      return FAILED for errors.
 * 
 */
STATUS i2cIoExpInit 
(
    UINT8 u8I2cBusNum, 
    UINT8 u8SlaveAddr
)
{
    STATUS u32RetVal = SUCCESS;
    
    /* input parameter validation */
    if ((u8I2cBusNum > 3) ||
        (u8SlaveAddr > 0x7F))
        {
        u32RetVal = FAILED;
        printf ("%s:- Invalid input params\r\n", __FUNCTION__);
        return (u32RetVal);
        }
    
    u32RetVal = DM814xI2cInit (u8I2cBusNum);
    
    if (SUCCESS == u32RetVal)
        {
        u32RetVal = DM814xI2cProbe (u8I2cBusNum, u8SlaveAddr);
        }
    
    if (SUCCESS != u32RetVal)
        printf ("Unable to detect the IO expander on EVM at Slave addr 0x%x.\r\n",
                u8SlaveAddr);
                
    return (u32RetVal);
}

/** **************************************************************************
 * \n \brief Routine to get the states of IO Lines of the PCF8575
 *
 * This routine gets the states of switches.It takes states of the Switches 
 * as a parameter.
 *
 * \param u8I2cBusNum   [IN]    I2C bus number [0, 1, 2, 3]
 * \param u8SlaveAddr   [IN]    Slave address of the IO Expander
 * \param *pu16Val		[OUT]	buffer pointer which has the states of the 
 *                              switches.
 *
 * \return
 * \n      return SUCCESS for success  - Description 
 * 
 */

STATUS i2c0IoExpStatusGet
( 
    UINT8 u8I2cBusNum, 
    UINT8 u8SlaveAddr, 
    UINT16* pu16Val 
)  
{
	STATUS u32RetVal = SUCCESS;
	
    UINT8 u8BytesOutput;
    UINT8 au8Val[2];

    /* input parameter validation */
    if ((u8I2cBusNum > 3) ||
        (u8SlaveAddr > 0x7F) ||
        (NULL == pu16Val))
        {
        u32RetVal = FAILED;
        printf ("%s:- Invalid input params\r\n", __FUNCTION__);
        return (u32RetVal);
        }

    au8Val[0] = 0x00;                       /* Lower 8 IOs */
    au8Val[1] = 0x00;                       /* Higher 8 IOs */
    
	u32RetVal = DM814xI2cRead (u8I2cBusNum, u8SlaveAddr, au8Val, 2, &u8BytesOutput);
    
	* pu16Val =  (au8Val[1] << 8) | au8Val[0];
    
    return (u32RetVal);           /* Lower four bits of the lower 8 bits are SWs */
}

/** **************************************************************************
 * \n \brief Routine to set the state of all IO lines at the same time
 *
 * This routine sets single LED.It takes num as paramter which gives Led number
 * along with that state that LED to be made.
 * 
 * \param u8I2cBusNum   [IN]    I2C bus instance number [0, 1, 2, 3]
 * \param u8SlaveAddr   [IN]    Slave address of the IO Expander
 * \param u8Index		[IN]	Index number of the bit to be set 0 - 15.
 * \param u8State       [IN]    State to be set/reset
 * 
 * \return
 * \n      return SUCCESS on successful completion of the routine
 * 
 */

STATUS i2c0IoExpStatusBitSet
(
    UINT8 u8I2cBusNum,
    UINT8 u8SlaveAddr,
    UINT8 u8Index, 
    UINT8 u8State
)
{
	STATUS u32RetVal = SUCCESS;
    UINT8 u8BytesOutput;
    UINT8 au8Val[2];
    
    /* input parameter validation */
    if ((u8I2cBusNum > 3) ||
        (u8SlaveAddr > 0x7F) ||
        (u8Index > 15))
        {
        u32RetVal = FAILED;
        printf ("%s:- Invalid input params\r\n", __FUNCTION__);
        return (u32RetVal);
        }
    
    /* Get the current state so it isnt overwritten*/
	u32RetVal = DM814xI2cRead (u8I2cBusNum, u8SlaveAddr, au8Val, 2, &u8BytesOutput);    
    if (u8Index < 8)
    	{
    	au8Val[0] &= ~(1 << u8Index);       /* Ensure the bit is cleared first */
    	au8Val[0] = au8Val[0] | (u8State << u8Index);  /* Set the appropriate bit in IO line */
    	}
	else
		{
		au8Val[1] &= ~(1 << (u8Index - 8) );    /* Ensure the bit is cleared first */
    	au8Val[1] = au8Val[1] | (u8State << (u8Index - 8) );  /* Set the appropriate bit in IO line */
		}
    	
	u32RetVal = DM814xI2cWite (u8I2cBusNum, u8SlaveAddr, au8Val, 2, &u8BytesOutput);
	return (u32RetVal);
}

/** **************************************************************************
 * \n \brief Routine to set all IO lines to be desired state.
 *
 * This routine sets the state IO lines on the GPIO Expander to the desired state
 * Be aware that this routine may also drive the input lines to the state given
 * as input parameter. It is recommended to use this routine only if all the iO
 * lines are used as output only lines. 
 *
 * \param u8I2cBusNum   [IN]    I2C bus instance number [0, 1, 2, 3]
 * \param u8SlaveAddr   [IN]    Slave address of the IO Expander
 * \param u16Output		[IN]	State of all IO Lines to be set
 * 
 * 
 * \return
 * \n      return SUCCESS on successful completion of the routine
 * 
 */

STATUS i2c0IoExpStatusSetAll
(
    UINT8  u8I2cBusNum,
    UINT8  u8SlaveAddr,
    UINT16 u16Output
)
{
	STATUS u32RetVal = SUCCESS;
    UINT8 u8BytesOutput;
	UINT8 au8Val[2];
    
    /* input parameter validation */
    if ((u8I2cBusNum > 3) ||
        (u8SlaveAddr > 0x7F))
        {
        u32RetVal = FAILED;
        printf ("%s:- Invalid input params\r\n", __FUNCTION__);
        return (u32RetVal);
        }
    
    au8Val[0] = u16Output & 0xFF;      
    au8Val[1] = u16Output >> 8; 
	u32RetVal = DM814xI2cWite (u8I2cBusNum, u8SlaveAddr, au8Val, 2, &u8BytesOutput);
    return (u32RetVal);
}
