]>
Commit | Line | Data |
---|---|---|
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 |