Skip to content

Instantly share code, notes, and snippets.

@RozeDoyanawa
Created March 20, 2019 22:39
Show Gist options
  • Save RozeDoyanawa/3271bc3f0569d9fcfebcbe77c20bd84b to your computer and use it in GitHub Desktop.
Save RozeDoyanawa/3271bc3f0569d9fcfebcbe77c20bd84b to your computer and use it in GitHub Desktop.
#define MAX_BUFFER 32
// SLAVE
void I2C_SlaveInit(unsigned char addr);
void I2C_SlaveInterruptRoutine(void);
typedef struct _I2C_BufferInfo{
unsigned char size;
unsigned char* buffer;
}I2C_BufferInfo;
void I2C_InputCallback(unsigned char buffer[], unsigned char count);
void I2C_OutputCallback(I2C_BufferInfo* bufferInfo);
// STRUCTURES
typedef struct _I2C_BaseData{
char size;
unsigned char type;
} I2C_BaseData;
typedef struct _I2C_SingleChangeData{
I2C_BaseData i2cbase;
char index;
char state;
} I2C_SingleChangeData;
typedef struct _I2C_UnitInfo{
I2C_BaseData i2cbase;
char inputs;
char outputs;
}I2C_UnitInfo;
typedef struct _ARP {
unsigned long UDID;
unsigned char I2CAddress;
} ARP_INFO;
unsigned char inputBuffer[MAX_BUFFER];
I2C_BufferInfo bufferInfo;
//char* bufferData;
//char expectedWriteSize = 0;
/****************************************************************************
* Function:
* static void I2C_SlaveInit(unsigned char addr)
*
* Description:
* This routine initializes I2C in slave mode.
*
*
* Preconditions:
* None
*
* Parameters:
* None
*
* Returns:
* None
*
* Remarks:
* None
*
****************************************************************************/
void I2C_SlaveInit(unsigned char addr){
char temp;
SSP1CON1bits.WCOL = 0;
SSP1CON1bits.SSPOV = 0;
SSP1CON1bits.SSPEN = 0;
SSP1CON1bits.CKP = 1;
SSP1CON1bits.SSPM3 = 0;
SSP1CON1bits.SSPM2 = 1;
SSP1CON1bits.SSPM1 = 1;
SSP1CON1bits.SSPM0 = 0;
SSP1CON2bits.GCEN = 0;
SSP1CON2bits.RCEN = 0;
SSP1CON2bits.RSEN = 0;
SSP1CON2bits.SEN = 1;
//I2C_AHEN = 1;
//I2C_SDAHT = 1;
SSP1CON2bits.ACKSTAT = 0;
SSP1CON2bits.ACKDT = 0;
SSP1CON2bits.ACKEN = 0;
SSP1CON2bits.PEN = 0;
SSP1ADD = addr;
SSP1STATbits.SMP = 1; // Slew Rate Control Disabled (1Mhz)
temp = SSP1BUF;
PIR1bits.SSPIF = 0;
PIE1bits.SSPIE = 1;
SSP1CON1bits.SSPEN = 1; // Enable SSP
}
/****************************************************************************
* Function:
* void I2C_SlaveInterruptRoutine(void)
*
* Description:
* This routine should be called when an interrupt was generated to
* check if it was I2C-related
*
*
* Preconditions:
* None
*
* Parameters:
* None
*
* Returns:
* None
*
* Remarks:
* None
*
****************************************************************************/
void I2C_SlaveInterruptRoutine(void){
if(PIR1bits.SSPIF && PIE1bits.SSPIE){
char SSP_status = (SSP1STAT & 0b00101101); // Mask out State bits
char Temp;
static char Widx = 0;
static char Ridx = 0;
//LED_INT_B_IO = !LED_INT_B_IO;
switch(SSP_status)
{
case 0b00001001: // I2C master write last byte was an address byte 0 0 A 0 S W 0 BF
if(SSP1CON1bits.SSPOV){ // Recive overflow
SSP1CON1bits.SSPOV = 0;
}
Temp = SSP1BUF; // Read out buffer to clear BF flag
Widx = 0;
break;
//case I2C_Write_Data2:
case 0b00101001: // I2C master write last byte was a data byte 0 0 D 0 S W 0 BF
if(SSP1CON1bits.SSPOV){ // Recive overflow
SSP1CON1bits.SSPOV = 0;
}
if( Widx >= sizeof(I2C_BaseData)){
I2C_BaseData* i2cbase = (I2C_BaseData*)&inputBuffer;
if(i2cbase->size == Widx){
Temp = SSP1BUF; // Read out buffer to clear BF flag
}else{
inputBuffer[Widx++] = SSP1BUF;
}
if(i2cbase->size == Widx){
I2C_InputCallback(inputBuffer, Widx);
}
}else{
inputBuffer[Widx++] = SSP1BUF;// Store data in buffer
}
break;
case 0b00001101: // I2C master read last byte was an address byte 0 0 A 0 S R 0 0
case 0b00001100: // I2C master read last byte was an address byte 0 0 A 0 S R 0 0
I2C_OutputCallback(&bufferInfo);
SSP1BUF = bufferInfo.buffer[0]; // Write data to I2C
Ridx = 1;
break;
case 0b00101101: // I2C master read last byte was a data byte 0 0 D 0 S R 0 0
case 0b00101100: // I2C master read last byte was a data byte 0 0 D 0 S R 0 0
if(Ridx == bufferInfo.size){ // Prevent reading beond buffer
SSP1BUF = 0; // Write dummy data to I2C
}else{
SSP1BUF = bufferInfo.buffer[Ridx++];// Write next data to I2C
}
if(SSP1CON1bits.WCOL){ // Writing while prev not
SSP1CON1bits.WCOL = 0;
}
break;
case 0b00101000: // I2C slave reset by nack from master 0 0 D 0 S W 0 0
Temp = SSP1BUF; // Read out buffer to clear BF flag
break;
default:
Temp = SSP1BUF; // Read out buffer to clear BF flag
break;
}
PIR1bits.SSPIF = 0; // Clear activity flag
SSP1CON1bits.CKP = 1; // Enable clock
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment