///Copyright (c) 2022, 四川汇源光通信有限公司 
///All rights reserved. 
///@file        mb85rc64.h 
///@brief       mb85rc64驱动程序 铁电存储器
///
///@details     
///@note        
///@author      dufresne
///@date        2025/09/26
///
///@version		v1.0 2022/05/26 初始版本

#include "mb85rc64.h"

#ifdef  SOFTWARE_I2C

/*
  @ brief  设置SDA引脚为输出模式
  @ param  
  @ return 
  @ note  2022-5-26 lqc
*/
static void mb85rc64_sda_output()
{
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, I2C_SDA_PIN);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
  MB85RC64_SDA_HIGH;
}

/*
  @ brief  设置SDA引脚为输入模式
  @ param  
  @ return 
  @ note   2022-5-26 lqc
*/
static void mb85rc64_sda_input()
{
  gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
  gpio_output_options_set(GPIOB, GPIO_PUPD_NONE, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
}

/*
  @ brief  I2C start信号
  @ param  
  @ return 
  @ note  2022-5-25
*/
static void i2c_start()
{
  MB85RC64_SDA_HIGH;
  delay_us(5);
  MB85RC64_SCL_HIGH;
  delay_us(5);
  MB85RC64_SDA_LOW;
  delay_us(4);
}

/* 
  @ brief  I2C stop信号
  @ param
  @ return
  @ note  2022-05-25
*/
static void i2c_stop()
{
  MB85RC64_SDA_LOW;
  delay_us(5);
  MB85RC64_SCL_HIGH;
  delay_us(5);
  MB85RC64_SDA_HIGH;  
  delay_us(4);
}

/*
  @ brief  mb85rc64接收数据产生ACK信号
  @ param  SDA被从设备拉为低电平表示应答
  @ return
  @ note  2022-05-26
*/
static void mb85rc64_ack()
{
  int i = 0;
  mb85rc64_sda_input();
  delay_us(5);
  MB85RC64_SCL_HIGH;
  delay_us(5);
  while((MB85RC64_SDA_GET) && i<1000)
  {
    i++;
  }
  delay_us(5);
  MB85RC64_SCL_LOW;
  delay_us(5);
  mb85rc64_sda_output();
}

/*
  @ brief  主机读取数据发送ACK信号,SDA为低电平
  @ param  SCL下降沿发送
  @ return 
  @ note   2022-05-26
*/
static void master_ack()
{
  MB85RC64_SDA_LOW;
  delay_us(5);
  MB85RC64_SCL_HIGH;
  delay_us(5);
  MB85RC64_SCL_LOW;
  delay_us(5);
}

/*
  @ brief 主机读取数据完毕，发送no_ack信号，SDA为高电平
  @ param  
  @ return
  @ note   2022-05-26
*/
static void master_no_ack()
{
  MB85RC64_SDA_HIGH;
  delay_us(5);
  MB85RC64_SCL_HIGH;
  delay_us(5);
  MB85RC64_SCL_LOW;
  delay_us(5);
}

/*
  @ brief 写一个字节数据
  @ param
  @ return
  @ note  2022-05-26
*/
static void mb85rc64_write_byte(uint8_t byte)
{
  for(int i = 0; i < 8; i++)
  {
    MB85RC64_SCL_LOW;
    delay_us(5);
    if(byte & 0x80)
    {
      MB85RC64_SDA_HIGH;
    }
    else
    {
      MB85RC64_SDA_LOW;
    }
    
    MB85RC64_SCL_HIGH;
    delay_us(5);
    byte <<= 1;
  }
  MB85RC64_SCL_LOW;
}

/*
  @ brief 读一个字节数据
  @ param
  @ return
  @ note  2022-05-26
*/
static uint8_t mb85rc64_read_byte()
{
  uint8_t value = 0;
  MB85RC64_SCL_LOW;
  delay_us(5);
  mb85rc64_sda_input();
  
  
  for(int i = 0; i < 8; i++)
  {
    
    value <<= 1;
    MB85RC64_SCL_LOW;
    delay_us(5);
    MB85RC64_SCL_HIGH;
    
    delay_us(5);
    if(MB85RC64_SDA_GET)
    {
      value = value | 0x01;
    }
    else {
      value = value & 0xfe;
    }
  }
   MB85RC64_SCL_LOW;
  delay_us(5);
  mb85rc64_sda_output();
  return value;
}

/*
  @ brief 保存数据，页写
  @ param  addr:保存数据的地址，data:需保存的数据，data_len：保存数据的长度，statues：页写还是地址读
  @ return
  @ note   2022-05-27
*/
bool mb85rc64_write_read(unsigned short int addr, unsigned char* data, int data_len, bool statues)
{
	uint8_t addr_H = 0;
	uint8_t addr_L = 0;

	addr_H = (addr >> 8) & 0x00ff;
	addr_L = addr & 0x00ff;
	//启动信号
	i2c_start();
	//写地址,R/W位=0
	// mb85rc64_write_byte(MB85RC64_ADDRESS_WRITE);
	mb85rc64_write_byte(MB85RC64_ADDRESS << 1);
	//ack信号
	mb85rc64_ack();
	//写高8位地址
	mb85rc64_write_byte(addr_H);
	//ack信号
	mb85rc64_ack();
	//写低8位地址
	mb85rc64_write_byte(addr_L);
	//ack信号
	mb85rc64_ack();

	if (statues == PAGE_WRITE)
	{
		for(int i = 0; i < data_len; i++)
		{
			mb85rc64_write_byte(*data);
			mb85rc64_ack();
			data++;
		}
	}
	else if (statues == ADDR_READ)
	{
		//启动信号
		i2c_start();
		//写地址，R/W为为1，读数据
		mb85rc64_write_byte((MB85RC64_ADDRESS << 1) + 1);
		//ack信号
		mb85rc64_ack();
		for(int i = 0; i < data_len; i++)
		{
			//读数据
			data[i] = mb85rc64_read_byte();
			if(i == data_len - 1)
			{
				master_no_ack();
			}
			else
			{
				master_ack();
			}
		}
	}
	//停止信号
	i2c_stop();
	return 1;
}

#endif

#ifdef  HARDWARE_I2C

/*
  @ brief 保存数据，页写
  @ param  addr:操作数据的地址，data:需保存的数据，data_len：保存数据的长度，statues：页写还是地址读
  @ return
  @ note   2022-05-27
*/
bool mb85rc64_write_read(unsigned short int addr, unsigned char* data, int data_len, bool statues)
{
	uint8_t addr_HL[2];

	addr_HL[0] = (addr >> 8) & 0x00ff;
	addr_HL[1] = addr & 0x00ff;

    /* 等待总线空闲 */
    while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));
    /* 发送起始条件 */
    i2c_start_on_bus(I2C_PERIPH);
    /* 等待起始条件已发送标志 */
    while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));
    /* 发送从机地址（写模式） */
    i2c_master_addressing(I2C_PERIPH, MB85RC64_ADDRESS << 1, I2C_TRANSMITTER);
    /* 等待地址已发送标志 */
    while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));
    /* 清除地址发送标志 */
    i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);

    for(int i = 0; i < 2; i++)
    {
        /* 等待发送数据缓冲区为空 */
        while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));
        /* 发送一个字节数据 */
        i2c_data_transmit(I2C_PERIPH, addr_HL[i]);
    }
    /* 等待数据传输完成 */
    while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));
    /* 清除数据传输完成标志 */
    i2c_flag_clear(I2C_PERIPH, I2C_FLAG_TBE);


	if (statues == PAGE_WRITE)
	{
		for(int i = 0; i < data_len; i++)
		{
			/* 等待发送数据缓冲区为空 */
			while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));
			/* 发送一个字节数据 */
			i2c_data_transmit(I2C_PERIPH, data[i]);
		}
	}
	else if (statues == ADDR_READ)
	{
		// /* 等待总线空闲 */
		// while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));
		/* 发送起始条件 */
		i2c_start_on_bus(I2C_PERIPH);
		/* 等待起始条件已发送标志 */
		while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));
		/* 发送从机地址（写模式） */
		i2c_master_addressing(I2C_PERIPH, MB85RC64_ADDRESS << 1, I2C_RECEIVER);
		/* 等待地址已发送标志 */
		while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));
		/* 清除地址发送标志 */
		i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);

		/* 5. 接收数据 */
		if(data_len > 1)
		{
			/* 使能ACK（多个字节接收时需要应答） */
			i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);
			
			for(int i = 0; i < data_len; i++)
			{
				if(i == (data_len - 1))
				{
					/* 最后一个字节前禁用ACK */
					i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);
				}
				
				/* 等待RBNE标志（接收缓冲区非空） */
				while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE));
				
				/* 读取数据 */
				data[i] = i2c_data_receive(I2C_PERIPH);
			}
		}
		else
		{
			/* 单字节接收：直接禁用ACK */
			i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);
			
			/* 等待RBNE标志 */
			while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE));
			
			/* 读取数据 */
			data[0] = i2c_data_receive(I2C_PERIPH);
		}
	}
		/* 发送停止信号 */
    i2c_stop_on_bus(I2C_PERIPH);
    /* 等待停止信号完成 */
    while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP);

	return 1;
}


#endif