/************************************************************************
*                             ---- 居加居 ----                           
*  文件名:      	Main.c
*  编写人员:    	Kinve JQ
*  说明:         
*  版本:        		V0.1
*  编写日期:    	2018-08-21
*  程序维护:     
*  维护记录:    
*    					2018-09-30.Kinve:1.创建文件
* 免责声明：
* (c) Author Kinve JQ. All rights reserved.
**************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "Common.h"
#include "Delay.h"
#include "Timer.h"
#include "Interrupt.h"
#include "Flash.h"
#include "Version.h"
#include "Packdata.h"
#include "DHT11.h"
#include "Keys.h"
#include "Adc.h"

#define USE_2401_API
#ifdef USE_2401_API
#include "nRF24L01_API.h"
#else
#include "NRF24L01_inte.H"
#define TX_PLOAD_WIDTH	NRF24L01_TX_PLOAD_LEN
#define RX_PLOAD_WIDTH	NRF24L01_TX_PLOAD_LEN
#endif
unsigned char P12_Led_state = 0;
unsigned char P04_Delay_state = 0;
unsigned char Sys_Type = SysRun_Norm;

//***********************************************************************************************************
//  Application: SPI Function
//  Master send 0x90 and recevie 0x4E
//  Master send 0x01 and recevie 0x55
//  Master send 0x02 and recevie 0x56
//  Master send 0x03 and recevie 0x4F
//  Master send 0x04 and recevie 0x54
//
//  Master recevie 0x4E and 0x4F form slave after transmitting
//***********************************************************************************************************

//-----------------------------------------------------------------------------------------------------------
void SPI_Error ( void )
{
    DBG ( "\nSPI error.\n" );

    while ( 1 )                                 // SPI error and P0.7 flash/
    {
        P07 = 1;
        Timer0_Delay1ms ( 500 );
        P07 = 0;
        Timer0_Delay1ms ( 500 );
    }
}

//-----------------------------------------------------------------------------------------------------------
void SPI_Initial ( void )
{
    clr_SPIEN;									//禁止SPI
    P15_Quasi_Mode;								// P15 (SS) Quasi mode
    P10_Quasi_Mode;								// P10(SPCLK) Quasi mode
    P00_Quasi_Mode;								// P00 (MOSI) Quasi mode
    P01_Quasi_Mode;								// P22 (MISO) Quasi mode

    //SS仅在从机有效
    set_DISMODF;                                // 1 = 禁止模式错误检测. SS的特征依赖SSOE 位
    clr_SSOE;									// SS 作为 0.普通IO  1.自动拉低

    clr_LSBFE;                                  // 0.MSB first

    clr_CPOL;									// 0.SPI空闲时SCL为低
    clr_CPHA;									// 0.在第1个边沿采样

    set_MSTR;                                   // 主设备
    //SPICLK_DIV16; 								// Select SPI clock=1Mhz
    SPICLK_DIV4; 								// 16/4=4Mhz, 24l01速度不能太快,最大的数据传输率为 10Mbps
    set_SPIEN;                                  // 使能SPI
    clr_SPIF;									// 清标志位
}
//-----------------------------------------------------------------------------------------------------------
void Start_Sending_SPI ( uint8 *pu8MID, uint8 *pu8DID )
{
    SS = 0;

    SPDR = 0x90;
    Timer3_Delay10us ( 1 );                            // Send 0x90 to Slave

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;

    if ( SPDR != 0x4E )
        SPI_Error();

    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0x01;                                // Send 0x01 to Slave
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;

    if ( SPDR != 0x55 )
        SPI_Error();

    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0x02;                                // Send 0x02 to Slave
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;

    if ( SPDR != 0x56 )
        SPI_Error();

    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0x03;                                // Send 0x03 to Slave
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;

    if ( SPDR != 0x4F )
        SPI_Error();

    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0x04;                                // Send 0x04 to Slave
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;

    if ( SPDR != 0x54 )
        SPI_Error();

    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0xFF;
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;
    *pu8MID = SPDR;                             // Receive Slave 1st DATA from Slave
    DBG ( "\nSlave Return %c!\n", SPDR );

    SPDR = 0xFF;
    Timer3_Delay10us ( 1 );

    while ( ! ( SPSR & SET_BIT7 ) );

    clr_SPIF;
    *pu8DID = SPDR;                             // Receive Slave 2nd DATA from Slave
    DBG ( "\nSlave Return %c!\n", SPDR );

    SS = 1;
}

//1.关闭POR (TA 保护) 上电复位(检测电源上升到系统可以工作的电压)
#ifdef N76E003_IAR
__sfr __no_init volatile unsigned char PORDIS @ 0XFD;
#else
sfr PORDIS = 0XFD;
#endif
void CLOSE_POR ( void )
{
    TA = 0XAA;
    TA = 0X55;
    PORDIS = 0X5A;
    TA = 0XAA;
    TA = 0X55;
    PORDIS = 0XA5;
}

/******************************************************************************
 This code illustrates how to do APROM and CONFIG IAP from LDROM.
 APROM are re-programmed by the code to output P1 as 55h and P0 as aah.
 The CONFIG2 is also updated to disable BOD reset.
 User needs to configure CONFIG0 = 0x7F, CONFIG1 = 0xFE, CONFIG2 = 0xFF.
******************************************************************************/
//2.关闭BOD 欠压检测 (监测运行期间VDD电平)
#ifdef N76E003_IAR
__sfr __no_init volatile unsigned char BODCON0 @ 0XA3;
__sfr __no_init volatile unsigned char BODCON1 @ 0XAB;
//__sfr __no_init volatile unsigned char CONFIG2 @ 0XFD;
#else
//sfr BODCON0 = 0XA3;
//sfr BODCON1 = 0XAB;
#endif
void CLOSE_BOD ( void )
{
    BODCON0 &= ~ ( 1 << 7 );    //0 =禁用欠压检测电路
}

enum
{
    UMKNOW_RESET,
    POWER_ON_RESET,               //上电复位
    BROWN_OUT_RESET,              //欠压复位
    RST_PIN_RESET,                //RST引脚复位
    HARD_FAULT_RESET,             //硬件故障复位
    WATCHGOD_TIMER_RESET,         //看门狗定时器复位
    SOFTWARE_RESET,               //软件复位
    MAX_RESET
};
/*
RST pin reset
Brown-out reset
Software reset
Power-on reset
Watchgod Timer reset
Hard Fault reset
*/
unsigned char Reset_Reason ( void )
{
    unsigned char res = UMKNOW_RESET;

    if ( PCON & ( 1 << 4 ) )
    {
        PCON &= ~ ( 1 << 4 );
        res = POWER_ON_RESET;
    }

    if ( BODCON0 & ( 1 << 1 ) )
    {
        BODCON0 &= ~ ( 1 << 1 );
        res = BROWN_OUT_RESET;
    }

    if ( AUXR1 & ( 1 << 6 ) )
    {
        AUXR1 &= ~ ( 1 << 6 );
        res = RST_PIN_RESET;
    }

    if ( AUXR1 & ( 1 << 5 ) )
    {
        AUXR1 &= ~ ( 1 << 5 );
        res = HARD_FAULT_RESET;
    }

    if ( WDCON & ( 1 << 3 ) )
    {
        WDCON &= ~ ( 1 << 3 );
        res = WATCHGOD_TIMER_RESET;
    }

    if ( AUXR1 & ( 1 << 7 ) )
    {
        AUXR1 &= ~ ( 1 << 7 );
        res = SOFTWARE_RESET;
    }

    return res;
}


void ResetSys ( void )
{
    AUXR1 &= ~ ( 1 << 7 );        //software reset flag clear
    EA = 0;
    TA = 0xAA;
    TA = 0x55;
    CHPCON |= ( 1 << 7 );         //software reset
}

void P12_Flash ( unsigned char num )
{
    unsigned char i;

    for ( i = 0; i < num && num < 5 ; i++ )
    {
        P12 = 1;
        Timer3_Delay100ms ( 1 );
        P12 = 0;
        Timer3_Delay100ms ( 1 );
    }

    P12_Led_state = P12;
}
#if 0
unsigned char flag;
//NRF24L01中断处理
#ifdef N76E003_IAR
#pragma vector=0x3B
__interrupt void NRF24L01_Handler ( void )
#else
void NRF24L01_Handler ( void ) interrupt 7            //interrupt address is 0x001B
#endif
{
    clr_EPI;				//关闭管脚中断7

    flag = PIF;
    PIF = 0x00;				//清除全部标志

    DBG ( "\nNRF24L01 interrupt!\n" );
    set_EPI;				//开启管脚中断7
}

void NRF24L01_Interrupt_P03 ( void )
{
    //P0M1|=SET_BIT3;P0M2&=~SET_BIT3;				//input
    PICON &= ~ ( SET_BIT0 | SET_BIT1 );
    PICON |= ( 0x00 );							//[1:0]=0.端口0
    PICON |= SET_BIT5;							//通道3=1.边沿触发
    PINEN |= SET_BIT3;							// 1 = 低电平/ 下降沿触发中断
    PIPEN &= ~SET_BIT3;							//0 = 关闭中断(高电平/ 上升沿触发中断)
    EIE |= SET_BIT1;							//管脚中断，最多8个,中断号7
    EA = 1;										//总中断
}
#endif
//96位 UID与128位UCID
unsigned char xdata UIDBuf[12];                //本机的存储96bit的UID内容
unsigned char xdata UID_Master[12];            //主机的存储96bit的UID内容
UINT8 UID_BYTE ( UINT8 Addr )
{
    UINT8 DATATEMP;
    set_IAPEN;
    IAPAL = Addr;
    IAPAH = 0x00;
    IAPCN = READ_UID;
    set_IAPGO;
    DATATEMP = IAPFD;
    clr_IAPEN;
    return DATATEMP;
}

//读出芯片的96bit的UID
void ReadUID_UCID ( UINT8 UID, UINT8 *out )
{
    UINT8 i;

    for ( i = 0; i < 12; i++ )
    {
        out[i] = UID_BYTE ( i + UID );	//ucid=0x20
    }
}

int Humi,Temp,Light;	//printf 用int
//最长4byte
#define GET_VER_POS(NUM,VER)	((VER>>(8*NUM))&0xff)
//-----------------------------------------------------------------------------------------------------------
void main ( void )
{
    unsigned char reset_num, i;
    //unsigned char datatemp[8];
	unsigned char TxBuf[TX_PLOAD_WIDTH] = {'>', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};	 //
	unsigned char RxBuf[RX_PLOAD_WIDTH] = {0};	
	unsigned char PackBuf[TX_PLOAD_WIDTH];
	pDataBuff CheckRxBuf = {0};
	unsigned char CheckUID = 0;
    //uint8 u8MID, u8DID;
    reset_num = Reset_Reason();

    CLOSE_POR();
    CLOSE_BOD();

    Set_All_GPIO_Quasi_Mode;
	

    //NRF24L01_Interrupt_P03();
    //定时器
    Timer0_init ( TIMER_SCAN );								//1ms

    //ResetSys();
    InitialUART0_Timer1 ( 115200 );          /* 115200	 Baud Rate*/
    Timer3_Delay10us ( 1000 );
    DBG ( "\nHome Light %s, Build by Kinve in %ld\n", THIS_VER, CUSTOM_VER );

    ReadUID_UCID ( 0x00, UIDBuf );			//0x00=uid   0x20=ucid
    DBG ( "UID=%x%x%x%x\n", UIDBuf[0], UIDBuf[1], UIDBuf[2], UIDBuf[3] );

	#if 0
    //call read byte
    datatemp[5] = Read_APROM_BYTE ( 0x3885 );

    if ( datatemp[5] != 0x4A )
    {
        //call write byte
        for ( i = 0; i < sizeof ( datatemp ); i++ )
        {
            if ( i == 5 )	Write_DATAFLASH_BYTE ( 0x3880 + i,  0x4A );
            else			Write_DATAFLASH_BYTE ( 0x3880 + i,  GET_VER_POS ( i, CUSTOM_VER ) );

            datatemp[i] = Read_APROM_BYTE ( ( UINT16 code * ) ( 0x3880 + i ) );
        }
    }
	#endif
    for ( i = 0; i < sizeof ( UID_Master ); i++ )
    {
        UID_Master[i] = Read_APROM_BYTE ( ( UINT16 code * ) ( 0x3881 + i ) );
    }

	if(Fast_Check_CS())
	{
		Sys_Type = SysRun_Test;
	}

    SPI_Initial();

    NRF24L01_Wait_Check(); // 等待检测到NRF24L01，程序才会向下执行
    NRF24L01_RT_Init ();
    DBG ( "NRF24L01 init OK!\n" );

    while ( 1 )
    {
		switch(Sys_Type)
		{
			case SysRun_Test:
				if ( System_Flag_500Ms)
				{
					System_Flag_500Ms = 0;
					P12_Led_state = !P12_Led_state;
					P12 = P12_Led_state;
				}

				if(Keys[KEY_CS].Res == ONE_HITS_KEY_FLAG)	//本机请求ID
				{
					Keys[KEY_CS].Res = NO_KEY_FLAG;
					memset(TxBuf, 0, sizeof(TxBuf));
					TxBuf[0] = '*'; 				//*(1byte)+?(1byte)
					TxBuf[1] = '?';
					PackData(TxBuf, 2, PackBuf);
					SEND_BUF ( PackBuf, sizeof(PackBuf) );
					DBG ( "Send: %s\n", &PackBuf[2] );
				}

				if(Keys[KEY_CS].Res == LONG_KEY_FLAG)		//删除配对ID
				{
					Keys[KEY_CS].Res = NO_KEY_FLAG;
					//保存到flash
					memset(UID_Master, 0xFF, sizeof(UID_Master));
					Write_DATAFLASH_BYTE ( 0x3880,	0xFF );
					for ( i = 0; i < sizeof ( UID_Master ); i++ )
					{
						Write_DATAFLASH_BYTE ( 0x3881 + i, UID_Master[i] );
					}
					P12_Flash(4);
					DBG ( "Clear Pair Num\n" );
				}
				break;
			case SysRun_Norm:
			default:
				if ( System_Flag_1s )
				{
					System_Flag_1s = 0;
					P12_Led_state = !P12_Led_state;
					P12 = P12_Led_state;

					//温湿度获取
					DHT11_Read_Data( &DHT11_Data );
					Adc_read();
    				if( abs(Light-Group_Light) > 10 ){
						Humi = DHT11_Data.humi_int;
						Temp = DHT11_Data.temp_int;
						Light = Group_Light;
						DBG ( "Humi:%02u%% - Temp:%02uC - Light:%02u\n", Humi, Temp, Light );
					}
				}	
				
				if(Keys[KEY_CS].Res == ONE_HITS_KEY_FLAG)//配对发
				{
					Keys[KEY_CS].Res = NO_KEY_FLAG;
					memset(TxBuf, 0, sizeof(TxBuf));
					TxBuf[0] = '>'; 				//*(1byte)+?(1byte)
					TxBuf[1] = 'L';					//灯
					TxBuf[2] = 'T';					//翻转
					memcpy(&TxBuf[3], UID_Master, 12);
					PackData(TxBuf, 15, PackBuf);
					SEND_BUF ( PackBuf, sizeof(PackBuf) );
					DBG ( "Send: %s\n", &PackBuf[2] );
				}				
				break;
		}
	

		if ( NRF_IRQ == 0 ) 	
		{
			if ( NRF24L01_RxPacket ( RxBuf, sizeof ( RxBuf ) ) )
			{
				if(CheckData(RxBuf, RX_PLOAD_WIDTH, &CheckRxBuf)){
					P12_Flash ( 2 );
					DBG ( "Recv: %s\n", &(CheckRxBuf.Data[2]) );
					switch(CheckRxBuf.Data[2]){
						case '*':		//配对
							switch(CheckRxBuf.Data[3]){
								case '?':				//对方收到,发送ID
									memset(TxBuf, 0, sizeof(TxBuf));
									TxBuf[0] = '*'; 				//*(1byte)+Y(1byte)+uid(12byte)
									TxBuf[1] = '1';
									memcpy(&TxBuf[2], UIDBuf, 12);
									PackData(TxBuf, 14, PackBuf);
									SEND_BUF ( PackBuf, sizeof(PackBuf) );
									DBG ( "Send: %s\n", &PackBuf[2] );
									break;
								case '1':				//本机收到,保存ID
									memcpy(UID_Master, &CheckRxBuf.Data[4], 12);
									//保存到flash
									Write_DATAFLASH_BYTE ( 0x3880,	0x4A );
									for ( i = 0; i < sizeof ( UID_Master ); i++ )
									{
										Write_DATAFLASH_BYTE ( 0x3881 + i, UID_Master[i] );
									}
									//返回成功
									memset(TxBuf, 0, sizeof(TxBuf));
									TxBuf[0] = '*'; 				//*(1byte)+Y(1byte)+uid(10byte)
									TxBuf[1] = '2';
									PackData(TxBuf, 2, PackBuf);
									SEND_BUF ( PackBuf, sizeof(PackBuf) );
									DBG ( "Send: %s\n", &PackBuf[2] );
									DBG ( "Pair Save OK\n" );
									break;
								case '2':				//对方收到,我已保存ID
									DBG ( "One Client Pair OK\n" );
									break;
							}
							break;
						case '>':		//数据
							switch(CheckRxBuf.Data[3]){
								case 'L':
									if(CheckRxBuf.Data[4] == 'T'){
										CheckUID = 0;
										if(0 == memcmp(&(CheckRxBuf.Data[5]), UIDBuf, 12)){
											P04_Delay_state = !P04_Delay_state;
											P04 = P04_Delay_state;
											CheckUID = 1;
										}
										//返回成功
										memset(TxBuf, 0, sizeof(TxBuf));
										TxBuf[0] = '<'; 				//*(1byte)+Y(1byte)+uid(10byte)
										TxBuf[1] = 'L';
										TxBuf[2] = 'T';
										TxBuf[3] = CheckUID?'Y':'N';
										PackData(TxBuf, 4, PackBuf);
										SEND_BUF ( PackBuf, sizeof(PackBuf) );
										DBG ( "Send: %s\n", &PackBuf[2] );
									}
									break;
							}
							break;
					}
				}
			}
		}	

    }
}
//-----------------------------------------------------------------------------------------------------------


/*************** (C) COPYRIGHT Kinve JQ  *******END OF FILE **************/


