66 boolean __attribute__ ((noinline)) i2c_init(
void);
71 bool __attribute__ ((noinline)) i2c_start(uint8_t addr);
75 void __attribute__ ((noinline)) i2c_start_wait(uint8_t addr);
81 bool __attribute__ ((noinline)) i2c_rep_start(uint8_t addr);
84 void __attribute__ ((noinline)) i2c_stop(
void) asm("ass_i2c_stop");
89 bool __attribute__ ((noinline)) i2c_write(uint8_t value) asm("ass_i2c_write");
93 uint8_t __attribute__ ((noinline)) i2c_read(
bool last);
99 #define I2C_CPUFREQ F_CPU
105 #define I2C_FASTMODE 0
112 #define I2C_SLOWMODE 0
120 #ifndef I2C_NOINTERRUPT
121 #define I2C_NOINTERRUPT 0
128 #define I2C_TIMEOUT 0
130 #if I2C_TIMEOUT > 10000
131 #error I2C_TIMEOUT is too large
135 #define I2C_TIMEOUT_DELAY_LOOPS (I2C_CPUFREQ/1000UL)*I2C_TIMEOUT/4000UL
136 #if I2C_TIMEOUT_DELAY_LOOPS < 1
137 #define I2C_MAX_STRETCH 1
139 #if I2C_TIMEOUT_DELAY_LOOPS > 60000UL
140 #define I2C_MAX_STRETCH 60000UL
142 #define I2C_MAX_STRETCH I2C_TIMEOUT_DELAY_LOOPS
147 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/400000L)/2-19)/3)
150 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/25000L)/2-19)/3)
152 #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/100000L)/2-19)/3)
167 #define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1)
168 #define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1)
169 #define SDA_OUT _SFR_IO_ADDR(SDA_PORT)
170 #define SCL_OUT _SFR_IO_ADDR(SCL_PORT)
171 #define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2)
172 #define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)
175 #define __tmp_reg__ 0
180 void __attribute__ ((noinline)) i2c_delay_half(
void) asm("ass_i2c_delay_half");
181 void __attribute__ ((noinline)) i2c_wait_scl_high(
void) asm("ass_i2c_wait_scl_high");
183 void i2c_delay_half(
void)
185 #if I2C_DELAY_COUNTER < 1
186 __asm__ __volatile__ (
" ret");
191 " ldi r25, %[DELAY] ;load delay constant ;; 4C \n\t"
193 " dec r25 ;decrement counter ;; 4C+xC \n\t"
194 " brne _Lidelay ;;5C+(x-1)2C+xC\n\t"
195 " ret ;; 9C+(x-1)2C+xC = 7C+xC"
196 : : [DELAY]
"M" I2C_DELAY_COUNTER :
"r25");
201 void i2c_wait_scl_high(
void)
205 (
"_Li2c_wait_stretch: \n\t"
206 " sbis %[SCLIN],%[SCLPIN] ;wait for SCL high \n\t"
207 " rjmp _Li2c_wait_stretch \n\t"
208 " cln ;signal: no timeout \n\t"
210 : : [SCLIN]
"I" (SCL_IN), [SCLPIN]
"I" (SCL_PIN));
213 (
" ldi r27, %[HISTRETCH] ;load delay counter \n\t"
214 " ldi r26, %[LOSTRETCH] \n\t"
215 "_Lwait_stretch: \n\t"
216 " clr __tmp_reg__ ;do next loop 255 times \n\t"
217 "_Lwait_stretch_inner_loop: \n\t"
218 " rcall _Lcheck_scl_level ;call check function ;; 12C \n\t"
219 " brpl _Lstretch_done ;done if N=0 ;; +1 = 13C\n\t"
220 " dec __tmp_reg__ ;dec inner loop counter;; +1 = 14C\n\t"
221 " brne _Lwait_stretch_inner_loop ;; +2 = 16C\n\t"
222 " sbiw r26,1 ;dec outer loop counter \n\t"
223 " brne _Lwait_stretch ;continue with outer loop \n\t"
224 " sen ;timeout -> set N-bit=1 \n\t"
225 " rjmp _Lwait_return ;and return with N=1\n\t"
226 "_Lstretch_done: ;SCL=1 sensed \n\t"
227 " cln ;OK -> clear N-bit \n\t"
228 " rjmp _Lwait_return ; and return with N=0 \n\t"
230 "_Lcheck_scl_level: ;; call = 3C\n\t"
231 " cln ;; +1C = 4C \n\t"
232 " sbic %[SCLIN],%[SCLPIN] ;skip if SCL still low ;; +2C = 6C \n\t"
233 " rjmp _Lscl_high ;; +0C = 6C \n\t"
234 " sen ;; +1 = 7C\n\t "
236 " nop ;; +1C = 8C \n\t"
237 " ret ;return N-Bit=1 if low ;; +4 = 12C\n\t"
240 : : [SCLIN]
"I" (SCL_IN), [SCLPIN]
"I" (SCL_PIN),
241 [HISTRETCH]
"M" (I2C_MAX_STRETCH>>8),
242 [LOSTRETCH]
"M" (I2C_MAX_STRETCH&0xFF)
248 boolean i2c_init(
void)
251 (
" cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
252 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
253 " cbi %[SDAOUT],%[SDAPIN] ;clear SDA output value \n\t"
254 " cbi %[SCLOUT],%[SCLPIN] ;clear SCL output value \n\t"
255 " clr r24 ;set return value to false \n\t"
256 " clr r25 ;set return value to false \n\t"
257 " sbis %[SDAIN],%[SDAPIN] ;check for SDA high\n\t"
258 " ret ;if low return with false \n\t"
259 " sbis %[SCLIN],%[SCLPIN] ;check for SCL high \n\t"
260 " ret ;if low return with false \n\t"
261 " ldi r24,1 ;set return value to true \n\t"
264 [SCLDDR]
"I" (SCL_DDR), [SCLPIN]
"I" (SCL_PIN),
265 [SCLIN]
"I" (SCL_IN), [SCLOUT]
"I" (SCL_OUT),
266 [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
267 [SDAIN]
"I" (SDA_IN), [SDAOUT]
"I" (SDA_OUT));
271 bool i2c_start(uint8_t addr)
276 " cli ;clear IRQ bit \n\t"
278 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
279 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
280 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
281 " rcall ass_i2c_delay_half ;wait T/2 \n\t"
282 " rcall ass_i2c_write ;now write address \n\t"
284 : : [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
285 [SCLIN]
"I" (SCL_IN),[SCLPIN]
"I" (SCL_PIN));
289 bool i2c_rep_start(uint8_t addr)
297 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
298 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
299 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
300 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
301 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
302 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
303 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
304 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
305 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
306 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
307 " rcall ass_i2c_write \n\t"
309 : : [SCLDDR]
"I" (SCL_DDR), [SCLPIN]
"I" (SCL_PIN),[SCLIN]
"I" (SCL_IN),
310 [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN));
314 void i2c_start_wait(uint8_t addr)
318 " push r24 ;save original parameter \n\t"
319 "_Li2c_start_wait1: \n\t"
320 " pop r24 ;restore original parameter\n\t"
321 " push r24 ;and save again \n\t"
323 " cli ;disable interrupts \n\t"
325 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
326 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
327 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
328 " rcall ass_i2c_delay_half ;delay T/2 \n\t"
329 " rcall ass_i2c_write ;write address \n\t"
330 " tst r24 ;if device not busy -> done \n\t"
331 " brne _Li2c_start_wait_done \n\t"
332 " rcall ass_i2c_stop ;terminate write & enable IRQ \n\t"
333 " rjmp _Li2c_start_wait1 ;device busy, poll ack again \n\t"
334 "_Li2c_start_wait_done: \n\t"
335 " pop __tmp_reg__ ;pop off orig argument \n\t"
337 : : [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN),
338 [SCLIN]
"I" (SCL_IN),[SCLPIN]
"I" (SCL_PIN));
345 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
346 " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
347 " rcall ass_i2c_delay_half ;T/2 delay \n\t"
348 " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
349 " rcall ass_i2c_delay_half ;T/2 delay \n\t"
350 " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
351 " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
352 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
353 " rcall ass_i2c_delay_half \n\t"
355 " sei ;enable interrupts again!\n\t"
357 : : [SCLDDR]
"I" (SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (SCL_IN),
358 [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN));
361 bool i2c_write(uint8_t value)
365 " sec ;set carry flag \n\t"
366 " rol r24 ;shift in carry and shift out MSB \n\t"
367 " rjmp _Li2c_write_first \n\t"
368 "_Li2c_write_bit:\n\t"
369 " lsl r24 ;left shift into carry ;; 1C\n\t"
370 "_Li2c_write_first:\n\t"
371 " breq _Li2c_get_ack ;jump if TXreg is empty;; +1 = 2C \n\t"
372 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 4C \n\t"
376 " brcc _Li2c_write_low ;;+1/+2=5/6C\n\t"
377 " nop ;; +1 = 7C \n\t"
378 " cbi %[SDADDR],%[SDAPIN] ;release SDA ;; +2 = 9C \n\t"
379 " rjmp _Li2c_write_high ;; +2 = 11C \n\t"
380 "_Li2c_write_low: \n\t"
381 " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; +2 = 9C \n\t"
382 " rjmp _Li2c_write_high ;;+2 = 11C \n\t"
383 "_Li2c_write_high: \n\t"
384 #
if I2C_DELAY_COUNTER >= 1
385 " rcall ass_i2c_delay_half ;delay T/2 ;;+X = 11C+X\n\t"
387 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;;+2 = 13C+X\n\t"
388 " cln ;clear N-bit ;;+1 = 14C+X\n\t"
392 " sbis %[SCLIN],%[SCLPIN] ;check for SCL high ;;+2 = 16C+X\n\t"
393 " rcall ass_i2c_wait_scl_high \n\t"
394 " brpl _Ldelay_scl_high ;;+2 = 18C+X\n\t"
395 "_Li2c_write_return_false: \n\t"
396 " clr r24 ; return false because of timeout \n\t"
397 " rjmp _Li2c_write_return \n\t"
398 "_Ldelay_scl_high: \n\t"
399 #
if I2C_DELAY_COUNTER >= 1
400 " rcall ass_i2c_delay_half ;delay T/2 ;;+X= 18C+2X\n\t"
402 " rjmp _Li2c_write_bit \n\t"
403 " ;; +2 = 20C +2X for one bit-loop \n\t"
404 "_Li2c_get_ack: \n\t"
405 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 5C \n\t"
408 " cbi %[SDADDR],%[SDAPIN] ;release SDA ;;+2 = 7C \n\t"
409 #
if I2C_DELAY_COUNTER >= 1
410 " rcall ass_i2c_delay_half ;delay T/2 ;; +X = 7C+X \n\t"
412 " clr r25 ;; 17C+2X \n\t"
413 " clr r24 ;return 0 ;; 14C + X \n\t"
414 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; +2 = 9C+X\n\t"
415 "_Li2c_ack_wait: \n\t"
416 " cln ; clear N-bit ;; 10C + X\n\t"
418 " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X \n\t"
419 " rcall ass_i2c_wait_scl_high \n\t"
420 " brmi _Li2c_write_return_false ;; 13C + X \n\t "
421 " sbis %[SDAIN],%[SDAPIN] ;if SDA hi -> return 0 ;; 15C + X \n\t"
422 " ldi r24,1 ;return true ;; 16C + X \n\t"
423 #
if I2C_DELAY_COUNTER >= 1
424 " rcall ass_i2c_delay_half ;delay T/2 ;; 16C + 2X \n\t"
426 "_Li2c_write_return: \n\t"
429 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
431 " ;; + 4 = 17C + 2X for acknowldge bit"
433 [SCLDDR]
"I" (SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (SCL_IN),
434 [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN), [SDAIN]
"I" (SDA_IN));
438 uint8_t i2c_read(
bool last)
443 "_Li2c_read_bit: \n\t"
444 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
445 " cbi %[SDADDR],%[SDAPIN] ;release SDA(prev. ACK);; 4C \n\t"
449 #
if I2C_DELAY_COUNTER >= 1
450 " rcall ass_i2c_delay_half ;delay T/2 ;; 4C+X \n\t"
452 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 6C + X \n\t"
453 #
if I2C_DELAY_COUNTER >= 1
454 " rcall ass_i2c_delay_half ;delay T/2 ;; 6C + 2X \n\t"
456 " cln ; clear N-bit ;; 7C + 2X \n\t"
460 " sbis %[SCLIN], %[SCLPIN] ;check for SCL high ;; 9C +2X \n\t"
461 " rcall ass_i2c_wait_scl_high \n\t"
462 " brmi _Li2c_read_return ;return if timeout ;; 10C + 2X\n\t"
463 " clc ;clear carry flag ;; 11C + 2X\n\t"
464 " sbic %[SDAIN],%[SDAPIN] ;if SDA is high ;; 11C + 2X\n\t"
465 " sec ;set carry flag ;; 12C + 2X\n\t"
466 " rol r23 ;store bit ;; 13C + 2X\n\t"
467 " brcc _Li2c_read_bit ;while receiv reg not full \n\t"
468 " ;; 15C + 2X for one bit loop \n\t"
470 "_Li2c_put_ack: \n\t"
471 " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
472 " cpi r24,0 ;; 3C \n\t"
473 " breq _Li2c_put_ack_low ;if (ack=0) ;; 5C \n\t"
474 " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
475 " rjmp _Li2c_put_ack_high \n\t"
476 "_Li2c_put_ack_low: ;else \n\t"
477 " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; 7C \n\t"
478 "_Li2c_put_ack_high: \n\t"
482 #
if I2C_DELAY_COUNTER >= 1
483 " rcall ass_i2c_delay_half ;delay T/2 ;; 7C + X \n\t"
485 " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 9C +X \n\t"
486 " cln ;clear N ;; +1 = 10C\n\t"
489 " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X\n\t"
490 " rcall ass_i2c_wait_scl_high \n\t"
491 #
if I2C_DELAY_COUNTER >= 1
492 " rcall ass_i2c_delay_half ;delay T/2 ;; 11C + 2X\n\t"
494 "_Li2c_read_return: \n\t"
497 "sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
498 " mov r24,r23 ;; 12C + 2X \n\t"
499 " clr r25 ;; 13 C + 2X\n\t"
502 [SCLDDR]
"I" (SCL_DDR), [SCLPIN]
"I" (SCL_PIN), [SCLIN]
"I" (SCL_IN),
503 [SDADDR]
"I" (SDA_DDR), [SDAPIN]
"I" (SDA_PIN), [SDAIN]
"I" (SDA_IN)
509 #error "ONLY SUPPORTED ON AVR PROCESSORS"
510 #endif // defined (__AVR__)