Last active
March 31, 2019 16:29
-
-
Save RozeDoyanawa/61752e9e54155c5a2f30f104cf14a162 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#define I2C_Allow0Adress | |
#define I2C_DefaultAddress 2 | |
//#define I2C_DoAddressShift | |
typedef enum _I2C_TYPE_DATA{ | |
NO_CHANGE_I2C_MSG = 0, | |
SINGLE_CHANGE_I2C_MSG = 1, | |
ALL_CHANGE_I2C_MSG = 2, | |
UNIT_DESCRIPTOR = 3 | |
} I2C_TYPE_DATA; | |
// MASTER | |
void I2C_Start(void); | |
void I2C_Stop(void); | |
void I2C_Write_Byte(unsigned char byte); | |
unsigned char I2C_Read_Byte(unsigned char ubAck); | |
void I2C_MasterInit(void); | |
signed char I2C_Read(unsigned char ubSlaveId, unsigned char aubData[], | |
unsigned char ubCount) ; | |
void I2C_Write(unsigned char ubSlaveId, unsigned char aubData[], | |
unsigned char ubCount) ; | |
// 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; | |
#define MAX_BUFFER 32 | |
char WriteCollision = 0; // @TODO: Implement this | |
char I2C_SSPBUF_Overwrite = 0; // @TODO: Implement this | |
unsigned char inputBuffer[MAX_BUFFER]; | |
I2C_BufferInfo bufferInfo; | |
//char* bufferData; | |
//char expectedWriteSize = 0; | |
void I2C_SlaveInit(unsigned char addr){ | |
// 7bit Slave Mode (MODE = 0) | |
I2C1CON0 = 0x00; | |
//I2C1CON0bits.CSTR = 1; | |
// Slave Address Match | |
#ifndef I2C_Allow0Adress | |
if (addr == 0x00){ | |
addr = I2C_DefaultAddress; | |
} | |
#endif | |
#ifdef I2C_DoAddressShift | |
addr = addr << 1; | |
#endif | |
I2C1ADR0 = addr; | |
I2C1ADR1 = addr; | |
I2C1ADR2 = addr; | |
I2C1ADR3 = addr; | |
// ACK for every valid byte (ACKDT = 0) | |
// ACK at the end of a Read (ACKCNT = 0) | |
// Clock stretching DISabled (CSTRDIS = 1) | |
I2C1CON1 = 0b00000000; | |
//I2C1CON1bits.ACKCNT = 1; | |
// Auto-count disabled (ACNT = 0) | |
// General Call disabled (GCEN = 0) | |
// Fast mode enabled (FME = 1) | |
// ADB0 address buffer used (ADB = 0) | |
// SDA Hold time of 30 ns (SDAHT = 2) | |
// Bus free time of 8 I2C Clock pulses | |
// (BFRET = 1) | |
I2C1CON2 = 0b00101000; | |
// Clear all I2C flags | |
PIR3bits.I2C1IF = 0; | |
I2C1PIR = 0x00; | |
// Enable I2C interrupts | |
PIE3bits.I2C1IE = 1; | |
IPR3bits.I2C1IP = 1; | |
// NOTE: Enable global and peripheral interrupts somewhere! | |
//INTCON0bits.IPEN = 1; | |
//INTCON0bits.GIEH = 1; | |
// Enable local interrupt on ACK Sequence | |
I2C1PIE = 0; | |
I2C1PIEbits.ACKTIE = 1; | |
//I2C1PIEbits.PCIE = 1; | |
//I2C1PIEbits.RSCIE = 1; | |
//I2C1PIEbits.ADRIE = 1; | |
// Enable I2C module | |
I2C1CON0bits.EN = 1; | |
// Set the read and write position pointers to zero | |
} | |
void I2C_SlaveInterruptRoutine(void) { | |
static unsigned char Widx = 0; | |
static unsigned char Ridx = 0; | |
static unsigned long msgNum_Reads = 0; | |
static unsigned long msgAdrNum = 0; | |
char Temp = 0; | |
// I2C2 | |
if (PIR3bits.I2C1IF){ | |
// Clear the I2C interrupt flag | |
// ACK Sequence Interrupt Detected | |
// Clear the interrupt flag | |
// For Slave Read/Master Write | |
if(I2C1PIRbits.ACKTIF){ | |
if (!I2C1STAT0bits.R){ | |
// Data Byte Received | |
if (!I2C1STAT0bits.D){ | |
I2C1STAT1bits.CLRBF = 1; | |
Widx = 0; | |
}else{ | |
// Read from RXB | |
if( Widx >= sizeof(I2C_BaseData)){ // Widx has gotten past message frame and is now msg data | |
I2C_BaseData* i2cbase = (I2C_BaseData*)&inputBuffer; | |
if(i2cbase->size == Widx){ // Ensure not writing beyond buffer | |
Temp = I2C1RXB; // Read out buffer to clear BF flag | |
}else{ | |
inputBuffer[Widx++] = I2C1RXB; // Read out i2c buffer and store in local buffer | |
} | |
if(i2cbase->size == Widx){ // If read reached target size | |
I2C_InputCallback(inputBuffer, Widx); // Call user function for handling the received data | |
} | |
}else{ | |
inputBuffer[Widx++] = I2C1RXB;// Store data in buffer | |
} | |
} | |
} | |
// For Slave Write/Master Read | |
else { | |
// Write to TXB | |
if(!I2C1STAT0bits.D){ | |
I2C1STAT1bits.CLRBF = 1; | |
I2C_OutputCallback(&bufferInfo); | |
Ridx = 0; | |
I2C1TXB = bufferInfo.buffer[Ridx++]; | |
}else{ | |
if(Ridx >= sizeof(I2C_BaseData)){ | |
if(Ridx == bufferInfo.size){ | |
I2C1TXB = 0; | |
}else{ | |
I2C1TXB = bufferInfo.buffer[Ridx++]; | |
} | |
}else{ | |
I2C1TXB = bufferInfo.buffer[Ridx++]; | |
} | |
} | |
} | |
} | |
I2C1PIR = 0; | |
I2C1ERR = 0; | |
PIR3bits.I2C1IF = 0; | |
if(I2C1CON0bits.CSTR){ | |
I2C1CON0bits.CSTR = 0; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment