//mem_24LC_lib_i2c.c


#include "mem_24LC_lib_i2c.h"

int mem24LC_Clock = 200000000; //Hz: システムクロック

char read_data[20]; //I2Cデータ受信用



void mem24LC_delay_us(unsigned int usec) //1μsec遅延関数
{
volatile int count;

count = (int)(mem24LC_Clock/20000000)*usec;

do //実測 at 200MH (mem24LC_Clock=200000000)
{ //delay_us(1000):1000.4μsec delay_us(100):100.6μsec delay_us(10):10.5μsec  delay_us(1):1.5μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

count--;
}while(count != 0);


}

void mem24LC_delay_ms(unsigned int msec) //1msec遅延関数
{
unsigned int i;

for(i=0; i<msec; i++)
delay_us(1000);
}


void mem24LC_Reset_i2C(void)
{
I2CXCONbits.ON = 0; //IC2モジュール:OFF
I2CXCONbits.ON = 1; //IC2モジュール:ON
}


void mem24LC_Idle_i2c(void) //アイドル待ち
{
while(I2CXCONbits.SEN || I2CXCONbits.PEN || I2CXCONbits.RCEN
|| I2CXCONbits.ACKEN || I2CXSTATbits.TRSTAT);
}


void mem24LC_start_i2c(void) //I2Cスタート
{
mem24LC_Idle_i2c();
I2CXCONbits.SEN = 1; // スタート出力//
while(I2CXCONbits.SEN); // スタート終了待ち
}


void mem24LC_stop_i2c(void) //I2Cストップ
{
I2CXCONbits.PEN = 1; // ストップ出力
while(I2CXCONbits.PEN); // ストップ終了待ち

}




void mem24LC_write_byte_i2c(unsigned char byte) //1バイト書込み
{

I2CXTRN = byte; // データセット送信開始
while(I2CXSTATbits.TBF); // 送信終了待ち
while(I2CXSTATbits.ACKSTAT); // ACK返信待ち
mem24LC_Idle_i2c(); // アイドル待ち

}

void mem24LC_restart_i2c(void)
{
I2CXCONbits.RSEN = 1; //リスタート条件出力
while(I2CXCONbits.RSEN); //出力完了待ち
}

unsigned char mem24LC_ReadChr(unsigned char adr_chips, unsigned int adr_chip_inner)
{
unsigned char data; //EEPROM読み込みデータ
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
char adr_read_cmd = ((0xa0 | (adr_chips << 1)) | (0b00000001)); //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

mem24LC_Reset_i2C(); //erratta 対策

mem24LC_start_i2c(); //スタート条件送信
mem24LC_Idle_i2c(); //アイドル待

mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();

mem24LC_restart_i2c(); //再スタート条件送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_read_cmd); //(I2Cバスアドレス + 読み込みコマンド)送信
mem24LC_Idle_i2c();

I2CXCONbits.RCEN = 1; //受信許可

while(!I2CXSTATbits.RBF); //受信バッファI2CXRCVが フルになるまで待つ  //Receive complete, I2CxRCV is full

data = I2CXRCV; //受信バッファI2CXRCV読み込み

mem24LC_stop_i2c(); //ストップ条件送信
mem24LC_Idle_i2c();

mem24LC_Reset_i2C(); //erratta 対策

return data;

}

void mem24LC_ReadStr(unsigned char adr_chips, unsigned int adr_chip_inner) //文字列 読み込み
{
int ix = 0;

char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
char adr_read_cmd = ((0xa0 | (adr_chips << 1)) | (0b00000001)); //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

mem24LC_Reset_i2C(); //erratta 対策

mem24LC_start_i2c(); //スタート条件送信
mem24LC_Idle_i2c(); //アイドル待

mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();

mem24LC_restart_i2c(); //再スタート条件送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_read_cmd); //(I2Cバスアドレス + 読み込みコマンド)送信
mem24LC_Idle_i2c();


while(1) //文字列データの取得
{
I2CXCONbits.RCEN = 1; //受信許可
while(!I2CXSTATbits.RBF); //受信バッファI2CXRCVが フルになるまで待つ  //Receive complete, I2CxRCV is full
read_data[ix] = I2CXRCV; //受信バッファI2CXRCV読み込み

if(read_data[ix] == '\r' || ix >= 16)break; //データ終端検出

I2CXCONbits.ACKDT = 0; //更にデータ送信をスレーブに要求するのでACK=0をセットする //AckIC1();
I2CXCONbits.ACKEN = 1; //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
while(I2CXCONbits.ACKEN); //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

ix++;

}

read_data[ix] = '\0'; //配列を文字列化

I2CXCONbits.ACKDT = 1; //スレーブからの文字送信要求は終了なのでNACK=1をセット // NotAckI2C1();
//vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
I2CXCONbits.ACKEN = 1; //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
while(I2CXCONbits.ACKEN); //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

mem24LC_stop_i2c(); //ストップ条件送信
mem24LC_Idle_i2c();

mem24LC_Reset_i2C(); //erratta 対策



}


void mem24LC_WriteChr(unsigned char adr_chips, unsigned int adr_chip_inner, unsigned char data)
{
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0


mem24LC_Reset_i2C(); //erratta 対策

mem24LC_start_i2c(); //スタート条件 送信
mem24LC_Idle_i2c(); //アイドル待ち

mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();


mem24LC_write_byte_i2c(data); //データ送信
mem24LC_Idle_i2c();


mem24LC_stop_i2c(); //ストップ条件 送信
mem24LC_Reset_i2C(); //errata 対策
mem24LC_Idle_i2c();

mem24LC_delay_ms(5); //EEPROM書き込み待ち

mem24LC_Reset_i2C(); //erratta 対策


}



void mem24LC_WriteStr(unsigned char adr_chips, unsigned int adr_chip_inner, char* str) //文字列書込み
{
char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110)); //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0

mem24LC_Reset_i2C(); //erratta 対策

mem24LC_start_i2c(); //スタート条件 送信
mem24LC_Idle_i2c(); //アイドル待ち

mem24LC_write_byte_i2c(adr_write_cmd); // (I2Cバスアドレス + 書き込みコマンド)送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner >> 8); //EEPROM内部アドレスの上位送信
mem24LC_Idle_i2c();

mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF); //EEPROM内部アドレスの下位送信
mem24LC_Idle_i2c();

while(*str)
{
mem24LC_write_byte_i2c(*str); //データ送信
mem24LC_Idle_i2c();
str++;

}


mem24LC_stop_i2c(); //ストップ条件 送信
mem24LC_Reset_i2C(); //errata 対策
mem24LC_Idle_i2c();


mem24LC_delay_ms(5); //EEPROM書き込み待ち

mem24LC_Reset_i2C(); //erratta 対策


}