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