#include <stdlib.h>
#include "Simulated_IIC_master\Simulated_IIC_master.h"

static void SIIC_Master_Delay(uint32_t u32Interval);

uint32_t g_u32SIICMasterDelay;

SIIC_M_Result_en_t SIIC_Master_Init(SIIC_M_Handler_st_t *pHandler, uint16_t u16SCLPin, uint16_t u16SDAPin, uint32_t u32SpeedTrim)
{
    int32_t i32SCLCfg;
    int32_t i32SDACfg;
    SIIC_M_Result_en_t enResult;

    enResult = SIIC_M_FAIL;

    if (pHandler != NULL)
    {
        /* Rest and test SCL/SDA GPIOs */
        i32SCLCfg = SIIC_Master_Set_GPIO(u16SCLPin, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(u32SpeedTrim);
        SIIC_Master_Delay(u32SpeedTrim);

        i32SDACfg = SIIC_Master_Set_GPIO(u16SDAPin, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(u32SpeedTrim);
        SIIC_Master_Delay(u32SpeedTrim);

        if ((i32SCLCfg == 0) && (i32SDACfg == 0))    /* GPIOs are available */
        {
            pHandler->u16SCLPinNum   = u16SCLPin;
            pHandler->u16SDAPinNum   = u16SDAPin;
            pHandler->u32SpeedTrim   = u32SpeedTrim;
            pHandler->u8Busy         = (uint8_t)SIIC_M_IDLE;
            pHandler->u8ReceivedACK  = SIIC_M_ACK_INVALID;
            
            enResult = SIIC_M_PASS;
        }
    }
    
    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_DeInit(SIIC_M_Handler_st_t *pHandler)
{
    SIIC_M_Result_en_t enResult;

    enResult = SIIC_Master_Stop(pHandler);

    return enResult;
}

SIIC_M_Status_en_t SIIC_Master_Get_Status(SIIC_M_Handler_st_t *pHandler)
{
    SIIC_M_Status_en_t enStatus;
    
    enStatus = SIIC_M_INVALID;
    if (pHandler != NULL)
    {
        enStatus = (SIIC_M_Status_en_t)(pHandler->u8Busy);
    }
    
    return enStatus;
}

SIIC_M_Result_en_t SIIC_Master_Start(SIIC_M_Handler_st_t *pHandler)
{
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    if (pHandler != NULL)
    {
        pHandler->u8ReceivedACK = SIIC_M_ACK_INVALID;
            
        /* SDA = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        
        /* SCL = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* SDA = 0 */
        SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_OUT_LOW);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* SCL = 0 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_OUT_LOW);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);

        pHandler->u8Busy = (uint8_t)SIIC_M_BUSY;
            
        enResult = SIIC_M_PASS;
    }

    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_Stop(SIIC_M_Handler_st_t *pHandler)
{
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    if (pHandler != NULL)
    {
        pHandler->u8ReceivedACK = SIIC_M_ACK_INVALID;
            
        /* SDA = 0 */
        SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_OUT_LOW);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* SCL = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* SDA = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);

        pHandler->u8Busy = (uint8_t)SIIC_M_IDLE;
            
        enResult = SIIC_M_PASS;
    }

    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_Write_Data(SIIC_M_Handler_st_t *pHandler, uint8_t u8Data)
{
    uint32_t i;
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    if (pHandler != NULL)
    {
        pHandler->u8ReceivedACK = SIIC_M_ACK_INVALID;
            
        for (i = 0UL; i < 8UL; i++)
        {
            if (u8Data & 0x80U)
            {
                /* SDA = 1 */
                SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
            }
            else
            {
                /* SDA = 0 */
                SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_OUT_LOW);
            }
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
                
            /* SCL = 1 */
            SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
                
            /* SCL = 0 */
            SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_OUT_LOW);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
                
            u8Data <<= 1;
        }
            
        /* SDA = Input */
        SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* SCL = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
            
        /* Read ACK */
        if (SIIC_Master_Get_GPIO(pHandler->u16SDAPinNum))
        {
            pHandler->u8ReceivedACK = SIIC_M_NAK;
        }
        else
        {
            pHandler->u8ReceivedACK = SIIC_M_ACK;
        }
        
        /* SCL = 0 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_OUT_LOW);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        
        enResult = SIIC_M_PASS;
    }
    
    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_Read_Data(SIIC_M_Handler_st_t *pHandler, uint8_t *pu8Data)
{
    uint32_t i;
    uint8_t  u8Buffer;
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    if (pu8Data != NULL)
    {
        if (pHandler != NULL)
        {
            u8Buffer = 0U;
                
            /* SDA = Input */
            SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
            SIIC_Master_Delay(pHandler->u32SpeedTrim);
                
            for (i = 0UL; i < 8UL; i++)
            {
                u8Buffer <<= 1;
                    
                /* SCL = 1 */
                SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
                SIIC_Master_Delay(pHandler->u32SpeedTrim);
                SIIC_Master_Delay(pHandler->u32SpeedTrim);
                SIIC_Master_Delay(pHandler->u32SpeedTrim);
                    
                /* Read SDA */
                if (SIIC_Master_Get_GPIO(pHandler->u16SDAPinNum))
                {
                    u8Buffer |= 0x01U;
                }
                
                /* SCL = 0 */
                SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_OUT_LOW);
                SIIC_Master_Delay(pHandler->u32SpeedTrim);
                SIIC_Master_Delay(pHandler->u32SpeedTrim);
            }
            
            *pu8Data = u8Buffer;
            enResult = SIIC_M_PASS;
        }
    }
    
    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_Write_ACK(SIIC_M_Handler_st_t *pHandler, uint8_t u8ACK)
{
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    
    if ((pHandler != NULL) && (u8ACK < SIIC_M_ACK_INVALID))
    {
        if (u8ACK) /* u8ACK == SIIC_M_NAK */
        {
            /* SDA = 1 */
            SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_IN_HiZ);
        }
        else       /* u8ACK == SIIC_M_ACK */
        {
            /* SDA = 0 */
            SIIC_Master_Set_GPIO(pHandler->u16SDAPinNum, SIIC_M_GPIO_OUT_LOW);
        }
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        
        /* SCL = 1 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_IN_HiZ);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        
        /* SCL = 0 */
        SIIC_Master_Set_GPIO(pHandler->u16SCLPinNum, SIIC_M_GPIO_OUT_LOW);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);
        SIIC_Master_Delay(pHandler->u32SpeedTrim);

        enResult = SIIC_M_PASS;
    }
    
    return enResult;
}

SIIC_M_Result_en_t SIIC_Master_Read_ACK(SIIC_M_Handler_st_t *pHandler, uint8_t *pu8ACK)
{
    SIIC_M_Result_en_t  enResult;
    
    enResult  = SIIC_M_FAIL;
    
    if ((pHandler != NULL) && (pu8ACK != NULL))
    {
        *pu8ACK = pHandler->u8ReceivedACK;
        pHandler->u8ReceivedACK = SIIC_M_ACK_INVALID;
        
        enResult = SIIC_M_PASS;
    }
    
    return enResult;
}

static void SIIC_Master_Delay(uint32_t u32Interval)
{
    g_u32SIICMasterDelay = u32Interval;
    while (g_u32SIICMasterDelay)
    {
        g_u32SIICMasterDelay--;
    }
}