]>
Commit | Line | Data |
---|---|---|
d8fa6a36 L |
1 | ; I2C (TWI) master interface. |
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 | ; | |
21 | ; $Id$ | |
22 | ; | |
23 | ||
825ecc9d | 24 | #if I2C_SUPPORT |
d8fa6a36 L |
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 | ||
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 | |
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 | ||
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 | |
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 | ||
155 | i2ci_12: | |
79986122 L |
156 | std z+oi2c_result,_0 ;done |
157 | rjmp i2ci_default ;stop transceiver | |
d8fa6a36 L |
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: | |
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 | ||
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 ; | |
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 | ||
212 | i2c_waitready: | |
79986122 L |
213 | |
214 | ldi temp,30 | |
215 | sts delay_timer1,temp | |
216 | i2c_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 | |
226 | i2c_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 | ||
237 | i2c_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 | |
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 | |
79986122 | 266 | i2c_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 | ||
278 | i2c_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 |
303 | i2c_rl: |
304 | ld temp,x+ | |
305 | st z+,temp | |
306 | dec temp2 | |
307 | brne i2c_rl | |
308 | ||
309 | i2c_ex: | |
d8fa6a36 L |
310 | pop xl |
311 | pop xh | |
312 | pop zl | |
313 | pop zh | |
79986122 L |
314 | i2c_re: |
315 | lds temp,i2c_result | |
d8fa6a36 L |
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: | |
79986122 | 332 | lds temp,i2c_result |
d8fa6a36 L |
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: | |
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 |
381 | vi2c_rl: |
382 | ld temp,z+ | |
383 | lcall dram_write_pp | |
384 | dec temp3 | |
385 | brne vi2c_rl | |
386 | ||
79986122 | 387 | vi2c_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 | ||
397 | vi2c_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 | |
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 | |
79986122 | 419 | vi2c_wex: |
d8fa6a36 L |
420 | ret |
421 | ||
79986122 L |
422 | ;------------------------------------------------------------------ |
423 | ||
d8fa6a36 L |
424 | |
425 | vi2c_ctrl: | |
426 | cpi temp,1 | |
427 | brne vi2c_c1 | |
79986122 L |
428 | rjmp vi2c_read |
429 | ||
d8fa6a36 L |
430 | vi2c_c1: |
431 | cpi temp,2 | |
79986122 L |
432 | brne vi2c_c2 |
433 | rjmp vi2c_write | |
d8fa6a36 | 434 | vi2c_c2: |
d8fa6a36 | 435 | vi2c_ce: |
d8fa6a36 L |
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 | ||
825ecc9d | 472 | #endif /* I2C_SUPPORT */ |
d8fa6a36 L |
473 | ;------------------------------------------------------------------ |
474 | ; vim:set ts=8 noet nowrap | |
475 |