]>
Commit | Line | Data |
---|---|---|
4bd49b80 | 1 | ; I2C (TWI) master interface. |
d8fa6a36 L |
2 | ; This is part of the Z80-CP/M emulator written by Sprite_tm. |
3 | ; | |
825ecc9d | 4 | ; Copyright (C) 2013 Leo C. |
d8fa6a36 L |
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 | ; | |
12a27f27 | 21 | ; $Id: i2c.asm 242 2015-12-11 16:05:52Z rapid $ |
d8fa6a36 L |
22 | ; |
23 | ||
4bd49b80 | 24 | #if I2C_SUPPORT |
d8fa6a36 | 25 | |
12a27f27 | 26 | |
d8fa6a36 L |
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 | |
4bd49b80 | 59 | ; |
d8fa6a36 L |
60 | ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT) |
61 | ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)| (1<<TWEA) | |
62 | ; (1<<TWEN)|(1<<TWIE)|(1<<TWINT) | |
4bd49b80 | 63 | ; |
d8fa6a36 L |
64 | ; default: |
65 | ; (1<<TWEN)| (1<<TWINT)| (1<<TWSTO) | |
4bd49b80 | 66 | ; |
d8fa6a36 L |
67 | ; Init: |
68 | ; (1<<TWEN) | |
4bd49b80 | 69 | ; |
d8fa6a36 L |
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) | |
4bd49b80 | 75 | ; |
d8fa6a36 L |
76 | ; wait ready: |
77 | ; (1<<TWIE)|(1<<TWSTO) | |
79986122 L |
78 | ; |
79 | ;---------------------------------------------------------------------- | |
80 | ; | |
12a27f27 L |
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 | ; | |
79986122 | 91 | ; |
d8fa6a36 L |
92 | ;---------------------------------------------------------------------- |
93 | ||
94 | .dseg | |
95 | ||
96 | i2c_var: | |
97 | i2ci_idx: | |
98 | .byte 1 | |
99 | i2c_result: | |
100 | .byte 1 | |
12a27f27 L |
101 | i2c_txcnt: |
102 | .byte 1 | |
103 | i2c_rxcnt: | |
d8fa6a36 L |
104 | .byte 1 |
105 | i2c_buf: | |
106 | .byte I2C_BUFSIZE | |
107 | ||
108 | .equ oi2ci_idx = 0 | |
109 | .equ oi2c_result = 1 | |
12a27f27 L |
110 | .equ oi2c_txcnt = 2 |
111 | .equ oi2c_rxcnt = 3 | |
112 | .equ oi2c_buf = 4 | |
d8fa6a36 L |
113 | |
114 | ;------------------------------------------------------------------ | |
115 | ||
116 | .cseg | |
117 | ||
118 | ||
119 | INTERRUPT TWIaddr | |
4bd49b80 | 120 | |
d8fa6a36 L |
121 | push temp |
122 | in temp,sreg | |
123 | push temp | |
12a27f27 L |
124 | inm8 temp,TWSR |
125 | .if I2C_STATE_DEBUG | |
126 | push temp | |
127 | .endif | |
d8fa6a36 | 128 | push temp2 |
12a27f27 | 129 | push temp3 |
d8fa6a36 L |
130 | push zh |
131 | push zl | |
132 | ||
133 | ldiw z,i2c_var | |
4bd49b80 | 134 | ldd temp2,z+oi2ci_idx |
12a27f27 | 135 | ldd temp3,z+oi2c_result |
d8fa6a36 | 136 | |
d8fa6a36 L |
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 | |
12a27f27 L |
145 | cpi temp,TWI_MTX_DATA_NACK |
146 | breq i2ci_MTX_DATA_NACK | |
d8fa6a36 L |
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 | |
12a27f27 | 153 | |
d8fa6a36 L |
154 | rjmp i2ci_default |
155 | ||
12a27f27 L |
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? | |
79986122 | 170 | brsh i2ci_12 ; yes |
d8fa6a36 L |
171 | add zl,temp2 |
172 | adc zh,_0 | |
173 | inc temp2 | |
79986122 | 174 | ldd temp,z+oi2c_buf ;next byte |
d8fa6a36 L |
175 | outm8 TWDR,temp |
176 | ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT) | |
177 | rjmp i2ci_end | |
178 | ||
12a27f27 | 179 | i2ci_MTX_DATA_NACK: ;Data byte has been transmitted and NACK received |
d8fa6a36 | 180 | i2ci_12: |
12a27f27 L |
181 | ori temp3,0b00000001 ;tx complete |
182 | sbrs temp3,4 ;Read after Write? | |
183 | rjmp i2ci_default ; no, stop transceiver | |
d8fa6a36 | 184 | |
12a27f27 L |
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 | |
d8fa6a36 L |
197 | add zl,temp2 |
198 | adc zh,_0 | |
199 | inc temp2 | |
200 | inm8 temp,TWDR | |
201 | std z+oi2c_buf,temp | |
12a27f27 L |
202 | i2ci_31: |
203 | lds temp,i2c_rxcnt | |
d8fa6a36 L |
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 | ||
12a27f27 L |
213 | i2ci_MRX_DATA_NACK: ;Data byte has been received and NACK transmitted |
214 | ori temp3,0b00000011 ;rx complete | |
d8fa6a36 L |
215 | add zl,temp2 |
216 | adc zh,_0 | |
12a27f27 | 217 | inc temp2 |
d8fa6a36 L |
218 | inm8 temp,TWDR |
219 | std z+oi2c_buf,temp | |
220 | ; fall thru | |
221 | ||
222 | i2ci_default: | |
12a27f27 L |
223 | andi temp3,~0b10000000 |
224 | ldi temp,(1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO) | |
d8fa6a36 | 225 | |
4bd49b80 | 226 | i2ci_end: |
d8fa6a36 | 227 | outm8 TWCR,temp |
12a27f27 | 228 | sts i2c_result,temp3 |
d8fa6a36 L |
229 | sts i2ci_idx,temp2 |
230 | pop zl | |
231 | pop zh | |
12a27f27 | 232 | pop temp3 |
d8fa6a36 | 233 | pop temp2 |
12a27f27 L |
234 | |
235 | .if I2C_STATE_DEBUG | |
236 | ldi temp,'|' | |
237 | sei | |
238 | rcall uartputc | |
239 | pop temp | |
240 | rcall printhex | |
241 | .endif | |
242 | ||
d8fa6a36 L |
243 | pop temp |
244 | out sreg,temp | |
245 | pop temp | |
246 | reti | |
247 | ||
248 | ;------------------------------------------------------------------ | |
249 | ||
250 | i2c_init: | |
12a27f27 L |
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 | ||
d8fa6a36 L |
258 | ldi temp,I2C_BR |
259 | outm8 TWBR,temp | |
260 | outm8 TWDR,_255 ; | |
79986122 | 261 | ldi temp,(1<<TWEN) ;Enable TWI, disable TWI interrupt. |
d8fa6a36 L |
262 | outm8 TWCR,temp |
263 | ||
12a27f27 L |
264 | ; sts i2c_result,_0 |
265 | ||
d8fa6a36 L |
266 | ret |
267 | ||
268 | ;------------------------------------------------------------------ | |
269 | ||
270 | i2c_waitready: | |
79986122 L |
271 | |
272 | ldi temp,30 | |
273 | sts delay_timer1,temp | |
274 | i2c_wrl: | |
d8fa6a36 L |
275 | inm8 temp,TWCR |
276 | andi temp,(1<<TWIE)|(1<<TWSTO) | |
79986122 L |
277 | breq i2c_wre |
278 | lds temp,delay_timer1 | |
279 | tst temp | |
280 | brne i2c_wrl | |
281 | ||
12a27f27 L |
282 | rcall i2c_init |
283 | ||
284 | ldi temp,0b01000000 | |
285 | ||
79986122 | 286 | i2c_wre: |
12a27f27 L |
287 | lds _tmp0,i2c_result |
288 | or temp,_tmp0 | |
289 | sts i2c_result,temp | |
d8fa6a36 L |
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: | |
d8fa6a36 | 300 | |
79986122 | 301 | rcall i2c_waitready |
12a27f27 L |
302 | cpi temp,0b01000000 |
303 | brsh i2c_we | |
d8fa6a36 L |
304 | push zh |
305 | push zl | |
12a27f27 L |
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 ; | |
d8fa6a36 | 316 | i2c_wl: |
12a27f27 | 317 | st y+,temp |
d8fa6a36 L |
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 | ||
12a27f27 L |
327 | pop yl |
328 | pop yh | |
d8fa6a36 L |
329 | pop zl |
330 | pop zh | |
79986122 | 331 | i2c_we: |
d8fa6a36 L |
332 | ret |
333 | ||
334 | ||
335 | ;------------------------------------------------------------------ | |
336 | ; | |
337 | ; z: Pointer to data buffer. | |
338 | ; First byte of buffer is slave address | |
12a27f27 | 339 | ; temp2: Buffer len. (Number of bytes to read + address byte.) |
d8fa6a36 | 340 | ; |
12a27f27 | 341 | ; temp: return (fail < 0, else succsess) |
d8fa6a36 L |
342 | |
343 | i2c_read: | |
344 | rcall i2c_waitready | |
12a27f27 L |
345 | cpi temp,0b01000000 |
346 | brsh i2c_re | |
d8fa6a36 L |
347 | |
348 | push zh | |
349 | push zl | |
12a27f27 L |
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 | |
d8fa6a36 | 356 | ld temp,z |
12a27f27 L |
357 | sbr temp,0x01 ;<SLA+R> |
358 | std y+oi2c_buf,temp | |
d8fa6a36 L |
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 | ||
12a27f27 | 366 | sbrs temp,1 ;at least 1 byte received |
79986122 | 367 | rjmp i2c_ex ; |
12a27f27 L |
368 | ldd temp2,y+oi2ci_idx |
369 | adiw y,oi2c_buf | |
d8fa6a36 | 370 | i2c_rl: |
12a27f27 L |
371 | ld _tmp0,y+ |
372 | st z+,_tmp0 | |
d8fa6a36 L |
373 | dec temp2 |
374 | brne i2c_rl | |
375 | ||
376 | i2c_ex: | |
12a27f27 L |
377 | pop yl |
378 | pop yh | |
d8fa6a36 L |
379 | pop zl |
380 | pop zh | |
79986122 L |
381 | i2c_re: |
382 | lds temp,i2c_result | |
d8fa6a36 L |
383 | ret |
384 | ||
12a27f27 L |
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 | ||
d8fa6a36 L |
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: | |
79986122 | 467 | lds temp,i2c_result |
d8fa6a36 L |
468 | ret |
469 | ||
470 | vi2c_param_get: | |
12a27f27 L |
471 | tst temp3 |
472 | brne vi2c_pg2 | |
473 | ||
474 | lds temp,i2ci_idx | |
475 | rjmp vi2c_pge | |
476 | ||
477 | vi2c_pg2: | |
d8fa6a36 L |
478 | ldiw z,vi2c_blen |
479 | add zl,temp3 | |
480 | adc zh,_0 | |
481 | ld temp,z | |
12a27f27 | 482 | vi2c_pge: |
d8fa6a36 L |
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 | ||
12a27f27 L |
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 | ||
d8fa6a36 L |
530 | ;------------------------------------------------------------------ |
531 | ; | |
532 | ; x: Pointer to the data buffer. | |
533 | ; First byte is slave address | |
12a27f27 | 534 | ; temp3: Buffer len. (Number of bytes to read + address byte.) |
d8fa6a36 L |
535 | ; |
536 | ||
537 | vi2c_read: | |
79986122 | 538 | |
d8fa6a36 | 539 | rcall i2c_waitready |
12a27f27 L |
540 | cpi temp,0b01000000 |
541 | brsh vi2c_rex | |
d8fa6a36 L |
542 | |
543 | ldiw z,i2c_var | |
12a27f27 L |
544 | ldi temp,0b10000000 |
545 | std z+oi2c_result,temp ;result = busy | |
d8fa6a36 | 546 | lds temp3,vi2c_blen |
12a27f27 L |
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 | |
d8fa6a36 L |
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 | |
12a27f27 L |
564 | andi temp,0b00000011 |
565 | breq vi2c_rex ; | |
d8fa6a36 L |
566 | vi2c_rl: |
567 | ld temp,z+ | |
568 | lcall dram_write_pp | |
569 | dec temp3 | |
570 | brne vi2c_rl | |
571 | ||
79986122 | 572 | vi2c_rex: |
d8fa6a36 L |
573 | ret |
574 | ||
575 | ;------------------------------------------------------------------ | |
576 | ; | |
12a27f27 L |
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. | |
d8fa6a36 L |
582 | ; |
583 | ||
12a27f27 | 584 | vi2c_write_read: |
79986122 | 585 | |
d8fa6a36 | 586 | rcall i2c_waitready |
12a27f27 L |
587 | cpi temp,0b01000000 |
588 | brsh vi2c_wr_ex | |
d8fa6a36 | 589 | ldiw z,i2c_var |
12a27f27 L |
590 | ldi temp,0b10010000 |
591 | std z+oi2c_result,temp ;result = busy | |
592 | std z+oi2c_txcnt,temp2 ;store tx size | |
d8fa6a36 | 593 | lds temp3,vi2c_blen |
12a27f27 L |
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 | |
d8fa6a36 L |
599 | adiw z,oi2c_buf |
600 | ldsw x,vi2c_addr | |
601 | lcall dram_read_pp | |
602 | cbr temp,0x01 | |
12a27f27 | 603 | vi2c_wr_wl: |
d8fa6a36 | 604 | st z+,temp |
12a27f27 L |
605 | dec temp2 |
606 | breq vi2c_wr_wle | |
d8fa6a36 | 607 | lcall dram_read_pp |
12a27f27 L |
608 | rjmp vi2c_wr_wl |
609 | vi2c_wr_wle: | |
d8fa6a36 L |
610 | ; Enable TWI, TWI int and initiate start condition |
611 | ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA) | |
612 | outm8 TWCR,temp | |
12a27f27 L |
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: | |
d8fa6a36 L |
634 | ret |
635 | ||
79986122 L |
636 | ;------------------------------------------------------------------ |
637 | ||
d8fa6a36 L |
638 | |
639 | vi2c_ctrl: | |
12a27f27 | 640 | cpi temp,1 ;read ? |
d8fa6a36 | 641 | brne vi2c_c1 |
79986122 L |
642 | rjmp vi2c_read |
643 | ||
d8fa6a36 | 644 | vi2c_c1: |
12a27f27 | 645 | cpi temp,2 ;write? |
79986122 L |
646 | brne vi2c_c2 |
647 | rjmp vi2c_write | |
d8fa6a36 | 648 | vi2c_c2: |
12a27f27 L |
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: | |
d8fa6a36 | 654 | vi2c_ce: |
d8fa6a36 L |
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 | ||
12a27f27 L |
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 | ||
825ecc9d | 729 | #endif /* I2C_SUPPORT */ |
d8fa6a36 L |
730 | ;------------------------------------------------------------------ |
731 | ; vim:set ts=8 noet nowrap |