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