/************************************************************************************************/
/**
* @file               interrupts.c
* @author             MCU Ecosystem Development Team
* @brief              中断服务程序。
*
*
**************************************************************************************************
* @attention
* Copyright (c) CEC Huada Electronic Design Co.,Ltd. All rights reserved.
*
**************************************************************************************************
*/

/*------------------------------------------includes--------------------------------------------*/
#include "interrupts.h"
  
/*------------------------------------------define----------------------------------------------*/
extern bsp_i2c_master_sim_t i2c_master_instance;

/*-------------------------------------------functions------------------------------------------*/
/******************************************************************************/
/*                        Cortex-M0+ 中断服务程序入口                         */
/******************************************************************************/
/**
* @brief  NMI中断服务程序
* @retval 无
*/
void NMI_Handler(void)
{

}


/**
* @brief  HardFault中断服务程序
* @retval 无
*/
void HardFault_Handler(void)
{
    while (1)
    {
    }
}


/**
* @brief  SVC中断服务程序
* @retval 无
*/
void SVC_Handler(void)
{

}


/**
* @brief  PendSV中断服务程序
* @retval 无
*/
void PendSV_Handler(void)
{
   
}


/**
* @brief  SysTick中断服务程序
* @retval 无
*/
void SysTick_Handler(void)
{

}


/******************************************************************************/
/*                            外设中断服务程序入口                            */
/******************************************************************************/
/**
* @brief  I2C_SIM_TIM中断服务函数
* @retval 无
*/
void I2C_TIM_IRQHandler(void)
{   
    register uint8_t temp_val;
    I2C_SIM_TIM_CLR_FLAG();
    i2c_master_instance.i2c_scl_edge_cnt++;
    switch(i2c_master_instance.i2c_status)
    {
        /* 发送起始位 */
        case I2C_START:
        {
            SDA_L();
            i2c_master_instance.i2c_status = I2C_ADDRESS;
            i2c_master_instance.i2c_scl_edge_cnt = 0;
        }break;
        
        /* 发送地址 */
        case I2C_ADDRESS:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，主机控制SDA变化
            {
                SCL_L();
                if((i2c_master_instance.i2c_slave_address << (i2c_master_instance.i2c_scl_edge_cnt >> 1)) & 0x80)
                {
                    SDA_H();
                }
                else
                {
                    SDA_L();
                }
            }
            else//偶数次，SCL拉高，从机读取SDA
            {
                SCL_H();
                if(i2c_master_instance.i2c_scl_edge_cnt == BYTE_LAST_BIT_SCL)
                {
                    i2c_master_instance.i2c_status = I2C_ADDRESS_ACK;
                }
            }
        }break;
        
        /* 主机发送地址后接收ACK/NACK */
        case I2C_ADDRESS_ACK:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，主机控制SDA变化
            {
                SCL_L();
                SDA_MODE_INPUT();
            }
            else//偶数次，SCL拉高
            {
                SCL_H();
                i2c_master_instance.i2c_scl_edge_cnt = 0;
                
                if((SDA_READ() == 0) && (i2c_master_instance.i2c_master_data_len != 0))//ACK
                {
                    if(i2c_master_instance.i2c_read_write_flag == 0)//写
                    {
                        i2c_master_instance.i2c_status = I2C_SEND_DATA;
                    }
                    else//读
                    {
                        i2c_master_instance.i2c_status = I2C_RECEIVE_DATA;
                        
                    }
                }
                else//NACK
                {
                    i2c_master_instance.i2c_status = I2C_STOP;
                }
            }
        }break;
        
        /* 主机发送数据 */
        case I2C_SEND_DATA:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，主机控制SDA变化
            {
                temp_val = (i2c_master_instance.i2c_scl_edge_cnt >> 1);
                SCL_L();
                if((i2c_master_instance.i2c_master_data << temp_val) & 0x80)
                {
                    SDA_H();
                }
                else
                {
                    SDA_L();
                }
                SDA_MODE_OUTPUT();
            }
            else//偶数次，SCL拉高，从机读取SDA
            {
                SCL_H();
                if(i2c_master_instance.i2c_scl_edge_cnt == BYTE_LAST_BIT_SCL)
                {
                    i2c_master_instance.i2c_master_data_cnt++;
                    i2c_master_instance.i2c_master_data = *(i2c_master_instance.i2c_master_buffer + i2c_master_instance.i2c_master_data_cnt);
                    i2c_master_instance.i2c_status = I2C_RECEIVE_ACK;
                }
            }
        }break;
        
        /* 主机接收ACK/NACK */
        case I2C_RECEIVE_ACK:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，主机控制SDA变化
            {
                SCL_L();
                SDA_MODE_INPUT();
            }
            else//偶数次，SCL拉高
            {
                SCL_H();
                i2c_master_instance.i2c_scl_edge_cnt = 0;
                
                if(SDA_READ() == 0)//ACK
                {
                    if(i2c_master_instance.i2c_master_data_cnt < i2c_master_instance.i2c_master_data_len)//数据发送完，发送结束
                    {
                        i2c_master_instance.i2c_status = I2C_SEND_DATA;
                    }
                    else
                    {
                        i2c_master_instance.i2c_status = I2C_STOP;
                    }
                }
                else//NACK
                {
                    i2c_master_instance.i2c_status = I2C_STOP;
                }
            }
        }break;
        
        /* 主机接收数据 */
        case I2C_RECEIVE_DATA:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，从机控制SDA变化
            {
                SCL_L();
                SDA_MODE_INPUT();
            }
            else//偶数次，SCL拉高，主机读取SDA
            {
                SCL_H();
                i2c_master_instance.i2c_master_data = (i2c_master_instance.i2c_master_data << 1);
                if(SDA_READ() == 1)
                {
                    i2c_master_instance.i2c_master_data += 1;
                }
                if(i2c_master_instance.i2c_scl_edge_cnt == BYTE_LAST_BIT_SCL)
                {
                    temp_val = i2c_master_instance.i2c_master_data;
                    *(i2c_master_instance.i2c_master_buffer + i2c_master_instance.i2c_master_data_cnt) = temp_val;
                    i2c_master_instance.i2c_master_data = 0;
                    i2c_master_instance.i2c_master_data_cnt++;
                    i2c_master_instance.i2c_status = I2C_SEND_ACK;
                }
            }
        }break;
        
        /* 主机发送ACK/NACK */
        case I2C_SEND_ACK:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt & 0x01)//奇数次，SCL拉低，主机控制SDA变化
            {
                SCL_L();
                
                if(i2c_master_instance.i2c_master_data_cnt < i2c_master_instance.i2c_master_data_len)//数据接收完成，接收结束，NACK
                {
                    SDA_L();
                }
                else//ACK
                {
                    SDA_H();
                }
                SDA_MODE_OUTPUT();
            }
            else//偶数次，SCL拉高
            {
                SCL_H();
                if(i2c_master_instance.i2c_master_data_cnt < i2c_master_instance.i2c_master_data_len)//数据接收完成，接收结束
                {
                    i2c_master_instance.i2c_status = I2C_RECEIVE_DATA;
                }
                else
                {
                    i2c_master_instance.i2c_status = I2C_STOP;
                }
                i2c_master_instance.i2c_scl_edge_cnt = 0;
            }
        }break;
        
        /* 主机发送停止位 */
        default:
        case I2C_STOP:
        {
            if(i2c_master_instance.i2c_scl_edge_cnt == 0x01)
            {
                SCL_L();
                SDA_L();
                SDA_MODE_OUTPUT();
            }
            else if(i2c_master_instance.i2c_scl_edge_cnt == 0x02)
            {
                SCL_H();
            }
            else
            {
                I2C_SIM_TIM_DISABLE();
                SDA_H();
                i2c_master_instance.i2c_status = I2C_IDLE;
            }
        }break;
    }
}


