@@ -56,105 +56,148 @@ static w_status_t wait_for_idle(void) {
5656}
5757
5858w_status_t i2c_init (uint8_t clkdiv ) {
59- // CSTR Enable clocking; S Cleared by hardware after Start; MODE 7-bit address; EN enabled; RSEN
60- // disabled;
61- I2C1CON0 = 0x84 ;
62- // TXU 0; CSD Clock Stretching enabled; ACKT 0; RXO 0; ACKDT Acknowledge; ACKSTAT ACK received;
63- // ACKCNT Not Acknowledge;
64- I2C1CON1 = 0x80 ;
65- // ABD enabled; GCEN disabled; ACNT disabled; SDAHT 300 ns hold time; BFRET 8 I2C Clock pulses;
66- // FME disabled;
67- I2C1CON2 = 0x00 ;
68- // Setup clock reference to be base (500khz)/32
69- CLKRCON = 0b10010000 | clkdiv ;
70- CLKRCLK = 0b00000011 ;
71- // CLK clock reference
72- I2C1CLK = 0x04 ;
73- I2C1PIR = 0 ; // ;Clear all the error flags
59+ // Disable module for configuration
60+ I2C1CON0bits .EN = 0 ;
61+
62+ // Setup and verify clock configuration
63+ CLKRCON = 0b10010000 | (clkdiv & 0x07 );
64+ CLKRCLK = 0b00000011 ; // MFINTOSC source
65+
66+ // Wait for clock to stabilize
67+ unsigned int timeout = 1000 ;
68+ while (!CLKRCONbits .CLKRDY && -- timeout )
69+ ;
70+ if (!timeout ) {
71+ return W_IO_ERROR ;
72+ }
73+
74+ // Select I2C clock source
75+ I2C1CLK = 0x04 ; // Clock reference
76+
77+ // Configure I2C module registers
78+ I2C1CON0 = 0x04 ; // 7-bit master mode
79+ I2C1CON1 = 0x80 ; // Enable ACK, clock stretching
80+ I2C1CON2 = 0x00 ; // Standard timing
81+
82+ // Clear all flags
83+ I2C1PIR = 0 ;
7484 I2C1ERR = 0 ;
7585
76- return W_SUCCESS ;
86+ // Enable module and verify bus is free
87+ I2C1CON0bits .EN = 1 ;
88+ return wait_for_idle ();
7789}
7890
7991static w_status_t i2c_write (uint8_t address , const uint8_t * data , uint8_t len ) {
80- I2C1ADB1 = (uint8_t )(address << 1 );
92+ // Verify bus state and prepare for transfer
93+ w_status_t status = check_i2c_state ();
94+ if (status != W_SUCCESS ) {
95+ return status ;
96+ }
97+
98+ clear_i2c_buffers ();
99+ I2C1PIR = 0 ;
100+ I2C1ERR = 0 ;
101+
102+ // Configure transfer
103+ I2C1ADB1 = (uint8_t )(address << 1 ); // Write address
81104 I2C1CNT = len ;
82- I2C1PIRbits . PCIF = 0 ;
83- I2C1ERRbits . NACKIF = 0 ;
105+
106+ // Start transfer
84107 I2C1CON0bits .S = 1 ;
85108
86- unsigned int timeout ;
109+ // Send each byte
87110 while (len -- ) {
88- I2C1TXB = * data ++ ;
89- timeout = 0 ;
90- while (!I2C1STAT1bits .TXBE && !I2C1ERRbits .NACKIF ) {
91- if (timeout >= I2C_POLL_TIMEOUT ) {
111+ unsigned int timeout = 0 ;
112+ // Wait for transmit buffer to be ready
113+ while (!I2C1STAT1bits .TXBE ) {
114+ if (I2C1ERRbits .NACKIF || I2C1ERRbits .BCLIF ) {
115+ return W_IO_ERROR ;
116+ }
117+
118+ // Handle clock stretching
119+ if (I2C1CON0bits .CSTR ) {
120+ __delay_us (I2C_STRETCH_DELAY );
121+ timeout = 0 ;
122+ } else if (timeout ++ >= I2C_POLL_TIMEOUT ) {
92123 return W_IO_TIMEOUT ;
93124 }
94- timeout ++ ;
95- }
96- if (I2C1ERRbits .NACKIF ) {
97- return W_IO_ERROR ;
98125 }
126+
127+ I2C1TXB = * data ++ ;
99128 }
100129
101- timeout = 0 ;
130+ // Wait for transfer completion
131+ unsigned int timeout = 0 ;
102132 while (!I2C1PIRbits .PCIF ) {
103- if (timeout >= I2C_POLL_TIMEOUT ) {
133+ if (timeout ++ >= I2C_POLL_TIMEOUT ) {
104134 return W_IO_TIMEOUT ;
105135 }
106- timeout ++ ;
107- }
108-
109- I2C1PIRbits .PCIF = 0 ;
110- I2C1STAT1bits .CLRBF = 1 ;
111-
112- if ((I2C1ERR & 0x70 ) != 0 ) {
113- return W_IO_ERROR ;
114136 }
115137
116138 return W_SUCCESS ;
117139}
118140
119141static w_status_t i2c_read (uint8_t address , uint8_t * data , uint8_t len ) {
120- I2C1ADB1 = (uint8_t )((address << 1 ) | 1 );
142+ // Verify bus state and prepare for transfer
143+ w_status_t status = check_i2c_state ();
144+ if (status != W_SUCCESS ) {
145+ return status ;
146+ }
147+
148+ clear_i2c_buffers ();
149+ I2C1PIR = 0 ;
150+ I2C1ERR = 0 ;
151+
152+ // Configure transfer
153+ I2C1ADB1 = (uint8_t )((address << 1 ) | 0x01 ); // Read address
121154 I2C1CNT = len ;
122- I2C1PIRbits .PCIF = 0 ;
123- I2C1ERRbits .NACKIF = 0 ;
155+
156+ // Configure acknowledgment behavior
157+ I2C1CON1bits .ACKDT = 0 ; // ACK bytes
158+ if (len == 1 ) {
159+ I2C1CON1bits .ACKCNT = 1 ; // NACK last byte
160+ }
161+
162+ // Start transfer
124163 I2C1CON0bits .S = 1 ;
125164
126- unsigned int timeout ;
165+ // Receive each byte
127166 while (len -- ) {
128- timeout = 0 ;
129- while (!I2C1STAT1bits .RXBF && !I2C1ERRbits .NACKIF ) {
130- if (timeout >= I2C_POLL_TIMEOUT ) {
167+ unsigned int timeout = 0 ;
168+ // Wait for receive buffer to have data
169+ while (!I2C1STAT1bits .RXBF ) {
170+ if (I2C1ERRbits .NACKIF || I2C1ERRbits .BCLIF ) {
171+ return W_IO_ERROR ;
172+ }
173+
174+ // Handle clock stretching
175+ if (I2C1CON0bits .CSTR ) {
176+ __delay_us (I2C_STRETCH_DELAY );
177+ timeout = 0 ;
178+ } else if (timeout ++ >= I2C_POLL_TIMEOUT ) {
131179 return W_IO_TIMEOUT ;
132180 }
133- timeout ++ ;
134- }
135- if (I2C1ERRbits .NACKIF ) {
136- return W_IO_ERROR ;
137181 }
182+
138183 * data ++ = I2C1RXB ;
139184 }
140185
141- timeout = 0 ;
186+ // Wait for transfer completion
187+ unsigned int timeout = 0 ;
142188 while (!I2C1PIRbits .PCIF ) {
143- if (timeout >= I2C_POLL_TIMEOUT ) {
189+ if (timeout ++ >= I2C_POLL_TIMEOUT ) {
144190 return W_IO_TIMEOUT ;
145191 }
146- timeout ++ ;
147- }
148- I2C1PIRbits .PCIF = 0 ;
149- I2C1STAT1bits .CLRBF = 1 ;
150-
151- if ((I2C1ERR & 0x70 ) != 0 ) {
152- return W_IO_ERROR ;
153192 }
154193
155194 return W_SUCCESS ;
156195}
157196
197+ /*
198+ * Public interface functions
199+ * These provide the high-level API for I2C communication
200+ */
158201w_status_t i2c_write_data (uint8_t address , const uint8_t * data , uint8_t len ) {
159202 return i2c_write (address , data , len );
160203}
@@ -169,35 +212,40 @@ w_status_t i2c_write_reg8(uint8_t address, uint8_t reg, uint8_t val) {
169212}
170213
171214w_status_t i2c_write_reg16 (uint8_t address , uint8_t reg , uint16_t val ) {
172- uint8_t data [3 ] = {reg , (uint8_t )(val >> 8 ), (uint8_t )val };
215+ uint8_t data [3 ] = {
216+ reg ,
217+ (uint8_t )(val >> 8 ), // MSB first
218+ (uint8_t )(val & 0xFF ) // LSB second
219+ };
173220 return i2c_write (address , data , 3 );
174221}
175222
176223w_status_t i2c_read_reg8 (uint8_t address , uint8_t reg , uint8_t * value ) {
224+ // Write register address
177225 w_status_t status = i2c_write (address , & reg , 1 );
178226 if (status != W_SUCCESS ) {
179- return W_IO_ERROR ;
227+ return status ;
180228 }
181229
182- uint8_t data ;
183- status = i2c_read (address , & data , 1 );
184- if (status != W_SUCCESS ) {
185- return W_IO_ERROR ;
186- }
187- * value = data ;
188- return W_SUCCESS ;
230+ // Read register value
231+ return i2c_read (address , value , 1 );
189232}
190233
191234w_status_t i2c_read_reg16 (uint8_t address , uint8_t reg , uint16_t * value ) {
235+ // Write register address
192236 w_status_t status = i2c_write (address , & reg , 1 );
193237 if (status != W_SUCCESS ) {
194- return W_IO_ERROR ;
238+ return status ;
195239 }
240+
241+ // Read register value
196242 uint8_t data [2 ];
197243 status = i2c_read (address , data , 2 );
198244 if (status != W_SUCCESS ) {
199- return W_IO_ERROR ;
245+ return status ;
200246 }
201- * value = (uint16_t )(data [0 ]) << 8 | data [1 ];
247+
248+ // Combine bytes (MSB first)
249+ * value = ((uint16_t )data [0 ] << 8 ) | data [1 ];
202250 return W_SUCCESS ;
203- }
251+ }
0 commit comments