1 #include "config.h"
2 #include "i2c.h"
3 
4 #include <util/delay.h>
5 
6 #include "io.h"
7 #include "debug.h"
8 
9 /*
10 	- Reset bus on failure (lack of ACK, etc)
11 	- Clock stretching
12 	- In pull-up mode, much code was commented out to ever avoid driving the bus (for a fleeting moment) as this was visible on the scope as short peaks (instead the line will briefly go Hi Z).
13 */
14 
15 volatile bool _i2c_disable_ack_check = false;
16 
17 // FIXME: Follow magic numbers should be in a struct that is passed into each function
18 
19 #define I2C_DEFAULT_RETRY_DELAY     1   // us MAGIC
20 #define I2C_DEFAULT_MAX_ACK_RETRIES 10  // * I2C_DEFAULT_RETRY_DELAY us
21 
22 #define I2C_DEFAULT_BUS_WAIT		10	// us MAGIC
23 #define I2C_DEFAULT_MAX_BUS_RETRIES	10
24 
25 #define I2C_DEFAULT_SCL_LOW_PERIOD  2   // 1.3 us
26 #define I2C_DEFAULT_SCL_HIGH_PERIOD 1   // 0.6 us
27 #define I2C_DEFAULT_BUS_FREE_TIME   2   // 1.3 us
28 #define I2C_DEFAULT_STOP_TIME       1   // 0.6 us
29 
30 #define I2C_DELAY	_delay_us	// _delay_ms
31 
_i2c_start_ex(io_pin_t sda,io_pin_t scl,bool pull_up)32 static bool _i2c_start_ex(io_pin_t sda, io_pin_t scl, bool pull_up)
33 {
34 	// Assumes: SDA/SCL are both inputs
35 
36 	uint8_t retries = I2C_DEFAULT_MAX_BUS_RETRIES;
37 	while ((io_test_pin(sda) == false) || (io_test_pin(scl) == false))
38 	{
39 		I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
40 		if (retries-- == 0)
41 		{
42 debug_log("I2C:S1");
43 			return false;
44 		}
45 	}
46 
47 	// START condition
48 //	if (pull_up == false)
49 		io_clear_pin(sda);	// Set LOW before switching to output
50 	io_output_pin(sda);
51 //	if (pull_up)
52 //		io_clear_pin(sda);
53 	I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);  // Thd, sta
54 
55 	retries = I2C_DEFAULT_MAX_BUS_RETRIES;
56 	while (io_test_pin(scl) == false)	// SCL should remain high
57 	{
58 		I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
59 		if (retries-- == 0)
60 		{
61 			io_input_pin(sda);
62 debug_log_ex("I2C:S2", false);
63 debug_log_hex(scl);
64 			return false;
65 		}
66 	}
67 
68 //	if (pull_up == false)
69 		io_clear_pin(scl);
70 	io_output_pin(scl);
71 //	if (pull_up)
72 //		io_clear_pin(scl);
73 	I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD / 2);   // MAGIC
74 
75 	return true;
76 }
77 
_i2c_stop_ex(io_pin_t sda,io_pin_t scl,bool pull_up)78 static bool _i2c_stop_ex(io_pin_t sda, io_pin_t scl, bool pull_up)
79 {
80 	// Assumes:
81 	//	SCL is output & LOW
82 	//	SDA is input (Hi-Z, or pull-up enabled)
83 
84 	// Assuming pull-up already enabled
85 	//if (pull_up)
86 	//	io_set_pin(sda);
87 
88 	bool result = true;
89 
90 	// SDA should be HIGH after ACK has been clocked away
91 //	bool skip_drive = false;
92 	uint8_t retries = 0;
93 	while (io_test_pin(sda) == false)
94 	{
95 		if (retries == I2C_DEFAULT_MAX_ACK_RETRIES)
96 		{
97 			debug_log_ex("I2C:STP ", false);
98 			debug_log_hex(sda);
99 			debug_blink_rev(4);
100 
101 //			skip_drive = true;
102 			result = false;
103 			break;	// SDA is being held low?!
104 		}
105 
106 		++retries;
107 		I2C_DELAY(I2C_DEFAULT_RETRY_DELAY);
108 	}
109 
110 	// STOP condition
111 //	if ((pull_up == false) || (skip_drive))
112 		io_clear_pin(sda);	// Don't tri-state if internal pull-up is used
113 //	//else
114 //	// Pin will now be driven, but having checked SDA is HIGH above means slave's SDA should be Open Collector (i.e. it won't blow up)
115 	io_output_pin(sda);	// Drive LOW
116 //	if (pull_up)
117 //		io_clear_pin(sda);
118 
119 	///////////////////////////////////
120 
121 //	if (pull_up)
122 //		io_set_pin(scl);	// Don't tri-state if internal pull-up is used. Line will be driven, but assuming this is the only master on the clock line (i.e. no one else will pull it low).
123 	io_input_pin(scl);
124 	if (pull_up)
125 		io_set_pin(scl);
126 	I2C_DELAY(I2C_DEFAULT_STOP_TIME);
127 
128 	///////////////////////////////////
129 
130 //	if ((pull_up) && (skip_drive == false))
131 //		io_set_pin(sda);	// Don't tri-state if internal pull-up is used
132 	io_input_pin(sda);
133 //	if ((pull_up) && (skip_drive))
134 		io_set_pin(sda);
135 	I2C_DELAY(I2C_DEFAULT_BUS_FREE_TIME);
136 
137 	return result;
138 }
139 /*
140 static void _i2c_stop(io_pin_t sda, io_pin_t scl)
141 {
142 	_i2c_stop_ex(sda, scl, false);
143 }
144 *//*
145 static void _i2c_abort_safe_ex(io_pin_t pin, bool pull_up)
146 {
147 	if (io_is_output(pin))
148 	{
149 		if (io_is_pin_set(pin))	// This is bad - hope no slave is pulling down the line
150 		{
151 			io_input_pin(pin);	// Pull-up already enabled
152 
153 			if (pull_up == false)
154 				io_clear_pin(pin);	// Doing this after changing direction ensures the line is not brought down
155 		}
156 		else	// Currently pulling line down
157 		{
158 			io_input_pin(pin);	// Hi-Z
159 
160 			if (pull_up)	// There will be a moment where the line will float (better than driving the line though...)
161 			{
162 				io_set_pin(pin);
163 			}
164 		}
165 	}
166 	else	// Already an input
167 	{
168 		if (pull_up)
169 		{
170 			io_set_pin(pin);	// Enable pull-ups
171 		}
172 		else
173 		{
174 			io_clear_pin(pin);	// Disable pull-ups
175 		}
176 	}
177 
178 	// Normally: pin will be Hi-Z input
179 	// With internal pull-up: pin will be input with pull-up enabled
180 }
181 */
_i2c_abort_safe(io_pin_t pin,bool pull_up)182 static void _i2c_abort_safe(io_pin_t pin, bool pull_up)
183 {
184 	if (pull_up == false)
185 		io_clear_pin(pin);	// Should never be output/HIGH, could be input/<was outputting HIGH> so disable pull-ups
186 
187 	io_input_pin(pin);
188 
189 	if (pull_up)
190 		io_set_pin(pin);	// Enable pull-up
191 }
192 
_i2c_abort_ex(io_pin_t sda,io_pin_t scl,bool pull_up)193 static void _i2c_abort_ex(io_pin_t sda, io_pin_t scl, bool pull_up)
194 {
195 /*	if (pull_up == false)
196 	{
197 		io_clear_pin(sda);
198 		io_clear_pin(scl);
199 	}
200 
201 	io_input_pin(scl);
202 	io_input_pin(sda);
203 
204 	if (pull_up)
205 	{
206 		io_set_pin(sda);
207 		io_set_pin(scl);
208 	}
209 */
210 	_i2c_abort_safe(scl, pull_up);
211 	_i2c_abort_safe(sda, pull_up);
212 
213 	//_i2c_abort_safe_ex(scl, pull_up);
214 	//_i2c_abort_safe_ex(sda, pull_up);
215 }
216 /*
217 static void _i2c_abort(io_pin_t sda, io_pin_t scl)
218 {
219 	_i2c_abort_ex(sda, scl, false);
220 }
221 */
_i2c_write_byte_ex(io_pin_t sda,io_pin_t scl,uint8_t value,bool pull_up)222 static bool _i2c_write_byte_ex(io_pin_t sda, io_pin_t scl, uint8_t value, bool pull_up)
223 {
224     // Assumes:
225     //  SDA output is LOW
226     //  SCL output is LOW
227 
228     for (uint8_t i = 0; i < 8; ++i)
229     {
230 		bool b = ((value & (0x01 << (7 - i))) != 0x00);	// MSB first
231 
232 		if (b)
233 		{
234 			if (pull_up)
235 			{
236 //				io_set_pin(sda);	// This is bad (will drive line for a moment), but more stable than letting line float
237 				io_input_pin(sda);
238 				io_set_pin(sda);
239 			}
240 			else
241 				io_input_pin(sda);	// Release HIGH
242 
243 			if (io_test_pin(sda) == false)
244 			{
245 				debug_log("I2C:WR ");
246 				debug_log_hex(sda);
247 				debug_blink_rev(1);
248 				return false;
249 			}
250 		}
251 		else
252 		{
253 			if (pull_up)
254 			{
255 //				if (io_is_output(sda))
256 					io_clear_pin(sda);
257 //				else
258 //				{
259 					io_output_pin(sda);	// [This is bad (will drive line for a moment), but more stable than letting line float]
260 //					io_clear_pin(sda);
261 //				}
262 			}
263 			else
264 			{
265 				io_enable_pin(sda, false);
266 				io_output_pin(sda);	// Drive LOW
267 			}
268 		}
269 
270 		///////////////////////////////
271 
272         io_input_pin(scl);	// Release HIGH
273 		if (pull_up)
274 			io_set_pin(scl);
275         I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
276 #ifdef I2C_ALLOW_CLOCK_STRETCH
277 		uint8_t retries = I2C_DEFAULT_MAX_BUS_RETRIES;
278 		while (io_test_pin(scl) == false)	// Clock stretch requested?
279 		{
280 			I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
281 			if (--retries == 0)
282 			{
283 				io_input_pin(sda);	// Release HIGH
284 				if (pull_up)
285 					io_set_pin(sda);
286 
287 				debug_log_ex("I2C:STRTCH ", false);
288 				debug_log_hex(scl);
289 				debug_blink_rev(2);
290 				return false;
291 			}
292 		}
293 #endif // I2C_ALLOW_CLOCK_STRETCH
294 		if (pull_up)
295 			io_clear_pin(scl);
296         io_output_pin(scl);	// Drive LOW
297         I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);
298     }
299 
300     io_input_pin(sda);	// Release HIGH
301 	if (pull_up)
302 		io_set_pin(sda);	// Assuming letting line float won't confuse slave when pulling line LOW for ACK
303     I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
304 
305     uint8_t retries = 0;
306     while ((_i2c_disable_ack_check == false) && (io_test_pin(sda)))
307     {
308         if (retries == I2C_DEFAULT_MAX_ACK_RETRIES)
309 		{
310 			debug_log_ex("I2C:ACK ", false);
311 			debug_log_hex_ex(sda, false);
312 			debug_log_hex(value);
313 			debug_blink_rev(3);
314             return false;	// Will abort and not release bus - done by caller
315 		}
316 
317         ++retries;
318         I2C_DELAY(I2C_DEFAULT_RETRY_DELAY);
319     }
320 
321     // Clock away acknowledge
322 //	if (pull_up)
323 //		io_set_pin(scl);
324     io_input_pin(scl);	// Release HIGH
325 	if (pull_up)
326 		io_set_pin(scl);
327     I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
328 
329 	if (pull_up)
330 		io_clear_pin(scl);
331     io_output_pin(scl);	// Drive LOW
332 //	if (pull_up)
333 //		io_clear_pin(scl);
334     I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);
335 
336     return true;
337 }
338 
_i2c_read_byte_ex(io_pin_t sda,io_pin_t scl,uint8_t * value,bool pull_up)339 static bool _i2c_read_byte_ex(io_pin_t sda, io_pin_t scl, uint8_t* value, bool pull_up)
340 {
341     // Assumes:
342     //  SDA output is LOW
343     //  SCL output is LOW
344 
345 	io_input_pin(sda);
346 	if (pull_up)
347 		io_set_pin(sda);	// OK to leave line floating for a moment (better not to drive as slave will be pulling it to ground)
348 
349     (*value) = 0x00;
350 
351     for (uint8_t i = 0; i < 8; ++i)
352     {
353 //		if (pull_up)
354 //			io_set_pin(scl);	// [Not ideal with pull-up]
355         io_input_pin(scl);	// Release HIGH
356 		if (pull_up)
357 			io_set_pin(scl);
358         I2C_DELAY(I2C_DEFAULT_SCL_HIGH_PERIOD);
359 #ifdef I2C_ALLOW_CLOCK_STRETCH
360 		uint8_t retries = I2C_DEFAULT_MAX_BUS_RETRIES;
361 		while (io_test_pin(scl) == false)	// Clock stretch requested?
362 		{
363 			I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
364 			if (--retries == 0)
365 			{
366 				debug_log_ex("I2C:R ");
367 				debug_log_hex(scl);
368 				debug_blink_rev(5);
369 				return false;
370 			}
371 		}
372 #endif // I2C_ALLOW_CLOCK_STRETCH
373         (*value) |= ((io_test_pin(sda) ? 0x1 : 0x0) << (7 - i));   // MSB first
374 
375 		if (pull_up)
376 			io_clear_pin(scl);
377         io_output_pin(scl);	// Drive LOW (not ideal with pull-up)
378 //		if (pull_up)
379 //			io_clear_pin(scl);
380         I2C_DELAY(I2C_DEFAULT_SCL_LOW_PERIOD);
381     }
382 
383     // Not necessary to ACK since it's only this one byte
384 
385     return true;
386 }
387 
i2c_read2_ex(io_pin_t sda,io_pin_t scl,uint8_t addr,uint8_t subaddr,uint8_t * value,bool pull_up)388 bool i2c_read2_ex(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t* value, bool pull_up)
389 {
390 	if (_i2c_start_ex(sda, scl, pull_up) == false)
391 		return false;
392 
393 	if (_i2c_write_byte_ex(sda, scl, addr & ~0x01, pull_up) == false)
394 	{
395 #ifdef I2C_EXTRA_DEBUGGING
396 		//debug_log_ex("R21:", false);
397 		debug_log("R21");
398 		//debug_log_hex(addr);
399 #endif // I2C_EXTRA_DEBUGGING
400 		goto i2c_read2_fail;
401 	}
402 
403 	if (_i2c_write_byte_ex(sda, scl, subaddr, pull_up) == false)
404 	{
405 #ifdef I2C_EXTRA_DEBUGGING
406 		//debug_log_ex("R22:", false);
407 		debug_log("R22");
408 		//debug_log_hex(subaddr);
409 #endif // I2C_EXTRA_DEBUGGING
410 		goto i2c_read2_fail;
411 	}
412 
413 	io_input_pin(scl);
414 	if (pull_up)
415 		io_set_pin(scl);
416 	I2C_DELAY(I2C_DEFAULT_BUS_WAIT);
417 
418 	if (_i2c_start_ex(sda, scl, pull_up) == false)
419 	{
420 		return false;
421 	}
422 
423 	if (_i2c_write_byte_ex(sda, scl, addr | 0x01, pull_up) == false)
424 	{
425 #ifdef I2C_EXTRA_DEBUGGING
426 		//debug_log_ex("R23:", false);
427 		debug_log("R23");
428 		//debug_log_hex(addr);
429 #endif // I2C_EXTRA_DEBUGGING
430 		goto i2c_read2_fail;
431 	}
432 
433 	if (_i2c_read_byte_ex(sda, scl, value, pull_up) == false)
434 	{
435 #ifdef I2C_EXTRA_DEBUGGING
436 		//debug_log_ex("R24:", false);
437 		debug_log("R24");
438 		//debug_log_hex(*value);
439 #endif // I2C_EXTRA_DEBUGGING
440 		goto i2c_read2_fail;
441 	}
442 
443 	if (_i2c_stop_ex(sda, scl, pull_up) == false)
444 	{
445 #ifdef I2C_EXTRA_DEBUGGING
446 		debug_log("R25");
447 #endif // I2C_EXTRA_DEBUGGING
448 	}
449 
450 	return true;
451 i2c_read2_fail:
452 	_i2c_abort_ex(sda, scl, pull_up);
453 	return false;
454 }
455 
i2c_write_ex(io_pin_t sda,io_pin_t scl,uint8_t addr,uint8_t subaddr,uint8_t value,bool pull_up)456 bool i2c_write_ex(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t value, bool pull_up)
457 {
458 	if (_i2c_start_ex(sda, scl, pull_up) == false)
459 		return false;
460 
461     if (_i2c_write_byte_ex(sda, scl, addr, pull_up) == false)
462         goto i2c_write_fail;
463 
464     if (_i2c_write_byte_ex(sda, scl, subaddr, pull_up) == false)
465         goto i2c_write_fail;
466 
467     if (_i2c_write_byte_ex(sda, scl, value, pull_up) == false)
468         goto i2c_write_fail;
469 
470     _i2c_stop_ex(sda, scl, pull_up);
471 
472     return true;
473 i2c_write_fail:
474 	_i2c_abort_ex(sda, scl, pull_up);
475 	return false;
476 }
477 
i2c_write(io_pin_t sda,io_pin_t scl,uint8_t addr,uint8_t subaddr,uint8_t value)478 bool i2c_write(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t value)
479 {
480 	return i2c_write_ex(sda, scl, addr, subaddr, value, false);
481 }
482 
i2c_read_ex(io_pin_t sda,io_pin_t scl,uint8_t addr,uint8_t subaddr,uint8_t * value,bool pull_up)483 bool i2c_read_ex(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t* value, bool pull_up)
484 {
485     if (_i2c_start_ex(sda, scl, pull_up) == false)
486 		return false;
487 
488     if (_i2c_write_byte_ex(sda, scl, addr, pull_up) == false)
489         goto i2c_read_fail;
490 
491     if (_i2c_write_byte_ex(sda, scl, subaddr, pull_up) == false)
492         goto i2c_read_fail;
493 
494     if (_i2c_read_byte_ex(sda, scl, value, pull_up) == false)
495         goto i2c_read_fail;
496 
497     _i2c_stop_ex(sda, scl, pull_up);
498 
499     return true;
500 i2c_read_fail:
501 	_i2c_abort_ex(sda, scl, pull_up);
502 	return false;
503 }
504 
i2c_read(io_pin_t sda,io_pin_t scl,uint8_t addr,uint8_t subaddr,uint8_t * value)505 bool i2c_read(io_pin_t sda, io_pin_t scl, uint8_t addr, uint8_t subaddr, uint8_t* value)
506 {
507 	return i2c_read_ex(sda, scl, addr, subaddr, value, false);
508 }
509 
i2c_init_ex(io_pin_t sda,io_pin_t scl,bool pull_up)510 void i2c_init_ex(io_pin_t sda, io_pin_t scl, bool pull_up)
511 {
512 	_i2c_abort_ex(sda, scl, pull_up);
513 }
514 
i2c_init(io_pin_t sda,io_pin_t scl)515 void i2c_init(io_pin_t sda, io_pin_t scl)
516 {
517 	i2c_init_ex(sda, scl, false);
518 }
519