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 "I2C1.h"
3
 
4
static I2C1_DATA *i2c_data_p;
273 Kevin 5
extern BTN_STATUS btns;
260 Kevin 6
 
7
// Set up the data structures for the base_I2C.code
8
// Should be called once before any i2c routines are called
9
void I2C1_Init(I2C1_DATA *data) {
10
    i2c_data_p = data;
11
 
12
    i2c_data_p->buffer_in_len = 0;
13
    i2c_data_p->buffer_in_len_tmp = 0;
14
    i2c_data_p->buffer_in_read_ind = 0;
15
    i2c_data_p->buffer_in_write_ind = 0;
16
 
17
    i2c_data_p->buffer_out_ind = 0;
18
    i2c_data_p->buffer_out_len = 0;
19
 
20
    i2c_data_p->operating_mode = 0;
21
    i2c_data_p->operating_state = I2C_IDLE;
22
    i2c_data_p->return_status = 0;
23
 
24
    i2c_data_p->slave_in_last_byte = 0;
25
    i2c_data_p->slave_sending_data = 0;
26
 
27
    i2c_data_p->master_dest_addr = 0;
28
    i2c_data_p->master_status = I2C_MASTER_IDLE;
29
 
30
    // Enable I2C interrupt
31
    PIE1bits.SSP1IE = 1;
32
}
33
 
34
// Setup the PIC to operate as a master.
35
void I2C1_Configure_Master(uint8_t speed) {
36
    i2c_data_p->operating_mode = I2C_MODE_MASTER;
37
 
38
    I2C_1_CLK_TRIS = 1;
39
    I2C_1_DAT_TRIS = 1;
40
 
41
    SSP1STAT = 0x0;
42
    SSP1CON1 = 0x0;
43
    SSP1CON2 = 0x0;
44
    SSP1CON1bits.SSPM = 0x8; // I2C Master Mode
275 Kevin 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
260 Kevin 51
    } else {
275 Kevin 52
        SSP1ADD = 0x4F;         // Operate at 100KHz (32MHz)
53
        SSP1STATbits.SMP = 0;    // Enable Slew Rate Control
260 Kevin 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 length, uint8_t *msg) {
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, 1, &c);
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
    SSP1CON1bits.SSPM = 0xE; // Enable Slave 7-bit w/ start/stop interrupts
138
    SSP1STATbits.SMP = 1;    // Slew Off
139
    SSP1CON2bits.SEN = 1;    // Enable clock-stretching
140
    SSP1CON1bits.SSPEN = 1;  // Enable MSSP1 Module
141
}
142
 
143
void I2C1_Interrupt_Handler() {
144
    // Call interrupt depending on which mode we are operating in
145
    if (i2c_data_p->operating_mode == I2C_MODE_MASTER) {
146
        I2C1_Interrupt_Master();
147
    } else if (i2c_data_p->operating_mode == I2C_MODE_SLAVE) {
148
        I2C1_Interrupt_Slave();
149
    }
150
}
151
 
152
// An internal subroutine used in the master version of the i2c_interrupt_handler
153
void I2C1_Interrupt_Master() {
154
    // If we are in the middle of sending data
155
    if (i2c_data_p->master_status == I2C_MASTER_SEND) {
156
        switch (i2c_data_p->operating_state) {
157
            case I2C_IDLE:
158
                break;
159
            case I2C_SEND_ADDR:
160
                // Send the address with read bit set
161
                i2c_data_p->operating_state = I2C_CHECK_ACK_SEND;
162
                SSP1BUF = (i2c_data_p->master_dest_addr << 1) | 0x0;
163
                break;
164
            case I2C_CHECK_ACK_SEND:
165
                // Check if ACK is received or not
166
                if (!SSP1CON2bits.ACKSTAT) {
167
                    // If an ACK is received, send next byte of data
168
                    if (i2c_data_p->buffer_in_read_ind < i2c_data_p->buffer_in_len) {
169
                        SSP1BUF = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
170
                        i2c_data_p->buffer_in_read_ind++;
171
                    } else {
172
                        // If no more data is to be sent, send stop bit
173
                        i2c_data_p->operating_state = I2C_IDLE;
174
                        SSP1CON2bits.PEN = 1;
175
                        i2c_data_p->master_status = I2C_MASTER_IDLE;
176
                        i2c_data_p->return_status = I2C_SEND_OK;
177
                    }
178
                } else {
179
                    // If a NACK is received, stop transmission and send error
180
                    i2c_data_p->operating_state = I2C_IDLE;
181
                    SSP1CON2bits.PEN = 1;
182
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
183
                    i2c_data_p->return_status = I2C_SEND_FAIL;
184
                }
185
                break;
186
        }
187
    // If we are in the middle of receiving data
188
    } else if (i2c_data_p->master_status == I2C_MASTER_RECV) {
189
        switch (i2c_data_p->operating_state) {
190
            case I2C_IDLE:
191
                break;
192
            case I2C_SEND_ADDR:
193
                // Send address with write bit set
194
                i2c_data_p->operating_state = I2C_CHECK_ACK_RECV;
195
                uint8_t tmp = (i2c_data_p->master_dest_addr << 1);
196
                tmp |= 0x01;
197
                SSP1BUF = tmp;
198
                break;
199
            case I2C_CHECK_ACK_RECV:
200
                // Check if ACK is received
201
                if (!SSP1CON2bits.ACKSTAT) {
202
                    // If an ACK is received, set module to receive 1 byte of data
203
                    i2c_data_p->operating_state = I2C_RCV_DATA;
204
                    SSP1CON2bits.RCEN = 1;
205
                } else {
206
                    // If a NACK is received, stop transmission and send error
207
                    i2c_data_p->operating_state = I2C_IDLE;
208
                    SSP1CON2bits.PEN = 1;
209
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
210
                    i2c_data_p->return_status = I2C_RECV_FAIL;
211
                }
212
                break;
213
            case I2C_RCV_DATA:
214
                // On receive, save byte into buffer
215
                // TODO: Handle I2C buffer overflow
216
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = SSP1BUF;
217
                i2c_data_p->buffer_in_write_ind++;
218
                if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
219
                    // If we still need to read, send an ACK to the slave
220
                    i2c_data_p->operating_state = I2C_REQ_DATA;
221
                    SSP1CON2bits.ACKDT = 0;  // ACK
222
                    SSP1CON2bits.ACKEN = 1;
223
                } else {
224
                    // If we are done reading, send an NACK to the slave
225
                    i2c_data_p->operating_state = I2C_SEND_STOP;
226
                    SSP1CON2bits.ACKDT = 1;  // NACK
227
                    SSP1CON2bits.ACKEN = 1;
228
                }
229
                break;
230
            case I2C_REQ_DATA:
231
                // Set module to receive one byte of data
232
                i2c_data_p->operating_state = I2C_RCV_DATA;
233
                SSP1CON2bits.RCEN = 1;
234
                break;
235
            case I2C_SEND_STOP:
236
                // Send the stop bit and copy message to send to Main()
237
                i2c_data_p->operating_state = I2C_IDLE;
238
                SSP1CON2bits.PEN = 1;
239
                i2c_data_p->master_status = I2C_MASTER_IDLE;
240
                i2c_data_p->return_status = I2C_RECV_OK;
241
                break;
242
        }
243
    } else if (i2c_data_p->master_status == I2C_MASTER_RESTART) {
244
        switch (i2c_data_p->operating_state) {
245
            case I2C_IDLE:
246
                break;
247
            case I2C_SEND_ADDR:
248
                // Send the address with read bit set
249
                i2c_data_p->operating_state = I2C_CHECK_ACK_SEND;
250
                SSP1BUF = (i2c_data_p->master_dest_addr << 1) | 0x0;
251
                break;
252
            case I2C_CHECK_ACK_SEND:
253
                // Check if ACK is received or not
254
                if (!SSP1CON2bits.ACKSTAT) {
255
                    // If an ACK is received, send first byte of data
256
                    SSP1BUF = i2c_data_p->buffer_in[0];
257
                    i2c_data_p->operating_state = I2C_CHECK_ACK_RESTART;
258
                } else {
259
                    // If a NACK is received, stop transmission and send error
260
                    i2c_data_p->operating_state = I2C_IDLE;
261
                    SSP1CON2bits.PEN = 1;
262
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
263
                    i2c_data_p->return_status = I2C_SEND_FAIL;
264
                }
265
                break;
266
            case I2C_CHECK_ACK_RESTART:
267
                if (!SSP1CON2bits.ACKSTAT) {
268
                    SSP1CON2bits.RSEN = 1;
269
                    i2c_data_p->operating_state = I2C_SEND_ADDR_2;
270
                } else {
271
                    // If a NACK is received, stop transmission and send error
272
                    i2c_data_p->operating_state = I2C_IDLE;
273
                    SSP1CON2bits.PEN = 1;
274
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
275
                    i2c_data_p->return_status = I2C_SEND_FAIL;
276
                }
277
                break;
278
            case I2C_SEND_ADDR_2:
279
                // Send the address with read bit set
280
                i2c_data_p->operating_state = I2C_CHECK_ACK_RECV;
281
                uint8_t tmp = (i2c_data_p->master_dest_addr << 1);
282
                tmp |= 0x01;
283
                SSP1BUF = tmp;
284
                break;
285
            case I2C_CHECK_ACK_RECV:
286
                // Check if ACK is received
287
                if (!SSP1CON2bits.ACKSTAT) {
288
                    // If an ACK is received, set module to receive 1 byte of data
289
                    i2c_data_p->operating_state = I2C_RCV_DATA;
290
                    SSP1CON2bits.RCEN = 1;
291
                } else {
292
                    // If a NACK is received, stop transmission and send error
293
                    i2c_data_p->operating_state = I2C_IDLE;
294
                    SSP1CON2bits.PEN = 1;
295
                    i2c_data_p->master_status = I2C_MASTER_IDLE;
296
                    i2c_data_p->return_status = I2C_RECV_FAIL;
297
                }
298
                break;
299
            case I2C_RCV_DATA:
300
                // On receive, save byte into buffer
301
                // TODO: Handle I2C buffer overflow
302
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = SSP1BUF;
303
                i2c_data_p->buffer_in_write_ind++;
304
                if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
305
                    // If we still need to read, send an ACK to the slave
306
                    i2c_data_p->operating_state = I2C_REQ_DATA;
307
                    SSP1CON2bits.ACKDT = 0;  // ACK
308
                    SSP1CON2bits.ACKEN = 1;
309
                } else {
310
                    // If we are done reading, send an NACK to the slave
311
                    i2c_data_p->operating_state = I2C_SEND_STOP;
312
                    SSP1CON2bits.ACKDT = 1;  // NACK
313
                    SSP1CON2bits.ACKEN = 1;
314
                }
315
                break;
316
            case I2C_REQ_DATA:
317
                // Set module to receive one byte of data
318
                i2c_data_p->operating_state = I2C_RCV_DATA;
319
                SSP1CON2bits.RCEN = 1;
320
                break;
321
            case I2C_SEND_STOP:
322
                // Send the stop bit
323
                i2c_data_p->operating_state = I2C_IDLE;
324
                SSP1CON2bits.PEN = 1;
325
                i2c_data_p->master_status = I2C_MASTER_IDLE;
326
                i2c_data_p->return_status = I2C_RECV_OK;
327
                break;
328
        }
329
    }
330
}
331
 
332
void I2C1_Interrupt_Slave() {
333
    uint8_t received_data;
334
    uint8_t data_read_from_buffer = 0;
335
    uint8_t data_written_to_buffer = 0;
336
    uint8_t overrun_error = 0;
337
 
338
    // Clear SSPOV (overflow bit)
339
    if (SSP1CON1bits.SSPOV == 1) {
340
        SSP1CON1bits.SSPOV = 0;
341
        // We failed to read the buffer in time, so we know we
342
        //  can't properly receive this message, just put us in the
343
        //  a state where we are looking for a new message
344
        i2c_data_p->operating_state = I2C_IDLE;
345
        overrun_error = 1;
346
        i2c_data_p->return_status = I2C_ERR_OVERRUN;
347
    }
348
 
349
    // Read SPPxBUF if it is full
350
    if (SSP1STATbits.BF == 1) {
351
        received_data = SSP1BUF;
352
//        DBG_PRINT_I2C("I2C: data read from buffer: %x\r\n", SSP1BUF);
353
        data_read_from_buffer = 1;
354
    }
355
 
356
    if (!overrun_error) {
357
        switch (i2c_data_p->operating_state) {
358
            case I2C_IDLE:
359
            {
360
                // Ignore anything except a start
361
                if (SSP1STATbits.S == 1) {
362
                    i2c_data_p->buffer_in_len_tmp = 0;
363
                    i2c_data_p->operating_state = I2C_STARTED;
364
                }
365
                break;
366
            }
367
            case I2C_STARTED:
368
            {
369
                // In this case, we expect either an address or a stop bit
370
                if (SSP1STATbits.P == 1) {
371
                    // Return to idle mode
372
                    i2c_data_p->operating_state = I2C_IDLE;
373
                } else if (data_read_from_buffer) {
374
                    if (SSP1STATbits.D_nA == 0) {
375
                        // Address received
376
                        if (SSP1STATbits.R_nW == 0) {
377
                            // Slave write mode
378
                            i2c_data_p->operating_state = I2C_RCV_DATA;
379
                        } else {
380
                            // Slave read mode
381
                            i2c_data_p->operating_state = I2C_SEND_DATA;
382
                            // Process the first byte immediatly if sending data
383
                            goto send;
384
                        }
385
                    } else {
386
                        i2c_data_p->operating_state = I2C_IDLE;
387
                        i2c_data_p->return_status = I2C_ERR_NODATA;
388
                    }
389
                }
390
                break;
391
            }
392
            send:
393
            case I2C_SEND_DATA:
394
            {
395
                if (!i2c_data_p->slave_sending_data) {
396
                    // If we are not currently sending data, figure out what to reply with
397
                    if (I2C1_Process_Receive(i2c_data_p->slave_in_last_byte)) {
398
                        // Data exists to be returned, send first byte
399
                        SSP1BUF = i2c_data_p->buffer_out[0];
400
                        i2c_data_p->buffer_out_ind = 1;
401
                        i2c_data_p->slave_sending_data = 1;
402
                        data_written_to_buffer = 1;
403
                    } else {
404
                        // Unknown request
405
                        i2c_data_p->slave_sending_data = 0;
406
                        i2c_data_p->operating_state = I2C_IDLE;
407
                    }
408
                } else {
409
                    // Sending remaining data back to master
410
                    if (i2c_data_p->buffer_out_ind < i2c_data_p->buffer_out_len) {
411
                        SSP1BUF = i2c_data_p->buffer_out[i2c_data_p->buffer_out_ind];
412
                        i2c_data_p->buffer_out_ind++;
413
                        data_written_to_buffer = 1;
414
                    } else {
415
                        // Nothing left to send
416
                        i2c_data_p->slave_sending_data = 0;
417
                        i2c_data_p->operating_state = I2C_IDLE;
418
                    }
419
                }
420
                break;
421
            }
422
            case I2C_RCV_DATA:
423
            {
424
                // We expect either data or a stop bit or a (if a restart, an addr)
425
                if (SSP1STATbits.P == 1) {
426
                    // Stop bit detected, we need to check to see if we also read data
427
                    if (data_read_from_buffer) {
428
                        if (SSP1STATbits.D_nA == 1) {
429
                            // Data received with stop bit
430
                            // TODO: Handle I2C buffer overflow
431
                            i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
432
                            if (i2c_data_p->buffer_in_write_ind == MAXI2C1BUF-1) {
433
                                i2c_data_p->buffer_in_write_ind = 0;
434
                            } else {
435
                                i2c_data_p->buffer_in_write_ind++;
436
                            }
437
                            i2c_data_p->buffer_in_len_tmp++;
438
                            // Save the last byte received
439
                            i2c_data_p->slave_in_last_byte = received_data;
440
                            i2c_data_p->return_status = I2C_DATA_AVAL;
441
                        } else {
442
                            i2c_data_p->operating_state = I2C_IDLE;
443
                            i2c_data_p->return_status = I2C_ERR_NODATA;
444
                        }
445
                    }
446
                    i2c_data_p->buffer_in_len += i2c_data_p->buffer_in_len_tmp;
447
                    i2c_data_p->operating_state = I2C_IDLE;
448
                } else if (data_read_from_buffer) {
449
                    if (SSP1STATbits.D_nA == 1) {
450
                        // Data received
451
                        i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
452
                        if (i2c_data_p->buffer_in_write_ind == MAXI2C1BUF-1) {
453
                            i2c_data_p->buffer_in_write_ind = 0;
454
                        } else {
455
                            i2c_data_p->buffer_in_write_ind++;
456
                        }
457
                        i2c_data_p->buffer_in_len_tmp++;
458
                        // Save the last byte received
459
                        i2c_data_p->slave_in_last_byte = received_data;
460
                        i2c_data_p->return_status = I2C_DATA_AVAL;
461
                    } else {
462
                        // Restart bit detected
463
                        if (SSP1STATbits.R_nW == 1) {
464
                            i2c_data_p->buffer_in_len += i2c_data_p->buffer_in_len_tmp;
465
                            i2c_data_p->operating_state = I2C_SEND_DATA;
466
                            // Process the first byte immediatly if sending data
467
                            goto send;
468
                        } else {
469
                            // Bad to recv an address again, we aren't ready
470
                            i2c_data_p->operating_state = I2C_IDLE;
471
                            i2c_data_p->return_status = I2C_ERR_NODATA;
472
                        }
473
                    }
474
                }
475
                break;
476
            }
477
        }
478
    }
479
 
480
    // Release the clock stretching bit (if we should)
481
    if (data_read_from_buffer || data_written_to_buffer) {
482
        // Release the clock
483
        if (SSP1CON1bits.CKP == 0) {
484
            SSP1CON1bits.CKP = 1;
485
        }
486
    }
487
}
488
 
489
/* Returns 0 if I2C module is currently busy, otherwise returns status code */
490
uint8_t I2C1_Get_Status() {
491
    if (i2c_data_p->operating_mode == I2C_MODE_MASTER) {
492
        if (i2c_data_p->master_status != I2C_MASTER_IDLE || i2c_data_p->buffer_in_len == 0) {
493
            return 0;
494
        } else {
495
            return i2c_data_p->return_status;
496
        }
497
    } else {
498
        if (i2c_data_p->operating_state != I2C_IDLE || i2c_data_p->buffer_in_len == 0) {
499
            return 0;
500
        } else {
501
            return i2c_data_p->return_status;
502
        }
503
    }
504
}
505
 
506
uint8_t I2C1_Buffer_Len() {
507
    return i2c_data_p->buffer_in_len;
508
}
509
 
510
/* Returns 0 if I2C module is currently busy, otherwise returns buffer length */
511
uint8_t I2C1_Read_Buffer(uint8_t *buffer) {
512
    uint8_t i = 0;
513
    while (i2c_data_p->buffer_in_len != 0) {
514
        buffer[i] = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
515
        i++;
516
        if (i2c_data_p->buffer_in_read_ind == MAXI2C1BUF-1) {
517
            i2c_data_p->buffer_in_read_ind = 0;
518
        } else {
519
            i2c_data_p->buffer_in_read_ind++;
520
        }
521
        i2c_data_p->buffer_in_len--;
522
    }
523
    return i;
524
}
525
 
526
/* Put data to be returned here */
527
uint8_t I2C1_Process_Receive(uint8_t c) {
528
    uint8_t ret = 0;
529
    switch (c) {
530
        case CMD_QUERY_BTN:
273 Kevin 531
            i2c_data_p->buffer_out[0] = btns.w;
532
            i2c_data_p->buffer_out_len = 1;
533
            ret = 1;
260 Kevin 534
            break;
273 Kevin 535
        default:
536
            break;
260 Kevin 537
    }
273 Kevin 538
 
260 Kevin 539
    return ret;
540
}