Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

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