//lcd_ACM1602_lib_i2c.c
///////////////////////////////////////////////
// 秋月 キャラクタ液晶 ACM1602NI
// I2Cインターフェース 16文字 x 2行 for PIC32MZ & XC32コンパイラ
// Vcc: 2.7v -5.5v
//
//  lcd_ACM1602_init_i2c() ----- 初期化
// lcd_ACM1602_cmd_i2c(cmd) ----- コマンド出力
// lcd_ACM1602_data_i2c(chr) ----- 1文字表示出力
// lcd_ACM1602_clear_i2c() ----- 全消去
// lcd_ACM1602_str_i2c(str*) ----- 文字列表示
// lcd_ACM1602_cmd_i2c(0x0C); //カーソル:0FF、ブリンク:0FF
// lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ
// lcd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ
//////////////////////////////////////////////


#include "lcd_ACM1602_lib_i2c.h"

#ifndef MY_INCLUDE_XC_H
#define MY_INCLUDE_XC_H
#include <xc.h> //追加
#endif


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

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

do //実測: at 200MH (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 lcd_ACM1602_delay_ms_i2c(unsigned int msec) //1msec遅延関数
{
unsigned int i;

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




void lcd_ACM1602_Reset_i2C(void)
{

I2CXCONbits.ON = 0; //IC2モジュール:OFF
I2CXCONbits.ON = 1; //IC2モジュール:ON
}


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

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

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

}


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

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

}



void lcd_ACM1602_WtiteCommand_i2c(unsigned char command) //コマンド送信
{
lcd_ACM1602_Reset_i2C(); //i2Cモジュール 再スタート

lcd_ACM1602_start_i2c();
lcd_ACM1602_write_byte_i2c(0xa0); // アドレス+送信モード送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);

lcd_ACM1602_write_byte_i2c(0x00); // レジスタ指定送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);

lcd_ACM1602_write_byte_i2c(command);// コマンド送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);


lcd_ACM1602_stop_i2c();



}


void lcd_ACM1602_WriteData_i2c(unsigned char data) //データ送信
{
lcd_ACM1602_Reset_i2C(); //i2Cモジュール 再スタート

lcd_ACM1602_start_i2c();
lcd_ACM1602_write_byte_i2c(0xa0); // アドレス+送信モード送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);

lcd_ACM1602_write_byte_i2c(0x80); // レジスタ指定送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);

lcd_ACM1602_write_byte_i2c(data); // データ送信
lcd_ACM1602_Idle_i2c();
lcd_ACM1602_delay_us_i2c(10);
lcd_ACM1602_stop_i2c();

}

void lcd_ACM1602_cmd_i2c(unsigned char cmd)
{

lcd_ACM1602_WtiteCommand_i2c(cmd); //
lcd_ACM1602_Idle_i2c();

if((cmd == 0x01)||(cmd == 0x02)) // Clear or Homeコマンドの場合
lcd_ACM1602_delay_ms_i2c(3); // 3msec待ち
else
lcd_ACM1602_delay_us_i2c(60); //60μsec待ち
}


void lcd_ACM1602_init_i2c(void) //液晶初期化
{

lcd_ACM1602_delay_ms_i2c(100);

lcd_ACM1602_cmd_i2c(0x01); //WtiteCommand(0x01);
lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms


lcd_ACM1602_cmd_i2c(0x38); //WtiteCommand(0x38);
lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms



lcd_ACM1602_cmd_i2c(0x0f); //WtiteCommand(0x0f);
lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms


lcd_ACM1602_cmd_i2c(0x0f); //WtiteCommand(0x06);
lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms


}


void lcd_ACM1602_data_i2c(unsigned char data) //1文字表示
{
lcd_ACM1602_WriteData_i2c(data); //
lcd_ACM1602_delay_us_i2c(30); //delay_us(30); // 遅延
}


void lcd_ACM1602_clear_i2c(void) //画面クリア
{
lcd_ACM1602_cmd_i2c(0x01); //初期化コマンド出力
}


void lcd_ACM1602_str_i2c(const unsigned char* str) //文字列表示
{
while(*str != 0) ////文字列終端の '\0'を検出するまで
lcd_ACM1602_data_i2c(*str++); //1文字表示
}