]> cloudbase.mooo.com Git - avrcpm.git/blob - avr/i2c.asm
Remove unsupported experimental ADC support
[avrcpm.git] / avr / i2c.asm
1 ; I2C (TWI) master interface.
2 ; This is part of the Z80-CP/M emulator written by Sprite_tm.
3 ;
4 ; Copyright (C) 2013 Leo C.
5 ;
6 ; This file is part of avrcpm.
7 ;
8 ; avrcpm is free software: you can redistribute it and/or modify it
9 ; under the terms of the GNU General Public License as published by
10 ; the Free Software Foundation, either version 3 of the License, or
11 ; (at your option) any later version.
12 ;
13 ; avrcpm is distributed in the hope that it will be useful,
14 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ; GNU General Public License for more details.
17 ;
18 ; You should have received a copy of the GNU General Public License
19 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
20 ;
21 ; $Id: i2c.asm 242 2015-12-11 16:05:52Z rapid $
22 ;
23
24 #if I2C_SUPPORT
25
26
27 /* General TWI Master status codes */
28 #define TWI_START 0x08 /* START has been transmitted */
29 #define TWI_REP_START 0x10 /* Repeated START has been transmitted */
30 #define TWI_ARB_LOST 0x38 /* Arbitration lost */
31
32 /* TWI Master Transmitter status codes */
33 #define TWI_MTX_ADR_ACK 0x18 /* SLA+W has been transmitted and ACK received */
34 #define TWI_MTX_ADR_NACK 0x20 /* SLA+W has been transmitted and NACK received */
35 #define TWI_MTX_DATA_ACK 0x28 /* Data byte has been transmitted and ACK received */
36 #define TWI_MTX_DATA_NACK 0x30 /* Data byte has been transmitted and NACK received */
37
38 /* TWI Master Receiver status codes */
39 #define TWI_MRX_ADR_ACK 0x40 /* SLA+R has been transmitted and ACK received */
40 #define TWI_MRX_ADR_NACK 0x48 /* SLA+R has been transmitted and NACK received */
41 #define TWI_MRX_DATA_ACK 0x50 /* Data byte has been received and ACK transmitted */
42 #define TWI_MRX_DATA_NACK 0x58 /* Data byte has been received and NACK transmitted */
43
44 /* TWI Miscellaneous status codes */
45 #define TWI_NO_STATE 0xF8 /* No relevant state information available */
46 #define TWI_BUS_ERROR 0x00 /* Bus error due to an illegal START or STOP condition */
47
48
49 #define I2C_BR ((F_CPU / (2 * I2C_CLOCK)) - 8) /* I2C Bit Rate */
50
51 ;----------------------------------------------------------------------
52 ;
53 ; TWINT: TWI Interrupt Flag
54 ; TWEA: TWI Enable Acknowledge Bit
55 ; TWSTA: TWI START Condition Bit
56 ; TWSTO: TWI STOP Condition Bit
57 ; TWEN: TWI Enable Bit
58 ; TWIE: TWI Interrupt Enable
59 ;
60 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
61 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)| (1<<TWEA)
62 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
63 ;
64 ; default:
65 ; (1<<TWEN)| (1<<TWINT)| (1<<TWSTO)
66 ;
67 ; Init:
68 ; (1<<TWEN)
69 ;
70 ; start read/write:
71 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
72 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
73 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
74 ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
75 ;
76 ; wait ready:
77 ; (1<<TWIE)|(1<<TWSTO)
78 ;
79 ;----------------------------------------------------------------------
80 ;
81 ;i2c_result
82 ;
83 ; 0b10000000 Busy (Transmission in progress)
84 ; 0b01000000 Timeout
85 ; 0b00010000 Read after Write
86 ; 0b00001000 Start transmitted
87 ; 0b00000100 Slave acknowledged address
88 ; 0b00000010 Data byte(s) transmitted/received
89 ; 0b00000001 Transmission completed
90 ;
91 ;
92 ;----------------------------------------------------------------------
93
94 .dseg
95
96 i2c_var:
97 i2ci_idx:
98 .byte 1
99 i2c_result:
100 .byte 1
101 i2c_txcnt:
102 .byte 1
103 i2c_rxcnt:
104 .byte 1
105 i2c_buf:
106 .byte I2C_BUFSIZE
107
108 .equ oi2ci_idx = 0
109 .equ oi2c_result = 1
110 .equ oi2c_txcnt = 2
111 .equ oi2c_rxcnt = 3
112 .equ oi2c_buf = 4
113
114 ;------------------------------------------------------------------
115
116 .cseg
117
118
119 INTERRUPT TWIaddr
120
121 push temp
122 in temp,sreg
123 push temp
124 inm8 temp,TWSR
125 .if I2C_STATE_DEBUG
126 push temp
127 .endif
128 push temp2
129 push temp3
130 push zh
131 push zl
132
133 ldiw z,i2c_var
134 ldd temp2,z+oi2ci_idx
135 ldd temp3,z+oi2c_result
136
137 cpi temp,TWI_START
138 breq i2ci_START
139 cpi temp,TWI_REP_START
140 breq i2ci_REP_START
141 cpi temp,TWI_MTX_ADR_ACK
142 breq i2ci_MTX_ADR_ACK
143 cpi temp,TWI_MTX_DATA_ACK
144 breq i2ci_MTX_DATA_ACK
145 cpi temp,TWI_MTX_DATA_NACK
146 breq i2ci_MTX_DATA_NACK
147 cpi temp,TWI_MRX_ADR_ACK
148 breq i2ci_MRX_ADR_ACK
149 cpi temp,TWI_MRX_DATA_ACK
150 breq i2ci_MRX_DATA_ACK
151 cpi temp,TWI_MRX_DATA_NACK
152 breq i2ci_MRX_DATA_NACK
153
154 rjmp i2ci_default
155
156 i2ci_REP_START: ;Repeated START has been transmitted
157 cbr temp3,0b00010000
158 i2ci_START: ;START has been transmitted
159 clr temp2 ;reset buffer index
160 ori temp3,0b10001000
161 rjmp i2ci_11
162 i2ci_MTX_ADR_ACK: ;SLA+W has been transmitted and ACK received
163 ori temp3,0b00000100
164 rjmp i2ci_11
165 i2ci_MTX_DATA_ACK: ;Data byte has been transmitted and ACK received
166 ori temp3,0b00000010
167 i2ci_11:
168 ldd temp,z+oi2c_txcnt
169 cp temp2,temp ;all bytes transmited?
170 brsh i2ci_12 ; yes
171 add zl,temp2
172 adc zh,_0
173 inc temp2
174 ldd temp,z+oi2c_buf ;next byte
175 outm8 TWDR,temp
176 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
177 rjmp i2ci_end
178
179 i2ci_MTX_DATA_NACK: ;Data byte has been transmitted and NACK received
180 i2ci_12:
181 ori temp3,0b00000001 ;tx complete
182 sbrs temp3,4 ;Read after Write?
183 rjmp i2ci_default ; no, stop transceiver
184
185 lds temp,i2c_buf
186 sbr temp,0x01 ;<SLA+R>
187 sts i2c_buf,temp
188 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
189 rjmp i2ci_end
190
191 i2ci_MRX_ADR_ACK: ;SLA+R has been transmitted and ACK received
192 ori temp3,0b00000100
193 rjmp i2ci_31
194
195 i2ci_MRX_DATA_ACK: ;Data byte has been received and ACK transmitted
196 ori temp3,0b00000010
197 add zl,temp2
198 adc zh,_0
199 inc temp2
200 inm8 temp,TWDR
201 std z+oi2c_buf,temp
202 i2ci_31:
203 lds temp,i2c_rxcnt
204 dec temp
205 cp temp2,temp
206 brsh i2ci_32
207 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)
208 rjmp i2ci_end
209 i2ci_32:
210 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
211 rjmp i2ci_end
212
213 i2ci_MRX_DATA_NACK: ;Data byte has been received and NACK transmitted
214 ori temp3,0b00000011 ;rx complete
215 add zl,temp2
216 adc zh,_0
217 inc temp2
218 inm8 temp,TWDR
219 std z+oi2c_buf,temp
220 ; fall thru
221
222 i2ci_default:
223 andi temp3,~0b10000000
224 ldi temp,(1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO)
225
226 i2ci_end:
227 outm8 TWCR,temp
228 sts i2c_result,temp3
229 sts i2ci_idx,temp2
230 pop zl
231 pop zh
232 pop temp3
233 pop temp2
234
235 .if I2C_STATE_DEBUG
236 ldi temp,'|'
237 sei
238 rcall uartputc
239 pop temp
240 rcall printhex
241 .endif
242
243 pop temp
244 out sreg,temp
245 pop temp
246 reti
247
248 ;------------------------------------------------------------------
249
250 i2c_init:
251 outm8 TWCR,_0 ;Disable TWI, disable TWI interrupt.
252 ;(Reset TWI hardware state machine.)
253 ldi temp,(5 * TC_1US+3)/3 ;1 Delay 5 us
254 i2c_iwl: ;
255 dec temp ;1
256 brne i2c_iwl ;2
257
258 ldi temp,I2C_BR
259 outm8 TWBR,temp
260 outm8 TWDR,_255 ;
261 ldi temp,(1<<TWEN) ;Enable TWI, disable TWI interrupt.
262 outm8 TWCR,temp
263
264 ; sts i2c_result,_0
265
266 ret
267
268 ;------------------------------------------------------------------
269
270 i2c_waitready:
271
272 ldi temp,30
273 sts delay_timer1,temp
274 i2c_wrl:
275 inm8 temp,TWCR
276 andi temp,(1<<TWIE)|(1<<TWSTO)
277 breq i2c_wre
278 lds temp,delay_timer1
279 tst temp
280 brne i2c_wrl
281
282 rcall i2c_init
283
284 ldi temp,0b01000000
285
286 i2c_wre:
287 lds _tmp0,i2c_result
288 or temp,_tmp0
289 sts i2c_result,temp
290 ret
291
292 ;------------------------------------------------------------------
293 ;
294 ; z: Pointer to the data to write.
295 ; First byte is slave address
296 ; temp2: Number of bytes to write including address byte.
297 ;
298
299 i2c_write:
300
301 rcall i2c_waitready
302 cpi temp,0b01000000
303 brsh i2c_we
304 push zh
305 push zl
306 push yh
307 push yl
308
309 ldiw y,i2c_var
310 ldi temp,0b10000000
311 std y+oi2c_result,temp ;result = busy
312 std y+oi2c_txcnt,temp2 ;store size
313 adiw y,oi2c_buf
314 ld temp,z+ ;get SLA
315 cbr temp,0x01 ;
316 i2c_wl:
317 st y+,temp
318 dec temp2
319 breq i2c_wle
320 ld temp,z+
321 rjmp i2c_wl
322 i2c_wle:
323 ; Enable TWI, TWI int and initiate start condition
324 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
325 outm8 TWCR,temp
326
327 pop yl
328 pop yh
329 pop zl
330 pop zh
331 i2c_we:
332 ret
333
334
335 ;------------------------------------------------------------------
336 ;
337 ; z: Pointer to data buffer.
338 ; First byte of buffer is slave address
339 ; temp2: Buffer len. (Number of bytes to read + address byte.)
340 ;
341 ; temp: return (fail < 0, else succsess)
342
343 i2c_read:
344 rcall i2c_waitready
345 cpi temp,0b01000000
346 brsh i2c_re
347
348 push zh
349 push zl
350 push yh
351 push yl
352 ldiw y,i2c_var
353 ldi temp,0b10000000
354 std y+oi2c_result,temp ;result = busy
355 std y+oi2c_rxcnt,temp2 ;store size
356 ld temp,z
357 sbr temp,0x01 ;<SLA+R>
358 std y+oi2c_buf,temp
359
360 ; Enable TWI, TWI int and initiate start condition
361 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
362 outm8 TWCR,temp
363
364 rcall i2c_waitready
365
366 sbrs temp,1 ;at least 1 byte received
367 rjmp i2c_ex ;
368 ldd temp2,y+oi2ci_idx
369 adiw y,oi2c_buf
370 i2c_rl:
371 ld _tmp0,y+
372 st z+,_tmp0
373 dec temp2
374 brne i2c_rl
375
376 i2c_ex:
377 pop yl
378 pop yh
379 pop zl
380 pop zh
381 i2c_re:
382 lds temp,i2c_result
383 ret
384
385 ;------------------------------------------------------------------
386 ;
387 ; z: Pointer to the data to write/read.
388 ; First byte is slave address
389 ; temp2: Number of bytes to read, including address byte.
390 ;
391
392 i2c_write_read:
393
394 rcall i2c_waitready
395 cpi temp,0b01000000
396 brsh i2c_wr_e
397 push yh
398 push yl
399 push zh
400 push zl
401
402 ldiw y,i2c_var
403 ldi temp,0b10010000
404 std y+oi2c_result,temp ;result = busy
405 ldi temp,2
406 std y+oi2c_txcnt,temp ;store tx size
407 std y+oi2c_rxcnt,temp2 ;store rx size
408 adiw y,oi2c_buf
409
410 mov _tmp0,temp ;save tx count
411 ld temp,z+ ;get SLA
412 cbr temp,0x01 ;
413 i2c_wr_wl:
414 st y+,temp
415 dec _tmp0
416 breq i2c_wr_wle
417 ld temp,z+
418 rjmp i2c_wr_wl
419 i2c_wr_wle:
420 ; Enable TWI, TWI int and initiate start condition
421 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
422 outm8 TWCR,temp
423
424 rcall i2c_waitready
425
426 sbrc temp,4 ;
427 rjmp i2c_wr_ex ;
428 sbrs temp,1 ;at least 1 byte received
429 rjmp i2c_wr_ex ;
430 ldiw y,i2c_var
431 ldd temp2,y+oi2ci_idx
432 adiw y,oi2c_buf
433 pop zl
434 pop zh
435 push zh
436 push zl
437 i2c_wr_rl:
438 ld _tmp0,y+
439 st z+,_tmp0
440 dec temp2
441 brne i2c_wr_rl
442
443 i2c_wr_ex:
444 pop zl
445 pop zh
446 pop yl
447 pop yh
448 i2c_wr_e:
449 lds temp,i2c_result
450 ret
451
452
453 ;------------------------------------------------------------------
454
455 .dseg
456
457 vi2c_stat:
458 .byte 1
459 vi2c_blen:
460 .byte 1
461 vi2c_addr:
462 .byte 2
463
464 .cseg
465
466 vi2c_stat_get:
467 lds temp,i2c_result
468 ret
469
470 vi2c_param_get:
471 tst temp3
472 brne vi2c_pg2
473
474 lds temp,i2ci_idx
475 rjmp vi2c_pge
476
477 vi2c_pg2:
478 ldiw z,vi2c_blen
479 add zl,temp3
480 adc zh,_0
481 ld temp,z
482 vi2c_pge:
483 ret
484
485 vi2c_param_set:
486 ldiw z,vi2c_blen
487 add zl,temp3
488 adc zh,_0
489 st z,temp
490 ret
491
492 ;------------------------------------------------------------------
493 ;
494 ; vi2c_addr: Pointer to the data to write.
495 ; First byte is slave address
496 ; vi2c_blen: Number of bytes to write including address byte.
497 ;
498
499 vi2c_write:
500
501 rcall i2c_waitready
502 cpi temp,0b01000000
503 brsh vi2c_wex
504 ldiw z,i2c_var
505 ldi temp,0b10000000
506 std z+oi2c_result,temp ;result = busy
507 lds temp3,vi2c_blen
508 cpi temp3,I2C_BUFSIZE
509 brlo vi2c_w1
510 ldi temp3,I2C_BUFSIZE
511 vi2c_w1:
512 std z+oi2c_txcnt,temp3 ;store size
513 adiw z,oi2c_buf
514 ldsw x,vi2c_addr
515 lcall dram_read_pp
516 cbr temp,0x01
517 vi2c_wl:
518 st z+,temp
519 dec temp3
520 breq vi2c_wle
521 lcall dram_read_pp
522 rjmp vi2c_wl
523 vi2c_wle:
524 ; Enable TWI, TWI int and initiate start condition
525 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
526 outm8 TWCR,temp
527 vi2c_wex:
528 ret
529
530 ;------------------------------------------------------------------
531 ;
532 ; x: Pointer to the data buffer.
533 ; First byte is slave address
534 ; temp3: Buffer len. (Number of bytes to read + address byte.)
535 ;
536
537 vi2c_read:
538
539 rcall i2c_waitready
540 cpi temp,0b01000000
541 brsh vi2c_rex
542
543 ldiw z,i2c_var
544 ldi temp,0b10000000
545 std z+oi2c_result,temp ;result = busy
546 lds temp3,vi2c_blen
547 cpi temp3,I2C_BUFSIZE
548 brlo vi2c_r1
549 ldi temp3,I2C_BUFSIZE
550 vi2c_r1:
551 std z+oi2c_rxcnt,temp3 ;store size
552 adiw z,oi2c_buf
553 ldsw x,vi2c_addr
554 lcall dram_read_pp
555 sbr temp,0x01
556 st z+,temp
557 dec temp3
558
559 ; Enable TWI, TWI int and initiate start condition
560 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
561 outm8 TWCR,temp
562
563 rcall i2c_waitready
564 andi temp,0b00000011
565 breq vi2c_rex ;
566 vi2c_rl:
567 ld temp,z+
568 lcall dram_write_pp
569 dec temp3
570 brne vi2c_rl
571
572 vi2c_rex:
573 ret
574
575 ;------------------------------------------------------------------
576 ;
577 ; vi2c_addr: Pointer to the data to write.
578 ; First byte is slave address
579 ; temp2: Number of bytes to write including address byte.
580 ;
581 ; vi2c_blen: Number of bytes to read including address byte.
582 ;
583
584 vi2c_write_read:
585
586 rcall i2c_waitready
587 cpi temp,0b01000000
588 brsh vi2c_wr_ex
589 ldiw z,i2c_var
590 ldi temp,0b10010000
591 std z+oi2c_result,temp ;result = busy
592 std z+oi2c_txcnt,temp2 ;store tx size
593 lds temp3,vi2c_blen
594 cpi temp3,I2C_BUFSIZE
595 brlo vi2c_wr_w1
596 ldi temp3,I2C_BUFSIZE
597 vi2c_wr_w1:
598 std z+oi2c_rxcnt,temp3 ;store rx size
599 adiw z,oi2c_buf
600 ldsw x,vi2c_addr
601 lcall dram_read_pp
602 cbr temp,0x01
603 vi2c_wr_wl:
604 st z+,temp
605 dec temp2
606 breq vi2c_wr_wle
607 lcall dram_read_pp
608 rjmp vi2c_wr_wl
609 vi2c_wr_wle:
610 ; Enable TWI, TWI int and initiate start condition
611 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
612 outm8 TWCR,temp
613
614 rcall i2c_waitready
615
616 sbrc temp,4 ;
617 rjmp i2c_wr_ex ;
618 andi temp,0b00000011 ;
619 breq vi2c_rex ;
620 ldiw z,i2c_var
621 ldd temp2,z+oi2ci_idx
622 adiw z,oi2c_buf+1
623 ldsw x,vi2c_addr
624 adiw x,1
625 rjmp vi2c_wr_rl0
626 vi2c_wr_rl:
627 ld temp,z+
628 lcall dram_write_pp
629 vi2c_wr_rl0:
630 dec temp2
631 brne vi2c_wr_rl
632
633 vi2c_wr_ex:
634 ret
635
636 ;------------------------------------------------------------------
637
638
639 vi2c_ctrl:
640 cpi temp,1 ;read ?
641 brne vi2c_c1
642 rjmp vi2c_read
643
644 vi2c_c1:
645 cpi temp,2 ;write?
646 brne vi2c_c2
647 rjmp vi2c_write
648 vi2c_c2:
649 cpi temp,3 ;write and read ?
650 brne vi2c_c3
651 ldi temp2,2 ;write 1 byte (subaddress), then read
652 rjmp vi2c_write_read
653 vi2c_c3:
654 vi2c_ce:
655 ret
656
657 ;------------------------------------------------------------------
658
659
660 pcf8574_in:
661 ; make a buffer on stack
662 push _255 ;place holder for input value
663 in zh,sph
664 in zl,spl
665 ldi temp,0x20 ;pcf8574 address (7 bit)
666 add temp,temp3
667 lsl temp
668 push temp ;slave address
669 ldi temp2,2
670 rcall i2c_read
671 pop temp ;remove slave address from stack
672 pop temp ;return input value
673 ret
674
675 pcf8574_out:
676 ; make a buffer on stack
677 push temp ;output value
678 in zh,sph
679 in zl,spl
680 ldi temp,0x20 ;pcf8574 address (7 bit)
681 add temp,temp3
682 lsl temp
683 push temp ;slave address
684 ldi temp2,2
685 rcall i2c_write
686 pop temp ;remove buffer from stack
687 pop temp ;
688 ret
689
690
691 ;------------------------------------------------------------------
692
693 #if I2C_UART_SUPPORT
694
695 SC16IS740_in:
696 ; make a buffer on stack
697 swap temp3
698 lsr temp3
699 push temp3 ;register address
700 in zh,sph
701 in zl,spl
702 ldi temp,SC16IS740_ADDR ;chip address (8 bit)
703 push temp ;slave address
704 ldi temp2,2
705 rcall i2c_write_read
706 pop temp ;remove slave address from stack
707 pop temp ;return input value
708 ret
709
710 SC16IS740_out:
711 ; make a buffer on stack
712 push temp ;output value
713 swap temp3
714 lsr temp3
715 push temp3 ;register address
716 in zh,sph
717 in zl,spl
718 ldi temp,SC16IS740_ADDR ;chip address (8 bit)
719 push temp ;slave address
720 ldi temp2,3
721 rcall i2c_write
722 pop temp ;remove buffer from stack
723 pop temp ;
724 pop temp ;
725 ret
726
727 #endif /* I2C_UART_SUPPORT */
728
729 #endif /* I2C_SUPPORT */
730 ;------------------------------------------------------------------
731 ; vim:set ts=8 noet nowrap