]>
Commit | Line | Data |
---|---|---|
a3be4966 BP |
1 | ; usbduxfast_firmware.asm |
2 | ; Copyright (C) 2004,2009 Bernd Porr, Bernd.Porr@f2s.com | |
3 | ; | |
4 | ; This program is free software; you can redistribute it and/or modify | |
5 | ; it under the terms of the GNU General Public License as published by | |
6 | ; the Free Software Foundation; either version 2 of the License, or | |
7 | ; (at your option) any later version. | |
8 | ; | |
9 | ; This program is distributed in the hope that it will be useful, | |
10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ; GNU General Public License for more details. | |
13 | ; | |
14 | ; You should have received a copy of the GNU General Public License | |
15 | ; along with this program; if not, write to the Free Software | |
16 | ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 | ; | |
18 | ; | |
19 | ; Firmware: usbduxfast_firmware.asm for usbdux.c | |
20 | ; Description: Firmware for usbduxfast | |
21 | ; Devices: [ITL] USB-DUX (usbdux.o) | |
22 | ; Author: Bernd Porr <Bernd.Porr@f2s.com> | |
23 | ; Updated: 17 Apr 2009 | |
24 | ; Status: stable | |
25 | ; | |
26 | ;;; | |
27 | ;;; | |
28 | ;;; | |
29 | ||
30 | .inc fx2-include.asm | |
31 | ||
32 | .equ WFLOADED,70H ; waveform is loaded | |
33 | ||
34 | .org 0000h ; after reset the processor starts here | |
35 | ljmp main ; jump to the main loop | |
36 | ||
37 | .org 0043h ; the IRQ2-vector | |
38 | ljmp jmptbl ; irq service-routine | |
39 | ||
40 | .org 0100h ; start of the jump table | |
41 | ||
42 | jmptbl: ljmp sudav_isr | |
43 | nop | |
44 | ljmp sof_isr | |
45 | nop | |
46 | ljmp sutok_isr | |
47 | nop | |
48 | ljmp suspend_isr | |
49 | nop | |
50 | ljmp usbreset_isr | |
51 | nop | |
52 | ljmp hispeed_isr | |
53 | nop | |
54 | ljmp ep0ack_isr | |
55 | nop | |
56 | ljmp spare_isr | |
57 | nop | |
58 | ljmp ep0in_isr | |
59 | nop | |
60 | ljmp ep0out_isr | |
61 | nop | |
62 | ljmp ep1in_isr | |
63 | nop | |
64 | ljmp ep1out_isr | |
65 | nop | |
66 | ljmp ep2_isr | |
67 | nop | |
68 | ljmp ep4_isr | |
69 | nop | |
70 | ljmp ep6_isr | |
71 | nop | |
72 | ljmp ep8_isr | |
73 | nop | |
74 | ljmp ibn_isr | |
75 | nop | |
76 | ljmp spare_isr | |
77 | nop | |
78 | ljmp ep0ping_isr | |
79 | nop | |
80 | ljmp ep1ping_isr | |
81 | nop | |
82 | ljmp ep2ping_isr | |
83 | nop | |
84 | ljmp ep4ping_isr | |
85 | nop | |
86 | ljmp ep6ping_isr | |
87 | nop | |
88 | ljmp ep8ping_isr | |
89 | nop | |
90 | ljmp errlimit_isr | |
91 | nop | |
92 | ljmp spare_isr | |
93 | nop | |
94 | ljmp spare_isr | |
95 | nop | |
96 | ljmp spare_isr | |
97 | nop | |
98 | ljmp ep2isoerr_isr | |
99 | nop | |
100 | ljmp ep4isoerr_isr | |
101 | nop | |
102 | ljmp ep6isoerr_isr | |
103 | nop | |
104 | ljmp ep8isoerr_isr | |
105 | ||
106 | ||
107 | ;; dummy isr | |
108 | sof_isr: | |
109 | sudav_isr: | |
110 | sutok_isr: | |
111 | suspend_isr: | |
112 | usbreset_isr: | |
113 | hispeed_isr: | |
114 | ep0ack_isr: | |
115 | spare_isr: | |
116 | ep0in_isr: | |
117 | ep0out_isr: | |
118 | ep1out_isr: | |
119 | ep1in_isr: | |
120 | ibn_isr: | |
121 | ep0ping_isr: | |
122 | ep1ping_isr: | |
123 | ep2ping_isr: | |
124 | ep4ping_isr: | |
125 | ep6ping_isr: | |
126 | ep8ping_isr: | |
127 | errlimit_isr: | |
128 | ep2isoerr_isr: | |
129 | ep4isoerr_isr: | |
130 | ep6isoerr_isr: | |
131 | ep8isoerr_isr: | |
132 | ep6_isr: | |
133 | ep2_isr: | |
134 | ep8_isr: | |
135 | ||
136 | push dps | |
137 | push dpl | |
138 | push dph | |
139 | push dpl1 | |
140 | push dph1 | |
141 | push acc | |
142 | push psw | |
143 | ||
144 | ;; clear the USB2 irq bit and return | |
145 | mov a,EXIF | |
146 | clr acc.4 | |
147 | mov EXIF,a | |
148 | ||
149 | pop psw | |
150 | pop acc | |
151 | pop dph1 | |
152 | pop dpl1 | |
153 | pop dph | |
154 | pop dpl | |
155 | pop dps | |
156 | ||
157 | reti | |
158 | ||
159 | ||
160 | ;;; main program | |
161 | ;;; basically only initialises the processor and | |
162 | ;;; then engages in an endless loop | |
163 | main: | |
164 | mov dptr,#REVCTL | |
165 | mov a,#00000011b ; allows skip | |
166 | lcall syncdelaywr | |
167 | ||
168 | mov DPTR,#CPUCS ; CPU control register | |
169 | mov a,#00010000b ; 48Mhz | |
170 | lcall syncdelaywr | |
171 | ||
172 | mov dptr,#IFCONFIG ; switch on IFCLK signal | |
173 | mov a,#10100010b ; gpif, 30MHz | |
174 | lcall syncdelaywr | |
175 | ||
176 | mov dptr,#FIFORESET | |
177 | mov a,#80h | |
178 | lcall syncdelaywr | |
179 | mov a,#8 | |
180 | lcall syncdelaywr | |
181 | mov a,#2 | |
182 | lcall syncdelaywr | |
183 | mov a,#4 | |
184 | lcall syncdelaywr | |
185 | mov a,#6 | |
186 | lcall syncdelaywr | |
187 | mov a,#0 | |
188 | lcall syncdelaywr | |
189 | ||
190 | mov dptr,#INTSETUP ; IRQ setup register | |
191 | mov a,#08h ; enable autovector | |
192 | lcall syncdelaywr | |
193 | ||
194 | lcall initeps ; init the isochronous data-transfer | |
195 | ||
196 | lcall initGPIF | |
197 | ||
198 | ;;; main loop | |
199 | ||
200 | mloop2: | |
201 | lcall gpif_run | |
202 | sjmp mloop2 ; do nothing. The rest is done by the IRQs | |
203 | ||
204 | ||
205 | gpif_run: | |
206 | mov a,WFLOADED | |
207 | jz no_trig ; do not trigger | |
208 | mov a,GPIFTRIG ; GPIF status | |
209 | anl a,#80h ; done bit | |
210 | jz no_trig ; GPIF busy | |
211 | ||
212 | ;;; gpif has stopped | |
213 | mov a,#06h ; RD,EP6 | |
214 | mov GPIFTRIG,a | |
215 | no_trig: | |
216 | ret | |
217 | ||
218 | ||
219 | ||
220 | initGPIF: | |
221 | mov DPTR,#EP6CFG ; BLK data from here to the host | |
222 | mov a,#11100000b ; Valid, quad buffering | |
223 | lcall syncdelaywr ; write | |
224 | ||
225 | mov dptr,#EP6FIFOCFG | |
226 | mov a,#00001001b ; autoin, wordwide | |
227 | lcall syncdelaywr | |
228 | ||
229 | mov dptr,#EP6AUTOINLENH | |
230 | mov a,#00000010b ; 512 bytes | |
231 | lcall syncdelaywr ; write | |
232 | ||
233 | mov dptr,#EP6AUTOINLENL | |
234 | mov a,#00000000b ; 0 | |
235 | lcall syncdelaywr ; write | |
236 | ||
237 | mov dptr,#GPIFWFSELECT | |
238 | mov a,#11111100b ; waveform 0 for FIFO RD | |
239 | lcall syncdelaywr | |
240 | ||
241 | mov dptr,#GPIFCTLCFG | |
242 | mov a,#10000000b ; tri state for CTRL | |
243 | lcall syncdelaywr | |
244 | ||
245 | mov dptr,#GPIFIDLECTL | |
246 | mov a,#11111111b ; all CTL outputs high | |
247 | lcall syncdelaywr | |
248 | mov a,#11111101b ; reset counter | |
249 | lcall syncdelaywr | |
250 | mov a,#11111111b ; reset to high again | |
251 | lcall syncdelaywr | |
252 | ||
253 | mov a,#00000010b ; abort when full | |
254 | mov dptr,#EP6GPIFFLGSEL | |
255 | lcall syncdelaywr | |
256 | ||
257 | mov a,#00000001b ; stop when buffer overfl | |
258 | mov dptr,#EP6GPIFPDFSTOP | |
259 | lcall syncdelaywr | |
260 | ||
261 | mov a,#0 | |
262 | mov dptr,#GPIFREADYCFG | |
263 | lcall syncdelaywr | |
264 | ||
265 | mov a,#0 | |
266 | mov dptr,#GPIFIDLECS | |
267 | lcall syncdelaywr | |
268 | ||
269 | ; waveform 1 | |
270 | ; this is a dummy waveform which is used | |
271 | ; during the upload of another waveform into | |
272 | ; wavefrom 0 | |
273 | ; it branches directly into the IDLE state | |
274 | mov dptr,#0E420H | |
275 | mov a,#00111111b ; branch to IDLE | |
276 | lcall syncdelaywr | |
277 | ||
278 | mov dptr,#0E428H ; opcode | |
279 | mov a,#00000001b ; deceision point | |
280 | lcall syncdelaywr | |
281 | ||
282 | mov dptr,#0E430H | |
283 | mov a,#0FFH ; output is high | |
284 | lcall syncdelaywr | |
285 | ||
286 | mov dptr,#0E438H | |
287 | mov a,#0FFH ; logic function | |
288 | lcall syncdelaywr | |
289 | ||
290 | ; signals that no waveform 0 is loaded so far | |
291 | mov WFLOADED,#0 ; waveform flag | |
292 | ||
293 | ret | |
294 | ||
295 | ||
296 | ||
297 | ;;; initilise the transfer | |
298 | ;;; It is assumed that the USB interface is in alternate setting 1 | |
299 | initeps: | |
300 | mov DPTR,#EP4CFG | |
301 | mov a,#10100000b ; valid, bulk, out | |
302 | lcall syncdelaywr | |
303 | ||
304 | mov dptr,#EP4BCL ; "arm" it | |
305 | mov a,#00h | |
306 | lcall syncdelaywr ; wait until we can write again | |
307 | lcall syncdelaywr ; wait | |
308 | lcall syncdelaywr ; wait | |
309 | ||
310 | mov DPTR,#EP8CFG | |
311 | mov a,#0 ; disable EP8, it overlaps with EP6!! | |
312 | lcall syncdelaywr | |
313 | ||
314 | mov dptr,#EPIE ; interrupt enable | |
315 | mov a,#00100000b ; enable irq for ep4 | |
316 | lcall syncdelaywr ; do it | |
317 | ||
318 | mov dptr,#EPIRQ ; clear IRQs | |
319 | mov a,#00100100b | |
320 | movx @dptr,a | |
321 | ||
322 | mov DPTR,#USBIE ; USB int enable register | |
323 | mov a,#0 ; SOF etc | |
324 | movx @DPTR,a ; | |
325 | ||
326 | mov DPTR,#GPIFIE ; GPIF int enable register | |
327 | mov a,#0 ; done IRQ | |
328 | movx @DPTR,a ; | |
329 | ||
330 | mov EIE,#00000001b ; enable INT2 in the 8051's SFR | |
331 | mov IE,#80h ; IE, enable all interrupts | |
332 | ||
333 | ret | |
334 | ||
335 | ||
336 | ;;; interrupt-routine for ep4 | |
337 | ;;; receives the channel list and other commands | |
338 | ep4_isr: | |
339 | push dps | |
340 | push dpl | |
341 | push dph | |
342 | push dpl1 | |
343 | push dph1 | |
344 | push acc | |
345 | push psw | |
346 | push 00h ; R0 | |
347 | push 01h ; R1 | |
348 | push 02h ; R2 | |
349 | push 03h ; R3 | |
350 | push 04h ; R4 | |
351 | push 05h ; R5 | |
352 | push 06h ; R6 | |
353 | push 07h ; R7 | |
354 | ||
355 | mov dptr,#0f400h ; FIFO buffer of EP4 | |
356 | movx a,@dptr ; get the first byte | |
357 | ||
358 | mov dptr,#ep4_jmp ; jump table for the different functions | |
359 | rl a ; multiply by 2: sizeof sjmp | |
360 | jmp @a+dptr ; jump to the jump table | |
361 | ||
362 | ep4_jmp: | |
363 | sjmp storewaveform ; a=0 | |
364 | sjmp init_ep6 ; a=1 | |
365 | ||
366 | init_ep6: | |
367 | ; stop ep6 | |
368 | ; just now do nothing | |
369 | ||
370 | ljmp over_wf | |
371 | ||
372 | ||
373 | storewaveform: | |
374 | mov WFLOADED,#0 ; waveform flag | |
375 | ||
376 | mov dptr,#EP6FIFOCFG | |
377 | mov a,#00000000b ; | |
378 | lcall syncdelaywr | |
379 | ||
380 | mov dptr,#GPIFABORT | |
381 | mov a,#0ffh ; abort all transfers | |
382 | lcall syncdelaywr | |
383 | ||
384 | wait_f_abort: | |
385 | mov a,GPIFTRIG ; GPIF status | |
386 | anl a,#80h ; done bit | |
387 | jz wait_f_abort ; GPIF busy | |
388 | ||
389 | mov dptr,#GPIFWFSELECT | |
390 | mov a,#11111101b ; select dummy waveform | |
391 | movx @dptr,a | |
392 | lcall syncdelay | |
393 | ||
394 | mov dptr,#FIFORESET | |
395 | mov a,#80h ; NAK | |
396 | lcall syncdelaywr | |
397 | mov a,#6 ; reset EP6 | |
398 | lcall syncdelaywr | |
399 | mov a,#0 ; normal op | |
400 | lcall syncdelaywr | |
401 | ||
402 | ; change to dummy waveform 1 | |
403 | mov a,#06h ; RD,EP6 | |
404 | mov GPIFTRIG,a | |
405 | ||
406 | ; wait a bit | |
407 | mov r2,255 | |
408 | loopx: | |
409 | djnz r2,loopx | |
410 | ||
411 | ; abort waveform if not already so | |
412 | mov dptr,#GPIFABORT | |
413 | mov a,#0ffh ; abort all transfers | |
414 | lcall syncdelaywr | |
415 | ||
416 | ; wait again | |
417 | mov r2,255 | |
418 | loopx2: | |
419 | djnz r2,loopx2 | |
420 | ||
421 | ; check for DONE | |
422 | wait_f_abort2: | |
423 | mov a,GPIFTRIG ; GPIF status | |
424 | anl a,#80h ; done bit | |
425 | jz wait_f_abort2 ; GPIF busy | |
426 | ||
427 | ; upload the new waveform into waveform 0 | |
428 | mov AUTOPTRH2,#0E4H ; XDATA0H | |
429 | lcall syncdelay | |
430 | mov AUTOPTRL2,#00H ; XDATA0L | |
431 | lcall syncdelay | |
432 | ||
433 | mov AUTOPTRH1,#0F4H ; EP4 high | |
434 | lcall syncdelay | |
435 | mov AUTOPTRL1,#01H ; EP4 low | |
436 | lcall syncdelay | |
437 | ||
438 | mov AUTOPTRSETUP,#7 ; autoinc and enable | |
439 | lcall syncdelay | |
440 | ||
441 | mov r2,#20H ; 32 bytes to transfer | |
442 | ||
443 | wavetr: | |
444 | mov dptr,#XAUTODAT1 | |
445 | movx a,@dptr | |
446 | lcall syncdelay | |
447 | mov dptr,#XAUTODAT2 | |
448 | movx @dptr,a | |
449 | lcall syncdelay | |
450 | djnz r2,wavetr | |
451 | ||
452 | mov dptr,#EP6FIFOCFG | |
453 | mov a,#00001001b ; autoin, wordwide | |
454 | lcall syncdelaywr | |
455 | ||
456 | mov dptr,#GPIFWFSELECT | |
457 | mov a,#11111100b | |
458 | movx @dptr,a | |
459 | lcall syncdelay | |
460 | ||
461 | mov dptr,#FIFORESET | |
462 | mov a,#80h ; NAK | |
463 | lcall syncdelaywr | |
464 | mov a,#6 ; reset EP6 | |
465 | lcall syncdelaywr | |
466 | mov a,#0 ; normal op | |
467 | lcall syncdelaywr | |
468 | ||
469 | mov dptr,#0E400H+10H; waveform 0: first CTL byte | |
470 | movx a,@dptr ; get it | |
471 | orl a,#11111011b ; force all bits to one except the range bit | |
472 | mov dptr,#GPIFIDLECTL | |
473 | lcall syncdelaywr | |
474 | ||
475 | mov WFLOADED,#1 ; waveform flag | |
476 | ||
477 | ; do the common things here | |
478 | over_wf: | |
479 | mov dptr,#EP4BCL | |
480 | mov a,#00h | |
481 | movx @DPTR,a ; arm it | |
482 | lcall syncdelay ; wait | |
483 | movx @DPTR,a ; arm it | |
484 | lcall syncdelay ; wait | |
485 | ||
486 | ;; clear INT2 | |
487 | mov a,EXIF ; FIRST clear the USB (INT2) interrupt request | |
488 | clr acc.4 | |
489 | mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable | |
490 | ||
491 | mov DPTR,#EPIRQ ; | |
492 | mov a,#00100000b ; clear the ep4irq | |
493 | movx @DPTR,a | |
494 | ||
495 | pop 07h | |
496 | pop 06h | |
497 | pop 05h | |
498 | pop 04h ; R4 | |
499 | pop 03h ; R3 | |
500 | pop 02h ; R2 | |
501 | pop 01h ; R1 | |
502 | pop 00h ; R0 | |
503 | pop psw | |
504 | pop acc | |
505 | pop dph1 | |
506 | pop dpl1 | |
507 | pop dph | |
508 | pop dpl | |
509 | pop dps | |
510 | reti | |
511 | ||
512 | ||
513 | ;; need to delay every time the byte counters | |
514 | ;; for the EPs have been changed. | |
515 | ||
516 | syncdelay: | |
517 | nop | |
518 | nop | |
519 | nop | |
520 | nop | |
521 | nop | |
522 | nop | |
523 | nop | |
524 | nop | |
525 | nop | |
526 | ret | |
527 | ||
528 | ||
529 | syncdelaywr: | |
530 | lcall syncdelay | |
531 | movx @dptr,a | |
532 | ret | |
533 | ||
534 | ||
535 | .End | |
536 | ||
537 | ||
538 | ||
539 | ||
540 | ||
541 | ||
542 | ||
543 | ||
544 | ||
545 | ||
546 | ||
547 |