#include <p18f2550.h>	//PIC18F2550のヘッダファイル
#include <delays.h>     //遅延関数
#include <i2c.h>        //I2C関数

//PIC18F2550　初期設定
#pragma config FOSC = HSPLL_HS
#pragma config WDT = OFF
#pragma config PLLDIV = 5
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2
#pragma config PWRT = ON
#pragma config BOR = OFF
#pragma config BORV = 2
#pragma config LVP = OFF
#pragma config VREGEN = ON
#pragma config MCLRE = OFF
#pragma config PBADEN = OFF

//関数定義
unsigned int acc_startup(unsigned char control);
unsigned int acc_read(unsigned char control);
unsigned int mag_startup(unsigned char control);
unsigned int mag_read(unsigned char control);

//グローバル変数定義
unsigned int acc_internal_register, acc_X_MSB, acc_X_LSB, acc_Y_MSB, acc_Y_LSB;
unsigned int mag_internal_register, mag_X_MSB, mag_X_LSB, mag_Y_MSB, mag_Y_LSB;


//メインプログラム
void main(void)
{
//変数定義
	int i, temp_acc, data_acc, temp_mag, data_mag;

//起動待ち時間設定
	for (i=0; i<0; i++){
	Delay10KTCYx(600);  // Delay of 500ms
    	               // Cycles = (TimeDelay * Fosc) / 4
        	           // Cycles = (500ms * 48MHz) / 4
            	       // Cycles = 6,000,000
	}

//入出力ポートの初期設定
    TRISA = 0; 			//Aポートを出力に設定
    TRISB = 0b00000011; //Bポートを入力：RB0〜RB1、出力：RB2〜RB7に設定

	OpenI2C(MASTER, SLEW_ON); //SSPモジュールの設定（マスターモード、400ｋHzモード）
	SSPADD = 11.5;		// Fosc/(4*SSPADD+1) 400kHz=20MHz/(4*(SSPADD+1))


while (1){							//永久ループ（以下、電源を切るまで繰り返し）

	temp_acc = acc_startup(0x20);		//加速度センサ立ち上げ

	if (temp_acc < 0) {					//エラーチェック
		break;
	}

	Delay10KTCYx(120);  // Delay of 100ms　　//加速度センサ立ち上げのための待ち時間設定
                   // Cycles = (TimeDelay * Fosc) / 4
                   // Cycles = (100ms * 48MHz) / 4
                   // Cycles = 1,200,000
	
	data_acc =acc_read(0x20);	//加速度センサ信号読み込み
	
	if ( data_acc < 0) {                //エラーチェック
		break;
	}
	
	temp_mag = mag_startup(0x60);	//磁気センサ立ち上げ

	if (temp_mag < 0) {					//エラーチェック
		break;
	}

	Delay10KTCYx(6);  // Delay of 5ms　 //磁気センサ立ち上げのための待ち時間設定
    	               // Cycles = (TimeDelay * Fosc) / 4
        	           // Cycles = (5ms * 48MHz) / 4
            	       // Cycles = 60,000

	data_mag = mag_read(0x60);	//磁気センサ信号読み取り

	if ( data_mag < 0) {                //エラーチェック
		break;
	}

	}
}

//サブ関数群
unsigned int acc_startup(unsigned char control)
//加速度センサ立ち上げ//
{

	IdleI2C();					//アイドル状態確認
	StartI2C();					//初期start condition送出
	while (SSPCON2bits.SEN);	//start出力待ち
	if (PIR2bits.BCLIF)			//バス上の衝突確認
		{return(-1);}				//衝突発生時、エラーリターン
	else						//正常時（衝突がない場合）、以下を実行
	{
		if (WriteI2C(control))	//センサアドレスと送信モード（00100000）信号を送信
			{return(-2);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-3);}		//エラーリターン
		PIR1bits.SSPIF = 0;		//SSPIFクリア		

		if (WriteI2C(0x00))		//センサのレジスタに(00000000)を送信
			{return(-4);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-5);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア

		if (WriteI2C(0x00))		//センサ立ち上げのためにセンサのレジスタに(00000000)を送信
			{return(-6);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-7);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア		
		
		IdleI2C();
		StopI2C();				//センサ書き込み動作終了
	
		return(0);				//エラーなしの場合0を戻す
	}
}

unsigned int mag_startup(unsigned char control)
//磁気センサ立ち上げ//
{
	IdleI2C();					//アイドル状態確認
	StartI2C();					//初期start condition送出
	while (SSPCON2bits.SEN);	//start出力待ち
	if (PIR2bits.BCLIF)			//バス上の衝突確認
		{return(-15);}			//衝突発生時、エラーリターン
	else						//正常時（衝突がない場合）、以下を実行
	{
		if (WriteI2C(control))	//センサアドレスと送信モード（00100000）信号を送信
			{return(-16);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-17);}		//エラーリターン
		PIR1bits.SSPIF = 0;		//SSPIFクリア		

		if (WriteI2C(0x00))		//センサのレジスタに(00000000)を送信
			{return(-18);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-19);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア

		if (WriteI2C(0x01))		//センサ立ち上げのためにセンサのレジスタに(00000000)を送信
			{return(-20);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-21);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア		
		
		IdleI2C();
		StopI2C();				//センサ書き込み動作終了

		return(0);				//エラーなしの場合0を戻す
	}
}

unsigned int acc_read(unsigned char control)
//加速度センサ信号読込み	//
{
	char buffer[4];

//    OpenI2C(MASTER, SLEW_ON); //SSPモジュールの設定（マスターモード、400ｋHzモード）

	IdleI2C();
	StartI2C();
	while (SSPCON2bits.SEN);	//start出力待ち
	if (PIR2bits.BCLIF)			//バス上の衝突確認
		{return(-8);}				//衝突発生時、エラーリターン
	else						//正常時（衝突がない場合）、以下を実行
	{
		if (WriteI2C(control))	//センサアドレスと送信モード（00100000）信号を送信
			{return(-9);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-10);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア

		if (WriteI2C(0b00000000))		//センサレジスタに読込み先アドレス（00000000）信号を送信
			{return(-11);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-12);}		//エラーリターン
		PIR1bits.SSPIF = 0;		//SSPIFクリア

		StopI2C();
		IdleI2C();
		StartI2C();
		IdleI2C();

		if (WriteI2C(control+1))//センサアドレスと受信モード（00100001）信号を送信
			{return(-13);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-14);}		//エラーリターン

//register値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		acc_internal_register = (unsigned int) SSPBUF;	//register読込み

//X（MSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		acc_X_MSB = (unsigned int) SSPBUF;	//X（MSB）値読込み

//X（LSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		acc_X_LSB = (unsigned int) SSPBUF;	//X（LSB）値読込み

//Y（MSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		acc_Y_MSB = (unsigned int) SSPBUF;	//Y（MSB）値読込み

//Y（LSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 1;		//ACK信号送信しない
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		acc_Y_LSB = (unsigned int) SSPBUF;	//Y（LSB）値読込み

		PIR1bits.SSPIF = 0;			//SSPIFクリア
		
		IdleI2C();
		StopI2C();

		return(0);				//エラーなしの場合0を戻す
	}	
}

unsigned int mag_read(unsigned char control)
//磁気センサ信号読込み	//
{
	char buffer[8];

	IdleI2C();
	StartI2C();
	while (SSPCON2bits.SEN);	//start出力待ち
	if (PIR2bits.BCLIF)			//バス上の衝突確認
		{return(-22);}			//衝突発生時、エラーリターン
	else						//正常時（衝突がない場合）、以下を実行
	{
		if (WriteI2C(control))	//センサアドレスと送信モード（01100000）信号を送信
			{return(-23);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-24);}		//エラーリターン	
		PIR1bits.SSPIF = 0;		//SSPIFクリア

		if (WriteI2C(0x00))		//センサレジスタに読込み先アドレス（00000000）信号を送信
			{return(-25);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-26);}		//エラーリターン
		PIR1bits.SSPIF = 0;		//SSPIFクリア
	
		StopI2C();
		IdleI2C();
		StartI2C();
		IdleI2C();

		if (WriteI2C(control+1))//センサアドレスと受信モード（01100001）信号を送信
			{return(-27);}		//エラーリターン
		while (SSPSTATbits.BF);	//送信待ち
		IdleI2C();				//アイドル状態確認
		if (SSPCON2bits.ACKSTAT)//センサからのACK確認
			{return(-28);}		//エラーリターン

//register値読込み
		SSPCON2bits.RCEN = 1;
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		mag_internal_register = (unsigned int) SSPBUF;	//register値読込み

//X（MSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		mag_X_MSB = (unsigned int) SSPBUF;	//X（MSB）値読込み

//X（LSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		mag_X_LSB = (unsigned int) SSPBUF;	//X（LSB）値読込み

//Y（MSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 0;		//ACK信号送信
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		mag_Y_MSB = (unsigned int) SSPBUF;	//Y（MSB）値読込み

//Y（LSB）値読込み
		SSPCON2bits.RCEN = 1;
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.RCEN);	//データ受信待ち
		SSPCON2bits.ACKEN = 1;
		SSPCON2bits.ACKDT = 1;		//ACK信号送信しない
		PIR1bits.SSPIF = 0;			//SSPIFクリア
		while (SSPCON2bits.ACKEN);
		mag_Y_LSB = (unsigned int) SSPBUF;	//Y（LSB）値読込み

		PIR1bits.SSPIF = 0;		//SSPIFクリア

		IdleI2C();
		StopI2C();

		return(0);				//エラーなしの場合0を戻す
	}
}

