//___________________________________________________________________
//___________________________________________________________________
//  Copyright : 2015 BY HOLTEK SEMICONDUCTOR INC
//  File Name : MasterII.c
// Description: IO模擬IIC主機
//     Note   : ROM SIZE 230 RAM 依據接收發送BUF不同大小不一,最小約15Byte以上
//___________________________________________________________________
//___________________________________________________________________
#include "BH67F5362.h"
#include "Drv_GPIO.h"
#include "Drv_24BitADC.h"

/********************************************************************
Function: IIC Start
INPUT	:
OUTPUT	:
NOTE	: IIC Start: when CLK is high,SDA change from high to low
********************************************************************/
void fun_IIC_Start()
{
    IIC_SCL_OUTPUTMODE();
    IIC_SDA_OUTPUTMODE();
    IIC_SDA_OUTPUTHIGH();
    IIC_SCL_OUTPUTHIGH();
	GCC_DELAY(IIC_SPEED);
    IIC_SDA_OUTPUTLOW();
	GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTLOW();
}
/********************************************************************
Function: IIC Stop
INPUT	:
OUTPUT	:
NOTE	:
********************************************************************/
void fun_IIC_Stop()
{
    IIC_SDA_OUTPUTLOW();
    IIC_SDA_OUTPUTMODE();
	GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTHIGH();
	GCC_DELAY(IIC_SPEED);
    IIC_SDA_OUTPUTHIGH();
	GCC_DELAY(IIC_SPEED);
    IIC_SDA_INPUTMODE();
}
/********************************************************************
Function: IIC 發送ACK繼續接收
INPUT	:
OUTPUT	:
NOTE	:
********************************************************************/
void fun_IIC_Ack()
{
    IIC_SDA_OUTPUTMODE();
    IIC_SDA_OUTPUTLOW();
    GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTHIGH();
    GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTLOW();
    GCC_DELAY(IIC_SPEED);
    IIC_SDA_OUTPUTHIGH();
    GCC_DELAY(IIC_SPEED);
}

//**********************************
//NoAck(1) signal
//**********************************
void fun_IIC_NoAck(void)
{
	IIC_SDA_OUTPUTMODE();
    IIC_SDA_OUTPUTHIGH();
    GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTHIGH();
    GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTLOW();
    GCC_DELAY(IIC_SPEED);
}
/********************************************************************
Function: IIC Wait ACK
INPUT	:
OUTPUT	:
NOTE	:
********************************************************************/
void fun_IIC_WaitACK()
{
    IIC_SDA_INPUTMODE();
    GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTHIGH();
	unsigned char i=0;
	while(IIC_SDA_ISHIGH() && ( i < 250 ))
	{
	 	i++;
	}
    IIC_SCL_OUTPUTLOW();
    GCC_DELAY(IIC_SPEED);
}
/********************************************************************
Function: IIC Write Byte
INPUT	: WData
OUTPUT	:
NOTE	:
********************************************************************/
void fun_IIC_WByte(unsigned char WData)
{
    IIC_SDA_OUTPUTMODE();
 	unsigned char i;
 	for( i=0; i<8; i++)
 	{
        IIC_SCL_OUTPUTLOW();
 		GCC_DELAY(IIC_SPEED);
 		if( WData & 0x80 )
 		{
            IIC_SDA_OUTPUTHIGH();
 		}
 		else
 		{
            IIC_SDA_OUTPUTLOW();
 		}
 		GCC_DELAY(IIC_SPEED);
        IIC_SCL_OUTPUTHIGH();
 		GCC_DELAY(IIC_SPEED);
 		WData <<= 1;
 	}
     IIC_SCL_OUTPUTLOW();
     IIC_SDA_INPUTMODE();
}
/********************************************************************
Function: IIC Read Byte
INPUT	:
OUTPUT	: RData
NOTE	:
********************************************************************/
unsigned char fun_IIC_RByte(unsigned char Ack)
{
    IIC_SDA_INPUTMODE();
    IIC_SCL_OUTPUTLOW();
	unsigned char i,RData = 0;
 	GCC_DELAY(IIC_SPEED);
    IIC_SCL_OUTPUTHIGH();
	for(i=0; i<8; i++)
	{
        IIC_SCL_OUTPUTHIGH()
		GCC_DELAY(IIC_SPEED);
		RData = (RData<<1)|IIC_SDA;
        IIC_SCL_OUTPUTLOW();
		GCC_DELAY(IIC_SPEED);
	}
	if (Ack){
		fun_IIC_Ack();
	}
	else{
		fun_IIC_NoAck();
	}
	return RData;
}

volatile ADCSource_t ADCSourceData;

/**
 * @brief Write 24Bit ADC Reg Data
 *
 * @param RegAddress
 * @param RegData
 */
void Drv_24BitADC_WriteReg(unsigned char RegAddress,unsigned char RegData)
{
	fun_IIC_Start();
	fun_IIC_WByte(IIC_ADDRESS);
	fun_IIC_WaitACK();
	fun_IIC_WByte(RegAddress);
	fun_IIC_WaitACK();
	fun_IIC_WByte(RegData);
	fun_IIC_WaitACK();
	fun_IIC_Stop();
}

/**
 * @brief Read 24Bit ADC Reg Data
 *
 * @param RegAddress
 * @param RegData
 */
unsigned char Drv_24BitADC_ReadReg(unsigned char RegAddress)
{
	unsigned char RegData;
	fun_IIC_Start();
	fun_IIC_WByte(IIC_ADDRESS);
	fun_IIC_WaitACK();
	fun_IIC_WByte(RegAddress);
	fun_IIC_WaitACK();
	fun_IIC_Start();
	fun_IIC_WByte(IIC_ADDRESS+1);
	fun_IIC_WaitACK();
	GCC_DELAY(IIC_SPEED);
	RegData = fun_IIC_RByte(0);
	fun_IIC_Stop();
	return RegData;
}

void Drv_24BitADC_ReadADCData()
{
	if (ADCSourceData.flag.b.IsCheck)
	{
		ADCSourceData.flag.b.IsCheck = 0;
		unsigned char temp;
		temp = Drv_24BitADC_ReadReg(ADCR1);
		if (temp && 0x02 == 0x02)	// EOC == 1?
		{
			ADCSourceData.SamplingCnt++;
			if (ADCSourceData.SamplingCnt > 3)
			{
				Drv_24BitADC_WriteReg(ADCR1, temp | 0x04); // ADCDL = 1 Lock Data for read
				ADCSourceData.data.byte.ByteRes = 0x00;
				ADCSourceData.data.byte.ByteLow = Drv_24BitADC_ReadReg(ADRL);
				ADCSourceData.data.byte.ByteMid = Drv_24BitADC_ReadReg(ADRM);
				ADCSourceData.data.byte.ByteHigh = Drv_24BitADC_ReadReg(ADRH);
				Drv_24BitADC_WriteReg(ADCR1, temp & 0xFB); // ADCDL = 0 Unlock Data for ADC Convert
				ADCSourceData.data.ADCData = ADCSourceData.data.ADCData / 256;
				ADCSourceData.flag.b.IsReady = 1;
			}
			Drv_24BitADC_WriteReg(ADCR1, temp & 0xFd);	// eoc = 0
		}
	}
}

void Drv_24BitADC_Init()
{
	_pcpu7 = 1;
	_pcc7 = 1;
	SET_PC7_INT3();
	_int3s1 = 1;
	_int3s0 = 0;	// 下降沿中斷
	_int3e = 1;
	_emi = 1;
		
	Drv_24BitADC_WriteReg(HIRCC ,0x01);
	do
	{
		GCC_CLRWDT();
	} while (Drv_24BitADC_ReadReg(HIRCC) != 0x03);
	Drv_24BitADC_WriteReg(SIMC0 ,0x00);  //選擇IIC通訊
	Drv_24BitADC_WriteReg(SIMTOC ,0x82); //配置IIC超時間

	Drv_24BitADC_WriteReg(PWRC, ((VCMEN << 7) + FADCK));
	Drv_24BitADC_WriteReg(PGAC0, ((VGS << 5) + (AGS << 3) + PGS));
	Drv_24BitADC_WriteReg(PGAC1, ((INIS << 6) + (INX << 4) + (DCSET << 1)));
	Drv_24BitADC_WriteReg(PGACS, ((CHSN << 3) + CHSP));

	Drv_24BitADC_WriteReg(ADCR0, (1<<5) +((ADOR << 1) + VREFS));    // 上電ADC默認關閉,否則會直接開啟轉換
	Drv_24BitADC_WriteReg(ADCR1, ((FLMS << 5) + (VRBUF << 3)));
	Drv_24BitADC_WriteReg(ADCS, ADCSN);
	Drv_24BitADC_WriteReg(ADCTE, 0xE7);	
}
void Drv_24BitADC_Start()
{
	unsigned char temp;
	temp = Drv_24BitADC_ReadReg(ADCR0);
	Drv_24BitADC_WriteReg(ADCR0, temp&0x1F);	// ADRST = 0 ADSLP = 0  ADOFF=0 (ADC power on and enter normal mode)
	temp = Drv_24BitADC_ReadReg(ADCR0);
	Drv_24BitADC_WriteReg(ADCR0, temp|0x80);	// ADRST = 1
	Drv_24BitADC_WriteReg(ADCR0, temp&0x7F);	// ADRST = 0

	ADCSourceData.SamplingCnt = 0;
	ADCSourceData.flag.b.IsReady = 0;
	ADCSourceData.flag.b.IsCheck = 0;
}

void Drv_24BitADC_Stop()
{
	unsigned char temp;
	Drv_24BitADC_WriteReg(PWRC,0x00);
	temp = Drv_24BitADC_ReadReg(ADCR0);
	Drv_24BitADC_WriteReg(ADCR0,temp|0x20);	// ADOFF = 1(ADC enter power off)
}

//@------------外部中斷1入口函數--------------@
DEFINE_ISR(INT3_ISR, 0x008)
{
	ADCSourceData.flag.b.IsCheck = 1;
}