]> cloudbase.mooo.com Git - avrcpm.git/blame - avr/i2c.asm
* I2C: Don't get stuck, if pullups are missing (timeout error)
[avrcpm.git] / avr / i2c.asm
CommitLineData
d8fa6a36
L
1; I2C (TWI) master interface.
2; This is part of the Z80-CP/M emulator written by Sprite_tm.
3;
4; Copyright (C) 2010 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$
22;
23
24#if I2C
25
26/* General TWI Master status codes */
27#define TWI_START 0x08 /* START has been transmitted */
28#define TWI_REP_START 0x10 /* Repeated START has been transmitted */
29#define TWI_ARB_LOST 0x38 /* Arbitration lost */
30
31/* TWI Master Transmitter status codes */
32#define TWI_MTX_ADR_ACK 0x18 /* SLA+W has been transmitted and ACK received */
33#define TWI_MTX_ADR_NACK 0x20 /* SLA+W has been transmitted and NACK received */
34#define TWI_MTX_DATA_ACK 0x28 /* Data byte has been transmitted and ACK received */
35#define TWI_MTX_DATA_NACK 0x30 /* Data byte has been transmitted and NACK received */
36
37/* TWI Master Receiver status codes */
38#define TWI_MRX_ADR_ACK 0x40 /* SLA+R has been transmitted and ACK received */
39#define TWI_MRX_ADR_NACK 0x48 /* SLA+R has been transmitted and NACK received */
40#define TWI_MRX_DATA_ACK 0x50 /* Data byte has been received and ACK transmitted */
41#define TWI_MRX_DATA_NACK 0x58 /* Data byte has been received and NACK transmitted */
42
43/* TWI Miscellaneous status codes */
44#define TWI_NO_STATE 0xF8 /* No relevant state information available */
45#define TWI_BUS_ERROR 0x00 /* Bus error due to an illegal START or STOP condition */
46
47
48#define I2C_BR ((F_CPU / (2 * I2C_CLOCK)) - 8) /* I2C Bit Rate */
49
50;----------------------------------------------------------------------
51;
52; TWINT: TWI Interrupt Flag
53; TWEA: TWI Enable Acknowledge Bit
54; TWSTA: TWI START Condition Bit
55; TWSTO: TWI STOP Condition Bit
56; TWEN: TWI Enable Bit
57; TWIE: TWI Interrupt Enable
58;
59; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
60; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)| (1<<TWEA)
61; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
62;
63; default:
64; (1<<TWEN)| (1<<TWINT)| (1<<TWSTO)
65;
66; Init:
67; (1<<TWEN)
68;
69; start read/write:
70; (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
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;
75; wait ready:
76; (1<<TWIE)|(1<<TWSTO)
79986122
L
77;
78;----------------------------------------------------------------------
79;
80;i2c_result < 0 Error.
81; -1 general/unknown error
82; -2 time out
83; >= 0 No error
84; > 0 status tbd.
85;
d8fa6a36
L
86;----------------------------------------------------------------------
87
88 .dseg
89
90i2c_var:
91i2ci_idx:
92 .byte 1
93i2c_result:
94 .byte 1
95i2c_bufcnt:
96 .byte 1
97i2c_buf:
98 .byte I2C_BUFSIZE
99
100 .equ oi2ci_idx = 0
101 .equ oi2c_result = 1
102 .equ oi2c_bufcnt = 2
103 .equ oi2c_buf = 3
104
105;------------------------------------------------------------------
106
107 .cseg
108
109
110 INTERRUPT TWIaddr
111
112 push temp
113 in temp,sreg
114 push temp
115 push temp2
116 push zh
117 push zl
118
119 ldiw z,i2c_var
120 ldd temp2,z+oi2ci_idx
121
122 inm8 temp,TWSR
d8fa6a36
L
123 cpi temp,TWI_START
124 breq i2ci_START
125 cpi temp,TWI_REP_START
126 breq i2ci_REP_START
127 cpi temp,TWI_MTX_ADR_ACK
128 breq i2ci_MTX_ADR_ACK
129 cpi temp,TWI_MTX_DATA_ACK
130 breq i2ci_MTX_DATA_ACK
131 cpi temp,TWI_MRX_ADR_ACK
132 breq i2ci_MRX_ADR_ACK
133 cpi temp,TWI_MRX_DATA_ACK
134 breq i2ci_MRX_DATA_ACK
135 cpi temp,TWI_MRX_DATA_NACK
136 breq i2ci_MRX_DATA_NACK
137 rjmp i2ci_default
138
139i2ci_START:
140i2ci_REP_START:
141 clr temp2 ;reset buffer pointer
142i2ci_MTX_ADR_ACK:
143i2ci_MTX_DATA_ACK:
144 ldd temp,z+oi2c_bufcnt
79986122
L
145 cp temp2,temp ;all bytes tranmited?
146 brsh i2ci_12 ; yes
d8fa6a36
L
147 add zl,temp2
148 adc zh,_0
149 inc temp2
79986122 150 ldd temp,z+oi2c_buf ;next byte
d8fa6a36
L
151 outm8 TWDR,temp
152 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
153 rjmp i2ci_end
154
155i2ci_12:
79986122
L
156 std z+oi2c_result,_0 ;done
157 rjmp i2ci_default ;stop transceiver
d8fa6a36
L
158
159i2ci_MRX_DATA_ACK:
160 add zl,temp2
161 adc zh,_0
162 inc temp2
163 inm8 temp,TWDR
164 std z+oi2c_buf,temp
165i2ci_MRX_ADR_ACK:
166 lds temp,i2c_bufcnt
167 dec temp
168 cp temp2,temp
169 brsh i2ci_32
170 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)
171 rjmp i2ci_end
172i2ci_32:
173 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
174 rjmp i2ci_end
175
176i2ci_MRX_DATA_NACK:
79986122 177 std z+oi2c_result,_0 ;result = ok
d8fa6a36
L
178 add zl,temp2
179 adc zh,_0
180 inm8 temp,TWDR
181 std z+oi2c_buf,temp
182; fall thru
183
184i2ci_default:
185 ldi temp,(1<<TWEN)|(1<<TWINT)|(1<<TWSTO)
186
187i2ci_end:
188 outm8 TWCR,temp
189 sts i2ci_idx,temp2
190 pop zl
191 pop zh
192 pop temp2
193 pop temp
194 out sreg,temp
195 pop temp
196 reti
197
198;------------------------------------------------------------------
199
200i2c_init:
201 ldi temp,I2C_BR
202 outm8 TWBR,temp
203 outm8 TWDR,_255 ;
79986122 204 ldi temp,(1<<TWEN) ;Enable TWI, disable TWI interrupt.
d8fa6a36
L
205 outm8 TWCR,temp
206
79986122 207 sts i2c_result,_0
d8fa6a36
L
208 ret
209
210;------------------------------------------------------------------
211
212i2c_waitready:
79986122
L
213
214 ldi temp,30
215 sts delay_timer1,temp
216i2c_wrl:
d8fa6a36
L
217 inm8 temp,TWCR
218 andi temp,(1<<TWIE)|(1<<TWSTO)
79986122
L
219 breq i2c_wre
220 lds temp,delay_timer1
221 tst temp
222 brne i2c_wrl
223
224 ldi temp,-2
225 sts i2c_result,temp
226i2c_wre:
227 tst temp
d8fa6a36
L
228 ret
229
230;------------------------------------------------------------------
231;
232; z: Pointer to the data to write.
233; First byte is slave address
234; temp2: Number of bytes to write including address byte.
235;
236
237i2c_write:
d8fa6a36 238
79986122
L
239 rcall i2c_waitready
240 brmi i2c_we
d8fa6a36
L
241 push zh
242 push zl
243 push xh
244 push xl
245
d8fa6a36 246 ldiw x,i2c_result
79986122 247 st x+,_255 ;result = not ok
d8fa6a36
L
248 st x+,temp2 ;store size
249 ld temp,z+
250 cbr temp,0x01
251i2c_wl:
252 st x+,temp
253 dec temp2
254 breq i2c_wle
255 ld temp,z+
256 rjmp i2c_wl
257i2c_wle:
258 ; Enable TWI, TWI int and initiate start condition
259 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
260 outm8 TWCR,temp
261
262 pop xl
263 pop xh
264 pop zl
265 pop zh
79986122 266i2c_we:
d8fa6a36
L
267 ret
268
269
270;------------------------------------------------------------------
271;
272; z: Pointer to data buffer.
273; First byte of buffer is slave address
274; temp2: Number of bytes to write including address byte.
275;
276; temp: return (fail = 0, else succsess)
277
278i2c_read:
79986122 279
d8fa6a36 280 rcall i2c_waitready
79986122 281 brmi i2c_re
d8fa6a36
L
282
283 push zh
284 push zl
285 push xh
286 push xl
287 ldiw x,i2c_result
79986122 288 st x+,_255 ;result = not ok
d8fa6a36
L
289 st x+,temp2 ;store size
290 ld temp,z
291 sbr temp,0x01
292 st x,temp
293
294 ; Enable TWI, TWI int and initiate start condition
295 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
296 outm8 TWCR,temp
297
298 rcall i2c_waitready
299
d8fa6a36 300 lds temp,i2c_result
79986122
L
301 sbrc temp,7
302 rjmp i2c_ex ;
d8fa6a36
L
303i2c_rl:
304 ld temp,x+
305 st z+,temp
306 dec temp2
307 brne i2c_rl
308
309i2c_ex:
d8fa6a36
L
310 pop xl
311 pop xh
312 pop zl
313 pop zh
79986122
L
314i2c_re:
315 lds temp,i2c_result
d8fa6a36
L
316 ret
317
318;------------------------------------------------------------------
319
320 .dseg
321
322vi2c_stat:
323 .byte 1
324vi2c_blen:
325 .byte 1
326vi2c_addr:
327 .byte 2
328
329 .cseg
330
331vi2c_stat_get:
79986122 332 lds temp,i2c_result
d8fa6a36
L
333 ret
334
335vi2c_param_get:
336 ldiw z,vi2c_blen
337 add zl,temp3
338 adc zh,_0
339 ld temp,z
340 ret
341
342vi2c_param_set:
343 ldiw z,vi2c_blen
344 add zl,temp3
345 adc zh,_0
346 st z,temp
347 ret
348
349;------------------------------------------------------------------
350;
351; x: Pointer to the data buffer.
352; First byte is slave address
353; temp3: Number of bytes to write including address byte.
354;
355
356vi2c_read:
79986122 357
d8fa6a36 358 rcall i2c_waitready
79986122 359 brmi vi2c_rex
d8fa6a36
L
360
361 ldiw z,i2c_var
79986122 362 std z+oi2c_result,_255 ;result = not ok
d8fa6a36
L
363 lds temp3,vi2c_blen
364 std z+oi2c_bufcnt,temp3 ;store size
365 adiw z,oi2c_buf
366 ldsw x,vi2c_addr
367 lcall dram_read_pp
368 sbr temp,0x01
369 st z+,temp
370 dec temp3
371
372 ; Enable TWI, TWI int and initiate start condition
373 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
374 outm8 TWCR,temp
375
376 rcall i2c_waitready
377
378 lds temp,i2c_result
79986122
L
379 sbrc temp,7
380 rjmp vi2c_rex ;
d8fa6a36
L
381vi2c_rl:
382 ld temp,z+
383 lcall dram_write_pp
384 dec temp3
385 brne vi2c_rl
386
79986122 387vi2c_rex:
d8fa6a36
L
388 ret
389
390;------------------------------------------------------------------
391;
392; x: Pointer to the data to write.
393; First byte is slave address
394; temp2: Number of bytes to write including address byte.
395;
396
397vi2c_write:
79986122 398
d8fa6a36 399 rcall i2c_waitready
79986122 400 brmi vi2c_wex
d8fa6a36 401 ldiw z,i2c_var
79986122 402 std z+oi2c_result,_255 ;result = not ok
d8fa6a36
L
403 lds temp3,vi2c_blen
404 std z+oi2c_bufcnt,temp3 ;store size
405 adiw z,oi2c_buf
406 ldsw x,vi2c_addr
407 lcall dram_read_pp
408 cbr temp,0x01
409vi2c_wl:
410 st z+,temp
411 dec temp3
412 breq vi2c_wle
413 lcall dram_read_pp
414 rjmp vi2c_wl
415vi2c_wle:
416 ; Enable TWI, TWI int and initiate start condition
417 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
418 outm8 TWCR,temp
79986122 419vi2c_wex:
d8fa6a36
L
420 ret
421
79986122
L
422;------------------------------------------------------------------
423
d8fa6a36
L
424
425vi2c_ctrl:
426 cpi temp,1
427 brne vi2c_c1
79986122
L
428 rjmp vi2c_read
429
d8fa6a36
L
430vi2c_c1:
431 cpi temp,2
79986122
L
432 brne vi2c_c2
433 rjmp vi2c_write
d8fa6a36 434vi2c_c2:
d8fa6a36 435vi2c_ce:
d8fa6a36
L
436 ret
437
438;------------------------------------------------------------------
439
440
441pcf8574_in:
442 ; make a buffer on stack
443 push _255 ;place holder for input value
444 in zh,sph
445 in zl,spl
446 ldi temp,0x20 ;pcf8574 address (7 bit)
447 add temp,temp3
448 lsl temp
449 push temp ;slave address
450 ldi temp2,2
451 rcall i2c_read
452 pop temp ;remove slave address from stack
453 pop temp ;return input value
454 ret
455
456pcf8574_out:
457 ; make a buffer on stack
458 push temp ;output value
459 in zh,sph
460 in zl,spl
461 ldi temp,0x20 ;pcf8574 address (7 bit)
462 add temp,temp3
463 lsl temp
464 push temp ;slave address
465 ldi temp2,2
466 rcall i2c_write
467 pop temp ;remove buffer from stack
468 pop temp ;
469 ret
470
471
472#endif /* I2C */
473;------------------------------------------------------------------
474; vim:set ts=8 noet nowrap
475