Subversion Repositories Code-Repo

Rev

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

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