|
/******************************************************************************/ // // 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:
Date Modified: 08/12/05 TL Rev 1.0
Software: VisualDSP++4.0, Assembler 2.6.7.5, Linker 3.5.2.2
Hardware: BF533 EZ-KIT Board (rev 1.7), Blackfin EZ-Extender (rev 1.2)
Chip: ADSP-BF533 REV 0.4
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;
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(FIO_FLAG_S); // drive SCL high r0 = SCL(z); w[p0] = r0; r0.l = W[p0]; CC = BITTST (r0,sda_bit); //Check SDA input. It should be low
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(FIO_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; // An error occured due to a miss of a slave Acknowledge! 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 sixty bytes 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; //If read has been chosen care must been taken of the write read r1 = [p1]; //interaction 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 and keep writing [p1] = r1;
SCCB_Write_Task: // disable PF inputs p0.l = lo(FIO_INEN); r0 = w[p0](z); bitclr(r0, sda_bit); w[p0] = r0;
p0.l = lo(FIO_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(FIO_INEN); r0 = w[p0](z); bitclr(r0, sda_bit); w[p0] = r0; p0.l = lo(FIO_DIR); r0.l = w[p0]; bitset(r0, sda_bit); //configure SDA as output w[p0] = r0;
p0.l = lo(FIO_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(FIO_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: //start the stop condition procedure after all bytes has been sent 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;
CC = r1 == 0; IF CC JUMP SCCB_Stop_Cond_Task; // Link to the Stop condition after all bytes has been received // make sure SDA is configured as input // 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 = w[p0](z); bitclr(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(FIO_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(FIO_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;
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; //go to this state to wait one int period [p0] = R0;
SCCB_End_Macro; RTI;
SCCB_Stop_Receive_Data: // disable PF inputs p0.l = lo(FIO_INEN); r0 = w[p0](z); bitclr(r0, sda_bit); w[p0] = r0; p0.l = lo(FIO_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(FIO_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(FIO_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(FIO_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(FIO_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(FIO_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.l = lo(TIMER_DISABLE); //disable timer r1 = 0x0001(z); w[p0] = r0;
p0.h = hi(System_MMR_High_Address); //High address of all the system registers p0.l = lo(TIMER_STATUS); r0 = 0x1011(z); w[p0] = r0; //disable the timer clear interrupt bit and overflow bit
p0.l = lo(SIC_IMASK); //disable mask the Timer0 again r0 = [p0]; bitclr(r0,16); [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; /*****************************************************************************************/
//本代码Blackfin示例
|