⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_bf561_rev04.asm

📁 adi black fin chip connect to cmos sensor
💻 ASM
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*	I2C_BF561_rev04.asm
*   
*	Copyright (c) 2007 Analog Devices, Inc.  All Rights Reserved.
*   This software is proprietary to Analog Devices, Inc. and its
*	licensors.
*  
* 	CHANGES:  10/24/2007  1.00  - initial public release
*
*	SOFTWARE: 	VisualDSP++ 5.0 August 2007 Update
* 
* 	HARDWARE: 	BF561 EZ-Kit Lite Board Rev 1.4
*				Micron MTV9022 or MTV9032 Sensor
*
*
*	DESCRIPTION:
* 
*	SCCB Software Interface for Video Device configurations - C Callable
*	
*	This header implements the I2C read and write functions.
*
* 
*	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]
*	HISTORY:
*	04 October 06:  Taken from TL's rev 3.0 
*					- added Error Handling. 
*					- modified labels to make this function C-callable 
*					  (not using macros)
*					- added TWI_primitives.c to this package to call 
*					  it for any combination of 8/16 register/data 
*					  size read/writes
*				  
*
*	NOTE: hard coded to use EVT10 and SICA_IMASK1 (bit 3)!
*
*******************************************************************************/

#include <defBF561.h>

/*************** 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 0x80                     // scl_period ~= 320kHz at 120MHz SYSCLK
//#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

#define MAX_TRANSACTIONS	(256*2)+ 10		// max bytes 

/*************** 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[MAX_TRANSACTIONS];				
.var		_SCCB_DataOut[MAX_TRANSACTIONS];				
.var		SCCB_Point_of_State;
.var		SCCB_Read_Count;
.var        _SCCB_In_Progress = 0;
.var		SCCB_Read_Start_Cond0_Task_Val;
.var		_SCCB_Error = 0;
/*************** 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;
.global     _SCCB_Error;
/**********************************************************************/

	

/*************** 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			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -