📄 bf53xsccb_interface.asm
字号:
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;
/*****************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -