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