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

#include "mb85rc64.h"


/*
  @ brief  延时函数
  @ param  
  @ return
  @ note   2022-5-23
*/
static void delay_us(int us)
{
  for(int i = 0; i < us; i++ )
  {
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
    asm("nop");
  }  
}

/*
  @ brief  芯片初始化
  @ param  
  @ return
  @ note  2022-05-26
*/
void mb85rc64_gpio_init()
{
  //配置引脚时钟
  rcu_periph_clock_enable(RCU_GPIOB);
  //设置引脚为输出模式:PB6
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
  
  //设置引脚PB7输出模式
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
  
  MB85RC64_SCL_HIGH;
  MB85RC64_SDA_HIGH;
}

/*
  @ brief  设置SDA引脚为输出模式
  @ param  
  @ return 
  @ note  2022-5-26 lqc
*/
static void mb85rc64_sda_output()
{
  gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
  gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
  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, GPIO_PIN_7);
  gpio_output_options_set(GPIOB, GPIO_PUPD_NONE, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
}

/*
  @ 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：保存数据的长度
  @ return
  @ note   2022-05-27
*/
char mb85rc64_page_write(unsigned short int addr, unsigned char* data, int data_len)
{
  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);
  //ack信号
  mb85rc64_ack();
  //写高8位地址
  mb85rc64_write_byte(addr_H);
  //ack信号
  mb85rc64_ack();
  //写低8位地址
  mb85rc64_write_byte(addr_L);
  //ack信号
  mb85rc64_ack();
  for(int i = 0; i < data_len; i++)
  {
    mb85rc64_write_byte(*data);
    mb85rc64_ack();
    data++;
  }
  //停止信号
  i2c_stop();
  return 1;
}

/*
  @ brief  读取数据 ，顺序读取，指定地址，连续接收数据
  @ param   addr :需要读取数据的地址，data:数据, data_len:数据长度
  @ return 
  @ note   2022-05-27 lqc
*/
char mb85rc64_add_read(unsigned short int addr, unsigned char *data, int data_len)
{
  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);
  //ack信号
  mb85rc64_ack();
  //写高8位地址
  mb85rc64_write_byte(addr_H);
  //ack信号
  mb85rc64_ack();
  //写低8位地址
  mb85rc64_write_byte(addr_L);
  //ack信号
  mb85rc64_ack();
  
  //启动信号
  i2c_start();
  //写地址，R/W为为1，读数据
  mb85rc64_write_byte(MB85RC64_ADDRESS_READ);
  //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;
}

void read_mb_id(uint8_t* buff)
{
  i2c_start();
  mb85rc64_write_byte(0xf8);
  mb85rc64_ack();
  mb85rc64_write_byte(MB85RC64_ADDRESS_WRITE);
  mb85rc64_ack();
  i2c_start();
  mb85rc64_write_byte(0xf9);
  mb85rc64_ack();
  for(int i = 0; i < 3; i++)
  {
    //读数据
    buff[i] = mb85rc64_read_byte();
    if(i == 3 - 1)
    {
      master_no_ack();
    }
    else
    {
      master_ack();
    }
  }
  i2c_stop();
}
