#include "hal_nca9555.h"



 

 
 
#define READ_SDA1    GPIO_ReadInputPins(GPIO_PORT_C,GPIO_PIN_10)
#define IIC_SDA1(n) (n?GPIO_SetPins(GPIO_PORT_C, GPIO_PIN_10):GPIO_ResetPins(GPIO_PORT_C, GPIO_PIN_10))
#define IIC_SCL1(n) (n?GPIO_SetPins(GPIO_PORT_C, GPIO_PIN_11):GPIO_ResetPins(GPIO_PORT_C, GPIO_PIN_11))

static void delay_us(uint16_t time)
{
	uint16_t i;

	for(i=time;i>0;i--)
	{
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();		
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	  __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
		__nop();__nop();__nop();
	}
}  

static void iic1_init(void)
{
	stc_gpio_init_t  pstcGpioInit1;
	GPIO_StructInit(&pstcGpioInit1);
	
	pstcGpioInit1.u16PinDir = PIN_DIR_OUT;
	pstcGpioInit1.u16PinState = PIN_STAT_RST;
	GPIO_Init(GPIO_PORT_C, GPIO_PIN_10,&pstcGpioInit1); 
	GPIO_Init(GPIO_PORT_C, GPIO_PIN_11,&pstcGpioInit1); 
	
	GPIO_SetPins(GPIO_PORT_C, GPIO_PIN_10);
	GPIO_SetPins(GPIO_PORT_C, GPIO_PIN_11);
}

 
static void SDA_IN1(void)
{
	 stc_gpio_init_t pstcGpioInit3;//iic的引脚
	 pstcGpioInit3.u16PinDir = PIN_DIR_IN;
	 GPIO_Init(GPIO_PORT_C, GPIO_PIN_10,&pstcGpioInit3);
}

static void SDA_OUT1(void)  
{
	stc_gpio_init_t pstcGpioInit3;
	pstcGpioInit3.u16PinDir = PIN_DIR_OUT;
	pstcGpioInit3.u16PinOutputType=PIN_OUT_TYPE_NMOS;
	GPIO_Init(GPIO_PORT_C, GPIO_PIN_10,&pstcGpioInit3);
}	
 
 

static void iic_start(void)
{
	SDA_OUT1();
	
	IIC_SDA1(1);
	IIC_SCL1(1);
	delay_us(5);
	
	IIC_SDA1(0);
	delay_us(5);
	IIC_SCL1(0);
}


static void iic_stop(void)
{
	SDA_OUT1();
	
	IIC_SCL1(0);
	IIC_SDA1(0);
	delay_us(5);
	
	IIC_SCL1(1);
	IIC_SDA1(1);
	delay_us(5);
}

static void iic_ack(void)
{
	SDA_OUT1();
	
	IIC_SCL1(0);
	IIC_SDA1(0);
	delay_us(5);
	
	IIC_SCL1(1);
	delay_us(5);
	IIC_SCL1(0);
}

static void iic_nack(void)
{
	SDA_OUT1();
	
	IIC_SCL1(0);
	IIC_SDA1(1);
	delay_us(5);
	
	IIC_SCL1(1);
	delay_us(5);
	IIC_SCL1(0);
}
 

static uint8_t iic_wait_ack(void)
{
	uint16_t t =200;
	SDA_OUT1();
	
	IIC_SDA1(1);delay_us(1);
	IIC_SCL1(1);delay_us(1);

	SDA_IN1();

	while(READ_SDA1) 
	{
		t--;
		
		if(t==0)
		{
			iic_stop();
			return 1;
		}
		delay_us(1);
	}
	IIC_SCL1(0);
		
	return 0;
}


static void iic_send_byte(uint8_t byte)
{
  uint8_t bit_cnt;
	SDA_OUT1();
	IIC_SCL1(0);
	 
	for(bit_cnt=0;bit_cnt<8;bit_cnt++)
	{	 
		if(byte&0x80)	
			IIC_SDA1(1); 
		else	
			IIC_SDA1(0);
		
		byte<<=1;
		delay_us(5);
		IIC_SCL1(1);
		delay_us(5);
		IIC_SCL1(0);
	}
}
 

static uint8_t iic_recive_byte(unsigned char ack)
{
  uint8_t retc = 0;
  uint8_t bit_cnt;

	SDA_IN1(); 
 
	for(bit_cnt=0;bit_cnt<8;bit_cnt++)
	{
		IIC_SCL1(0);
		delay_us(5);
		IIC_SCL1(1);
		
		retc=retc<<1;
		if(READ_SDA1) retc++;
		delay_us(5);
	}
 
	return(retc);
}
 



void nca9555_init(void)
{
    iic1_init();
}



uint8_t nca9555_write_byte(uint8_t addr, uint8_t command, uint8_t write_register_data)
{
    uint8_t ret = 1;
    iic_start();
    iic_send_byte(addr);
    ret =  iic_wait_ack();

    iic_send_byte(command);
    ret =  iic_wait_ack();

    iic_send_byte(write_register_data);
    ret =  iic_wait_ack();

    iic_stop();
    return SUCCESS;
}

/*
 * nca9555读取寄存器值
 *
 * addr 读取地址
 * read_register_data 要读取的寄存器
 * read_data 读取数据存放地址
 *
 *
 * 返回值:读取成功返回SUCCESS  失败返回ERROR
 *
 * */
uint8_t nca9555_read_byte(uint8_t slave_num, uint8_t addr, uint8_t read_register_data, uint8_t *read_data)
{
    uint8_t ret = 0;
    iic_start();
    iic_send_byte(slave_num);
    ret =  iic_wait_ack();

    iic_send_byte(read_register_data); 
    ret = iic_wait_ack();

    iic_start(); /* 开始接收数据 */
    iic_send_byte(addr);
    ret = iic_wait_ack();

    *read_data = iic_recive_byte(0);

    iic_stop();
    return SUCCESS;
}


/*
 * 设置指定GPIO的模式
 *
 * slave_num  需要操作的从机设备
 * gpio_port  gpio端口  端口0/1
 * gpio_num   哪一个GPIO
 *
 * 返回值:void
 * */
void nca9555_set_output_mode(uint8_t slave_num, uint8_t gpio_port,  uint8_t gpio_num)
{
    uint8_t register_original_data = 0;
    if(gpio_port > 1 || gpio_num > 0x80)  return;
    if(gpio_port == 0)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, CONFIG_PORT_REGISTER0, &register_original_data);
        nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER0, register_original_data & (~gpio_num));
    }
    else if(gpio_port == 1)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, CONFIG_PORT_REGISTER1, &register_original_data);
        nca9555_write_byte( slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER1, register_original_data & (~gpio_num));
    }
}



/*
 * 设置GPIO输出状态
 *
 * slave_num  需要操作的从机设备
 * gpio_port  gpio端口  端口0/1
 * gpio_num   哪一个GPIO
 * status     输出状态
 *
 * 返回值:void
 **/
void nca9555_set_gpio_output_status(uint8_t slave_num, uint8_t gpio_port,  uint8_t gpio_num, uint8_t status)
{
    uint8_t register_original_data = 0;
    if(gpio_port > 1 || gpio_num > 0x80)  return;
    if(gpio_port == 0)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, OUTPUT_PORT_REGISTER0, &register_original_data);
        if(status == 1)
        {
            nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER0, register_original_data | gpio_num);
        }
        else
        {
            nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER0, register_original_data & (~gpio_num));
        }
    }
    else if(gpio_port == 1)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, OUTPUT_PORT_REGISTER1, &register_original_data);
        if(status == 1)
        {
            nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER1, register_original_data | gpio_num);
        }
        else
        {
            nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, OUTPUT_PORT_REGISTER1, register_original_data & (~gpio_num));
        }
    }
}




/*
 * 设置GPIO为输入模式
 *
 * slave_num  需要操作的从机设备
 * gpio_port  gpio端口  端口0/1
 * gpio_num   哪一个GPIO
 *
 * 返回值:void
 **/
void nca9555_set_input_mode(uint8_t slave_num, uint8_t gpio_port,  uint8_t gpio_num)
{
    uint8_t register_original_data = 0;
    if(gpio_port > 1 || gpio_num > 0x80)  return;
    if(gpio_port == 0)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, CONFIG_PORT_REGISTER0, &register_original_data);
        nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER0, register_original_data & gpio_num);
    }
    else if(gpio_port == 1)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, CONFIG_PORT_REGISTER1, &register_original_data);
        nca9555_write_byte(slave_num | HOST_WRITE_COMMAND, CONFIG_PORT_REGISTER1, register_original_data & gpio_num);
    }
}
/*
 * 获取GPIO状态
 *
 * slave_num  需要操作的从机设备
 * gpio_port  gpio端口  端口0/1
 * gpio_num   哪一个GPIO
 *
 * 返回值:GPIO状态
 **/
uint8_t nca9555_get_gpio_status(uint8_t slave_num, uint8_t gpio_port,  uint8_t gpio_num)
{
    uint8_t register_original_data = 0;
    uint8_t gpio_status = 0;
    if(gpio_port > 1 || gpio_num > 0x80)
    {
        return 2;
    }
    if(gpio_port == 0)
    {

        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, INPUT_PORT_REGISTER0, &register_original_data);

    }
    else if(gpio_port == 1)
    {
        nca9555_read_byte(slave_num, slave_num  | HOST_READ_COMMAND, INPUT_PORT_REGISTER1, &register_original_data);
    }
    switch(gpio_num)
    {
        case 0x01:  gpio_status = register_original_data & gpio_num;break;
        case 0x02:  gpio_status = (register_original_data & gpio_num) >> 1;break;
        case 0x04:  gpio_status = (register_original_data & gpio_num) >> 2;break;
        case 0x08:  gpio_status = (register_original_data & gpio_num) >> 3;break;
        case 0x10:  gpio_status = (register_original_data & gpio_num) >> 4;break;
        case 0x20:  gpio_status = (register_original_data & gpio_num) >> 5;break;
        case 0x40:  gpio_status = (register_original_data & gpio_num) >> 6;break;
        case 0x80:  gpio_status = (register_original_data & gpio_num) >> 7;break;
        default: break;
    }
    return gpio_status;
}


#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "hal_sc7a20.h"

void nca9555_task(void *argv)
{
	nca9555_set_output_mode(SLAVE_ADDR0,GPIO_PORT0,GPIO_Pin00|GPIO_Pin01|GPIO_Pin02|GPIO_Pin03);
 
	while(1)
	{
		nca9555_set_gpio_output_status(SLAVE_ADDR0,GPIO_PORT0,GPIO_Pin00|GPIO_Pin01|GPIO_Pin02|GPIO_Pin03,HIGH); 
		vTaskDelay(500);
		nca9555_set_gpio_output_status(SLAVE_ADDR0,GPIO_PORT0,GPIO_Pin00|GPIO_Pin01|GPIO_Pin02|GPIO_Pin03,LOW); 
		vTaskDelay(500);
	}
}