23.6.4 Host Reception (10-bit Address)

Host Reception (10-bit Address)

#include <xc.h>

#define INIT                                0
#define ADDRESS_PHASE_UPPER_10BIT_WRITE     1
#define ADDRESS_PHASE_LOWER_10BIT           2
#define RESTART                             3
#define ADDRESS_PHASE_UPPER_10BIT_READ      4
#define DATA_READ                           5


unsigned char hostReceived[20], phase;
unsigned char count = 0;
#define mCLIENT_ADDRESS 0x14C

int main(void) {

    /*Configure I2C pins as digital*/


    /*I2C1 configured as Host */

    I2C1LBRG = 38; // 100kHz @ 8MIPS
    I2C1HBRG = 38; // 100kHz @ 8 MIPS


    /* Configure Bus IDle timeout*/
    I2C1CON2bits.BITE = 1;
    I2C1BITObits.BITOPR = 76;
    /* Configured interrupt enable bits*/

    I2C1INTCbits.HACKSIE = 1; // Assert HSTIF on ACK seq
    I2C1INTCbits.HDTXIE = 1; // Assert HSTIF on TX
    I2C1INTCbits.HDRXIE = 1; // Assert HSTIF on RX
    I2C1INTCbits.HSCIE = 1; // Assert HSTIF on start
    I2C1INTCbits.HSTIE = 1; // Assert I2CxIF when HSTIF is set


    I2C1CON2bits.SMEN = 1; // Smart mode enabled
    I2C1CON2bits.ACKC = 0b10; // ACK all the bytes expect last byte
    I2C1CON2bits.PSZ = 10; // Packet size
    I2C1CON2bits.EOPSC = 0b01; // End of packet will be set after data bytes
    I2C1CON1bits.ON = 1; // Enable I2C

    IFS2bits.I2C1IF = 0; // Clear I2C general interrupt    
    IEC2bits.I2C1IE = 1; // Enable I2C general interrupt 


    /*wait for bus idle */
    while (!I2C1STAT2bits.BITO);

    phase = ADDRESS_PHASE_UPPER_10BIT_WRITE;
    I2C1CON1bits.SEN = 1; // Send Start bit






    while (1);
}

void __attribute__((interrupt, no_auto_psv)) _I2C1Interrupt(void) {
    IFS2bits.I2C1IF = 0;

    switch (phase) {

        case ADDRESS_PHASE_UPPER_10BIT_WRITE:
            /*Verify if start has been sent*/
            if (I2C1STAT2bits.STARTE) {
                /* Transmit client address with RW =0 , write  client*/
                I2C1TRN = ((((mCLIENT_ADDRESS >> 8) & 0x03) << 1) | 0) + 0b11110000;
                phase = ADDRESS_PHASE_LOWER_10BIT;
            }
            break;
        case ADDRESS_PHASE_LOWER_10BIT:
            /*Verify if the upper 10bit address is ACKed*/
            if (I2C1STAT1bits.ACKSTAT == 0) {
                I2C1TRN = mCLIENT_ADDRESS & 0xFF;
                phase = RESTART;
            }
            break;
        case RESTART:
            I2C1CON1bits.RSEN = 1; // Send restart
            phase = ADDRESS_PHASE_UPPER_10BIT_READ;
            break;
        case ADDRESS_PHASE_UPPER_10BIT_READ:
            /* Transmit client address with RW =1 , read  client*/
            I2C1TRN = ((((mCLIENT_ADDRESS >> 8) & 0x03) << 1) | 1) + 0b11110000;
            phase = DATA_READ;
            break;
        case DATA_READ:
            /* Set NDA to indicate next byte is data */
            if (I2C1CON2bits.NDA != 1) {
                I2C1CON2bits.NDA = 1;
                /*Enable receive for the 1st time*/
                I2C1CON1bits.RCEN = 1;
            }
            /*Read the received data*/
            if (I2C1STAT1bits.RBF) {
                hostReceived[count++] = I2C1RCV;
            }
            /* If Packet size is 0, EOP will be asserted,send STOP on EOP*/
            if (I2C1STAT2bits.EOP) {
                I2C1CON1bits.PEN = 1;
            }

            break;
    }
}