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