www.pudn.com > ADSP-BF561_MicronSensorExample_I2C_ASM_in_C.zip > I2C_BF561_rev03.asm


/******************************************************************************/ 
// 
// Name: SCCB Software Interface for Video Device configurations - C Callable 
// 
/***************************************************************************************************************** 
 
(C) Copyright 2003 - Analog Devices, Inc.  All rights reserved. 
 
File Name:	I2C_BF561_rev03.asm	 
 
Date Modified:	22 December 04		TL		Rev 2.0 
 
Software:       VisualDSP++4.5 (November Update) 
 
Hardware:		BF561 EZ-KIT Board 
 
Special Connections:  None 
 
Purpose:		To configure video devices  
				 
				 
Program Parameters: 
 
************************************************************************************************/ 
 
/*************** SCCB Start Settings**************************************/ 
/*Before Calling the SCCB_Interface the inputs to the SCCB_Taskmanager	 */ 
/*must be done. 														 */ 
/* Write to the "SCCB_Control" a "1" for reading from the Device or 	 */ 
/* a "2" for writing to the Device.										 */ 
/*																		 */ 
/* Leave the total number of bytes in "SCCB_Wordcount".Device Addresses  */ 
/* and Word Addresses included.											 */ 
/*																		 */ 
/* Write all data to the "SCCB_DataIn". 								 */ 
/* e.g.Writing to the device:											 */ 
/*																		 */ 
/*			SCCB_DataIn 			Device Address	(LSB must be Zero)	 */ 
/*									Word Address						 */ 
/*									Data 1								 */ 
/*									Data 2								 */ 
/*									  .									 */ 
/*************************************************************************/ 
/* (e.g.Reading from the device:										 */ 
/*			SCCB_DataIn 			Device Address	(LSB must be zero)   */ 
/*									Word Address						 */ 
/*									Device Address	(LSB must be one)	 */ 
/*																		 */ 
/*																		 */ 
/*	The data elements received can be found in the array 				 */ 
/*									_SCCB_DataOut[10]					 */ 
/*																		 */ 
/*																		 */ 
/*																		 */ 
/*																		 */ 
/*************************************************************************/ 
 
#include  
 
/*************** SCCB Constants  ************************************/ 
#define ISR_SCCB_Timer 0xFFE02028	//Address of the interrupt register (EVT10 in this case) 
#define System_MMR_High_Address 0xFFC00000	//The high address word is handled like pages 
#define Core_MMR_High_Address 0xFFE00000	//The high address word is handled like pages 
#define SCL_PERIOD 0x200                  // scl_period >= 133MHz/(3 x 0.4MHz) 
#define SCL_HIGH SCL_PERIOD >> 1 
#define SCL 0x1            // serial clock is PF1 
#define SDA 0x2            // serial data is PF0 
#define scl_bit 0          // scl = PF1 
#define sda_bit 1          // sda = PF0 
 
 
/*************** SCCB Variables  ************************************/ 
.section L1_data_a; 
.var		SCCB_Variable_High_Address; 
.var		SCCB_Control; 
.var		SCCB_Bit_Count; 
.var		SCCB_Word_Count ; 
.var		SCCB_Write_Read_Register; 
.var		SCCB_Data_Pointer; 
.var		SCCB_DataIn[10];				 
.var		_SCCB_DataOut[10];				 
.var		SCCB_Point_of_State; 
.var		SCCB_Read_Count; 
.var        _SCCB_In_Progress = 0; 
.var		SCCB_Read_Start_Cond0_Task_Val; 
/*************** SCCB Macros ****************************************/ 
//These macros are used in all routine to push/pop all registers  
//and to reset the timer interrupt again 
#define SCCB_Start_Macro\ 
		[--SP] = ASTAT;\ 
		[--SP] = FP;\ 
		[-- SP] = (R7:0, P5:0);\ 
		SP+= -64;\ 
		SP+= -56;\ 
		link 0x0;\ 
		[FP+0x8] = R0;\ 
		[FP+0xC] = R1;\ 
		[FP + 0x10] = R2 
 
	 
 
#define SCCB_End_Macro\ 
		p0.h = hi(TMRS8_STATUS);\ 
		p0.l = lo(TMRS8_STATUS);\ 
		R0 = 0x0011 (z);\ 
		w[p0] = R0;\ 
		JUMP.S 2;\ 
		unlink;\ 
		SP+=60;\ 
		SP+=60;\ 
		(R7:0, P5:0) = [SP++];\ 
		FP = [SP++];\ 
		ASTAT = [SP++];\ 
		SSYNC 
 
/**********************************************************************/ 
 
/*************** SCCB Global Settings *********************************/ 
.section L1_code; 
 
.global		SCCB_Interface; 
.global		SCCB_Control; 
.global		SCCB_Word_Count; 
.global		SCCB_DataIn;				 
.global		_SCCB_DataOut; 
.global		SCCB_Read_Count; 
.global     _SCCB_In_Progress; 
/**********************************************************************/ 
 
	 
 
/*************** SCCB Main Init ***************************************/ 
/////////////////////////////////////////////////////////////////////////// 
//No register must be kept for this Interface because all contents are	 // 
//stored in the variables above. As you can see before entering the   	 // 
//SCCB_Interface Subroutine all registers will be pushed onto the stack. // 
//For each access to the SCCB device this subroutine will just be executed/ 
//one time. After execution the pushed registers are poped back again.   // 
//The Timer interrupt initialized in this "asm" file will link to the    // 
//subroutines required for this interface each time it comes up          // 
//The data sent to the device will be eight bits wide for configuration  // 
//purposes to video devices only.										 // 
/////////////////////////////////////////////////////////////////////////// 
SCCB_Interface: 
			SCCB_Start_Macro; 
			 
/*************** SCCB Timer Interrupt Vector Init ***********************/ 
//In case the timer will be used for several applications the Interrupt  
//vetctor for this Interface is set here. The address of the routine to be  
//executed at first is filled in the interrupt register here. 
 
P0.H = hi(ISR_SCCB_Timer); 
P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
r0.h =  SCCB_Start_Cond1; 
r0.l =  SCCB_Start_Cond1; 
[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
/*************** SCCB GPIO init as SDA and SCL ****************************/ 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
 
	 
	// disable PF inputs     
    p0.l = lo(FIO0_INEN); 
    r0 = w[p0](z); 
    bitclr(r0, scl_bit); 
    bitclr(r0, sda_bit); 
    w[p0] = r0; 
     
    //Set bit PF1(SDA) & PF0(SCL) as outputs 
	p0.l = lo(FIO0_DIR); 
	r0 = w[p0](z); 
	bitset(r0, scl_bit); 
	bitset(r0, sda_bit); 
	w[p0] = r0; 
	 
	//The Flag PF1(SDA) and PF0(SCL) shall be high  
	p0.l = lo(FIO0_FLAG_S);		 
	r0 = SCL (z); 
	bitset(r0, sda_bit); 
	bitset(r0, scl_bit); 
	w[p0] = r0; 
 
 
 
	 
/*************************************************************************/ 
 
/***************** SCCB Timer0 Init ***************************************/ 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
 
	p0.l = lo(TMRS8_STATUS);	 
	r0.l = 0x0011;	w[p0] = r0;			//Clear Timer Interrupt and Overflow bit  
 
	p0.l = lo(TMRS8_DISABLE);			//disable timer 
	r1 = 0x0001(z);	 
	w[p0] = r1; 
	 
	/* Setup Timer0:  PWM_OUT mode, pulse hi, count to end of */ 
	/* period, interrupt, sample TMR0 pin, disable pad, EMU_RUN enable    */ 
	/* Bit configuration:  0x025D = 0010 0010 0101 1101		  */ 
	 
	P0.L = TIMER0_CONFIG & 0xffff; 
	P0.H = TIMER0_CONFIG >> 16; 
	R0.L = 0x025D; 
	W[P0] = R0.L; 
 
	// The period is set to provide a 3:1 ratio of SCL to TMR0 
	 
	P0.L = TIMER0_PERIOD & 0xffff; 
	P0.H = TIMER0_PERIOD >> 16; 
	R0 = SCL_PERIOD (z); 
	[P0] = R0; 
 
	// Width of provides 50% duty cycle: scl_high = 1/2 of scl_period 
	 
	P0.L = TIMER0_WIDTH & 0xffff; 
	P0.H = TIMER0_WIDTH >> 16; 
	R0 = SCL_PERIOD >> 1 (z); 
	[P0] = R0; 
 
/*************************************************************************/ 
 
/*************** SCCB Timer0 Interrupt ************************************/ 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
 
	 
	p0.l = lo(SICA_IMASK1);		//Timer0 has been enabled 
	r0 = [p0]; 
	bitset(r0,3);				 
	[p0] = r0; 
 
 
	p0.h = hi(IMASK); 
	p0.l = lo(IMASK); 
	r0 = [p0]; 
	bitset(r0,10); 
	[p0] = r0;							//Enable the "IVEC10" interrupt 
 
	 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(TMRS8_ENABLE);				//enable timer 
	r1 = 0x0001(z);	 
	w[p0] = r1; 
 
/*************************************************************************/ 
 
/*************** SCCB Start Setup ****************************************/ 
/*																		 */ 
/*************************************************************************/ 
//prepares the variables used in this Interface 
 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
	p2.h = SCCB_Variable_High_Address; 
 
	p1.l = SCCB_Bit_Count; 
	r0 = 0x8; 
	[p1] = r0;	 
 
	p1.l = SCCB_Read_Count; 
	r0 = 0x2;               // dev wr addr + word addr to start 
	[p1] = r0; 
 
	p1.l = SCCB_Read_Start_Cond0_Task_Val; 
	r0 = 0;               // due to an extra start condition at reading from device 
	[p1] = r0;			  // this variable is reqired 
	 
		 
	p1.l = SCCB_DataIn; 
	p2.l = SCCB_Data_Pointer; 
	[p2] = p1; 
	p2.l = SCCB_Write_Read_Register; 
	r0 = [p1]; 
	[p2] = r0; 
 
/*************************************************************************/ 
 
	SCCB_End_Macro; 
SCCB_Interface.END:		 
RTS; 
 
//This is the end of the Init program. All other subroutine will be called 
//by the Timer Interrupt separately. 
/*************** SCCB End of Init ****************************************/ 
 
 
 
 
/*************************************************************************/ 
/*************************************************************************/ 
/*************************************************************************/ 
/*************************************************************************/ 
/*************************************************************************/ 
//Each timer interrupt will just call one of the following subroutines. 
//That restults to a SCCB speed depending of the Timer speed. The time  
//between the timer interrupts can be used for processing of user data 
//there are no loops that would cause a decrease of processor speed 
 
/*************** SCCB Start Cond1 ****************************************/ 
SCCB_Start_Cond1: 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
 
	p0.l = lo(FIO0_FLAG_C);		//The Flag PF0 (SDA) will be cleared at first (Start Condition!)	 
	r0.l = SDA; 
	w[p0] = r0; 
 
 
 
	 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Start_Cond2; r0.l =  SCCB_Start_Cond2; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
 
	SCCB_End_Macro; 
RTI; 
/*************** SCCB Start Cond2 ****************************************/ 
SCCB_Start_Cond2: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
 
	p0.l = lo(FIO0_FLAG_C);		//The Flag PF1 (SCL) will be cleared at second (Start Condition!) 
	r0.l = SCL; 
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Send_Data; r0.l =  SCCB_Send_Data; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
 
	SCCB_End_Macro; 
RTI; 
/*************** SCCB Send Data to the Device*******************************/ 
//"SCCB_Send_Data" will send all the addresses and data required for communication 
//to the device. The data must be shifted through the GPIO Pin 0 
SCCB_Send_Data: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);	//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
 
	p1.l = SCCB_Write_Read_Register; 
	r0 = [p1]; 
 
	p1.l = SCCB_Bit_Count;				//load the bit counter to count the  
	r1 = [p1]; 
	CC = r1 == 0; 
	IF CC JUMP SCCB_Send_DATA_Word_Sent;//If eight bits are sent get the next byte 
 
	CC = BITTST(r0, 7); 
	IF CC JUMP SCCB_Send_DATA_SET_SDA;	//Check the data bit in order to clear or  
	p0.l = lo(FIO0_FLAG_C);				//The contents of the bit check was zero 
	r5.l = SDA; 
	w[p0] = r5;			//so the GPIO pin must been cleared 
JUMP	SCCB_Bit_Sent_End; 
	 
SCCB_Send_DATA_SET_SDA:	 
	p0.l = lo(FIO0_FLAG_S);				//So, the GPIO pin must been set 
	r5.l = SDA; 
	w[p0] = r5;	 
 
SCCB_Bit_Sent_End:					 
	r0 = r0 << 1;						//shift the byte to get the next bit 
	p1.l = SCCB_Write_Read_Register;	//save the shifted byte for the run 
	[p1] = r0; 
 
	p1.l = SCCB_Bit_Count;				 
	r1 += -1;							//decrement the bit counter.  
	[p1] = r1;							//So, that last bit can be detected 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Write_Clock; r0.l =  SCCB_Write_Clock; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
 
SCCB_Send_DATA_Word_Sent:	//byte has been sent 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitclr(r0, sda_bit);    //configure SDA bit as an Input 
	w[p0] = r0;			 
 
	// enable PF inputs     
    p0.l = lo(FIO0_INEN); 
    r0 = w[p0](z); 
    bitset(r0, sda_bit); 
    w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_ACK_TST; r0.l =  SCCB_ACK_TST; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
/*************** SCCB Send Data to the Device finish *******************************/ 
 
/*************** SCCB SCCB Clock routine********************************************/ 
SCCB_Write_Clock: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
 
	p0.l = lo(FIO0_FLAG_S); 
	r0.l = W[p0]; 
	CC = BITTST (r0, scl_bit); 
	IF CC JUMP SCCB_Set_Write_Clock_Low; // if scl high, then set it low 
	r0 = SCL(z);                         // if scl low, then set it high 
	w[p0] = r0;		 
 
	SCCB_End_Macro; 
RTI;     // remain in this state upon the next interrupt 
 
SCCB_Set_Write_Clock_Low: 
	p0.l = lo(FIO0_FLAG_C); 
	r0 = SCL(z); 
	w[p0] = r0; 
	 
	p1.l = SCCB_Bit_Count;				//load the bit counter to count the  
	r1 = [p1]; 
	CC = r1 == 0; 
	IF !CC JUMP JUST_TOGGLE_LOW;//If eight bits are sent, stop driving SDA 
 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitclr(r0, sda_bit);    //configure SDA bit as an Input 
	w[p0] = r0;			 
 
	// enable PF inputs     
    p0.l = lo(FIO0_INEN); 
    r0 = w[p0](z); 
    bitset(r0, sda_bit); 
    w[p0] = r0; 
	 
JUST_TOGGLE_LOW: 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Send_Data; r0.l =  SCCB_Send_Data; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
/**************************************************************/ 
/*************** SCCB SCCB Acknowledge routines****************/ 
SCCB_ACK_Wait:   // After receiving a word an extra delay is insterted 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address); //High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
	 
	p1.l = SCCB_Word_Count; 
	r1 = [p1]; 
	CC = r1 == 1; 
	IF CC JUMP No_Acknowledge_By_Master;   
 
	 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr 
	r0.h =  SCCB_ACK_TST; 
	r0.l =  SCCB_ACK_TST;       // next state: test for ACK 
	[p0] = R0; 
	 
	SCCB_End_Macro; 
RTI; 
 
 
 
 
No_Acknowledge_By_Master:	 
 
	p0.l = lo(FIO0_FLAG_S);             // drive SCL high			 
	r0 = SCL(z); 
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr 
	r0.h =  SCCB_ACK_MNGR; 
	r0.l =  SCCB_ACK_MNGR;       // next state: test for ACK 
	[p0] = R0; 
 
	SCCB_End_Macro; 
RTI; 
 
SCCB_ACK_TST: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address); //High address of all the system registers 
	 
	p0.l = lo(FIO0_FLAG_S);             // drive SCL high			 
	r0 = SCL(z); 
	w[p0] = r0; 
	 
	p0.l = lo(FIO0_FLAG_S); 
	r0.l = W[p0]; 
	CC = BITTST (r0,sda_bit);		//Check SDA input. It must be low at this point 
 
 	IF CC JUMP SCCB_ACK_Error;	    //If not, something is wrong 
 
 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr 
	r0.h =  SCCB_ACK_MNGR; 
	r0.l =  SCCB_ACK_MNGR; // task manager state 
	[p0] = R0; 
	 
	SCCB_End_Macro; 
RTI; 
	 
SCCB_ACK_MNGR: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
	 
	 
	p0.l = lo(FIO0_FLAG_C); 
	r0 = SCL (z); 
	w[p0] = r0;                    // toggle SCL to low 
	 
	[--SP] = RETS;			// enable nesting;  save return address to the stack 
	CALL SCCB_Taskmanger; 
	RETS = [sp++]; 
 
	SCCB_End_Macro; 
RTI; 
 
 
SCCB_ACK_Error: 
NOP; 
	p0.h = hi(System_MMR_High_Address); //High address of all the system registers 
	p0.l = lo(FIO0_FLAG_S); 
	r0.l = W[p0]; 
	CC = BITTST (r0,sda_bit); 
if CC JUMP	SCCB_ACK_Error; 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);	// Int Vector Base Addr 
	r0.h =  SCCB_ACK_MNGR; 
	r0.l =  SCCB_ACK_MNGR; // task manager state 
	[p0] = R0; 
 
	JUMP	SCCB_ACK_Error; 
	SCCB_End_Macro; 
RTI; 
/*****************************************************************************************/ 
 
/*************** SCCB SCCB Taskmanger routine********************************************/ 
//The Taskmanager handles the different use of the interface. It can be written to the  
//device or read from the device. Up to ten bytes (can be changed) can be written to  
//or read from the device. Finishing the data transfer links to the stop condition. 
 
SCCB_Taskmanger: 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
	p2.h = SCCB_Variable_High_Address; 
 
	p1.l = SCCB_Bit_Count; //The bit counter must be loaded again after sending each byte 
	r0 = 0x8; 
	[p1] = r0;	 
 
	p1.l = SCCB_Control; 
	r0 = [p1]; 
 
	CC = r0 == 2;		//"1" means read from the device. "2" means write to the device 
	IF CC JUMP SCCB_Write_Task; 
 
	p1.l = SCCB_Read_Count; 
	r1 = [p1]; 
	CC = r1 == 0; 
	IF CC JUMP SCCB_Read1_Task;  // jump after first 3 bytes got sent 
	 
	p2.l = SCCB_Read_Start_Cond0_Task_Val;	 
	r2 = [p2];								// in read mode after device addr and sub addr has  
	r2 = r1 | r2;							// been sent an extra start condition must be inserted	 
	CC = r2 == 1;							// before the second device addr can be sent 
	IF CC JUMP SCCB_Read_Start_Cond0_Task;	 
	 
	CC = r1 == 3; 
	IF CC JUMP SCCB_Read2_Task;	//"3" means start reading the device 
	r1 += -1;                   // otherwise, decrement the count 
	[p1] = r1; 
 
SCCB_Write_Task: 
	p0.l = lo(FIO0_INEN);		 
	r0.l = w[p0]; 
	bitclr(r0, sda_bit);	//disable SDA input 
	w[p0] = r0; 
 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitset(r0, sda_bit);	//configure SDA as output 
	w[p0] = r0; 
 
	p1.l = SCCB_Word_Count; 
	r1 = [p1]; 
	r1 += -1; 
	[p1] = r1;	 
	CC = r1 == 0;		//check the number of bytes already sent  
	IF CC JUMP SCCB_Stop_Cond_Task;	//invoke the stop condition when all bytes are sent 
	 
	p1.l = SCCB_Data_Pointer; 
	p2 = [p1]; 
	NOP; 
	NOP; 
	NOP; 
	p3 = [p2++];		//Increment the pointer to the data array 
	[p1] = p2; 
 
	p1.l = SCCB_Write_Read_Register; 
	r1 = [p2]; 
	[p1] = r1; 
	 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Send_Data; r0.l =  SCCB_Send_Data; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
RTS; 
 
SCCB_Read_Start_Cond0_Task: 
//insert a delay to place the read start condition 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Read_Start_Cond1_Task; r0.l =  SCCB_Read_Start_Cond1_Task; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
RTS; 
 
SCCB_Read_Start_Cond1_Task: 
	SCCB_Start_Macro; 
//in order to generate the read start condition SDA & SCL must be set to high 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
 
	// disable PF inputs     
    p0.l = lo(FIO0_INEN); 
    r0 = w[p0](z); 
    bitclr(r0, sda_bit); 
    w[p0] = r0; 
	 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitset(r0, sda_bit);	//configure SDA as output 
	w[p0] = r0; 
 
	p0.l = lo(FIO0_FLAG_S); 
	r0 = SCL | SDA(z); 
	w[p0] = r0;	   // set SDA & SCL 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Read_Start_Cond2_Task; r0.l =  SCCB_Read_Start_Cond2_Task; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI;	 
 
SCCB_Read_Start_Cond2_Task: 
	SCCB_Start_Macro; 
//clear SDA at first to begin the start condition 
	 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
	 
	 
	p0.l = lo(FIO0_FLAG_C); 
	r0 = SDA(z); 
	w[p0] = r0;	   //SDA to low 
	 
	p1.l = SCCB_Read_Start_Cond0_Task_Val;	//after the read start condition has been executed  
	r0 = 0x8 (z);						//it must never apear again 
	[p1] = r0; 
	 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_ACK_MNGR; r0.l =  SCCB_ACK_MNGR; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI;	 
 
SCCB_Stop_Cond_Task: 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Stop_Cond0; r0.l =  SCCB_Stop_Cond0; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
RTS; 
 
SCCB_Read1_Task: 
	p1.l = SCCB_Read_Count; 
	r0 = 3; 
	[p1] = r0; 
 
	p1.l = SCCB_Write_Read_Register;	//Get the data to send 
	r0 = 0; 
	[p1] = r0; 
 
	p1.l = _SCCB_DataOut; 
	p2.l = SCCB_Data_Pointer; 
	[p2] = p1; 
 
SCCB_Read2_Task: 
 
	p1.l = SCCB_Word_Count; 
	r1 = [p1]; 
	r1 += -1; 
	[p1] = r1;	 
	 
	// make sure SDA is configured as input 
	p0.l = lo(FIO0_DIR); 
	r0 = w[p0](z); 
	bitclr(r0, sda_bit); 
	w[p0] = r0; 
 
	// enable sda input 
	p0.l = lo(FIO0_INEN); 
	r0 = w[p0](z); 
	bitset(r0, sda_bit); 
	w[p0] = r0; 
		 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Rcv_Clk_Test; r0.l =  SCCB_Rcv_Clk_Test; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
RTS; 
/*************** SCCB Receive Data***************************************/ 
SCCB_Receive_Data: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address); //High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;  //works as a page for all Variables 
	p2.h = SCCB_Variable_High_Address; 
 
	p1.l = SCCB_Write_Read_Register;	//Get the current rcv byte 
	r0 = [p1]; 
	r0 = r0 << 1;						//shift the byte to get the next bit 
 
	p1.l = SCCB_Word_Count; 
	r1 = [p1]; 
	CC = r1 == 0;		//check the number of bytes already received  
	IF CC JUMP SCCB_Stop_Receive_Data;	 
 
	p0.l = lo(FIO0_FLAG_S); 
	r5.l = w[p0]; 
	CC = BITTST (r5,sda_bit);		//Check the SDA bit. 
	IF CC JUMP SCCB_Receive_High_detected;	 
	 
	BITCLR (r0,0); 
JUMP	SCCB_End_of_Receive_Bit; 
 
SCCB_Receive_High_detected: 
	BITSET (r0,0); 
 
SCCB_End_of_Receive_Bit: 
 
	p0.l = lo(FIO0_FLAG_C); 
	r5.l = SCL;                      // drive SCL low 
	w[p0] = r5; 
 
	p1.l = SCCB_Write_Read_Register; //save the shifted byte for the run 
	[p1] = r0; 
 
	p1.l = SCCB_Bit_Count;           // update the bit count 
	r1 = [p1]; 
	r1 += -1; 
	[p1] = r1;	 
	CC = r1 == 0;                   // check if it was the last bit 
	IF CC JUMP SCCB_Receive_Data_Word_Sent; // jump when last bit 
 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Rcv_Clk_Test; 
	r0.l =  SCCB_Rcv_Clk_Test;   // next state 
	[p0] = R0; 
 
	SCCB_End_Macro; 
RTI; 
 
SCCB_Receive_Data_Word_Sent: 
 
	p1.l = SCCB_Data_Pointer; 
	p2 = [p1]; 
	p3.l = SCCB_Write_Read_Register;	//save the shifted byte for the run 
	p3.h = SCCB_Write_Read_Register;	 
	r0 = [p3]; 
	[p2] = r0; 
	r0 = 0; 
	[p3] = r0;			//clear the content of "SCCB_Write_Read_Register" for next byte 
	NOP;				//3 cycles will be required for read an write action 
	NOP; 
	NOP; 
	p3 = [p2++];		//Increment the pointer to the data array 
	[p1] = p2; 
//acknowledge the data received 
 
	// disable sda input 
	p0.l = lo(FIO0_INEN); 
	r0 = w[p0](z); 
	bitclr(r0, sda_bit); 
	w[p0] = r0; 
 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitset(r0, sda_bit); // configure SDA as output  
	w[p0] = r0; 
	 
//pull low the SDA line 
	 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(FIO0_FLAG_C);		//The Flag PF0 (SDA) will be cleared at first (Start Condition!)	 
	r0.l = SDA; 
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer); //Base address of the interrupt vector 
 
	r0.h = SCCB_ACK_Wait; 
	r0.l = SCCB_ACK_Wait; 
	[p0] = R0; 
	 
	 
	SCCB_End_Macro; 
RTI; 
 
SCCB_Stop_Receive_Data: 
	// disable sda input 
	p0.l = lo(FIO0_INEN); 
	r0 = w[p0](z); 
	bitclr(r0, sda_bit); 
	w[p0] = r0; 
	 
	p0.l = lo(FIO0_DIR);		 
	r0.l = w[p0]; 
	bitset(r0, sda_bit); // configure SDA as output  
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Stop_Cond2; r0.l =  SCCB_Stop_Cond2; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
 
/*************** SCCB Receive Clock Test routine********************************************/ 
 
SCCB_Rcv_Clk_Test: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address); //High address of all the system registers 
	p1.h = SCCB_Variable_High_Address;	//works as a page for all Variables 
 
	p0.l = lo(FIO0_FLAG_S); 
	r0.l = W[p0]; 
	CC = BITTST (r0, scl_bit); 
	IF CC JUMP SCCB_Set_Rcv_Clk_Lo;    // if scl high, jump to clear it 
	 
	// if scl low, then set it high in the next state 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);  //interrupt vector base addr 
	r0.h =  SCCB_Rcv_Clk_Hi; 
	r0.l =  SCCB_Rcv_Clk_Hi;    // next state 
	[p0] = R0; 
	 
	SCCB_End_Macro; 
RTI; 
 
SCCB_Set_Rcv_Clk_Lo: 
 
	p0.l = lo(FIO0_FLAG_C); 
	r0 = SCL(z); 
	w[p0] = r0;                  // set SCL low 
 
	SCCB_End_Macro; 
RTI;      // stay in this state until the next interrupt 
 
/*****************************************************************/ 
/*************** SCCB Receive Clock Hi routine********************/ 
 
SCCB_Rcv_Clk_Hi: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(FIO0_FLAG_S); 
	r0 = SCL (z); 
	w[p0] = r0;                             // set SCL high 
	 
	P0.H = hi(ISR_SCCB_Timer); 
	P0.L = lo(ISR_SCCB_Timer);  //interrupt vector base addr 
	r0.h =  SCCB_Receive_Data; 
	r0.l =  SCCB_Receive_Data;  // next state 
	[p0] = R0; 
	 
	SCCB_End_Macro; 
RTI; 
 
 
/**************************************************************/ 
 
/*************** SCCB Stop Cond0,1 ****************************/ 
//Invoke stop condition if the transmission is complete 
SCCB_Stop_Cond0:  // do nothing (just a delay) 
 
	SCCB_Start_Macro; 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Stop_Cond1; r0.l =  SCCB_Stop_Cond1; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
 
	SCCB_End_Macro; 
RTI; 
 
SCCB_Stop_Cond1: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(FIO0_FLAG_S);	 
	r0 = SCL(z); 
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_Stop_Cond2; r0.l =  SCCB_Stop_Cond2; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
/*************** SCCB Stop Cond2 ****************************************/ 
SCCB_Stop_Cond2: 
 
	SCCB_Start_Macro; 
 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(FIO0_FLAG_S);		            //set SDA high to stop 
	r0 = SDA (z); 
	w[p0] = r0; 
 
	P0.H = hi(ISR_SCCB_Timer); P0.L = lo(ISR_SCCB_Timer);	//Base address of the interrupt vector 
	r0.h =  SCCB_End_of_Transmission; r0.l =  SCCB_End_of_Transmission; 
	[p0] = R0;				//ISR Start Address will be written in the EVT register 
 
	SCCB_End_Macro; 
RTI; 
/*************** SCCB Stop Cond2 ****************************************/ 
//The transmission ends and all the timer settings must be diabled 
//This would be a good place to set a bit to replay the transfer is done 
SCCB_End_of_Transmission: 
 
	SCCB_Start_Macro; 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(TMRS8_DISABLE);			//disable timer 
	r1 = 0x0001(z);	 
	w[p0] = r1; //disable the timer 
	 
	p0.h = hi(System_MMR_High_Address);		//High address of all the system registers 
	p0.l = lo(TMRS8_STATUS);	 
	r0 = 0x1011(z); 
	w[p0] = r0;	//disable the timer clear interrupt bit and overflow bit 
 
	p0.l = lo(SICA_IMASK1);				//disable mask the Timer0 again 
	r0 = [p0]; 
	bitclr(r0,3); 
	[p0] = r0; 
	 
	p0.h = hi(IMASK); 
	p0.l = lo(IMASK); 
	r0 = [p0]; 
	bitclr(r0,10); 
	[p0] = r0;	 
	 
	p0.h = _SCCB_In_Progress;       //keeps the core away from calling the SCCB twice 
	p0.l = _SCCB_In_Progress; 
	r0 = 0; 
	[p0] = r0; 
	 
	SCCB_End_Macro; 
 
RTI; 
/*****************************************************************************************/