/********************************************************************* * Flowcode CAL I2C File * * File: PIC_CAL_I2C.c * * (c) 2011 Matrix Multimedia Ltd. * http://www.matrixmultimedia.com * * Software License Agreement * * The software supplied herewith by Matrix Multimedia Ltd (the * “Company”) for its Flowcode graphical programming language is * intended and supplied to you, the Company’s customer, for use * solely and exclusively on the Company's products. The software * is owned by the Company, and is protected under applicable * copyright laws. All rights are reserved. Any use in violation * of the foregoing restrictions may subject the user to criminal * sanctions under applicable laws, as well as to civil liability * for the breach of the terms and conditions of this licence. * * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * * Changelog: * * date | by | description * -------+----+----------------------------------------------------- * 210911 | BR | Created * 021211 | BR | Converted to new dynamic defines mechanism * 310512 | BR | Minor bug fix when using SW I2C on a device with no I2C peripheral * 120912 | BR | Minor bug fix to remove a bug with remappable I2C channel 2 * 120912 | BR | Minor bug fix to remove a bug with register ssp2con * 090413 | LM | removed I2C HW port overrides, all come from CAL component for V6 * 140613 | BR | Minor mod to error message to say not available or not supported * 020713 | LM | Standard API calls */ #define MX_I2C_CHANNEL_X CAL_APPEND(MX_I2C_CHANNEL_, MX_I2C_NUM) #define MX_I2C_SDA_PIN_X CAL_APPEND(MX_I2C_SDA_PIN_, MX_I2C_NUM) #define MX_I2C_SDA_PORT_X CAL_APPEND(MX_I2C_SDA_PORT_, MX_I2C_NUM) #define MX_I2C_SDA_TRIS_X CAL_APPEND(MX_I2C_SDA_TRIS_, MX_I2C_NUM) #define MX_I2C_SCL_PIN_X CAL_APPEND(MX_I2C_SCL_PIN_, MX_I2C_NUM) #define MX_I2C_SCL_PORT_X CAL_APPEND(MX_I2C_SCL_PORT_, MX_I2C_NUM) #define MX_I2C_SCL_TRIS_X CAL_APPEND(MX_I2C_SCL_TRIS_, MX_I2C_NUM) #define MX_I2C_BMODE_X CAL_APPEND(MX_I2C_BMODE_, MX_I2C_NUM) #define MX_I2C_BAUD_X CAL_APPEND(MX_I2C_BAUD_, MX_I2C_NUM) #define MX_I2C_INT_X CAL_APPEND(MX_I2C_INT_, MX_I2C_NUM) //Function Prototypes CALFUNCTION(void, FC_CAL_I2C_Master_Init_, (void)); CALFUNCTION(void, FC_CAL_I2C_Master_Uninit_, (void)); CALFUNCTION(void, FC_CAL_I2C_Master_Start_, (void)); CALFUNCTION(void, FC_CAL_I2C_Master_Restart_, (void)); CALFUNCTION(void, FC_CAL_I2C_Master_Stop_, (void)); CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_TxByte_, (MX_UINT8 Data)); CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_RxByte_, (MX_UINT8 Last)); CALFUNCTION(void, FC_CAL_I2C_Slave_Init_, (void)); CALFUNCTION(void, FC_CAL_I2C_Slave_Uninit_, (void)); CALFUNCTION(void, FC_CAL_I2C_Slave_TxByte_, (MX_UINT8 Data)); CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_RxByte_, (MX_UINT8 Last)); #if (MX_I2C_CHANNEL_X > 0) //Ensure SSPCON register is defined correctly #ifndef SSPCON #ifdef SSPCON1 #define sspcon sspcon1 #else #ifdef SSP1CON1 #define sspcon ssp1con1 #endif #endif #endif //Ensure SSPIF register is defined correctly #ifndef SSPIF #ifdef SSP1IF #define SSPIF SSP1IF #else #error "I2C does not have the SSPIF defined on this chip - does your chip support this feature?" #endif #endif //Ensure SSPCON2 register is defined correctly #ifndef SSPCON2 #ifdef SSP1CON2 #define sspcon2 ssp1con2 #endif #endif //Ensure SSPSTAT register is defined correctly #ifndef SSPSTAT #ifdef SSP1STAT #define sspstat ssp1stat #endif #endif //Ensure SSPADD register is defined correctly #ifndef SSPADD #ifdef SSP1ADD #define sspadd ssp1add #endif #endif //Ensure SSPBUFF register is defined correctly #ifndef SSPBUFF #ifdef SSP1BUFF #define sspbuff ssp1buff #endif #endif #if (MX_I2C_CHANNEL_X > 1) #ifndef SSP2CON #define ssp2con ssp2con1 #endif #endif #else #ifndef MX_I2C_SW_DEL #define MX_I2C_SW_DEL #define MX_I2C_SW_BAUD ((500000 / MX_I2C_BAUD_X)-1) #if (MX_I2C_SW_BAUD < 1) //#define MX_I2C_DELAY delay_us(1); #define MX_I2C_DELAY nop(); #else #define MX_I2C_DELAY delay_us(MX_I2C_SW_BAUD); #endif #endif #endif CALFUNCTION(void, FC_CAL_I2C_Master_Init_, (void)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Configure SDA as Input FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Configure SCL as Input #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 #ifndef MX_MI2C #error "This chip does not have Master I2C capability or Flowcode does not currently support it" #else #ifndef MX_I2C_1 #error "This chip does not have Master I2C channel 1" #endif #if (MX_I2C_BMODE_X & 0x01) cr_bit (sspstat,SMP); //Slew Rate Control Enabled #else st_bit (sspstat,SMP); //Slew Rate Control Disabled #endif #if (MX_I2C_BMODE_X & 0x02) st_bit (sspstat,CKE); //Enable SMBus specific inputs #else cr_bit (sspstat,CKE); //Disable SMBus specific inputs #endif sspcon = 0x28; //Setup I2C into Master Mode sspadd = ((MX_CLK_SPEED / 4)/ MX_I2C_BAUD_X) - 1; //Set the Baud Rate sspcon2 = 0x00; //Clear the control bits st_bit(intcon, GIE); FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Configure SDA as Input FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Configure SCL as Input #endif #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 #ifndef MX_MI2C #error "This chip does not have Master I2C capability or Flowcode does not currently support it" #else #ifndef MX_I2C_2 #error "This chip does not have Master I2C channel 2" #endif #if (MX_I2C_BMODE_X & 0x01) cr_bit (ssp2stat,SMP); //Slew Rate Control Enabled #else st_bit (ssp2stat,SMP); //Slew Rate Control Disabled #endif #if (MX_I2C_BMODE_X & 0x02) st_bit (ssp2stat,CKE); //Enable SMBus specific inputs #else cr_bit (ssp2stat,CKE); //Disable SMBus specific inputs #endif ssp2con = 0x28; //Setup I2C into Master Mode ssp2add = ((MX_CLK_SPEED / 4)/ MX_I2C_BAUD_X) - 1; //Set the Baud Rate ssp2con2 = 0x00; //Clear the control bits st_bit(intcon, GIE); FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Configure SDA as Input FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Configure SCL as Input #endif #endif } CALFUNCTION(void, FC_CAL_I2C_Master_Uninit_, (void)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Configure SDA as Input FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Configure SCL as Input #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(sspcon, SSPEN); //Disable SSP #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(ssp2con, SSPEN); //Disable SSP #endif } CALFUNCTION(void, FC_CAL_I2C_Master_Start_, (void)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Make Sure SCL is Set FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Make Sure SDA is Set MX_I2C_DELAY; //Small Delay FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Clear SDA MX_I2C_DELAY; //Small Delay FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Clear SCL //MX_I2C_DELAY; //Small Delay //Removed 050613 - BR #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(pir1, SSPIF); //Clear SSP interrupt flag st_bit(sspcon2,SEN); //Initiate start condition while(ts_bit(sspcon2,SEN)); //Wait for start bit to be generated #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(pir3, SSP2IF); //Clear SSP interrupt flag st_bit(ssp2con2,SEN); //Initiate start condition while(ts_bit(ssp2con2,SEN)); //Wait for start bit to be generated #endif } CALFUNCTION(void, FC_CAL_I2C_Master_Restart_, (void)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA High MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA Low MX_I2C_DELAY; FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low //MX_I2C_DELAY; //Removed 050613 - BR #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(pir1, SSPIF); //Clear SSP interrupt flag st_bit(sspcon2,RSEN); //Initiate restart condition while(ts_bit(sspcon2,RSEN)); //Wait for restart bit to be generated #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(pir3, SSP2IF); //Clear SSP interrupt flag st_bit(ssp2con2,RSEN); //Initiate restart condition while(ts_bit(ssp2con2,RSEN)); //Wait for restart bit to be generated #endif } CALFUNCTION(void, FC_CAL_I2C_Master_Stop_, (void)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA Low MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA High #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(pir1,SSPIF); //Clear SSP interrupt flag st_bit(sspcon2,PEN); //Initiate stop condition while(ts_bit(sspcon2,PEN)); //Wait for stop bit to be generated #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(pir3,SSP2IF); //Clear SSP interrupt flag st_bit(ssp2con2,PEN); //Initiate stop condition while(ts_bit(ssp2con2,PEN)); //Wait for stop bit to be generated #endif delay_ms(10); //Wait before reusing the I2C BUS } CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_TxByte_, (MX_UINT8 Data)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software char bit_mask; char local_ack = 0; for(bit_mask=0x80;bit_mask;bit_mask=bit_mask>>1) { if(Data & bit_mask) { FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA High } else { FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA Low } MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low //MX_I2C_DELAY; //Removed 050613 - BR } FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA High MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); if (FC_CAL_Bit_In(MX_I2C_SDA_PORT_X, MX_I2C_SDA_PIN_X)) //Get the Status Bit local_ack = 1; //MX_I2C_DELAY; //Small Delay //Removed 050613 - BR FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low //MX_I2C_DELAY; //Removed 050613 - BR return (local_ack); //0 = Ack received : 1 = Ack not received #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(pir1,SSPIF); //Clear SSP interrupt flag sspbuf=Data; //Send byte while(ts_bit(pir1,SSPIF) == 0); //Wait for control bit to be sent if(ts_bit(sspcon2,ACKSTAT)) //Check Acknowledgement return (1); //No Acknowledgement else return (0); //Acknowledgement received #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(pir3,SSP2IF); //Clear SSP interrupt flag ssp2buf=Data; //Send byte while(ts_bit(pir3,SSP2IF) == 0); //Wait for control bit to be sent if(ts_bit(ssp2con2,ACKSTAT)) //Check Acknowledgement return (1); //No Acknowledgement else return (0); //Acknowledgement received #endif } CALFUNCTION(MX_UINT8, FC_CAL_I2C_Master_RxByte_, (MX_UINT8 Last)) { #if (MX_I2C_CHANNEL_X == 0) //Use Master I2C Software char bit_mask; char Data = 0; char local_ack; FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Set SDA High MX_I2C_DELAY; for(bit_mask=0x80;bit_mask;bit_mask=bit_mask>>1) { FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); if(FC_CAL_Bit_In(MX_I2C_SDA_PORT_X, MX_I2C_SDA_PIN_X)) //Read Incoming Bit Data = Data | bit_mask; //Add data to variable FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low MX_I2C_DELAY; //Small Delay } if (Last) //Acknowledge? { FC_CAL_Bit_In_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Send Nack } else { FC_CAL_Bit_Low_DDR(MX_I2C_SDA_PORT_X, MX_I2C_SDA_TRIS_X, MX_I2C_SDA_PIN_X); //Send Ack } MX_I2C_DELAY; FC_CAL_Bit_In_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL High MX_I2C_DELAY; FC_CAL_Bit_Low_DDR(MX_I2C_SCL_PORT_X, MX_I2C_SCL_TRIS_X, MX_I2C_SCL_PIN_X); //Set SCL Low //MX_I2C_DELAY; //Removed 050613 - BR return (Data); #endif #if (MX_I2C_CHANNEL_X == 1) //Use Master I2C Hardware 1 cr_bit(pir1,SSPIF); //Clear SSP interrupt flag st_bit(sspcon2,RCEN); //Initiate Read while(ts_bit(pir1,3) == 0); //Wait for data read if (Last) st_bit(sspcon2,ACKDT); //Send Nack else cr_bit(sspcon2,ACKDT); //Send Ack st_bit(sspcon2,ACKEN); //Initiate Nack while(ts_bit(sspcon2,ACKEN)); //Wait for data read return(sspbuf); //Store incoming data #endif #if (MX_I2C_CHANNEL_X == 2) //Use Master I2C Hardware 2 cr_bit(pir3,SSP2IF); //Clear SSP interrupt flag st_bit(ssp2con2,RCEN); //Initiate Read while(ts_bit(pir3,SSP2IF) == 0); //Wait for data read if (Last) st_bit(ssp2con2,ACKDT); //Send Nack else cr_bit(ssp2con2,ACKDT); //Send Ack st_bit(ssp2con2,ACKEN); //Initiate Nack while(ts_bit(ssp2con2,ACKEN)); //Wait for data read return(ssp2buf); //Store incoming data #endif } //Slave functions currently not implemented CALFUNCTION(void, FC_CAL_I2C_Slave_Init_, (void)) { } CALFUNCTION(void, FC_CAL_I2C_Slave_Uninit_, (void)) { } CALFUNCTION(void, FC_CAL_I2C_Slave_TxByte_, (MX_UINT8 Data)) { } CALFUNCTION(MX_UINT8, FC_CAL_I2C_Slave_RxByte_, (MX_UINT8 Last)) { }