Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
234 Kevin 1
#include "defines.h"
2
#include "I2C1.h"
3
 
4
static I2C1_DATA *i2c_data_p;
5
 
6
// Initialize the data structures, should be called once before any I2C routines are called
7
void I2C1_Init(I2C1_DATA *data, uint8_t speed, uint8_t address) {
8
    i2c_data_p = data;
9
 
10
    i2c_data_p->buffer_in_len = 0;
11
    i2c_data_p->buffer_in_read_ind = 0;
12
    i2c_data_p->buffer_in_write_ind = 0;
13
 
14
    i2c_data_p->buffer_out_ind = 0;
15
    i2c_data_p->buffer_out_len = 0;
16
 
17
    i2c_data_p->operating_state = I2C1_IDLE;
18
    i2c_data_p->return_status = 0;
19
 
20
    i2c_data_p->slave_in_last_byte = 0;
21
    i2c_data_p->slave_sending_data = 0;
22
 
23
    i2c_data_p->master_dest_addr = 0;
24
    i2c_data_p->master_status = I2C1_MASTER_IDLE;
25
 
26
    INTDisableInterrupts();
27
 
28
    // Enable the I2C module and set the clock stretch enable bit
29
    // Note: Automatically overrides any other pin settings
30
    I2C1CONSET = 0x00008040;
31
    I2C1ADD = address;
276 Kevin 32
    if (speed == 0x01) {
33
        I2C1BRG = 0x0BE;    // Operate at 200kHZ (80MHz)
34
        I2C1CONbits.DISSLW = 0; // Slew rate control enabled
35
    } else if (speed == 0x02) {
36
        I2C1BRG = 0x05A;    // Operate at 400kHZ (80MHz)
37
        I2C1CONbits.DISSLW = 1; // Slew rate control disabled
38
    } else if (speed == 0x03) {
39
        I2C1BRG = 0x020; // Operate at 1MHz (80MHz)
40
        I2C1CONbits.DISSLW = 1; // Slew rate control disabled
41
    } else {
42
        I2C1BRG = 0x186;    // Operate at 100kHZ (80MHz)
43
        I2C1CONbits.DISSLW = 0; // Slew rate control enabled
44
    }
234 Kevin 45
    IFS0CLR = 0xE0000000;   // Clear any existing events
46
    IPC6CLR = 0x00001F00;   // Reset priority levels
276 Kevin 47
    IPC6SET = 0x00001600;   // Set IPL=6, Subpriority 2
234 Kevin 48
    IEC0SET = 0xE0000000;   // Enable I2C1 interrupts
49
 
50
    INTEnableInterrupts();
51
}
52
 
53
// Sends length number of bytes in msg to specified address (no R/W bit)
235 Kevin 54
// Will return status I2C1_SEND_OK or I2C1_SEND_FAIL
234 Kevin 55
void I2C1_Master_Send(uint8_t address, uint8_t *msg, uint32_t length) {
56
    uint32_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 = I2C1_SEND_ADDR;
71
    i2c_data_p->master_status = I2C1_MASTER_SEND;
72
 
73
    // Generate start condition
74
    I2C1CONbits.SEN = 1;
75
}
76
 
77
// Reads length number of bytes from address (no R/W bit)
235 Kevin 78
// Will return status I2C1_RECV_OK or I2C1_RECV_FAIL
234 Kevin 79
void I2C1_Master_Recv(uint8_t address, uint32_t length) {
80
    if (length == 0)
81
        return;
82
 
83
    // Save length and address to get data from
84
    i2c_data_p->buffer_in_len = length;
85
    i2c_data_p->master_dest_addr = address;
86
    i2c_data_p->buffer_in_read_ind = 0;
87
    i2c_data_p->buffer_in_write_ind = 0;
88
 
89
    // Change status to 'next' operation
90
    i2c_data_p->operating_state = I2C1_SEND_ADDR;
91
    i2c_data_p->master_status = I2C1_MASTER_RECV;
92
 
93
    // Generate start condition
94
    I2C1CONbits.SEN = 1;
95
}
96
 
97
// Writes msg to address then reads length number of bytes from address
235 Kevin 98
// Will return status I2C1_SEND_FAIL or I2C1_RECV_FAIL or I2C1_RECV_OK
234 Kevin 99
void I2C1_Master_Restart(uint8_t address, uint8_t msg, uint32_t length) {
100
    uint8_t c;
101
    if (length == 0) {
102
        c = msg;
103
        I2C1_Master_Send(address, &c, 1);
104
        return;
105
    }
106
 
107
    // Save length and address to get data from
108
    i2c_data_p->buffer_in[0] = msg;
109
    i2c_data_p->buffer_in_len = length;
110
    i2c_data_p->master_dest_addr = address;
111
    i2c_data_p->buffer_in_read_ind = 0;
112
    i2c_data_p->buffer_in_write_ind = 0;
113
 
114
    // Change status to 'next' operation
115
    i2c_data_p->operating_state = I2C1_SEND_ADDR;
116
    i2c_data_p->master_status = I2C1_MASTER_RESTART;
117
 
118
    // Generate start condition
119
    I2C1CONbits.SEN = 1;
120
}
121
 
122
void __ISR(_I2C_1_VECTOR, ipl5) __I2C_1_Interrupt_Handler(void) {
123
    // Bus collision event
124
    if (IFS0bits.I2C1BIF) {
237 Kevin 125
        // TODO: Handle bus collision events here
234 Kevin 126
        IFS0CLR = 0x20000000;
127
    }
128
    // Slave event
129
    if (IFS0bits.I2C1SIF) {
130
        I2C1_Interrupt_Slave();
131
        IFS0CLR = 0x40000000;
132
    }
133
    // Master event
134
    if (IFS0bits.I2C1MIF) {
135
        I2C1_Interrupt_Master();
136
        IFS0CLR = 0x80000000;
137
    }
138
}
139
 
140
// An internal subroutine used in the master version of the i2c_interrupt_handler
141
void I2C1_Interrupt_Master() {
142
 
143
    /* The PIC32 family has different master interrupts than the PIC8 family
144
     * Master mode operations that generate a slave interrupt are:
145
     * 1. Start condition
146
     * 2. Repeated start sequence
147
     * 3. Stop condition
148
     * 4. Data transfer byte received
149
     * 5. During a send ACK or NACK sequence to slave
150
     * 6. Data transfer byte transmitted
151
     * 7. During a slave-detected stop
152
     */
153
 
235 Kevin 154
    if (I2C1STATbits.IWCOL == 1) {
155
        // TODO: Handle write collisions
156
        I2C1STATbits.IWCOL = 0;
157
    }
158
 
234 Kevin 159
    // If we are in the middle of sending data
160
    if (i2c_data_p->master_status == I2C1_MASTER_SEND) {
161
        switch (i2c_data_p->operating_state) {
162
            case I2C1_IDLE:
163
                break;
164
            case I2C1_SEND_ADDR:
165
                // Send the address with read bit set
166
                i2c_data_p->operating_state = I2C1_CHECK_ACK_SEND;
167
                I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x0;
168
                break;
169
            case I2C1_CHECK_ACK_SEND:
170
                // Check if ACK is received or not
171
                if (!I2C1STATbits.ACKSTAT) {
172
                    // If an ACK is received, send next byte of data
173
                    if (i2c_data_p->buffer_in_read_ind < i2c_data_p->buffer_in_len) {
174
                        I2C1TRN = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
175
                        i2c_data_p->buffer_in_read_ind++;
176
                    } else {
177
                        // If no more data is to be sent, send stop bit
235 Kevin 178
                        i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 179
                        I2C1CONbits.PEN = 1;
180
                        i2c_data_p->return_status = I2C1_SEND_OK;
181
                    }
182
                } else {
183
                    // If a NACK is received, stop transmission and send error
235 Kevin 184
                    i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 185
                    I2C1CONbits.PEN = 1;
186
                    i2c_data_p->return_status = I2C1_SEND_FAIL;
187
                }
188
                break;
235 Kevin 189
            case I2C1_STOPPED:
190
                i2c_data_p->operating_state = I2C1_IDLE;
191
                i2c_data_p->master_status = I2C1_MASTER_IDLE;
192
                break;
234 Kevin 193
        }
194
    // If we are in the middle of receiving data
195
    } else if (i2c_data_p->master_status == I2C1_MASTER_RECV) {
196
        switch (i2c_data_p->operating_state) {
197
            case I2C1_IDLE:
198
                break;
199
            case I2C1_SEND_ADDR:
200
                // Send address with write bit set
201
                i2c_data_p->operating_state = I2C1_CHECK_ACK_RECV;
202
                I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x1;
203
                break;
204
            case I2C1_CHECK_ACK_RECV:
205
                // Check if ACK is received
206
                if (!I2C1STATbits.ACKSTAT) {
207
                    // If an ACK is received, set module to receive 1 byte of data
208
                    i2c_data_p->operating_state = I2C1_RCV_DATA;
209
                    I2C1CONbits.RCEN = 1;
210
                } else {
211
                    // If a NACK is received, stop transmission and send error
235 Kevin 212
                    i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 213
                    I2C1CONbits.PEN = 1;
214
                    i2c_data_p->return_status = I2C1_RECV_FAIL;
215
                }
216
                break;
217
            case I2C1_RCV_DATA:
218
                // On receive, save byte into buffer
235 Kevin 219
                // TODO: Handle possible I2C buffer overflow
234 Kevin 220
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = I2C1RCV;
221
                i2c_data_p->buffer_in_write_ind++;
222
                if (i2c_data_p->buffer_in_write_ind < i2c_data_p->buffer_in_len) {
223
                    // If we still need to read, send an ACK to the slave
224
                    i2c_data_p->operating_state = I2C1_REQ_DATA;
225
                    I2C1CONbits.ACKDT = 0;  // ACK
226
                    I2C1CONbits.ACKEN = 1;
227
                } else {
228
                    // If we are done reading, send an NACK to the slave
229
                    i2c_data_p->operating_state = I2C1_SEND_STOP;
230
                    I2C1CONbits.ACKDT = 1;  // NACK
231
                    I2C1CONbits.ACKEN = 1;
232
                }
233
                break;
234
            case I2C1_REQ_DATA:
235
                // Set module to receive one byte of data
236
                i2c_data_p->operating_state = I2C1_RCV_DATA;
237
                I2C1CONbits.RCEN = 1;
238
                break;
239
            case I2C1_SEND_STOP:
235 Kevin 240
                // Send the stop bit
241
                i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 242
                I2C1CONbits.PEN = 1;
243
                i2c_data_p->return_status = I2C1_RECV_OK;
244
                break;
235 Kevin 245
            case I2C1_STOPPED:
246
                i2c_data_p->operating_state = I2C1_IDLE;
247
                i2c_data_p->master_status = I2C1_MASTER_IDLE;
248
                break;
234 Kevin 249
        }
250
    } else if (i2c_data_p->master_status == I2C1_MASTER_RESTART) {
251
        switch (i2c_data_p->operating_state) {
252
            case I2C1_IDLE:
253
                break;
254
            case I2C1_SEND_ADDR:
255
                // Send the address with read bit set
256
                i2c_data_p->operating_state = I2C1_CHECK_ACK_SEND;
257
                I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x0;
258
                break;
259
            case I2C1_CHECK_ACK_SEND:
260
                // Check if ACK is received or not
261
                if (!I2C1STATbits.ACKSTAT) {
262
                    // If an ACK is received, send first byte of data
276 Kevin 263
                    uint8_t to_send = i2c_data_p->buffer_in[0];
264
                    I2C1TRN = to_send;
234 Kevin 265
                    i2c_data_p->operating_state = I2C1_CHECK_ACK_RESTART;
266
                } else {
267
                    // If a NACK is received, stop transmission and send error
235 Kevin 268
                    i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 269
                    I2C1CONbits.PEN = 1;
270
                    i2c_data_p->return_status = I2C1_SEND_FAIL;
271
                }
272
                break;
273
            case I2C1_CHECK_ACK_RESTART:
274
                if (!I2C1STATbits.ACKSTAT) {
275
                    I2C1CONbits.RSEN = 1;
276
                    i2c_data_p->operating_state = I2C1_SEND_ADDR_2;
277
                } else {
278
                    // If a NACK is received, stop transmission and send error
235 Kevin 279
                    i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 280
                    I2C1CONbits.PEN = 1;
281
                    i2c_data_p->return_status = I2C1_SEND_FAIL;
282
                }
283
                break;
284
            case I2C1_SEND_ADDR_2:
285
                // Send the address with read bit set
286
                i2c_data_p->operating_state = I2C1_CHECK_ACK_RECV;
287
                I2C1TRN = (i2c_data_p->master_dest_addr << 1) | 0x1;
288
                break;
289
            case I2C1_CHECK_ACK_RECV:
290
                // Check if ACK is received
291
                if (!I2C1STATbits.ACKSTAT) {
292
                    // If an ACK is received, set module to receive 1 byte of data
293
                    i2c_data_p->operating_state = I2C1_RCV_DATA;
294
                    I2C1CONbits.RCEN = 1;
295
                } else {
296
                    // If a NACK is received, stop transmission and send error
235 Kevin 297
                    i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 298
                    I2C1CONbits.PEN = 1;
299
                    i2c_data_p->return_status = I2C1_RECV_FAIL;
300
                }
301
                break;
302
            case I2C1_RCV_DATA:
303
                // On receive, save byte into buffer
235 Kevin 304
                // TODO: Handle possible I2C buffer overflow
234 Kevin 305
                i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = I2C1RCV;
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 = I2C1_REQ_DATA;
310
                    I2C1CONbits.ACKDT = 0;  // ACK
311
                    I2C1CONbits.ACKEN = 1;
312
                } else {
313
                    // If we are done reading, send an NACK to the slave
314
                    i2c_data_p->operating_state = I2C1_SEND_STOP;
315
                    I2C1CONbits.ACKDT = 1;  // NACK
316
                    I2C1CONbits.ACKEN = 1;
317
                }
318
                break;
319
            case I2C1_REQ_DATA:
320
                // Set module to receive one byte of data
321
                i2c_data_p->operating_state = I2C1_RCV_DATA;
322
                I2C1CONbits.RCEN = 1;
323
                break;
324
            case I2C1_SEND_STOP:
235 Kevin 325
                // Send the stop bit
326
                i2c_data_p->operating_state = I2C1_STOPPED;
234 Kevin 327
                I2C1CONbits.PEN = 1;
328
                i2c_data_p->return_status = I2C1_RECV_OK;
329
                break;
235 Kevin 330
            case I2C1_STOPPED:
331
                i2c_data_p->operating_state = I2C1_IDLE;
332
                i2c_data_p->master_status = I2C1_MASTER_IDLE;
333
                break;
234 Kevin 334
        }
335
    }
336
}
337
 
338
void I2C1_Interrupt_Slave() {
339
    // !!WARNING!! THIS CODE DOES -NOT- HAVE ANY ERROR HANDLING !!
340
    // TODO: Add error handling to this interrupt function
341
 
342
    /* The PIC32 family has different slave interrupts than the PIC8 family
343
     * Slave mode operations that generate a slave interrupt are:
344
     * 1. Detection of a valid device address (including general call)
345
     * 2. Reception of data
346
     * 3. Request to transmit data
347
     */
348
 
349
    uint8_t received_data;
350
    uint8_t data_read_from_buffer = 0;
351
    uint8_t data_written_to_buffer = 0;
352
    uint8_t overrun_error = 0;
353
 
354
    // Clear SSPOV (overflow bit)
355
    if (I2C1STATbits.I2COV == 1) {
356
        I2C1STATbits.I2COV = 0;
357
        overrun_error = 1;
358
        i2c_data_p->return_status = I2C1_ERR_OVERRUN;
359
    }
360
 
361
    // Read SPPxBUF if it is full
362
    if (I2C1STATbits.RBF == 1) {
363
        received_data = I2C1RCV;
364
        data_read_from_buffer = 1;
365
    }
366
 
367
    if (!overrun_error) {
368
        if (I2C1STATbits.R_W == 0) {
369
            // Slave is receiving data
370
            i2c_data_p->buffer_in[i2c_data_p->buffer_in_write_ind] = received_data;
371
            if (i2c_data_p->buffer_in_write_ind == MAXI2C1BUF - 1) {
372
                i2c_data_p->buffer_in_write_ind = 0;
373
            } else {
374
                i2c_data_p->buffer_in_write_ind++;
375
            }
376
            if (i2c_data_p->buffer_in_len < MAXI2C1BUF - 1) {
377
                i2c_data_p->buffer_in_len++;
378
            }
379
            i2c_data_p->slave_in_last_byte = received_data;
380
            i2c_data_p->return_status = I2C1_RECV_OK;
381
        } else {
382
            // Slave is returning data
383
            if (!i2c_data_p->slave_sending_data) {
384
                // If we are not currently sending data, figure out what to reply with
385
                if (I2C1_Process_Request(i2c_data_p->slave_in_last_byte)) {
386
                    // Data exists to be returned, send first byte
387
                    I2C1TRN = i2c_data_p->buffer_out[0];
388
                    data_written_to_buffer = 1;
389
                    i2c_data_p->buffer_out_ind = 1;
390
                    i2c_data_p->slave_sending_data = 1;
391
                } else {
392
                    // Unknown request, fill rest of request with 0s
393
                    I2C1TRN = 0x0;
394
                    data_written_to_buffer = 1;
395
                    i2c_data_p->slave_sending_data = 0;
396
                    i2c_data_p->return_status = I2C1_SEND_FAIL;
397
                }
398
            } else {
399
                // Sending remaining data back to master
400
                if (i2c_data_p->buffer_out_ind < i2c_data_p->buffer_out_len) {
401
                    I2C1TRN = i2c_data_p->buffer_out[i2c_data_p->buffer_out_ind];
402
                    data_written_to_buffer = 1;
403
                    i2c_data_p->buffer_out_ind++;
404
                } else {
405
                    // Nothing left to send, fill rest of request with 0s
406
                    I2C1TRN = 0x0;
407
                    data_written_to_buffer = 1;
408
                    i2c_data_p->slave_sending_data = 0;
409
                    i2c_data_p->return_status = I2C1_SEND_OK;
410
                }
411
            }
412
        }
413
    }
414
 
415
    // Release the clock stretching bit (if we should)
416
    if (data_read_from_buffer || data_written_to_buffer) {
417
        // Release the clock
418
        if (I2C1CONbits.SCLREL == 0) {
419
            I2C1CONbits.SCLREL = 1;
420
        }
421
    }
422
}
423
 
424
/* Returns 0 if I2C module is currently busy, otherwise returns status code */
425
uint8_t I2C1_Get_Status() {
235 Kevin 426
        if (i2c_data_p->master_status == I2C1_MASTER_IDLE &&
427
                i2c_data_p->operating_state == I2C1_IDLE &&
428
                I2C1STATbits.TBF == 0) {
429
            return i2c_data_p->return_status;
430
        } else {
234 Kevin 431
            return 0;
432
        }
433
}
434
 
435
uint8_t I2C1_Buffer_Len() {
436
    return i2c_data_p->buffer_in_len;
437
}
438
 
439
/* Returns 0 if I2C module is currently busy, otherwise returns buffer length */
440
uint8_t I2C1_Read_Buffer(uint8_t *buffer) {
441
    uint32_t i = 0;
442
    while (i2c_data_p->buffer_in_len != 0) {
443
        buffer[i] = i2c_data_p->buffer_in[i2c_data_p->buffer_in_read_ind];
444
        i++;
445
        if (i2c_data_p->buffer_in_read_ind == MAXI2C1BUF-1) {
446
            i2c_data_p->buffer_in_read_ind = 0;
447
        } else {
448
            i2c_data_p->buffer_in_read_ind++;
449
        }
450
        i2c_data_p->buffer_in_len--;
451
    }
452
    return i;
453
}
454
 
455
/* Put data to be returned here */
456
uint8_t I2C1_Process_Request(uint8_t c) {
457
    uint8_t ret = 0;
458
    switch (c) {
459
        case 0x01:
460
            i2c_data_p->buffer_out[0] = 0x12;
461
            i2c_data_p->buffer_out_len = 1;
462
            ret = 1;
463
            break;
464
        case 0x02:
465
            i2c_data_p->buffer_out[0] = 0x34;
466
            i2c_data_p->buffer_out[1] = 0x56;
467
            i2c_data_p->buffer_out_len = 2;
468
            ret = 1;
469
            break;
470
    }
471
    return ret;
472
}