Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
281 Kevin 1
#include "defines.h"
2
#include "I2C1.h"
3
 
4
extern I2C1_DATA i2c_data;
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(void) {
9
    i2c_data.buffer_in_len = 0;
10
    i2c_data.buffer_in_read_ind = 0;
11
    i2c_data.buffer_in_write_ind = 0;
12
 
13
    i2c_data.operating_state = I2C_IDLE;
14
    i2c_data.return_status = 0;
15
 
16
    i2c_data.master_dest_addr = 0;
17
    i2c_data.master_status = I2C_MASTER_IDLE;
18
 
19
    // Enable I2C interrupt
20
    PIE1bits.SSP1IE = 1;
21
}
22
 
23
// Setup the PIC to operate as a master.
24
void I2C1_Configure_Master(uint8_t speed) {
25
//    i2c_data.operating_mode = I2C_MODE_MASTER;
26
 
27
    I2C_1_CLK_TRIS = 1;
28
    I2C_1_DAT_TRIS = 1;
29
 
30
    SSP1STAT = 0x0;
31
    SSP1CON1 = 0x0;
32
    SSP1CON2 = 0x0;
33
    SSP1CON3 = 0x0;
34
    SSP1CON1bits.SSPM = 0x8; // I2C Master Mode
35
    if (speed == 0x01) {
36
        SSP1ADD = 0x13;         // Operate at 400KHz (32MHz)
37
        SSP1STATbits.SMP = 1;    // Disable Slew Rate Control
38
    } else if (speed == 0x02) {
39
        SSP1ADD = 0x07;         // Operate at 1Mhz (32Mhz)
40
        SSP1STATbits.SMP = 1;    // Disable Slew Rate Control
41
    } else {
42
        SSP1ADD = 0x4F;         // Operate at 100KHz (32MHz)
43
        SSP1STATbits.SMP = 0;    // Enable Slew Rate Control
44
    }
45
    SSP1CON1bits.SSPEN = 1;  // Enable MSSP1 Module
46
}
47
 
48
// Sends length number of bytes in msg to specified address (no R/W bit)
49
void I2C1_Master_Send(uint8_t address, uint8_t length, uint8_t *msg) {
50
    if (length == 0)
51
        return;
52
 
53
    // Copy message to send into buffer and save length/address
54
    for (uint8_t i = 0; i < length; i++) {
55
        i2c_data.buffer_in[i] = msg[i];
56
    }
57
    i2c_data.buffer_in_len = length;
58
    i2c_data.master_dest_addr = address;
59
    i2c_data.buffer_in_read_ind = 0;
60
    i2c_data.buffer_in_write_ind = 0;
61
 
62
    // Change status to 'next' operation
63
    i2c_data.operating_state = I2C_SEND_ADDR;
64
    i2c_data.master_status = I2C_MASTER_SEND;
65
 
66
    // Generate start condition
67
    SSP1CON2bits.SEN = 1;
68
}
69
 
70
// Reads length number of bytes from address (no R/W bit)
71
void I2C1_Master_Recv(uint8_t address, uint8_t length) {
72
    if (length == 0)
73
        return;
74
 
75
    // Save length and address to get data from
76
    i2c_data.buffer_in_len = length;
77
    i2c_data.master_dest_addr = address;
78
    i2c_data.buffer_in_read_ind = 0;
79
    i2c_data.buffer_in_write_ind = 0;
80
 
81
    // Change status to 'next' operation
82
    i2c_data.operating_state = I2C_SEND_ADDR;
83
    i2c_data.master_status = I2C_MASTER_RECV;
84
 
85
    // Generate start condition
86
    SSP1CON2bits.SEN = 1;
87
}
88
 
89
// Writes msg to address then reads length number of bytes from address
90
void I2C1_Master_Restart(uint8_t address, uint8_t msg, uint8_t length) {
91
    uint8_t c;
92
    if (length == 0) {
93
        c = msg;
94
        I2C1_Master_Send(address, 1, &c);
95
        return;
96
    }
97
 
98
    // Save length and address to get data from
99
    i2c_data.buffer_in[0] = msg;
100
    i2c_data.buffer_in_len = length;
101
    i2c_data.master_dest_addr = address;
102
    i2c_data.buffer_in_read_ind = 0;
103
    i2c_data.buffer_in_write_ind = 0;
104
 
105
    // Change status to 'next' operation
106
    i2c_data.operating_state = I2C_SEND_ADDR;
107
    i2c_data.master_status = I2C_MASTER_RESTART;
108
 
109
    // Generate start condition
110
    SSP1CON2bits.SEN = 1;
111
}
112
 
113
void I2C1_Interrupt_Handler() {
114
    // If we are in the middle of sending data
115
    if (i2c_data.master_status == I2C_MASTER_SEND) {
116
        switch (i2c_data.operating_state) {
117
            case I2C_IDLE:
118
                break;
119
            case I2C_SEND_ADDR:
120
                // Send the address with read bit set
121
                i2c_data.operating_state = I2C_CHECK_ACK_SEND;
122
                SSP1BUF = (i2c_data.master_dest_addr << 1) | 0x0;
123
                break;
124
            case I2C_CHECK_ACK_SEND:
125
                // Check if ACK is received or not
126
                if (!SSP1CON2bits.ACKSTAT) {
127
                    // If an ACK is received, send next byte of data
128
                    if (i2c_data.buffer_in_read_ind < i2c_data.buffer_in_len) {
129
                        SSP1BUF = i2c_data.buffer_in[i2c_data.buffer_in_read_ind];
130
                        i2c_data.buffer_in_read_ind++;
131
                    } else {
132
                        // If no more data is to be sent, send stop bit
133
                        i2c_data.operating_state = I2C_IDLE;
134
                        SSP1CON2bits.PEN = 1;
135
                        i2c_data.master_status = I2C_MASTER_IDLE;
136
                        i2c_data.return_status = I2C_SEND_OK;
137
                    }
138
                } else {
139
                    // If a NACK is received, stop transmission and send error
140
                    i2c_data.operating_state = I2C_IDLE;
141
                    SSP1CON2bits.PEN = 1;
142
                    i2c_data.master_status = I2C_MASTER_IDLE;
143
                    i2c_data.return_status = I2C_SEND_FAIL;
144
                }
145
                break;
146
        }
147
    // If we are in the middle of receiving data
148
    } else if (i2c_data.master_status == I2C_MASTER_RECV) {
149
        switch (i2c_data.operating_state) {
150
            case I2C_IDLE:
151
                break;
152
            case I2C_SEND_ADDR:
153
                // Send address with write bit set
154
                i2c_data.operating_state = I2C_CHECK_ACK_RECV;
155
                uint8_t tmp = (i2c_data.master_dest_addr << 1);
156
                tmp |= 0x01;
157
                SSP1BUF = tmp;
158
                break;
159
            case I2C_CHECK_ACK_RECV:
160
                // Check if ACK is received
161
                if (!SSP1CON2bits.ACKSTAT) {
162
                    // If an ACK is received, set module to receive 1 byte of data
163
                    i2c_data.operating_state = I2C_RCV_DATA;
164
                    SSP1CON2bits.RCEN = 1;
165
                } else {
166
                    // If a NACK is received, stop transmission and send error
167
                    i2c_data.operating_state = I2C_IDLE;
168
                    SSP1CON2bits.PEN = 1;
169
                    i2c_data.master_status = I2C_MASTER_IDLE;
170
                    i2c_data.return_status = I2C_RECV_FAIL;
171
                }
172
                break;
173
            case I2C_RCV_DATA:
174
                // On receive, save byte into buffer
175
                // TODO: Handle I2C buffer overflow
176
                i2c_data.buffer_in[i2c_data.buffer_in_write_ind] = SSP1BUF;
177
                i2c_data.buffer_in_write_ind++;
178
                if (i2c_data.buffer_in_write_ind < i2c_data.buffer_in_len) {
179
                    // If we still need to read, send an ACK to the slave
180
                    i2c_data.operating_state = I2C_REQ_DATA;
181
                    SSP1CON2bits.ACKDT = 0;  // ACK
182
                    SSP1CON2bits.ACKEN = 1;
183
                } else {
184
                    // If we are done reading, send an NACK to the slave
185
                    i2c_data.operating_state = I2C_SEND_STOP;
186
                    SSP1CON2bits.ACKDT = 1;  // NACK
187
                    SSP1CON2bits.ACKEN = 1;
188
                }
189
                break;
190
            case I2C_REQ_DATA:
191
                // Set module to receive one byte of data
192
                i2c_data.operating_state = I2C_RCV_DATA;
193
                SSP1CON2bits.RCEN = 1;
194
                break;
195
            case I2C_SEND_STOP:
196
                // Send the stop bit and copy message to send to Main()
197
                i2c_data.operating_state = I2C_IDLE;
198
                SSP1CON2bits.PEN = 1;
199
                i2c_data.master_status = I2C_MASTER_IDLE;
200
                i2c_data.return_status = I2C_RECV_OK;
201
                break;
202
        }
203
    } else if (i2c_data.master_status == I2C_MASTER_RESTART) {
204
        switch (i2c_data.operating_state) {
205
            case I2C_IDLE:
206
                break;
207
            case I2C_SEND_ADDR:
208
                // Send the address with read bit set
209
                i2c_data.operating_state = I2C_CHECK_ACK_SEND;
210
                SSP1BUF = (i2c_data.master_dest_addr << 1) | 0x0;
211
                break;
212
            case I2C_CHECK_ACK_SEND:
213
                // Check if ACK is received or not
214
                if (!SSP1CON2bits.ACKSTAT) {
215
                    // If an ACK is received, send first byte of data
216
                    SSP1BUF = i2c_data.buffer_in[0];
217
                    i2c_data.operating_state = I2C_CHECK_ACK_RESTART;
218
                } else {
219
                    // If a NACK is received, stop transmission and send error
220
                    i2c_data.operating_state = I2C_IDLE;
221
                    SSP1CON2bits.PEN = 1;
222
                    i2c_data.master_status = I2C_MASTER_IDLE;
223
                    i2c_data.return_status = I2C_SEND_FAIL;
224
                }
225
                break;
226
            case I2C_CHECK_ACK_RESTART:
227
                if (!SSP1CON2bits.ACKSTAT) {
228
                    SSP1CON2bits.RSEN = 1;
229
                    i2c_data.operating_state = I2C_SEND_ADDR_2;
230
                } else {
231
                    // If a NACK is received, stop transmission and send error
232
                    i2c_data.operating_state = I2C_IDLE;
233
                    SSP1CON2bits.PEN = 1;
234
                    i2c_data.master_status = I2C_MASTER_IDLE;
235
                    i2c_data.return_status = I2C_SEND_FAIL;
236
                }
237
                break;
238
            case I2C_SEND_ADDR_2:
239
                // Send the address with read bit set
240
                i2c_data.operating_state = I2C_CHECK_ACK_RECV;
241
                uint8_t tmp = (i2c_data.master_dest_addr << 1);
242
                tmp |= 0x01;
243
                SSP1BUF = tmp;
244
                break;
245
            case I2C_CHECK_ACK_RECV:
246
                // Check if ACK is received
247
                if (!SSP1CON2bits.ACKSTAT) {
248
                    // If an ACK is received, set module to receive 1 byte of data
249
                    i2c_data.operating_state = I2C_RCV_DATA;
250
                    SSP1CON2bits.RCEN = 1;
251
                } else {
252
                    // If a NACK is received, stop transmission and send error
253
                    i2c_data.operating_state = I2C_IDLE;
254
                    SSP1CON2bits.PEN = 1;
255
                    i2c_data.master_status = I2C_MASTER_IDLE;
256
                    i2c_data.return_status = I2C_RECV_FAIL;
257
                }
258
                break;
259
            case I2C_RCV_DATA:
260
                // On receive, save byte into buffer
261
                // TODO: Handle I2C buffer overflow
262
                i2c_data.buffer_in[i2c_data.buffer_in_write_ind] = SSP1BUF;
263
                i2c_data.buffer_in_write_ind++;
264
                if (i2c_data.buffer_in_write_ind < i2c_data.buffer_in_len) {
265
                    // If we still need to read, send an ACK to the slave
266
                    i2c_data.operating_state = I2C_REQ_DATA;
267
                    SSP1CON2bits.ACKDT = 0;  // ACK
268
                    SSP1CON2bits.ACKEN = 1;
269
                } else {
270
                    // If we are done reading, send an NACK to the slave
271
                    i2c_data.operating_state = I2C_SEND_STOP;
272
                    SSP1CON2bits.ACKDT = 1;  // NACK
273
                    SSP1CON2bits.ACKEN = 1;
274
                }
275
                break;
276
            case I2C_REQ_DATA:
277
                // Set module to receive one byte of data
278
                i2c_data.operating_state = I2C_RCV_DATA;
279
                SSP1CON2bits.RCEN = 1;
280
                break;
281
            case I2C_SEND_STOP:
282
                // Send the stop bit
283
                i2c_data.operating_state = I2C_IDLE;
284
                SSP1CON2bits.PEN = 1;
285
                i2c_data.master_status = I2C_MASTER_IDLE;
286
                i2c_data.return_status = I2C_RECV_OK;
287
                break;
288
        }
289
    }
290
}
291
 
292
/* Returns 0 if I2C module is currently busy, otherwise returns status code */
293
uint8_t I2C1_Get_Status() {
294
//    if (i2c_data.operating_mode == I2C_MODE_MASTER) {
295
        if (i2c_data.master_status != I2C_MASTER_IDLE || i2c_data.buffer_in_len == 0) {
296
            return 0;
297
        } else {
298
            return i2c_data.return_status;
299
        }
300
}
301
 
302
uint8_t I2C1_Buffer_Len() {
303
    return i2c_data.buffer_in_len;
304
}
305
 
306
/* Returns 0 if I2C module is currently busy, otherwise returns buffer length */
307
uint8_t I2C1_Read_Buffer(uint8_t *buffer) {
308
    uint8_t i = 0;
309
    while (i2c_data.buffer_in_len != 0) {
310
        buffer[i] = i2c_data.buffer_in[i2c_data.buffer_in_read_ind];
311
        i++;
312
        if (i2c_data.buffer_in_read_ind == MAXI2C1BUF-1) {
313
            i2c_data.buffer_in_read_ind = 0;
314
        } else {
315
            i2c_data.buffer_in_read_ind++;
316
        }
317
        i2c_data.buffer_in_len--;
318
    }
319
    return i;
320
}