//********************************************************* 
/*  文件名：TEST_60F02x_IIC.asm
*	功能：  FT60F02x-IIC功能演示
*   IC:    FT60F024 SOP18
*   晶振：  16M/4T                    
*   说明：  此演示程序位60F02x_IIC的演示程序.
*		   该程序读取(24C02)0x12地址的值,取反后存入0x13地址 
*
*                  FT60F024  SOP18 
*                 ----------------
*  NC------------|1(PC3)   (PC4)18|------------NC     
*  NC------------|2(PC2)   (PC5)17|------------NC 
*  NC------------|3(PC1)   (PC6)16|------------NC 
*  NC------------|4(PC0)   (PC7)15|------------NC 
*  GND-----------|5(GND)   (VDD)14|-----------VDD
*  NC------------|6(PA5)   (PA6)13|------------NC
*  IIC_SCL-------|7(PA4)   (PA7)12|------------NC 
*  NC------------|8(PA3)   (PA1)11|------------NC 
*  IIC_SDA-------|9(PA2)   (PA0)10|------------NC
*			      ----------------
*/
//*********************************************************
;===========================================================
;===========================================================
 #INCLUDE  <FT60F02X.inc>;
;==========================================================================
;RAM DEFINE
;==========================================================================
TEMP           	 	EQU     0X40
TEMP1           	EQU     0X41
TEMP2           	EQU     0X42
W_TMP           	EQU     0X43  
S_TMP          		EQU     0X44 
READPIN				EQU		0X45
IICDATTEMP			EQU		0X46
IICADRTEMP			EQU		0X47
IICDATA				EQU		0X48
IICADDR				EQU		0X49
buff          		EQU     0X4a 
#define f_ack		buff,0
count				EQU		0X4b
;==========================================================================
;CONSTANT DEFINE
;==========================================================================

LSB                 EQU     0
MSB                 EQU     7
;==========================================================================
;USER DEFINE
;==========================================================================

#define  IIC_SCL	PORTA,4   
#define  IIC_SDA	PORTA,2

;==========================================================================
;PROGRAM START
;==========================================================================
    ORG         0000H
    LJUMP       RESTART
    ORG         0004H
    LJUMP       interrupt  
;==========================================================================
;SYSTEM START
;==========================================================================
RESTART:
    BANKSEL     PORTA
    LCALL       INITIAL
   
   	BANKSEL 	IICADDR
    LDWI    	0x12
    STR			IICADDR
    LCALL		IIC_READ
  
    BANKSEL 	IICDATA
    LDWI		0X13
	STR         IICADDR
	COMR		IICDATA,R  ;取反
    LCALL       IIC_WRITE ;取反过后存到0x13地址

MAIN:
	NOP
    LJUMP	MAIN
;***************************************************************
;		中断程序
;***************************************************************
interrupt:
    STR         W_TMP
    SWAPR       STATUS,W
    STR         S_TMP
    BCR			STATUS,RP0
    
INT_RET:
	SWAPR   	S_TMP,0
	STR    	 	STATUS
	SWAPR   	W_TMP,1
	SWAPR   	W_TMP,0
	RETI
;==========================================================================
;SYSTEM INITIAL
;==========================================================================
INITIAL:
    BANKSEL     PORTA
    LDWI	    B'00000000'
    STR         PORTA        	
    LDWI	    B'00000000'
    STR         PORTC      
    BANKSEL     TRISA
    LDWI        B'00000000'  
    STR         TRISA        ;SET IO Direction
    LDWI        B'11111111'  ;PC 输入
    STR         TRISC        ;SET IO Direction    
   	LDWI    	B'00000000'	
    STR         WPUA
    LDWI        B'00001000'
    STR         OPTION_REG   ;SET OPTION
    LDWI        B'01110001'
    STR         OSCCON       ;SET OSCCON
    BANKSEL     INTCON
    LDWI        B'00000000'
    STR         INTCON
    LDWI        B'00000000'
    STR         MSCKCON     
    					       
    LDWI        B'00000111'
    STR         CMCON0      ;关闭比较器，CxIN为数字IO口

;***Clear SRAM**************************************
    BCF         STATUS,PAGE ;SEL BANK0
CLEAR_RAM:                   
    LDWI        20H
    STR         FSR
CLEAR_RAM_LOOP:
    CLRR        INDF
    INCR        FSR,F
    LDWI        80H
    XORWR       FSR,W
    BTSS        STATUS,Z
    LJUMP       CLEAR_RAM_LOOP
CLEAR_RAM_BANK1:
    BSF         STATUS,PAGE ;SEL BANK1
    LDWI        A0H
    STR         FSR
CLEAR_RAM_LOOP_1:
    CLRR        INDF
    INCR        FSR,F
    LDWI        C0H
    XORWR       FSR,W
    BTSS        STATUS,Z
    LJUMP       CLEAR_RAM_LOOP_1
    BCF         STATUS,PAGE ;SEL BANK0
    BSR			INTCON,GIE
    RET
 SDA_OUT:
 	BANKSEL		TRISA
    LDWI        B'11111011'    ;PA2  输出
    ANDWR       TRISA,1        ;SET IO Direction
    BANKSEL		INTCON
    RET
    
  SDA_IN:
 	BANKSEL		TRISA
    LDWI        B'00000100'    ;PA2  输入
    IORWR       TRISA,1        ;SET IO Direction
    BANKSEL		INTCON
    ret 
    
;==========================================================================
;DELAY_5US 16MHZ/4T
;==========================================================================
DELAY_5US:
    LDWI      	H'05'
    STR       	TEMP

DELAY_5USLOOP:
    CLRWDT
    DECRSZ      TEMP,F
    LJUMP       DELAY_5USLOOP
    RET 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;产生IIC起始信号;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_Start:
	LCALL	SDA_OUT     //SDA线输出
	BSR		IIC_SDA   	  
	BSR		IIC_SCL
	LCALL	DELAY_5US
    LCALL	DELAY_5US
 	BCR		IIC_SDA		//START:when CLK is high,DATA change form high to low 
	LCALL	DELAY_5US
    LCALL	DELAY_5US
    BCR		IIC_SCL		//钳住I2C总线，准备发送或接收数据 
    RET	  

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;产生IIC停止信号;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_Stop:
	LCALL	SDA_OUT     //SDA线输出
	BCR		IIC_SCL
	BCR		IIC_SDA		//STOP:when CLK is high DATA change form low to high
	LCALL	DELAY_5US
    LCALL	DELAY_5US
	BSR		IIC_SCL 
	BSR		IIC_SDA		//发送I2C总线结束信号
	LCALL	DELAY_5US
    LCALL	DELAY_5US							   	
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;等待应答信号到来
;接收应答失败 f_ack=1
;接收应答成功 f_ack=0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_Wait_Ack:
	CLRR	count
    BCR		f_ack
	LCALL	SDA_IN              //SDA设置为输入  
	BSR		IIC_SDA
    LCALL	DELAY_5US
    BSR		IIC_SCL
    LCALL	DELAY_5US
IIC_Wait_Ack_loop:    
    BTSS	IIC_SDA
    LJUMP	IIC_Wait_Ack_right
    INCR	count,1
  	LDWI	0xfa
	SUBWR	count,0
	BTSS	STATUS,0
	LJUMP	IIC_Wait_Ack_loop
	CLRR	count				;等待超时
    LCALL	IIC_Stop
    BSR		f_ack
    RET
IIC_Wait_Ack_right:
	BCR		IIC_SCL				;时钟输出0   
	RET 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;产生ACK应答
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_Ack:
	BCR		IIC_SCL
	LCALL	SDA_OUT
	BCR		IIC_SDA
    LCALL	DELAY_5US
	BSR		IIC_SCL
    LCALL	DELAY_5US
	BCR		IIC_SCL
	RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;不产生ACK应答		    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_NAck:
	BCR		IIC_SCL
	LCALL	SDA_OUT
	BSR		IIC_SDA
    LCALL	DELAY_5US
	BSR		IIC_SCL
    LCALL	DELAY_5US
	BCR		IIC_SCL
	RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;IIC发送一个字节
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IIC_Send_Byte:                       
    CLRR	count 
	LCALL	SDA_OUT	    
    BCR		IIC_SCL			;拉低时钟开始数据传输
IIC_Send_Byte_loop:
  	LDWI	0x08
	SUBWR	count,0
	BTSC	STATUS,0
  	RET
    INCR	count,1
    BTSS	IICDATTEMP,7
    LJUMP	$+3
    BSR		IIC_SDA
    LJUMP	$+2
    BCR		IIC_SDA
 
   	BCR		STATUS,0   
    RLR		IICDATTEMP,1
    LCALL	DELAY_5US			  
	BSR		IIC_SCL
    LCALL	DELAY_5US
	BCR		IIC_SCL	
    LCALL	DELAY_5US
    LJUMP	IIC_Send_Byte_loop 
  	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;读1个字节，ack=1时，发送ACK，ack=0，发送nACK  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 IIC_Read_Byte:
    CLRR	count 
    CLRR	IICDATTEMP 
	LCALL	SDA_IN			;SDA设置为输入
 IIC_Read_Byte_loop:
   	LDWI	0x08
	SUBWR	count,0
	BTSC	STATUS,0
    LJUMP	IIC_Read_Byte_end 
    INCR	count,1
    BCR		IIC_SCL
    LCALL	DELAY_5US  
    BSR		IIC_SCL
    
    BCR		STATUS,0
    RLR		IICDATTEMP,1 
    BTSC	IIC_SDA
    INCR	IICDATTEMP,1 
    LCALL	DELAY_5US 
    LJUMP	IIC_Read_Byte_loop   
    
 IIC_Read_Byte_end:
 	LCALL	IIC_Ack
    RET
/*-------------------------------------------------
 *  函数名：IIC_READ
 *	功能： IIC读出制定位置的数据
 *  	  读出IICADDR存储器里面的数据IICDATTEMP
 --------------------------------------------------*/
IIC_READ:
	LCALL	IIC_Start
    LDWI    0xa0
    STR     IICDATTEMP
	LCALL	IIC_Send_Byte
    LCALL	IIC_Wait_Ack
    BTSC	f_ack
    LJUMP	IIC_READ         ;填要读的数据地址
    LDR		IICADDR,0
    STR     IICDATTEMP  
	LCALL	IIC_Send_Byte	
    LCALL	IIC_Wait_Ack			
    BTSC	f_ack
    LJUMP	IIC_READ
	LCALL	IIC_Start();
    LDWI    0xa1
    STR     IICDATTEMP
	LCALL	IIC_Send_Byte
    LCALL	IIC_Wait_Ack
    BTSC	f_ack
    LJUMP	IIC_READ        
	LCALL	IIC_Read_Byte
	LCALL	IIC_Stop
    LDR		IICDATTEMP,0
    STR		IICDATA  
    RET		

 /*-------------------------------------------------
 *  函数名：IIC_WRITE
 *	功能：  IIC把数据data写入制定的位置IICADDR
 --------------------------------------------------*/
IIC_WRITE:
	LCALL	IIC_Start
    LDWI    0xa0
    STR     IICDATTEMP  
	LCALL	IIC_Send_Byte
    LCALL	IIC_Wait_Ack
    BTSC	f_ack
    LJUMP	IIC_WRITE         
    LDR		IICADDR,0
    STR     IICDATTEMP  
	LCALL	IIC_Send_Byte
    LCALL	IIC_Wait_Ack
    BTSC	f_ack
    LJUMP	IIC_WRITE 
    LDR		IICDATA,0
    STR     IICDATTEMP 
   	LCALL	IIC_Send_Byte
    LCALL	IIC_Wait_Ack
    BTSC	f_ack
    LJUMP	IIC_WRITE 
	LCALL	IIC_Stop	
	RET

;============================================ 
END
