]> cloudbase.mooo.com Git - avrcpm.git/blob - avr/i2c.asm
ee20d069c033891c9b234286f931ceee6a174b77
[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$
22 ;
23
24 #if I2C_SUPPORT
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)
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 ;
86 ;----------------------------------------------------------------------
87
88 .dseg
89
90 i2c_var:
91 i2ci_idx:
92 .byte 1
93 i2c_result:
94 .byte 1
95 i2c_bufcnt:
96 .byte 1
97 i2c_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
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
139 i2ci_START:
140 i2ci_REP_START:
141 clr temp2 ;reset buffer pointer
142 i2ci_MTX_ADR_ACK:
143 i2ci_MTX_DATA_ACK:
144 ldd temp,z+oi2c_bufcnt
145 cp temp2,temp ;all bytes tranmited?
146 brsh i2ci_12 ; yes
147 add zl,temp2
148 adc zh,_0
149 inc temp2
150 ldd temp,z+oi2c_buf ;next byte
151 outm8 TWDR,temp
152 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
153 rjmp i2ci_end
154
155 i2ci_12:
156 std z+oi2c_result,_0 ;done
157 rjmp i2ci_default ;stop transceiver
158
159 i2ci_MRX_DATA_ACK:
160 add zl,temp2
161 adc zh,_0
162 inc temp2
163 inm8 temp,TWDR
164 std z+oi2c_buf,temp
165 i2ci_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
172 i2ci_32:
173 ldi temp,(1<<TWEN)|(1<<TWIE)|(1<<TWINT)
174 rjmp i2ci_end
175
176 i2ci_MRX_DATA_NACK:
177 std z+oi2c_result,_0 ;result = ok
178 add zl,temp2
179 adc zh,_0
180 inm8 temp,TWDR
181 std z+oi2c_buf,temp
182 ; fall thru
183
184 i2ci_default:
185 ldi temp,(1<<TWEN)|(1<<TWINT)|(1<<TWSTO)
186
187 i2ci_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
200 i2c_init:
201 ldi temp,I2C_BR
202 outm8 TWBR,temp
203 outm8 TWDR,_255 ;
204 ldi temp,(1<<TWEN) ;Enable TWI, disable TWI interrupt.
205 outm8 TWCR,temp
206
207 sts i2c_result,_0
208 ret
209
210 ;------------------------------------------------------------------
211
212 i2c_waitready:
213
214 ldi temp,30
215 sts delay_timer1,temp
216 i2c_wrl:
217 inm8 temp,TWCR
218 andi temp,(1<<TWIE)|(1<<TWSTO)
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
226 i2c_wre:
227 tst temp
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
237 i2c_write:
238
239 rcall i2c_waitready
240 brmi i2c_we
241 push zh
242 push zl
243 push xh
244 push xl
245
246 ldiw x,i2c_result
247 st x+,_255 ;result = not ok
248 st x+,temp2 ;store size
249 ld temp,z+
250 cbr temp,0x01
251 i2c_wl:
252 st x+,temp
253 dec temp2
254 breq i2c_wle
255 ld temp,z+
256 rjmp i2c_wl
257 i2c_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
266 i2c_we:
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
278 i2c_read:
279
280 rcall i2c_waitready
281 brmi i2c_re
282
283 push zh
284 push zl
285 push xh
286 push xl
287 ldiw x,i2c_result
288 st x+,_255 ;result = not ok
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
300 lds temp,i2c_result
301 sbrc temp,7
302 rjmp i2c_ex ;
303 i2c_rl:
304 ld temp,x+
305 st z+,temp
306 dec temp2
307 brne i2c_rl
308
309 i2c_ex:
310 pop xl
311 pop xh
312 pop zl
313 pop zh
314 i2c_re:
315 lds temp,i2c_result
316 ret
317
318 ;------------------------------------------------------------------
319
320 .dseg
321
322 vi2c_stat:
323 .byte 1
324 vi2c_blen:
325 .byte 1
326 vi2c_addr:
327 .byte 2
328
329 .cseg
330
331 vi2c_stat_get:
332 lds temp,i2c_result
333 ret
334
335 vi2c_param_get:
336 ldiw z,vi2c_blen
337 add zl,temp3
338 adc zh,_0
339 ld temp,z
340 ret
341
342 vi2c_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
356 vi2c_read:
357
358 rcall i2c_waitready
359 brmi vi2c_rex
360
361 ldiw z,i2c_var
362 std z+oi2c_result,_255 ;result = not ok
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
379 sbrc temp,7
380 rjmp vi2c_rex ;
381 vi2c_rl:
382 ld temp,z+
383 lcall dram_write_pp
384 dec temp3
385 brne vi2c_rl
386
387 vi2c_rex:
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
397 vi2c_write:
398
399 rcall i2c_waitready
400 brmi vi2c_wex
401 ldiw z,i2c_var
402 std z+oi2c_result,_255 ;result = not ok
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
409 vi2c_wl:
410 st z+,temp
411 dec temp3
412 breq vi2c_wle
413 lcall dram_read_pp
414 rjmp vi2c_wl
415 vi2c_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
419 vi2c_wex:
420 ret
421
422 ;------------------------------------------------------------------
423
424
425 vi2c_ctrl:
426 cpi temp,1
427 brne vi2c_c1
428 rjmp vi2c_read
429
430 vi2c_c1:
431 cpi temp,2
432 brne vi2c_c2
433 rjmp vi2c_write
434 vi2c_c2:
435 vi2c_ce:
436 ret
437
438 ;------------------------------------------------------------------
439
440
441 pcf8574_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
456 pcf8574_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_SUPPORT */
473 ;------------------------------------------------------------------
474 ; vim:set ts=8 noet nowrap