Skip to content

Instantly share code, notes, and snippets.

@RozeDoyanawa
Last active March 31, 2019 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RozeDoyanawa/61752e9e54155c5a2f30f104cf14a162 to your computer and use it in GitHub Desktop.
Save RozeDoyanawa/61752e9e54155c5a2f30f104cf14a162 to your computer and use it in GitHub Desktop.
//#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