📄 bf53xsccb_interface.asm
字号:
/******************************************************************************/
//
// Name: BF533 EZ-KIT video GP receive mode (8bit) for the Omnivision chip OV6630
//
/*****************************************************************************************************************
/*****************************************************************************************
(C) Copyright 2003 - Analog Devices, Inc. All rights reserved.
File Name: Main.asm
Date Modified: 01/08/07 TL Rev 2.0
Software: VisualDSP++4.5, Assembler 1.1.0.2, Linker 3.8.0.2
Hardware: BF533 EZ-KIT Board (rev 1.2), Blackfin EZ-Extender (rev 1.2)
Chip: ADSP-BF533 REV 0.2
Special Connections: None
Purpose: To configure the ADV 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 number of bytes totaly 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 */
/* . */
/* . */
/*************************************************************************/
/* (e.g.Reading from the device: */
/* SCCB_DataIn Device Address (LSB must be zero) */
/* Word Address */
/* Device Address (LSB must be one) */
/* Data can be read via SCCB_DataOut */
/*************************************************************************/
#include <defBF533.h>
/*************** SCCB Constants ************************************/
#define ISR_SCCB_Timer 0xFFE0202C //Address of the interrupt register (EVT11 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 PF0
#define SDA 0x2 // serial data is PF1
#define scl_bit 0 // scl = PF0
#define sda_bit 1 // sda = PF1
/*************** 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[60];
.var SCCB_DataOut[60];
.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] = (R7:0, P5:0)
#define SCCB_End_Macro\
p0.h = hi(TIMER_STATUS);\
p0.l = lo(TIMER_STATUS);\
R0 = 0x0011 (z);\
w[p0] = R0;\
\
(R7:0, P5:0) = [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:
[--SP] = ASTAT;
[-- SP] = (R7:0, P5:0) ;
/*************** 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(FIO_INEN);
r0 = w[p0](z);
bitclr(r0, scl_bit);
bitclr(r0, sda_bit);
w[p0] = r0;
//The Flag PF1(SDA) and PF0(SCL) shall be high
p0.l = lo(FIO_FLAG_S);
r0 = w[p0](z);
bitset(r0, scl_bit);
bitset(r0, sda_bit);
w[p0] = r0;
//Set bit PF1(SDA) & PF0(SCL) as outputs
p0.l = lo(FIO_DIR);
r0 = w[p0](z);
bitset(r0, scl_bit);
bitset(r0, sda_bit);
w[p0] = r0;
/*************************************************************************/
/***************** SCCB Timer0 Init ***************************************/
p0.h = hi(System_MMR_High_Address); //High address of all the system registers
p0.l = lo(TIMER_STATUS);
r0.l = 0x0011; w[p0] = r0; //Clear Timer Interrupt and Overflow bit
p0.l = lo(TIMER_DISABLE); //disable timer
r1 = 0x0001(z);
w[p0] = r0;
/* Setup Timer0: PWM_OUT mode, pulse hi, count to end of */
/* period, interrupt, sample TMR0 pin, enable pad, */
/* Bit configuration: 0x001D = 0000 0000 0001 1101 */
P0.L = lo(TIMER0_CONFIG);
P0.H = hi(TIMER0_CONFIG);
R0.L = 0x001D;
W[P0] = R0.L;
// The period is set to provide a 3:1 ratio of SCL to TMR0
P0.L = lo(TIMER0_PERIOD);
P0.H = hi(TIMER0_PERIOD);
R0 = SCL_PERIOD (z);
[P0] = R0;
// Width of provides 50% duty cycle: scl_high = 1/2 of scl_period
P0.L = lo(TIMER0_WIDTH);
P0.H = hi(TIMER0_WIDTH);
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(SIC_IMASK); //Timer0 has been enabled
r0 = [p0];
bitset(r0,16);
[p0] = r0;
p0.h = hi(IMASK);
p0.l = lo(IMASK);
r0 = [p0];
bitset(r0,11);
[p0] = r0; //Enable the "IVEC11" interrupt
p0.h = hi(System_MMR_High_Address); //High address of all the system registers
p0.l = lo(TIMER_ENABLE); //enable timer
r1 = 0x0001(z);
w[p0] = r0;
/*************************************************************************/
/*************** 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;
/*************************************************************************/
(R7:0, P5:0) = [SP++];
ASTAT = [SP++];
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(FIO_FLAG_C); //The Flag PF1 (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(FIO_FLAG_C); //The Flag PF0 (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 PF1 (SDA)
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];
CC = BITTST(r0, 7);
IF CC JUMP SCCB_Send_DATA_SET_SDA; //Check the data bit in order to clear or
p0.l = lo(FIO_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(FIO_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; //load the bit counter to count the
r1 = [p1];
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
// enable PF inputs
p0.l = lo(FIO_INEN);
r0 = w[p0](z);
bitset(r0, sda_bit);
w[p0] = r0;
p0.l = lo(FIO_DIR);
r0.l = w[p0];
bitclr(r0, sda_bit); //configure SDA bit as an input to accept slave acknowledge
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(FIO_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(FIO_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 SCCB_Send_DATA_Word_Sent;//If eight bits are sent get the next byte
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;
// disable PF inputs
p0.l = lo(FIO_INEN);
r0 = w[p0](z);
bitclr(r0, sda_bit);
w[p0] = r0;
//Acknowledge by master
p0.l = lo(FIO_DIR);
r0.l = w[p0]; //Clear SDA to drive the master acknowledge
bitset(r0, sda_bit); //configure SDA bit as an output
w[p0] = r0;
p0.l = lo(FIO_FLAG_C); // drive SDA low
r0 = SDA(z);
w[p0] = r0;
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(FIO_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -