1 | /**
|
2 | I2C2 Generated Driver File
|
3 |
|
4 | @Company
|
5 | Microchip Technology Inc.
|
6 |
|
7 | @File Name
|
8 | i2c2_master.c
|
9 |
|
10 | @Summary
|
11 | This is the generated driver implementation file for the I2C2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs
|
12 |
|
13 | @Description
|
14 | This header file provides implementations for driver APIs for I2C2.
|
15 | Generation Information :
|
16 | ac Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.8
|
17 | Device : PIC18F45K42
|
18 | Driver Version : 1.0.2
|
19 | The generated drivers are tested against the following:
|
20 | Compiler : XC8 2.36 and above or later
|
21 | MPLAB : MPLAB X 6.00
|
22 | */
|
23 |
|
24 | /*
|
25 | (c) 2018 Microchip Technology Inc. and its subsidiaries.
|
26 |
|
27 | Subject to your compliance with these terms, you may use Microchip software and any
|
28 | derivatives exclusively with Microchip products. It is your responsibility to comply with third party
|
29 | license terms applicable to your use of third party software (including open source software) that
|
30 | may accompany Microchip software.
|
31 |
|
32 | THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
33 | EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
|
34 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
|
35 | FOR A PARTICULAR PURPOSE.
|
36 |
|
37 | IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
|
38 | INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
|
39 | WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
|
40 | HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
|
41 | THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
|
42 | CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
|
43 | OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
|
44 | SOFTWARE.
|
45 | */
|
46 |
|
47 | #include "i2c2_master.h"
|
48 | #include <xc.h>
|
49 |
|
50 | // I2C2 STATES
|
51 | typedef enum {
|
52 | I2C2_IDLE = 0,
|
53 | I2C2_SEND_ADR_READ,
|
54 | I2C2_SEND_ADR_WRITE,
|
55 | I2C2_TX,
|
56 | I2C2_RX,
|
57 | I2C2_TX_EMPTY,
|
58 | I2C2_RX_EMPTY,
|
59 | I2C2_SEND_RESTART_READ,
|
60 | I2C2_SEND_RESTART_WRITE,
|
61 | I2C2_SEND_RESTART,
|
62 | I2C2_SEND_STOP,
|
63 | I2C2_RX_ACK,
|
64 | I2C2_TX_ACK,
|
65 | I2C2_RX_NACK_STOP,
|
66 | I2C2_RX_NACK_RESTART,
|
67 | I2C2_RESET,
|
68 | I2C2_ADDRESS_NACK,
|
69 | I2C2_BUS_COLLISION,
|
70 | I2C2_BUS_ERROR
|
71 | } i2c2_fsm_states_t;
|
72 |
|
73 | // I2C2 Event callBack List
|
74 | typedef enum {
|
75 | I2C2_DATA_COMPLETE = 0,
|
76 | I2C2_WRITE_COLLISION,
|
77 | I2C2_ADDR_NACK,
|
78 | I2C2_DATA_NACK,
|
79 | I2C2_TIMEOUT,
|
80 | I2C2_NULL
|
81 | } i2c2_callbackIndex_t;
|
82 |
|
83 | // I2C2 Status Structure
|
84 | typedef struct
|
85 | {
|
86 | i2c2_callback_t callbackTable[6];
|
87 | void *callbackPayload[6]; // each callBack can have a payload
|
88 | uint16_t time_out; // I2C2 Timeout Counter between I2C2 Events.
|
89 | uint16_t time_out_value; // Reload value for the timeouts
|
90 | i2c2_address_t address; // The I2C2 Address
|
91 | uint8_t *data_ptr; // pointer to a data buffer
|
92 | size_t data_length; // Bytes in the data buffer
|
93 | i2c2_fsm_states_t state; // Driver State
|
94 | i2c2_error_t error;
|
95 | unsigned addressNackCheck:2;
|
96 | unsigned busy:1;
|
97 | unsigned inUse:1;
|
98 | unsigned bufferFree:1;
|
99 |
|
100 | } i2c2_status_t;
|
101 |
|
102 | static void I2C2_SetCallback(i2c2_callbackIndex_t idx, i2c2_callback_t cb, void *ptr);
|
103 | static void I2C2_Poller(void);
|
104 | static inline void I2C2_ClearInterruptFlags(void);
|
105 | static inline void I2C2_MasterFsm(void);
|
106 |
|
107 | /* I2C2 interfaces */
|
108 | static inline bool I2C2_MasterOpen(void);
|
109 | static inline void I2C2_MasterClose(void);
|
110 | static inline uint8_t I2C2_MasterGetRxData(void);
|
111 | static inline void I2C2_MasterSendTxData(uint8_t data);
|
112 | static inline void I2C2_MasterSetCounter(uint8_t counter);
|
113 | static inline uint8_t I2C2_MasterGetCounter();
|
114 | static inline void I2C2_MasterResetBus(void);
|
115 | static inline void I2C2_MasterEnableRestart(void);
|
116 | static inline void I2C2_MasterDisableRestart(void);
|
117 | static inline void I2C2_MasterStop(void);
|
118 | static inline bool I2C2_MasterIsNack(void);
|
119 | static inline void I2C2_MasterSendAck(void);
|
120 | static inline void I2C2_MasterSendNack(void);
|
121 | static inline void I2C2_MasterClearBusCollision(void);
|
122 | static inline bool I2C2_MasterIsRxBufFull(void);
|
123 | static inline bool I2C2_MasterIsTxBufEmpty(void);
|
124 | static inline bool I2C2_MasterIsStopFlagSet(void);
|
125 | static inline bool I2C2_MasterIsCountFlagSet(void);
|
126 | static inline bool I2C2_MasterIsNackFlagSet(void);
|
127 | static inline void I2C2_MasterClearStopFlag(void);
|
128 | static inline void I2C2_MasterClearCountFlag(void);
|
129 | static inline void I2C2_MasterClearNackFlag(void);
|
130 |
|
131 | /* Interrupt interfaces */
|
132 | static inline void I2C2_MasterEnableIrq(void);
|
133 | static inline bool I2C2_MasterIsIrqEnabled(void);
|
134 | static inline void I2C2_MasterDisableIrq(void);
|
135 | static inline void I2C2_MasterClearIrq(void);
|
136 | static inline void I2C2_MasterWaitForEvent(void);
|
137 |
|
138 | static i2c2_fsm_states_t I2C2_DO_IDLE(void);
|
139 | static i2c2_fsm_states_t I2C2_DO_SEND_ADR_READ(void);
|
140 | static i2c2_fsm_states_t I2C2_DO_SEND_ADR_WRITE(void);
|
141 | static i2c2_fsm_states_t I2C2_DO_TX(void);
|
142 | static i2c2_fsm_states_t I2C2_DO_RX(void);
|
143 | static i2c2_fsm_states_t I2C2_DO_TX_EMPTY(void);
|
144 | static i2c2_fsm_states_t I2C2_DO_RX_EMPTY(void);
|
145 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_READ(void);
|
146 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_WRITE(void);
|
147 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART(void);
|
148 | static i2c2_fsm_states_t I2C2_DO_SEND_STOP(void);
|
149 | static i2c2_fsm_states_t I2C2_DO_RX_ACK(void);
|
150 | static i2c2_fsm_states_t I2C2_DO_TX_ACK(void);
|
151 | static i2c2_fsm_states_t I2C2_DO_RX_NACK_STOP(void);
|
152 | static i2c2_fsm_states_t I2C2_DO_RX_NACK_RESTART(void);
|
153 | static i2c2_fsm_states_t I2C2_DO_RESET(void);
|
154 | static i2c2_fsm_states_t I2C2_DO_ADDRESS_NACK(void);
|
155 | static i2c2_fsm_states_t I2C2_DO_BUS_COLLISION(void);
|
156 | static i2c2_fsm_states_t I2C2_DO_BUS_ERROR(void);
|
157 |
|
158 | typedef i2c2_fsm_states_t (*i2c2FsmHandler)(void);
|
159 | const i2c2FsmHandler i2c2_fsmStateTable[] = {
|
160 | I2C2_DO_IDLE,
|
161 | I2C2_DO_SEND_ADR_READ,
|
162 | I2C2_DO_SEND_ADR_WRITE,
|
163 | I2C2_DO_TX,
|
164 | I2C2_DO_RX,
|
165 | I2C2_DO_TX_EMPTY,
|
166 | I2C2_DO_RX_EMPTY,
|
167 | I2C2_DO_SEND_RESTART_READ,
|
168 | I2C2_DO_SEND_RESTART_WRITE,
|
169 | I2C2_DO_SEND_RESTART,
|
170 | I2C2_DO_SEND_STOP,
|
171 | I2C2_DO_RX_ACK,
|
172 | I2C2_DO_TX_ACK,
|
173 | I2C2_DO_RX_NACK_STOP,
|
174 | I2C2_DO_RX_NACK_RESTART,
|
175 | I2C2_DO_RESET,
|
176 | I2C2_DO_ADDRESS_NACK,
|
177 | I2C2_DO_BUS_COLLISION,
|
178 | I2C2_DO_BUS_ERROR
|
179 | };
|
180 |
|
181 | i2c2_status_t I2C2_Status = {0};
|
182 |
|
183 | void I2C2_Initialize()
|
184 | {
|
185 | //EN disabled; RSEN disabled; S Cleared by hardware after Start; CSTR Enable clocking; MODE 7-bit address;
|
186 | I2C2CON0 = 0x04;
|
187 | //ACKCNT Acknowledge; ACKDT Acknowledge; ACKSTAT ACK received; ACKT 0; RXO 0; TXU 0; CSD Clock Stretching enabled;
|
188 | I2C2CON1 = 0x80;
|
189 | //ACNT disabled; GCEN disabled; FME disabled; ABD disabled; SDAHT 30 ns hold time; BFRET 8 I2C Clock pulses;
|
190 | I2C2CON2 = 0x18;
|
191 | //CLK MFINTOSC;
|
192 | I2C2CLK = 0x03;
|
193 | //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0;
|
194 | I2C2PIR = 0x00;
|
195 | //CNTIE disabled; ACKTIE disabled; WRIE disabled; ADRIE disabled; PCIE disabled; RSCIE disabled; SCIE disabled;
|
196 | I2C2PIE = 0x00;
|
197 | //BTOIF No bus timout; BCLIF No bus collision detected; NACKIF No NACK/Error detected; BTOIE disabled; BCLIE disabled; NACKIE disabled;
|
198 | I2C2ERR = 0x00;
|
199 | //Count register
|
200 | I2C2CNT = 0xFF;
|
201 | return;
|
202 | }
|
203 |
|
204 | i2c2_error_t I2C2_Open(i2c2_address_t address)
|
205 | {
|
206 | i2c2_error_t returnValue = I2C2_BUSY;
|
207 |
|
208 | if(!I2C2_Status.inUse)
|
209 | {
|
210 | I2C2_Status.address = address;
|
211 | I2C2_Status.busy = 0;
|
212 | I2C2_Status.inUse = 1;
|
213 | I2C2_Status.addressNackCheck = 0;
|
214 | I2C2_Status.state = I2C2_RESET;
|
215 | I2C2_Status.time_out_value = 500; // MCC should determine a reasonable starting value here.
|
216 | I2C2_Status.bufferFree = 1;
|
217 |
|
218 | // set all the call backs to a default of sending stop
|
219 | I2C2_Status.callbackTable[I2C2_DATA_COMPLETE]=I2C2_CallbackReturnStop;
|
220 | I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE] = NULL;
|
221 | I2C2_Status.callbackTable[I2C2_WRITE_COLLISION]=I2C2_CallbackReturnStop;
|
222 | I2C2_Status.callbackPayload[I2C2_WRITE_COLLISION] = NULL;
|
223 | I2C2_Status.callbackTable[I2C2_ADDR_NACK]=I2C2_CallbackReturnStop;
|
224 | I2C2_Status.callbackPayload[I2C2_ADDR_NACK] = NULL;
|
225 | I2C2_Status.callbackTable[I2C2_DATA_NACK]=I2C2_CallbackReturnStop;
|
226 | I2C2_Status.callbackPayload[I2C2_DATA_NACK] = NULL;
|
227 | I2C2_Status.callbackTable[I2C2_TIMEOUT]=I2C2_CallbackReturnReset;
|
228 | I2C2_Status.callbackPayload[I2C2_TIMEOUT] = NULL;
|
229 |
|
230 | I2C2_MasterClearIrq();
|
231 | I2C2_MasterOpen();
|
232 | returnValue = I2C2_NOERR;
|
233 | }
|
234 | return returnValue;
|
235 | }
|
236 |
|
237 | i2c2_error_t I2C2_Close(void)
|
238 | {
|
239 | i2c2_error_t returnValue = I2C2_BUSY;
|
240 | if(!I2C2_Status.busy)
|
241 | {
|
242 | I2C2_Status.inUse = 0;
|
243 | I2C2_Status.address = 0xff;
|
244 | I2C2_MasterClearIrq();
|
245 | I2C2_MasterDisableIrq();
|
246 | I2C2_MasterClose();
|
247 | returnValue = I2C2_Status.error;
|
248 | }
|
249 | return returnValue;
|
250 | }
|
251 |
|
252 | i2c2_error_t I2C2_MasterOperation(bool read)
|
253 | {
|
254 | i2c2_error_t returnValue = I2C2_BUSY;
|
255 | if(!I2C2_Status.busy)
|
256 | {
|
257 | I2C2_Status.busy = true;
|
258 | returnValue = I2C2_NOERR;
|
259 | I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length);
|
260 |
|
261 | if(read)
|
262 | {
|
263 | I2C2_Status.state = I2C2_RX;
|
264 | I2C2_DO_SEND_ADR_READ();
|
265 | }
|
266 | else
|
267 | {
|
268 | I2C2_Status.state = I2C2_TX;
|
269 | I2C2_DO_SEND_ADR_WRITE();
|
270 | }
|
271 | I2C2_Poller();
|
272 | }
|
273 | return returnValue;
|
274 | }
|
275 |
|
276 | i2c2_error_t I2C2_MasterRead(void)
|
277 | {
|
278 | return I2C2_MasterOperation(true);
|
279 | }
|
280 |
|
281 | i2c2_error_t I2C2_MasterWrite(void)
|
282 | {
|
283 | return I2C2_MasterOperation(false);
|
284 | }
|
285 |
|
286 | void I2C2_SetTimeOut(uint8_t timeOutValue)
|
287 | {
|
288 | I2C2_MasterDisableIrq();
|
289 | I2C2_Status.time_out_value = timeOutValue;
|
290 | I2C2_MasterEnableIrq();
|
291 | }
|
292 |
|
293 | void I2C2_SetBuffer(void *buffer, size_t bufferSize)
|
294 | {
|
295 | if(I2C2_Status.bufferFree)
|
296 | {
|
297 | I2C2_Status.data_ptr = buffer;
|
298 | I2C2_Status.data_length = bufferSize;
|
299 | I2C2_Status.bufferFree = false;
|
300 | }
|
301 | }
|
302 |
|
303 | void I2C2_SetDataCompleteCallback(i2c2_callback_t cb, void *ptr)
|
304 | {
|
305 | I2C2_SetCallback(I2C2_DATA_COMPLETE, cb, ptr);
|
306 | }
|
307 |
|
308 | void I2C2_SetWriteCollisionCallback(i2c2_callback_t cb, void *ptr)
|
309 | {
|
310 | I2C2_SetCallback(I2C2_WRITE_COLLISION, cb, ptr);
|
311 | }
|
312 |
|
313 | void I2C2_SetAddressNackCallback(i2c2_callback_t cb, void *ptr)
|
314 | {
|
315 | I2C2_SetCallback(I2C2_ADDR_NACK, cb, ptr);
|
316 | }
|
317 |
|
318 | void I2C2_SetDataNackCallback(i2c2_callback_t cb, void *ptr)
|
319 | {
|
320 | I2C2_SetCallback(I2C2_DATA_NACK, cb, ptr);
|
321 | }
|
322 |
|
323 | void I2C2_SetTimeoutCallback(i2c2_callback_t cb, void *ptr)
|
324 | {
|
325 | I2C2_SetCallback(I2C2_TIMEOUT, cb, ptr);
|
326 | }
|
327 |
|
328 | static void I2C2_SetCallback(i2c2_callbackIndex_t idx, i2c2_callback_t cb, void *ptr)
|
329 | {
|
330 | if(cb)
|
331 | {
|
332 | I2C2_Status.callbackTable[idx] = cb;
|
333 | I2C2_Status.callbackPayload[idx] = ptr;
|
334 | }
|
335 | else
|
336 | {
|
337 | I2C2_Status.callbackTable[idx] = I2C2_CallbackReturnStop;
|
338 | I2C2_Status.callbackPayload[idx] = NULL;
|
339 | }
|
340 | }
|
341 |
|
342 | static void I2C2_Poller(void)
|
343 | {
|
344 | while(I2C2_Status.busy)
|
345 | {
|
346 | I2C2_MasterWaitForEvent();
|
347 | I2C2_MasterFsm();
|
348 | }
|
349 | }
|
350 |
|
351 | static inline void I2C2_MasterFsm(void)
|
352 | {
|
353 | I2C2_ClearInterruptFlags();
|
354 |
|
355 | if(I2C2_Status.addressNackCheck && I2C2_MasterIsNack())
|
356 | {
|
357 | I2C2_Status.state = I2C2_ADDRESS_NACK;
|
358 | }
|
359 | I2C2_Status.state = i2c2_fsmStateTable[I2C2_Status.state]();
|
360 | }
|
361 |
|
362 | static inline void I2C2_ClearInterruptFlags(void)
|
363 | {
|
364 | if(I2C2_MasterIsCountFlagSet())
|
365 | {
|
366 | I2C2_MasterClearCountFlag();
|
367 | }
|
368 | else if(I2C2_MasterIsStopFlagSet())
|
369 | {
|
370 | I2C2_MasterClearStopFlag();
|
371 | }
|
372 | else if(I2C2_MasterIsNackFlagSet())
|
373 | {
|
374 | I2C2_MasterClearNackFlag();
|
375 | }
|
376 | }
|
377 |
|
378 | static i2c2_fsm_states_t I2C2_DO_IDLE(void)
|
379 | {
|
380 | I2C2_Status.busy = false;
|
381 | I2C2_Status.error = I2C2_NOERR;
|
382 | return I2C2_RESET;
|
383 | }
|
384 |
|
385 | static i2c2_fsm_states_t I2C2_DO_SEND_ADR_READ(void)
|
386 | {
|
387 | I2C2_Status.addressNackCheck = 2;
|
388 | if(I2C2_Status.data_length == 1)
|
389 | {
|
390 | I2C2_DO_RX_EMPTY();
|
391 | }
|
392 | I2C2_MasterSendTxData((uint8_t) (I2C2_Status.address << 1 | 1));
|
393 | return I2C2_RX;
|
394 | }
|
395 |
|
396 | static i2c2_fsm_states_t I2C2_DO_SEND_ADR_WRITE(void)
|
397 | {
|
398 | I2C2_Status.addressNackCheck = 2;
|
399 | I2C2_MasterSendTxData((uint8_t) (I2C2_Status.address << 1));
|
400 | return I2C2_TX;
|
401 | }
|
402 |
|
403 | static i2c2_fsm_states_t I2C2_DO_TX(void)
|
404 | {
|
405 | if(I2C2_MasterIsNack())
|
406 | {
|
407 | switch(I2C2_Status.callbackTable[I2C2_DATA_NACK](I2C2_Status.callbackPayload[I2C2_DATA_NACK]))
|
408 | {
|
409 | case I2C2_RESTART_READ:
|
410 | return I2C2_DO_SEND_RESTART_READ();
|
411 | case I2C2_RESTART_WRITE:
|
412 | return I2C2_DO_SEND_RESTART_WRITE();
|
413 | default:
|
414 | case I2C2_CONTINUE:
|
415 | case I2C2_STOP:
|
416 | return I2C2_IDLE;
|
417 | }
|
418 | }
|
419 | else if(I2C2_MasterIsTxBufEmpty())
|
420 | {
|
421 | if(I2C2_Status.addressNackCheck)
|
422 | {
|
423 | I2C2_Status.addressNackCheck--;
|
424 | }
|
425 | uint8_t dataTx = *I2C2_Status.data_ptr++;
|
426 | i2c2_fsm_states_t retFsmState = (--I2C2_Status.data_length)?I2C2_TX:I2C2_DO_TX_EMPTY();
|
427 | I2C2_MasterSendTxData(dataTx);
|
428 | return retFsmState;
|
429 | }
|
430 | else
|
431 | {
|
432 | return I2C2_TX;
|
433 | }
|
434 | }
|
435 |
|
436 | static i2c2_fsm_states_t I2C2_DO_RX(void)
|
437 | {
|
438 | if(!I2C2_MasterIsRxBufFull())
|
439 | {
|
440 | return I2C2_RX;
|
441 | }
|
442 | if(I2C2_Status.addressNackCheck)
|
443 | {
|
444 | I2C2_Status.addressNackCheck--;
|
445 | }
|
446 |
|
447 | if(--I2C2_Status.data_length)
|
448 | {
|
449 | *I2C2_Status.data_ptr++ = I2C2_MasterGetRxData();
|
450 | return I2C2_RX;
|
451 | }
|
452 | else
|
453 | {
|
454 | i2c2_fsm_states_t retFsmState = I2C2_DO_RX_EMPTY();
|
455 | *I2C2_Status.data_ptr++ = I2C2_MasterGetRxData();
|
456 | return retFsmState;
|
457 | }
|
458 | }
|
459 |
|
460 | static i2c2_fsm_states_t I2C2_DO_TX_EMPTY(void)
|
461 | {
|
462 | I2C2_Status.bufferFree = true;
|
463 | switch(I2C2_Status.callbackTable[I2C2_DATA_COMPLETE](I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE]))
|
464 | {
|
465 | case I2C2_RESTART_READ:
|
466 | I2C2_MasterEnableRestart();
|
467 | return I2C2_SEND_RESTART_READ;
|
468 | case I2C2_CONTINUE:
|
469 | // Avoid the counter stop condition , Counter is incremented by 1
|
470 | I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length + 1);
|
471 | return I2C2_TX;
|
472 | default:
|
473 | case I2C2_STOP:
|
474 | I2C2_MasterDisableRestart();
|
475 | return I2C2_SEND_STOP;
|
476 | }
|
477 | }
|
478 |
|
479 | static i2c2_fsm_states_t I2C2_DO_RX_EMPTY(void)
|
480 | {
|
481 | I2C2_Status.bufferFree = true;
|
482 | switch(I2C2_Status.callbackTable[I2C2_DATA_COMPLETE](I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE]))
|
483 | {
|
484 | case I2C2_RESTART_WRITE:
|
485 | I2C2_MasterEnableRestart();
|
486 | return I2C2_SEND_RESTART_WRITE;
|
487 | case I2C2_RESTART_READ:
|
488 | I2C2_MasterEnableRestart();
|
489 | return I2C2_SEND_RESTART_READ;
|
490 | case I2C2_CONTINUE:
|
491 | // Avoid the counter stop condition , Counter is incremented by 1
|
492 | I2C2_MasterSetCounter((uint8_t) (I2C2_Status.data_length + 1));
|
493 | return I2C2_RX;
|
494 | default:
|
495 | case I2C2_STOP:
|
496 | if(I2C2_Status.state != I2C2_SEND_RESTART_READ)
|
497 | {
|
498 | I2C2_MasterDisableRestart();
|
499 | }
|
500 | return I2C2_RESET;
|
501 | }
|
502 | }
|
503 |
|
504 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_READ(void)
|
505 | {
|
506 | I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length);
|
507 | return I2C2_DO_SEND_ADR_READ();
|
508 | }
|
509 |
|
510 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_WRITE(void)
|
511 | {
|
512 | return I2C2_SEND_ADR_WRITE;
|
513 | }
|
514 |
|
515 |
|
516 | static i2c2_fsm_states_t I2C2_DO_SEND_RESTART(void)
|
517 | {
|
518 | return I2C2_SEND_ADR_READ;
|
519 | }
|
520 |
|
521 | static i2c2_fsm_states_t I2C2_DO_SEND_STOP(void)
|
522 | {
|
523 | I2C2_MasterStop();
|
524 | if(I2C2_MasterGetCounter())
|
525 | {
|
526 | I2C2_MasterSetCounter(0);
|
527 | I2C2_MasterSendTxData(0);
|
528 | }
|
529 | return I2C2_IDLE;
|
530 | }
|
531 |
|
532 | static i2c2_fsm_states_t I2C2_DO_RX_ACK(void)
|
533 | {
|
534 | I2C2_MasterSendAck();
|
535 | return I2C2_RX;
|
536 | }
|
537 |
|
538 | static i2c2_fsm_states_t I2C2_DO_TX_ACK(void)
|
539 | {
|
540 | I2C2_MasterSendAck();
|
541 | return I2C2_TX;
|
542 | }
|
543 |
|
544 | static i2c2_fsm_states_t I2C2_DO_RX_NACK_STOP(void)
|
545 | {
|
546 | I2C2_MasterSendNack();
|
547 | I2C2_MasterStop();
|
548 | return I2C2_DO_IDLE();
|
549 | }
|
550 |
|
551 | static i2c2_fsm_states_t I2C2_DO_RX_NACK_RESTART(void)
|
552 | {
|
553 | I2C2_MasterSendNack();
|
554 | return I2C2_SEND_RESTART;
|
555 | }
|
556 |
|
557 | static i2c2_fsm_states_t I2C2_DO_RESET(void)
|
558 | {
|
559 | I2C2_MasterResetBus();
|
560 | I2C2_Status.busy = false;
|
561 | I2C2_Status.error = I2C2_NOERR;
|
562 | return I2C2_RESET;
|
563 | }
|
564 | static i2c2_fsm_states_t I2C2_DO_ADDRESS_NACK(void)
|
565 | {
|
566 | I2C2_Status.addressNackCheck = 0;
|
567 | I2C2_Status.error = I2C2_FAIL;
|
568 | I2C2_Status.busy = false;
|
569 | switch(I2C2_Status.callbackTable[I2C2_ADDR_NACK](I2C2_Status.callbackPayload[I2C2_ADDR_NACK]))
|
570 | {
|
571 | case I2C2_RESTART_READ:
|
572 | case I2C2_RESTART_WRITE:
|
573 | return I2C2_DO_SEND_RESTART();
|
574 | default:
|
575 | return I2C2_RESET;
|
576 | }
|
577 | }
|
578 |
|
579 | static i2c2_fsm_states_t I2C2_DO_BUS_COLLISION(void)
|
580 | {
|
581 | // Clear bus collision status flag
|
582 | I2C2_MasterClearIrq();
|
583 |
|
584 | I2C2_Status.error = I2C2_FAIL;
|
585 | switch (I2C2_Status.callbackTable[I2C2_WRITE_COLLISION](I2C2_Status.callbackPayload[I2C2_WRITE_COLLISION])) {
|
586 | case I2C2_RESTART_READ:
|
587 | return I2C2_DO_SEND_RESTART_READ();
|
588 | case I2C2_RESTART_WRITE:
|
589 | return I2C2_DO_SEND_RESTART_WRITE();
|
590 | default:
|
591 | return I2C2_DO_RESET();
|
592 | }
|
593 | }
|
594 |
|
595 | static i2c2_fsm_states_t I2C2_DO_BUS_ERROR(void)
|
596 | {
|
597 | I2C2_MasterResetBus();
|
598 | I2C2_Status.busy = false;
|
599 | I2C2_Status.error = I2C2_FAIL;
|
600 | return I2C2_RESET;
|
601 | }
|
602 |
|
603 | void I2C2_BusCollisionIsr(void)
|
604 | {
|
605 | I2C2_MasterClearBusCollision();
|
606 | I2C2_Status.state = I2C2_RESET;
|
607 | }
|
608 |
|
609 | i2c2_operations_t I2C2_CallbackReturnStop(void *funPtr)
|
610 | {
|
611 | return I2C2_STOP;
|
612 | }
|
613 |
|
614 | i2c2_operations_t I2C2_CallbackReturnReset(void *funPtr)
|
615 | {
|
616 | return I2C2_RESET_LINK;
|
617 | }
|
618 |
|
619 | i2c2_operations_t I2C2_CallbackRestartWrite(void *funPtr)
|
620 | {
|
621 | return I2C2_RESTART_WRITE;
|
622 | }
|
623 |
|
624 | i2c2_operations_t I2C2_CallbackRestartRead(void *funPtr)
|
625 | {
|
626 | return I2C2_RESTART_READ;
|
627 | }
|
628 |
|
629 |
|
630 |
|
631 | /* I2C2 Register Level interfaces */
|
632 | static inline bool I2C2_MasterOpen(void)
|
633 | {
|
634 | if(!I2C2CON0bits.EN)
|
635 | {
|
636 | //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0;
|
637 | I2C2PIR = 0x00;
|
638 | //CNTIE disabled; ACKTIE disabled; WRIE disabled; ADRIE disabled; PCIE disabled; RSCIE disabled; SCIE disabled;
|
639 | I2C2PIE = 0x00;
|
640 | //BTOIF No bus timout; BCLIF No bus collision detected; NACKIF No NACK/Error detected; BTOIE disabled; BCLIE disabled; NACKIE disabled;
|
641 | I2C2ERR = 0x00;
|
642 | //Count register
|
643 | I2C2CNT = 0xFF;
|
644 | //Clock PadReg Configuration
|
645 | RB1I2C = 0x51;
|
646 | //Data PadReg Configuration
|
647 | RB2I2C = 0x51;
|
648 | //Enable I2C2
|
649 | I2C2CON0bits.EN = 1;
|
650 | return true;
|
651 | }
|
652 | return false;
|
653 | }
|
654 |
|
655 | static inline void I2C2_MasterClose(void)
|
656 | {
|
657 | //Disable I2C2
|
658 | I2C2CON0bits.EN = 0;
|
659 | //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0;
|
660 | I2C2PIR = 0x00;
|
661 | //Set Clear Buffer Flag
|
662 | I2C2STAT1bits.CLRBF = 1;
|
663 | }
|
664 |
|
665 | static inline uint8_t I2C2_MasterGetRxData(void)
|
666 | {
|
667 | return I2C2RXB;
|
668 | }
|
669 |
|
670 | static inline void I2C2_MasterSendTxData(uint8_t data)
|
671 | {
|
672 | I2C2TXB = data;
|
673 | }
|
674 |
|
675 | static inline uint8_t I2C2_MasterGetCounter()
|
676 | {
|
677 | return I2C2CNT;
|
678 | }
|
679 |
|
680 | static inline void I2C2_MasterSetCounter(uint8_t counter)
|
681 | {
|
682 | I2C2CNT = counter;
|
683 | }
|
684 |
|
685 | static inline void I2C2_MasterResetBus(void)
|
686 | {
|
687 | //Disable I2C2
|
688 | I2C2CON0bits.EN = 0;
|
689 | //Set Clear Buffer Flag
|
690 | I2C2STAT1bits.CLRBF = 1;
|
691 | //Enable I2C2
|
692 | I2C2CON0bits.EN = 1;
|
693 | }
|
694 |
|
695 | static inline void I2C2_MasterEnableRestart(void)
|
696 | {
|
697 | //Enable I2C2 Restart
|
698 | I2C2CON0bits.RSEN = 1;
|
699 | }
|
700 |
|
701 | static inline void I2C2_MasterDisableRestart(void)
|
702 | {
|
703 | //Disable I2C2 Restart
|
704 | I2C2CON0bits.RSEN = 0;
|
705 | }
|
706 |
|
707 | static inline void I2C2_MasterStop(void)
|
708 | {
|
709 | //Clear Start Bit
|
710 | I2C2CON0bits.S = 0;
|
711 | }
|
712 |
|
713 | static inline bool I2C2_MasterIsNack(void)
|
714 | {
|
715 | return I2C2CON1bits.ACKSTAT;
|
716 | }
|
717 |
|
718 | static inline void I2C2_MasterSendAck(void)
|
719 | {
|
720 | I2C2CON1bits.ACKDT = 0;
|
721 | }
|
722 |
|
723 | static inline void I2C2_MasterSendNack(void)
|
724 | {
|
725 | I2C2CON1bits.ACKDT = 1;
|
726 | }
|
727 |
|
728 | static inline void I2C2_MasterClearBusCollision(void)
|
729 | {
|
730 | I2C2ERRbits.BCLIF = 0;
|
731 | I2C2ERRbits.BTOIF = 0;
|
732 | I2C2ERRbits.NACKIF = 0;
|
733 | }
|
734 |
|
735 | static inline bool I2C2_MasterIsRxBufFull(void)
|
736 | {
|
737 | return I2C2STAT1bits.RXBF;
|
738 | }
|
739 |
|
740 | static inline bool I2C2_MasterIsTxBufEmpty(void)
|
741 | {
|
742 | return I2C2STAT1bits.TXBE;
|
743 | }
|
744 |
|
745 | static inline bool I2C2_MasterIsStopFlagSet(void)
|
746 | {
|
747 | return I2C2PIRbits.PCIF;
|
748 | }
|
749 |
|
750 | static inline bool I2C2_MasterIsCountFlagSet(void)
|
751 | {
|
752 | return I2C2PIRbits.CNTIF;
|
753 | }
|
754 |
|
755 | static inline bool I2C2_MasterIsNackFlagSet(void)
|
756 | {
|
757 | return I2C2ERRbits.NACKIF;
|
758 | }
|
759 |
|
760 | static inline void I2C2_MasterClearStopFlag(void)
|
761 | {
|
762 | I2C2PIRbits.PCIF = 0;
|
763 | }
|
764 |
|
765 | static inline void I2C2_MasterClearCountFlag(void)
|
766 | {
|
767 | I2C2PIRbits.CNTIF = 0;
|
768 | }
|
769 |
|
770 | static inline void I2C2_MasterClearNackFlag(void)
|
771 | {
|
772 | I2C2ERRbits.NACKIF = 0;
|
773 | }
|
774 |
|
775 | static inline void I2C2_MasterEnableIrq(void)
|
776 | {
|
777 | PIE6bits.I2C2IE = 1;
|
778 | PIE6bits.I2C2EIE = 1;
|
779 | PIE5bits.I2C2RXIE = 1;
|
780 | PIE5bits.I2C2TXIE = 1;
|
781 |
|
782 | I2C2PIEbits.PCIE = 1;
|
783 | I2C2PIEbits.CNTIE = 1;
|
784 | I2C2ERRbits.NACKIE = 1;
|
785 | }
|
786 |
|
787 | static inline bool I2C2_MasterIsIrqEnabled(void)
|
788 | {
|
789 | return (PIE5bits.I2C2RXIE && PIE5bits.I2C2TXIE && PIE6bits.I2C2IE);
|
790 | }
|
791 |
|
792 | static inline void I2C2_MasterDisableIrq(void)
|
793 | {
|
794 | PIE6bits.I2C2IE = 0;
|
795 | PIE6bits.I2C2EIE = 0;
|
796 | PIE5bits.I2C2RXIE = 0;
|
797 | PIE5bits.I2C2TXIE = 0;
|
798 | I2C2PIEbits.SCIE = 0;
|
799 | I2C2PIEbits.PCIE = 0;
|
800 | I2C2PIEbits.CNTIE = 0;
|
801 | I2C2PIEbits.ACKTIE = 0;
|
802 | I2C2PIEbits.RSCIE = 0;
|
803 | I2C2ERRbits.BCLIE = 0;
|
804 | I2C2ERRbits.BTOIE = 0;
|
805 | I2C2ERRbits.NACKIE = 0;
|
806 | }
|
807 |
|
808 | static inline void I2C2_MasterClearIrq(void)
|
809 | {
|
810 | I2C2PIR = 0x00;
|
811 | }
|
812 |
|
813 | static inline void I2C2_MasterWaitForEvent(void)
|
814 | {
|
815 | while(1)
|
816 | {
|
817 | if(PIR5bits.I2C2TXIF)
|
818 | {
|
819 | break;
|
820 | }
|
821 | if(PIR5bits.I2C2RXIF)
|
822 | {
|
823 | break;
|
824 | }
|
825 | if(I2C2PIRbits.PCIF)
|
826 | {
|
827 | break;
|
828 | }
|
829 | if(I2C2PIRbits.CNTIF)
|
830 | {
|
831 | break;
|
832 | }
|
833 | if(I2C2ERRbits.NACKIF)
|
834 | {
|
835 | break;
|
836 | }
|
837 | }
|
838 | }
|