summaryrefslogtreecommitdiffstats
path: root/firmware/usbdrv/asmcommon.inc
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbdrv/asmcommon.inc')
-rw-r--r--firmware/usbdrv/asmcommon.inc55
1 files changed, 47 insertions, 8 deletions
diff --git a/firmware/usbdrv/asmcommon.inc b/firmware/usbdrv/asmcommon.inc
index d2a4f7c..19fb3d3 100644
--- a/firmware/usbdrv/asmcommon.inc
+++ b/firmware/usbdrv/asmcommon.inc
@@ -82,9 +82,41 @@ se0:
; rjmp handleSetupOrOut ; fallthrough
;Setup and Out are followed by a data packet two bit times (16 cycles) after
-;the end of SE0. The sync code allows up to 40 cycles delay from the start of
-;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
+;the end of SE0. The sync code allows up to 40 cycles delay (5 bit times) from
+;the start of the sync pattern until the first bit is sampled. That's a total of 56 cycles.
+
+; TB 2014-01-04
+; USB1.1 spec defines a minimum of two bit times and a maximum of 6.5 bit times
+; between Setup/Out and Data. We have to make sure we also cover the upper end
+; of the spec on a 16Mhz device.
+;
+; Bit times µs cycles @12Mhz cycles @16 Mhz
+; minimum 2 1.33 16 21
+; maximum 6.5 4.33 52 69
+; meas. Win7 3 2.04 24 32
+; meas. Linux 5 3.5 40 53
+;
+; Currently it is only checked at cycle 46..49 if another interrupt occured. This is
+; too early for 16 Mhz and the interrupt will not catch the data packet if it is later
+; than 4 bit times.
+;
+; fix: Introduce additional delay with timeout for the 16 und 16.5 Mhz version.
+; The 12 and 12.8 Mhz versions are still fine without as the maximum delay is less than 46 cycles.
+;
+; The total time until the next packet may not exceed 2 (min) +5 (sync tolerance) bit times
+; = 75 cycles @16Mhz to
+; The minimum time to cover max. timeout is 6.5 bit times = 70 cycles @16 Mhz
+;
+; Additional delay = 70-46=24 cycles. -> going to 21 cycles to be safe.
+
handleSetupOrOut: ;[32]
+; Delay, see above
+#if (F_CPU >= 16000000)
+ ldi YL, 7 ;
+USBdelay:
+ subi YL, 1
+ brne USBdelay
+#endif
#if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for endpoint != 0, set usbCurrentTok to address */
andi x3, 0xf ;[32]
breq storeTokenAndReturn ;[33]
@@ -94,13 +126,17 @@ storeTokenAndReturn:
sts usbCurrentTok, token;[35]
doReturn:
POP_STANDARD ;[37] 12...16 cycles
+
USB_LOAD_PENDING(YL) ;[49]
sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending
sofError:
POP_RETI ;macro call
- reti
-
+
+ CBI PORTB,0
+; reti
+ ret
+
handleData:
#if USB_CFG_CHECK_CRC
CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
@@ -120,10 +156,13 @@ handleData:
#endif
sts usbRxLen, cnt ;[28] store received data, swap buffers
sts usbRxToken, shift ;[30]
- lds x2, usbInputBufOffset;[32] swap buffers
- ldi cnt, USB_BUFSIZE ;[34]
- sub cnt, x2 ;[35]
- sts usbInputBufOffset, cnt;[36] buffers now swapped
+
+; Micronculeus v2 needs no double buffer due to in-order processing
+; TB 2014-01-04
+; lds x2, usbInputBufOffset;[32] swap buffers
+; ldi cnt, USB_BUFSIZE ;[34]
+; sub cnt, x2 ;[35]
+; sts usbInputBufOffset, cnt;[36] buffers now swapped
rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP
handleIn: