57 #ifndef SOFTI2CMASTER_H_
59 #define SOFTI2DMASTER_H_
64 #if defined(ARDUINO_AVR_FLORA8) || defined(ARDUINO_AVR_LILYPAD_USB)
65 #define SDA_PORT PORTD
67 #define SCL_PORT PORTD
71 #ifdef ARDUINO_AVR_UNO
72 #define SDA_PORT PORTC
74 #define SCL_PORT PORTC
78 #define I2C_TIMEOUT 100
79 #define I2C_NOINTERRUPT 0
80 #define I2C_SLOWMODE 1
82 #define I2C_CPUFREQ (F_CPU/FAC)
123 #define I2C_CPUFREQ F_CPU
129 #define I2C_FASTMODE 0
136 #define I2C_SLOWMODE 0
144 #ifndef I2C_NOINTERRUPT
145 #define I2C_NOINTERRUPT 0
152 #define I2C_TIMEOUT 0
154 #if I2C_TIMEOUT > 10000
155 #error I2C_TIMEOUT is too large
159 #define I2C_TIMEOUT_DELAY_LOOPS (I2C_CPUFREQ/1000UL)*I2C_TIMEOUT/4000UL
160 #if I2C_TIMEOUT_DELAY_LOOPS < 1
161 #define I2C_MAX_STRETCH 1
163 #if I2C_TIMEOUT_DELAY_LOOPS > 60000UL
164 #define I2C_MAX_STRETCH 60000UL
166 #define I2C_MAX_STRETCH I2C_TIMEOUT_DELAY_LOOPS
171 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/400000L)/2-19)/3)
174 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/25000L)/2-19)/3)
176 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/100000L)/2-19)/3)
191 #define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1)
192 #define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1)
193 #define SDA_OUT _SFR_IO_ADDR(SDA_PORT)
194 #define SCL_OUT _SFR_IO_ADDR(SCL_PORT)
195 #define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2)
196 #define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)
199 #define __tmp_reg__ 0
209 #if I2C_DELAY_COUNTER < 1
210 __asm__ __volatile__ (
" ret");
215 " ldi r25, %[DELAY] ;load delay constant ;; 4C \n\t"
217 " dec r25 ;decrement counter ;; 4C+xC \n\t"
218 " brne _Lidelay ;;5C+(x-1)2C+xC\n\t"
219 " ret ;; 9C+(x-1)2C+xC = 7C+xC"
229 (
"_Li2c_wait_stretch: \n\t"
230 " sbis %[SCLIN],%[SCLPIN] ;wait for SCL high \n\t"
231 " rjmp _Li2c_wait_stretch \n\t"
232 " cln ;signal: no timeout \n\t"
234 : : [SCLIN]
"I" (
SCL_IN), [SCLPIN]
"I" (SCL_PIN));
237 (
" ldi r27, %[HISTRETCH] ;load delay counter \n\t"
238 " ldi r26, %[LOSTRETCH] \n\t"
239 "_Lwait_stretch: \n\t"
240 " clr __tmp_reg__ ;do next loop 255 times \n\t"
241 "_Lwait_stretch_inner_loop: \n\t"
242 " rcall _Lcheck_scl_level ;call check function ;; 12C \n\t"
243 " brpl _Lstretch_done ;done if N=0 ;; +1 = 13C\n\t"
244 " dec __tmp_reg__ ;dec inner loop counter;; +1 = 14C\n\t"
245 " brne _Lwait_stretch_inner_loop ;; +2 = 16C\n\t"
246 " sbiw r26,1 ;dec outer loop counter \n\t"
247 " brne _Lwait_stretch ;continue with outer loop \n\t"
248 " sen ;timeout -> set N-bit=1 \n\t"
249 " rjmp _Lwait_return ;and return with N=1\n\t"
250 "_Lstretch_done: ;SCL=1 sensed \n\t"
251 " cln ;OK -> clear N-bit \n\t"
252 " rjmp _Lwait_return ; and return with N=0 \n\t"
254 "_Lcheck_scl_level: ;; call = 3C\n\t"
255 " cln ;; +1C = 4C \n\t"
256 " sbic %[SCLIN],%[SCLPIN] ;skip if SCL still low ;; +2C = 6C \n\t"
257 " rjmp _Lscl_high ;; +0C = 6C \n\t"
258 " sen ;; +1 = 7C\n\t "
260 " nop ;; +1C = 8C \n\t"
261 " ret ;return N-Bit=1 if low ;; +4 = 12C\n\t"
264 : : [SCLIN]
"I" (
SCL_IN), [SCLPIN]
"I" (SCL_PIN),
275 (
" cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
276 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
277 " cbi %[SDAOUT],%[SDAPIN] ;clear SDA output value \n\t"
278 " cbi %[SCLOUT],%[SCLPIN] ;clear SCL output value \n\t"
279 " clr r24 ;set return value to false \n\t"
280 " clr r25 ;set return value to false \n\t"
281 " sbis %[SDAIN],%[SDAPIN] ;check for SDA high\n\t"
282 " ret ;if low return with false \n\t"
283 " sbis %[SCLIN],%[SCLPIN] ;check for SCL high \n\t"
284 " ret ;if low return with false \n\t"
285 " ldi r24,1 ;set return value to true \n\t"
288 [SCLDDR]
"I" (
SCL_DDR), [SCLPIN]
"I" (SCL_PIN),
290 [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
300 " cli ;clear IRQ bit \n\t"
302 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
303 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
304 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
305 " rcall ass_i2c_delay_half ;wait T/2 \n\t"
306 " rcall ass_i2c_write ;now write address \n\t"
308 : : [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
309 [SCLIN]
"I" (
SCL_IN),[SCLPIN]
"I" (SCL_PIN));
321 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
322 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
323 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
324 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
325 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
326 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
327 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
328 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
329 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
330 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
331 " rcall ass_i2c_write \n\t"
333 : : [SCLDDR]
"I" (
SCL_DDR), [SCLPIN]
"I" (SCL_PIN),[SCLIN]
"I" (
SCL_IN),
334 [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN));
342 " push r24 ;save original parameter \n\t"
343 "_Li2c_start_wait1: \n\t"
344 " pop r24 ;restore original parameter\n\t"
345 " push r24 ;and save again \n\t"
347 " cli ;disable interrupts \n\t"
349 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
350 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
351 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
352 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
353 " rcall ass_i2c_write ;write address \n\t"
354 " tst r24 ;if device not busy -> done \n\t"
355 " brne _Li2c_start_wait_done \n\t"
356 " rcall ass_i2c_stop ;terminate write & enable IRQ \n\t"
357 " rjmp _Li2c_start_wait1 ;device busy, poll ack again \n\t"
358 "_Li2c_start_wait_done: \n\t"
359 " pop __tmp_reg__ ;pop off orig argument \n\t"
361 : : [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
362 [SCLIN]
"I" (
SCL_IN),[SCLPIN]
"I" (SCL_PIN));
369 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
370 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
371 " rcall ass_i2c_delay_half ;T/2 delay \n\t"
372 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
373 " rcall ass_i2c_delay_half ;T/2 delay \n\t"
374 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
375 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
376 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
377 " rcall ass_i2c_delay_half \n\t"
379 " sei ;enable interrupts again!\n\t"
381 : : [SCLDDR]
"I" (
SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (
SCL_IN),
382 [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN));
389 " sec ;set carry flag \n\t"
390 " rol r24 ;shift in carry and shift out MSB \n\t"
391 " rjmp _Li2c_write_first \n\t"
392 "_Li2c_write_bit:\n\t"
393 " lsl r24 ;left shift into carry ;; 1C\n\t"
394 "_Li2c_write_first:\n\t"
395 " breq _Li2c_get_ack ;jump if TXreg is empty;; +1 = 2C \n\t"
396 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 4C \n\t"
400 " brcc _Li2c_write_low ;;+1/+2=5/6C\n\t"
401 " nop ;; +1 = 7C \n\t"
402 " cbi %[SDADDR],%[SDAPIN] ;release SDA ;; +2 = 9C \n\t"
403 " rjmp _Li2c_write_high ;; +2 = 11C \n\t"
404 "_Li2c_write_low: \n\t"
405 " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; +2 = 9C \n\t"
406 " rjmp _Li2c_write_high ;;+2 = 11C \n\t"
407 "_Li2c_write_high: \n\t"
409 " rcall ass_i2c_delay_half ;delay T/2 ;;+X = 11C+X\n\t"
411 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;;+2 = 13C+X\n\t"
412 " cln ;clear N-bit ;;+1 = 14C+X\n\t"
416 " sbis %[SCLIN],%[SCLPIN] ;check for SCL high ;;+2 = 16C+X\n\t"
417 " rcall ass_i2c_wait_scl_high \n\t"
418 " brpl _Ldelay_scl_high ;;+2 = 18C+X\n\t"
419 "_Li2c_write_return_false: \n\t"
420 " clr r24 ; return false because of timeout \n\t"
421 " rjmp _Li2c_write_return \n\t"
422 "_Ldelay_scl_high: \n\t"
424 " rcall ass_i2c_delay_half ;delay T/2 ;;+X= 18C+2X\n\t"
426 " rjmp _Li2c_write_bit \n\t"
427 " ;; +2 = 20C +2X for one bit-loop \n\t"
428 "_Li2c_get_ack: \n\t"
429 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 5C \n\t"
432 " cbi %[SDADDR],%[SDAPIN] ;release SDA ;;+2 = 7C \n\t"
434 " rcall ass_i2c_delay_half ;delay T/2 ;; +X = 7C+X \n\t"
436 " clr r25 ;; 17C+2X \n\t"
437 " clr r24 ;return 0 ;; 14C + X \n\t"
438 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; +2 = 9C+X\n\t"
439 "_Li2c_ack_wait: \n\t"
440 " cln ; clear N-bit ;; 10C + X\n\t"
442 " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X \n\t"
443 " rcall ass_i2c_wait_scl_high \n\t"
444 " brmi _Li2c_write_return_false ;; 13C + X \n\t "
445 " sbis %[SDAIN],%[SDAPIN] ;if SDA hi -> return 0 ;; 15C + X \n\t"
446 " ldi r24,1 ;return true ;; 16C + X \n\t"
448 " rcall ass_i2c_delay_half ;delay T/2 ;; 16C + 2X \n\t"
450 "_Li2c_write_return: \n\t"
453 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
455 " ;; + 4 = 17C + 2X for acknowldge bit"
457 [SCLDDR]
"I" (
SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (
SCL_IN),
458 [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN), [SDAIN]
"I" (
SDA_IN));
467 "_Li2c_read_bit: \n\t"
468 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
469 " cbi %[SDADDR],%[SDAPIN] ;release SDA(prev. ACK);; 4C \n\t"
474 " rcall ass_i2c_delay_half ;delay T/2 ;; 4C+X \n\t"
476 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 6C + X \n\t"
478 " rcall ass_i2c_delay_half ;delay T/2 ;; 6C + 2X \n\t"
480 " cln ; clear N-bit ;; 7C + 2X \n\t"
484 " sbis %[SCLIN], %[SCLPIN] ;check for SCL high ;; 9C +2X \n\t"
485 " rcall ass_i2c_wait_scl_high \n\t"
486 " brmi _Li2c_read_return ;return if timeout ;; 10C + 2X\n\t"
487 " clc ;clear carry flag ;; 11C + 2X\n\t"
488 " sbic %[SDAIN],%[SDAPIN] ;if SDA is high ;; 11C + 2X\n\t"
489 " sec ;set carry flag ;; 12C + 2X\n\t"
490 " rol r23 ;store bit ;; 13C + 2X\n\t"
491 " brcc _Li2c_read_bit ;while receiv reg not full \n\t"
492 " ;; 15C + 2X for one bit loop \n\t"
494 "_Li2c_put_ack: \n\t"
495 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
496 " cpi r24,0 ;; 3C \n\t"
497 " breq _Li2c_put_ack_low ;if (ack=0) ;; 5C \n\t"
498 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
499 " rjmp _Li2c_put_ack_high \n\t"
500 "_Li2c_put_ack_low: ;else \n\t"
501 " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; 7C \n\t"
502 "_Li2c_put_ack_high: \n\t"
507 " rcall ass_i2c_delay_half ;delay T/2 ;; 7C + X \n\t"
509 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 9C +X \n\t"
510 " cln ;clear N ;; +1 = 10C\n\t"
513 " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X\n\t"
514 " rcall ass_i2c_wait_scl_high \n\t"
516 " rcall ass_i2c_delay_half ;delay T/2 ;; 11C + 2X\n\t"
518 "_Li2c_read_return: \n\t"
521 "sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
522 " mov r24,r23 ;; 12C + 2X \n\t"
523 " clr r25 ;; 13 C + 2X\n\t"
526 [SCLDDR]
"I" (
SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (
SCL_IN),
527 [SDADDR]
"I" (
SDA_DDR), [SDAPIN]
"I" (SDA_PIN), [SDAIN]
"I" (
SDA_IN)