Subversion Repositories Code-Repo

Rev

Rev 147 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
147 Kevin 1
#include "defines.h"
119 Kevin 2
#include "i2c.h"
3
 
120 Kevin 4
static I2C_DATA i2c_data;
128 Kevin 5
static I2C_DATA *i2c_data_p = &i2c_data;
119 Kevin 6
 
7
// Set up the data structures for the i2c code
8
// Should be called once before any i2c routines are called
120 Kevin 9
void I2C_Init() {
128 Kevin 10
    i2c_data_p->buffer_in_len = 0;
11
    i2c_data_p->buffer_in_len_tmp = 0;
12
    i2c_data_p->buffer_in_read_ind = 0;
13
    i2c_data_p->buffer_in_write_ind = 0;
120 Kevin 14
 
128 Kevin 15
    i2c_data_p->buffer_out_ind = 0;
16
    i2c_data_p->buffer_out_len = 0;
120 Kevin 17
 
128 Kevin 18
    i2c_data_p->operating_mode = 0;
19
    i2c_data_p->operating_state = I2C_IDLE;
20
    i2c_data_p->return_status = 0;
120 Kevin 21
 
128 Kevin 22
    i2c_data_p->slave_in_last_byte = 0;
23
    i2c_data_p->slave_sending_data = 0;
120 Kevin 24
 
128 Kevin 25
    i2c_data_p->master_dest_addr = 0;
26
    i2c_data_p->master_status = I2C_MASTER_IDLE;
120 Kevin 27
 
28
    // Enable I2C interrupt
29
    PIE1bits.SSPIE = 1;
119 Kevin 30
}
31
 
32
// Setup the PIC to operate as a master.
121 Kevin 33
void I2C_Configure_Master(unsigned char speed) {
128 Kevin 34
    i2c_data_p->operating_mode = I2C_MODE_MASTER;
119 Kevin 35
 
129 Kevin 36
    I2C_CLK_TRIS = 1;
37
    I2C_DAT_TRIS = 1;
119 Kevin 38
 
39
    SSPSTAT = 0x0;
40
    SSPCON1 = 0x0;
41
    SSPCON2 = 0x0;
42
    SSPCON1bits.SSPM = 0x8; // I2C Master Mode
121 Kevin 43
    if (speed) {
44
        SSPADD = 0x74;          // Operate at 100KHz (48MHz)
45
    } else {
46
        SSPADD = 0x1A;          // Operate at 400KHz (48MHz)
47
    }
119 Kevin 48
    SSPSTATbits.SMP = 1;    // Disable Slew Rate Control
49
    SSPCON1bits.SSPEN = 1;  // Enable MSSP Module
50
}
51
 
52
// Sends length number of bytes in msg to specified address (no R/W bit)
120 Kevin 53
void I2C_Master_Send(unsigned char address, unsigned char length, unsigned char *msg) {
54
    unsigned char i;
119 Kevin 55
    if (length == 0)
56
        return;
57
 
58
    // Copy message to send into buffer and save length/address
59
    for (i = 0; i < length; i++) {
128 Kevin 60
        i2c_data_p->buffer_in[i] = msg[i];
119 Kevin 61
    }
128 Kevin 62
    i2c_data_p->buffer_in_len = length;
63
    i2c_data_p->master_dest_addr = address;
64
    i2c_data_p->buffer_in_read_ind = 0;
65
    i2c_data_p->buffer_in_write_ind = 0;
119 Kevin 66
 
67
    // Change status to 'next' operation
128 Kevin 68
    i2c_data_p->operating_state = I2C_SEND_ADDR;
69
    i2c_data_p->master_status = I2C_MASTER_SEND;
119 Kevin 70
 
71
    // Generate start condition
72
    SSPCON2bits.SEN = 1;
73
}
74
 
75
// Reads length number of bytes from address (no R/W bit)
120 Kevin 76
void I2C_Master_Recv(unsigned char address, unsigned char length) {
119 Kevin 77
    if (length == 0)
78
        return;
79
 
80
    // Save length and address to get data from
128 Kevin 81
    i2c_data_p->buffer_in_len = length;
82
    i2c_data_p->master_dest_addr = address;
83
    i2c_data_p->buffer_in_read_ind = 0;
84
    i2c_data_p->buffer_in_write_ind = 0;
119 Kevin 85
 
86
    // Change status to 'next' operation
128 Kevin 87
    i2c_data_p->operating_state = I2C_SEND_ADDR;
88
    i2c_data_p->master_status = I2C_MASTER_RECV;
119 Kevin 89
 
90
    // Generate start condition
91
    SSPCON2bits.SEN = 1;
92
}
93
 
120 Kevin 94
// Writes msg to address then reads length number of bytes from address
95
void I2C_Master_Restart(unsigned char address, unsigned char msg, unsigned char length) {
96
    unsigned char c;
97
    if (length == 0) {
98
        c = msg;
99
        I2C_Master_Send(address, 1, &c);
100
        return;
101
    }
102
 
103
    // Save length and address to get data from
128 Kevin 104
    i2c_data_p->buffer_in[0] = msg;
105
    i2c_data_p->buffer_in_len = length;
106
    i2c_data_p->master_dest_addr = address;
107
    i2c_data_p->buffer_in_read_ind = 0;
108
    i2c_data_p->buffer_in_write_ind = 0;
120 Kevin 109
 
110
    // Change status to 'next' operation
128 Kevin 111
    i2c_data_p->operating_state = I2C_SEND_ADDR;
112
    i2c_data_p->master_status = I2C_MASTER_RESTART;
120 Kevin 113
 
114
    // Generate start condition
115
    SSPCON2bits.SEN = 1;
116
}
117
 
119 Kevin 118
// Setup the PIC to operate as a slave. The address must not include the R/W bit
120 Kevin 119
void I2C_Configure_Slave(unsigned char addr) {
128 Kevin 120
    i2c_data_p->operating_mode = I2C_MODE_SLAVE;
120 Kevin 121
 
119 Kevin 122
    // Ensure the two lines are set for input (we are a slave)
129 Kevin 123
    I2C_CLK_TRIS = 1;
124
    I2C_DAT_TRIS = 1;
119 Kevin 125
 
126
    SSPADD = addr << 1;     // Set the slave address
127
 
128
    SSPSTAT = 0x0;
129
    SSPCON1 = 0x0;
130
    SSPCON2 = 0x0;
131
    SSPCON1bits.SSPM = 0xE; // Enable Slave 7-bit w/ start/stop interrupts
132
    SSPSTATbits.SMP = 1;    // Slew Off
133
    SSPCON2bits.SEN = 1;    // Enable clock-stretching
134
    SSPCON1bits.SSPEN = 1;  // Enable MSSP Module
135
}
136
 
120 Kevin 137
void I2C_Interrupt_Handler() {
119 Kevin 138
    // Call interrupt depending on which mode we are operating in
128 Kevin 139
    if (i2c_data_p->operating_mode == I2C_MODE_MASTER) {
120 Kevin 140
        I2C_Interrupt_Master();
128 Kevin 141
    } else if (i2c_data_p->operating_mode == I2C_MODE_SLAVE) {
120 Kevin 142
        I2C_Interrupt_Slave();
119 Kevin 143
    }
144
}
145
 
146
// An internal subroutine used in the master version of the i2c_interrupt_handler
120 Kevin 147
void I2C_Interrupt_Master() {
119 Kevin 148
    // If we are in the middle of sending data
128 Kevin 149
    if (i2c_data_p->master_status == I2C_MASTER_SEND) {
150
        switch (i2c_data_p->operating_state) {
119 Kevin 151
            case I2C_IDLE:
152
                break;
153
            case I2C_SEND_ADDR:
154
                // Send the address with read bit set
128 Kevin 155
                i2c_data_p->operating_state = I2C_CHECK_ACK_SEND;
156
                SSPBUF = (i2c_data_p->master_dest_addr << 1) | 0x0;
119 Kevin 157
                break;
120 Kevin 158
            case I2C_CHECK_ACK_SEND:
119 Kevin 159
                // Check if ACK is received or not
160
                if (!SSPCON2bits.ACKSTAT) {
161
                    // If an ACK is received, send next byte of data
128 Kevin 162
                    if (i2c_data_p->buffer_in_read_ind < i2c_data_p->buffer_in_len) {
163
                        SSPBUF = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
164
                        i2c_data_p->buffer_in_read_ind++;
119 Kevin 165
                    } else {
166
                        // If no more data is to be sent, send stop bit
128 Kevin 167
                        i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 168
                        SSPCON2bits.PEN = 1;
128 Kevin 169
                        i2c_data_p->master_status = I2C_MASTER_IDLE;
170
                        i2c_data_p->return_status = I2C_SEND_OK;
119 Kevin 171
                    }
172
                } else {
173
                    // If a NACK is received, stop transmission and send error
128 Kevin 174
                    i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 175
                    SSPCON2bits.PEN = 1;
128 Kevin 176
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
177
                    i2c_data_p->return_status = I2C_SEND_FAIL;
119 Kevin 178
                }
179
                break;
180
        }
181
    // If we are in the middle of receiving data
128 Kevin 182
    } else if (i2c_data_p->master_status == I2C_MASTER_RECV) {
183
        switch (i2c_data_p->operating_state) {
119 Kevin 184
            case I2C_IDLE:
185
                break;
186
            case I2C_SEND_ADDR:
187
                // Send address with write bit set
128 Kevin 188
                i2c_data_p->operating_state = I2C_CHECK_ACK_RECV;
189
                SSPBUF = (i2c_data_p->master_dest_addr << 1) | 0x1;
119 Kevin 190
                break;
120 Kevin 191
            case I2C_CHECK_ACK_RECV:
119 Kevin 192
                // Check if ACK is received
193
                if (!SSPCON2bits.ACKSTAT) {
194
                    // If an ACK is received, set module to receive 1 byte of data
128 Kevin 195
                    i2c_data_p->operating_state = I2C_RCV_DATA;
119 Kevin 196
                    SSPCON2bits.RCEN = 1;
197
                } else {
198
                    // If a NACK is received, stop transmission and send error
128 Kevin 199
                    i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 200
                    SSPCON2bits.PEN = 1;
128 Kevin 201
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
202
                    i2c_data_p->return_status = I2C_RECV_FAIL;
119 Kevin 203
                }
204
                break;
205
            case I2C_RCV_DATA:
206
                // On receive, save byte into buffer
121 Kevin 207
                // TODO: handle i2c buffer overflow
128 Kevin 208
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = SSPBUF;
209
                i2c_data_p->buffer_in_write_ind++;
210
                if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
119 Kevin 211
                    // If we still need to read, send an ACK to the slave
128 Kevin 212
                    i2c_data_p->operating_state = I2C_REQ_DATA;
119 Kevin 213
                    SSPCON2bits.ACKDT = 0;  // ACK
214
                    SSPCON2bits.ACKEN = 1;
215
                } else {
216
                    // If we are done reading, send an NACK to the slave
128 Kevin 217
                    i2c_data_p->operating_state = I2C_SEND_STOP;
119 Kevin 218
                    SSPCON2bits.ACKDT = 1;  // NACK
219
                    SSPCON2bits.ACKEN = 1;
220
                }
221
                break;
222
            case I2C_REQ_DATA:
223
                // Set module to receive one byte of data
128 Kevin 224
                i2c_data_p->operating_state = I2C_RCV_DATA;
119 Kevin 225
                SSPCON2bits.RCEN = 1;
226
                break;
227
            case I2C_SEND_STOP:
228
                // Send the stop bit and copy message to send to Main()
128 Kevin 229
                i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 230
                SSPCON2bits.PEN = 1;
128 Kevin 231
                i2c_data_p->master_status = I2C_MASTER_IDLE;
232
                i2c_data_p->return_status = I2C_RECV_OK;
119 Kevin 233
                break;
234
        }
128 Kevin 235
    } else if (i2c_data_p->master_status == I2C_MASTER_RESTART) {
236
        switch (i2c_data_p->operating_state) {
120 Kevin 237
            case I2C_IDLE:
238
                break;
239
            case I2C_SEND_ADDR:
240
                // Send the address with read bit set
128 Kevin 241
                i2c_data_p->operating_state = I2C_CHECK_ACK_SEND;
242
                SSPBUF = (i2c_data_p->master_dest_addr << 1) | 0x0;
120 Kevin 243
                break;
244
            case I2C_CHECK_ACK_SEND:
245
                // Check if ACK is received or not
246
                if (!SSPCON2bits.ACKSTAT) {
247
                    // If an ACK is received, send first byte of data
128 Kevin 248
                    SSPBUF = i2c_data_p->buffer_in[0];
249
                    i2c_data_p->operating_state = I2C_CHECK_ACK_RESTART;
120 Kevin 250
                } else {
251
                    // If a NACK is received, stop transmission and send error
128 Kevin 252
                    i2c_data_p->operating_state = I2C_IDLE;
120 Kevin 253
                    SSPCON2bits.PEN = 1;
128 Kevin 254
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
255
                    i2c_data_p->return_status = I2C_SEND_FAIL;
120 Kevin 256
                }
257
                break;
258
            case I2C_CHECK_ACK_RESTART:
259
                if (!SSPCON2bits.ACKSTAT) {
260
                    SSPCON2bits.RSEN = 1;
128 Kevin 261
                    i2c_data_p->operating_state = I2C_SEND_ADDR_2;
120 Kevin 262
                } else {
263
                    // If a NACK is received, stop transmission and send error
128 Kevin 264
                    i2c_data_p->operating_state = I2C_IDLE;
120 Kevin 265
                    SSPCON2bits.PEN = 1;
128 Kevin 266
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
267
                    i2c_data_p->return_status = I2C_SEND_FAIL;
120 Kevin 268
                }
269
                break;
270
            case I2C_SEND_ADDR_2:
271
                // Send the address with read bit set
128 Kevin 272
                i2c_data_p->operating_state = I2C_CHECK_ACK_RECV;
273
                SSPBUF = (i2c_data_p->master_dest_addr << 1) | 0x1;
120 Kevin 274
                break;
275
            case I2C_CHECK_ACK_RECV:
276
                // Check if ACK is received
277
                if (!SSPCON2bits.ACKSTAT) {
278
                    // If an ACK is received, set module to receive 1 byte of data
128 Kevin 279
                    i2c_data_p->operating_state = I2C_RCV_DATA;
120 Kevin 280
                    SSPCON2bits.RCEN = 1;
281
                } else {
282
                    // If a NACK is received, stop transmission and send error
128 Kevin 283
                    i2c_data_p->operating_state = I2C_IDLE;
120 Kevin 284
                    SSPCON2bits.PEN = 1;
128 Kevin 285
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
286
                    i2c_data_p->return_status = I2C_RECV_FAIL;
120 Kevin 287
                }
288
                break;
289
            case I2C_RCV_DATA:
290
                // On receive, save byte into buffer
121 Kevin 291
                // TODO: handle i2c buffer overflow
128 Kevin 292
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = SSPBUF;
293
                i2c_data_p->buffer_in_write_ind++;
294
                if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
120 Kevin 295
                    // If we still need to read, send an ACK to the slave
128 Kevin 296
                    i2c_data_p->operating_state = I2C_REQ_DATA;
120 Kevin 297
                    SSPCON2bits.ACKDT = 0;  // ACK
298
                    SSPCON2bits.ACKEN = 1;
299
                } else {
300
                    // If we are done reading, send an NACK to the slave
128 Kevin 301
                    i2c_data_p->operating_state = I2C_SEND_STOP;
120 Kevin 302
                    SSPCON2bits.ACKDT = 1;  // NACK
303
                    SSPCON2bits.ACKEN = 1;
304
                }
305
                break;
306
            case I2C_REQ_DATA:
307
                // Set module to receive one byte of data
128 Kevin 308
                i2c_data_p->operating_state = I2C_RCV_DATA;
120 Kevin 309
                SSPCON2bits.RCEN = 1;
310
                break;
311
            case I2C_SEND_STOP:
312
                // Send the stop bit and copy message to send to Main()
128 Kevin 313
                i2c_data_p->operating_state = I2C_IDLE;
120 Kevin 314
                SSPCON2bits.PEN = 1;
128 Kevin 315
                i2c_data_p->master_status = I2C_MASTER_IDLE;
316
                i2c_data_p->return_status = I2C_RECV_OK;
120 Kevin 317
                break;
119 Kevin 318
        }
319
    }
320
}
321
 
120 Kevin 322
void I2C_Interrupt_Slave() {
323
    unsigned char received_data;
119 Kevin 324
    unsigned char data_read_from_buffer = 0;
325
    unsigned char data_written_to_buffer = 0;
326
    unsigned char overrun_error = 0;
327
 
328
    // Clear SSPOV (overflow bit)
329
    if (SSPCON1bits.SSPOV == 1) {
122 Kevin 330
        DBG_PRINT_I2C("I2C: (ERROR) overflow detected\r\n");
119 Kevin 331
        SSPCON1bits.SSPOV = 0;
332
        // We failed to read the buffer in time, so we know we
333
        //  can't properly receive this message, just put us in the
334
        //  a state where we are looking for a new message
128 Kevin 335
        i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 336
        overrun_error = 1;
128 Kevin 337
        i2c_data_p->return_status = I2C_ERR_OVERRUN;
119 Kevin 338
    }
339
 
340
    // Read SPPxBUF if it is full
341
    if (SSPSTATbits.BF == 1) {
120 Kevin 342
        received_data = SSPBUF;
122 Kevin 343
//        DBG_PRINT_I2C("I2C: data read from buffer: %x\r\n", SSPBUF);
119 Kevin 344
        data_read_from_buffer = 1;
345
    }
346
 
347
    if (!overrun_error) {
128 Kevin 348
        switch (i2c_data_p->operating_state) {
119 Kevin 349
            case I2C_IDLE:
350
            {
351
                // Ignore anything except a start
352
                if (SSPSTATbits.S == 1) {
128 Kevin 353
                    i2c_data_p->buffer_in_len_tmp = 0;
354
                    i2c_data_p->operating_state = I2C_STARTED;
120 Kevin 355
//                    if (data_read_from_buffer) {
356
//                        if (SSPSTATbits.D_A == 1) {
121 Kevin 357
//                            DBG_PRINT_I2C("I2C Start: (ERROR) no address recieved\r\n");
120 Kevin 358
//                            // This is bad because we got data and we wanted an address
128 Kevin 359
//                            i2c_data_p->operating_state = I2C_IDLE;
360
//                            i2c_data_p->return_status = I2C_ERR_NOADDR;
120 Kevin 361
//                        } else {
362
//                            // Determine if we are sending or receiving data
363
//                            if (SSPSTATbits.R_W == 1) {
128 Kevin 364
//                                i2c_data_p->operating_state = I2C_SEND_DATA;
120 Kevin 365
//                            } else {
128 Kevin 366
//                                i2c_data_p->operating_state = I2C_RCV_DATA;
120 Kevin 367
//                            }
368
//                        }
369
//                    } else {
128 Kevin 370
//                        i2c_data_p->operating_state = I2C_STARTED;
120 Kevin 371
//                    }
119 Kevin 372
                }
373
                break;
374
            }
375
            case I2C_STARTED:
376
            {
377
                // In this case, we expect either an address or a stop bit
378
                if (SSPSTATbits.P == 1) {
379
                    // Return to idle mode
128 Kevin 380
                    i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 381
                } else if (data_read_from_buffer) {
382
                    if (SSPSTATbits.D_A == 0) {
120 Kevin 383
                        // Address received
384
                        if (SSPSTATbits.R_W == 0) {
385
                            // Slave write mode
128 Kevin 386
                            i2c_data_p->operating_state = I2C_RCV_DATA;
120 Kevin 387
                        } else {
388
                            // Slave read mode
128 Kevin 389
                            i2c_data_p->operating_state = I2C_SEND_DATA;
120 Kevin 390
                            // Process the first byte immediatly if sending data
391
                            goto send;
119 Kevin 392
                        }
393
                    } else {
121 Kevin 394
                        DBG_PRINT_I2C("I2C: (ERROR) no data recieved\r\n");
128 Kevin 395
                        i2c_data_p->operating_state = I2C_IDLE;
396
                        i2c_data_p->return_status = I2C_ERR_NODATA;
119 Kevin 397
                    }
398
                }
399
                break;
400
            }
120 Kevin 401
            send:
119 Kevin 402
            case I2C_SEND_DATA:
403
            {
128 Kevin 404
                if (!i2c_data_p->slave_sending_data) {
120 Kevin 405
                    // If we are not currently sending data, figure out what to reply with
128 Kevin 406
                    if (I2C_Process_Send(i2c_data_p->slave_in_last_byte)) {
120 Kevin 407
                        // Data exists to be returned, send first byte
128 Kevin 408
                        SSPBUF = i2c_data_p->buffer_out[0];
409
                        i2c_data_p->buffer_out_ind = 1;
410
                        i2c_data_p->slave_sending_data = 1;
119 Kevin 411
                        data_written_to_buffer = 1;
412
                    } else {
120 Kevin 413
                        // Unknown request
128 Kevin 414
                        i2c_data_p->slave_sending_data = 0;
415
                        i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 416
                    }
417
                } else {
120 Kevin 418
                    // Sending remaining data back to master
128 Kevin 419
                    if (i2c_data_p->buffer_out_ind < i2c_data_p->buffer_out_len) {
420
                        SSPBUF = i2c_data_p->buffer_out[i2c_data_p->buffer_out_ind];
421
                        i2c_data_p->buffer_out_ind++;
119 Kevin 422
                        data_written_to_buffer = 1;
423
                    } else {
120 Kevin 424
                        // Nothing left to send
128 Kevin 425
                        i2c_data_p->slave_sending_data = 0;
426
                        i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 427
                    }
428
                }
429
                break;
430
            }
431
            case I2C_RCV_DATA:
432
            {
433
                // We expect either data or a stop bit or a (if a restart, an addr)
434
                if (SSPSTATbits.P == 1) {
120 Kevin 435
                    // Stop bit detected, we need to check to see if we also read data
119 Kevin 436
                    if (data_read_from_buffer) {
437
                        if (SSPSTATbits.D_A == 1) {
120 Kevin 438
                            // Data received with stop bit
121 Kevin 439
                            // TODO: handle i2c buffer overflow
128 Kevin 440
                            i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
441
                            if (i2c_data_p->buffer_in_write_ind == MAXI2CBUF-1) {
442
                                i2c_data_p->buffer_in_write_ind = 0;
120 Kevin 443
                            } else {
128 Kevin 444
                                i2c_data_p->buffer_in_write_ind++;
120 Kevin 445
                            }
128 Kevin 446
                            i2c_data_p->buffer_in_len_tmp++;
120 Kevin 447
                            // Save the last byte received
128 Kevin 448
                            i2c_data_p->slave_in_last_byte = received_data;
449
                            i2c_data_p->return_status = I2C_DATA_AVAL;
119 Kevin 450
                        } else {
121 Kevin 451
                            DBG_PRINT_I2C("I2C: (ERROR) no data recieved\r\n");
128 Kevin 452
                            i2c_data_p->operating_state = I2C_IDLE;
453
                            i2c_data_p->return_status = I2C_ERR_NODATA;
119 Kevin 454
                        }
455
                    }
128 Kevin 456
                    i2c_data_p->buffer_in_len += i2c_data_p->buffer_in_len_tmp;
457
                    i2c_data_p->operating_state = I2C_IDLE;
119 Kevin 458
                } else if (data_read_from_buffer) {
459
                    if (SSPSTATbits.D_A == 1) {
120 Kevin 460
                        // Data received
128 Kevin 461
                        i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
462
                        if (i2c_data_p->buffer_in_write_ind == MAXI2CBUF-1) {
463
                            i2c_data_p->buffer_in_write_ind = 0;
120 Kevin 464
                        } else {
128 Kevin 465
                            i2c_data_p->buffer_in_write_ind++;
120 Kevin 466
                        }
128 Kevin 467
                        i2c_data_p->buffer_in_len_tmp++;
120 Kevin 468
                        // Save the last byte received
128 Kevin 469
                        i2c_data_p->slave_in_last_byte = received_data;
470
                        i2c_data_p->return_status = I2C_DATA_AVAL;
120 Kevin 471
                    } else {
472
                        // Restart bit detected
119 Kevin 473
                        if (SSPSTATbits.R_W == 1) {
128 Kevin 474
                            i2c_data_p->buffer_in_len += i2c_data_p->buffer_in_len_tmp;
475
                            i2c_data_p->operating_state = I2C_SEND_DATA;
120 Kevin 476
                            // Process the first byte immediatly if sending data
477
                            goto send;
478
                        } else {
479
                            // Bad to recv an address again, we aren't ready
121 Kevin 480
                            DBG_PRINT_I2C("I2C: (ERROR) no data recieved\r\n");
128 Kevin 481
                            i2c_data_p->operating_state = I2C_IDLE;
482
                            i2c_data_p->return_status = I2C_ERR_NODATA;
119 Kevin 483
                        }
484
                    }
485
                }
486
                break;
487
            }
488
        }
489
    }
490
 
491
    // Release the clock stretching bit (if we should)
492
    if (data_read_from_buffer || data_written_to_buffer) {
493
        // Release the clock
494
        if (SSPCON1bits.CKP == 0) {
495
            SSPCON1bits.CKP = 1;
496
        }
497
    }
120 Kevin 498
}
119 Kevin 499
 
120 Kevin 500
/* Returns 0 if I2C module is currently busy, otherwise returns status code */
501
unsigned char I2C_Get_Status() {
128 Kevin 502
    if (i2c_data_p->operating_mode == I2C_MODE_MASTER) {
503
        if (i2c_data_p->master_status != I2C_MASTER_IDLE || i2c_data_p->buffer_in_len == 0) {
120 Kevin 504
            return 0;
505
        } else {
128 Kevin 506
            return i2c_data_p->return_status;
120 Kevin 507
        }
128 Kevin 508
    } else if (i2c_data_p->operating_mode = I2C_MODE_SLAVE) {
509
        if (i2c_data_p->operating_state != I2C_IDLE || i2c_data_p->buffer_in_len == 0) {
120 Kevin 510
            return 0;
511
        } else {
128 Kevin 512
            return i2c_data_p->return_status;
120 Kevin 513
        }
119 Kevin 514
    }
120 Kevin 515
}
119 Kevin 516
 
121 Kevin 517
unsigned char I2C_Buffer_Len() {
128 Kevin 518
    return i2c_data_p->buffer_in_len;
121 Kevin 519
}
520
 
120 Kevin 521
/* Returns 0 if I2C module is currently busy, otherwise returns buffer length */
522
unsigned char I2C_Read_Buffer(char *buffer) {
523
    unsigned char i = 0;
128 Kevin 524
    while (i2c_data_p->buffer_in_len != 0) {
525
        buffer[i] = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
120 Kevin 526
        i++;
128 Kevin 527
        if (i2c_data_p->buffer_in_read_ind == MAXI2CBUF-1) {
528
            i2c_data_p->buffer_in_read_ind = 0;
120 Kevin 529
        } else {
128 Kevin 530
            i2c_data_p->buffer_in_read_ind++;
120 Kevin 531
        }
128 Kevin 532
        i2c_data_p->buffer_in_len--;
119 Kevin 533
    }
120 Kevin 534
    return i;
119 Kevin 535
}
536
 
120 Kevin 537
/* Put data to be returned here */
538
unsigned char I2C_Process_Send(unsigned char c) {
539
    unsigned char ret = 0;
540
    switch (c) {
541
        case 0xAA:
128 Kevin 542
            i2c_data_p->buffer_out[0] = 'A';
543
            i2c_data_p->buffer_out_len = 1;
120 Kevin 544
            ret = 1;
545
            break;
546
        case 0xBB:
128 Kevin 547
            i2c_data_p->buffer_out[0] = '1';
548
            i2c_data_p->buffer_out[1] = '2';
549
            i2c_data_p->buffer_out_len = 2;
120 Kevin 550
            ret = 1;
551
            break;
119 Kevin 552
    }
120 Kevin 553
    return ret;
554
}