1 | #pragma vector = USI_VECTOR
|
2 | __interrupt void USI_ISR (void)
|
3 | {
|
4 | if (USICTL1 & USISTTIFG)
|
5 | {
|
6 | I2C_State = 2; // Enter 1st state on start
|
7 | }
|
8 |
|
9 | switch (I2C_State)
|
10 | {
|
11 | /* Idle */
|
12 | case 0:
|
13 | break;
|
14 |
|
15 | /* RX address */
|
16 | case 2:
|
17 | USICNT = (USIIFGCC | 0x08); // Stop auto clr USIIFG, read 8 bits
|
18 | USICTL1 &= ~USISTTIFG; // Clear start flag
|
19 | I2C_State = 4; // Next state: check addres
|
20 | break;
|
21 |
|
22 | /* Check address and send (N)ACK */
|
23 | case 4:
|
24 | if (USISRL & 0x01) // If Master read...
|
25 | {
|
26 | slv_addr = rd_addr; // Save R/W bit
|
27 | transmit = 1;
|
28 | }
|
29 | else
|
30 | {
|
31 | slv_addr = 0x60;
|
32 | transmit = 0;
|
33 | }
|
34 |
|
35 | USICTL0 |= USIOE; // SDA = Output
|
36 |
|
37 | if (USISRL == slv_addr) // Address match?
|
38 | {
|
39 | USISRL = 0x00; // Send ACK
|
40 |
|
41 | if (transmit == 0)
|
42 | {
|
43 | I2C_State = 6; // Next state: RX data
|
44 | }
|
45 | else
|
46 | {
|
47 | I2C_State = 10; // Next state: TX data
|
48 | }
|
49 | }
|
50 | else
|
51 | {
|
52 | USISRL = 0xFF; // Send NACK
|
53 | I2C_State = 8;
|
54 | }
|
55 |
|
56 | USICNT |= 0x01; // Bit counter = 1, send (N)ACK bit
|
57 | break;
|
58 |
|
59 | /* RX data byte */
|
60 | case 6:
|
61 | RX_Data ();
|
62 | break;
|
63 |
|
64 | /* Check data & TX (N)ACK */
|
65 | case 8:
|
66 | USICTL0 |= USIOE; // SDA = Output
|
67 | if(ByteCtr <= NUM_BYTES)
|
68 | {
|
69 | USISRL = 0x00; // Send ACK
|
70 | I2C_State = 6; // RX another byte
|
71 | ByteCtr++;
|
72 | USICNT |= 0x01; // Bit counter = 1, send (N)ACK
|
73 | //
|
74 | }
|
75 | else
|
76 | {
|
77 | USISRL = 0xFF; // Send NACK
|
78 | USICTL0 &= ~USIOE; // SDA = Input
|
79 | I2C_State = 0; // Reset state machine
|
80 | ByteCtr = 0; // Reset counter for next TX/RX
|
81 | //
|
82 | }
|
83 | break;
|
84 |
|
85 | /* TX data byte */
|
86 | case 10:
|
87 | TX_Data ();
|
88 | break;
|
89 |
|
90 | /* Receive (N)ACK */
|
91 | case 12:
|
92 | USICTL0 &= ~USIOE; // SDA = Input
|
93 | USICNT |= 0x01; // Bit counter = 1, receive (N)ACK
|
94 | I2C_State = 14; // Next state: check (N)ACK
|
95 | break;
|
96 |
|
97 | /* Process Data ACK/NACK */
|
98 | case 14:
|
99 | if (USISRL & 0x01) // If NACK received...
|
100 | {
|
101 | USICTL0 &= ~USIOE; // SDA = input
|
102 | slv_addr = 0x60;
|
103 | I2C_State = 0; // Reset state machine
|
104 | ByteCtr = 0; // Reset counter
|
105 | }
|
106 | else
|
107 | {
|
108 | TX_Data (); // TX next byte
|
109 | }
|
110 | break;
|
111 | }
|
112 |
|
113 | USICTL1 &= ~USIIFG; // Clear pending flags
|
114 | }
|
115 |
|
116 | /* Receive data over I2C */
|
117 | static void RX_Data (void)
|
118 | {
|
119 | USICTL0 &= ~USIOE; // SDA = Input
|
120 | USICNT |= 0x08; // Bit counter = 8
|
121 | RxBuffer[RXByteCtr] = USISRL;
|
122 | RXByteCtr++;
|
123 | I2C_State = 8; // Test data and send (N)ACK
|
124 | }
|
125 |
|
126 | /* Transmit data over I2C */
|
127 | static void TX_Data (void)
|
128 | {
|
129 | USICTL0 |= USIOE; // SDA = Output
|
130 | USISRL = TxBuffer[TXByteCtr];
|
131 | TXByteCtr++;
|
132 | USICNT |= 0x08; // Bit counter = 8
|
133 | I2C_State = 12; // Receive (N)ACK
|
134 | }
|