Source file: /~heha/Mikrocontroller/LEDs/u-wire.zip/usbdrv/asmcommon.inc

/* Name: asmcommon.inc
 * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
 * Author: Christian Starkjohann
 * Creation Date: 2007-11-05
 * Tabsize: 4
 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 * 
 * Heavily modified to be compatible with ATtiny10 - cpldcpu Jan 2014
 */

/* Do not link this file! Link usbdrvasm.S instead, which includes the
 * appropriate implementation!
 */

/*
General Description:
This file contains assembler code which is shared among the USB driver
implementations for different CPU cocks. Since the code must be inserted
in the middle of the module, it's split out into this file and #included.

Jump destinations called from outside:
    sofError: Called when no start sequence was found.
    se0: Called when a package has been successfully received.
    overflow: Called when receive buffer overflows.
    doReturn: Called after sending data.

Outside jump destinations used by this module:
    waitForJ: Called to receive an already arriving packet.
    sendAckAndReti:
    sendNakAndReti:
    sendCntAndReti:
    usbSendAndReti:

The following macros must be defined before this file is included:
    .macro POP_STANDARD
    .endm
    .macro POP_RETI
    .endm
*/

#define token   x1

overflow:
	ldi	x2, 1<<USB_INTR_PENDING_BIT
	USB_STORE_PENDING(x2)       ; clear any pending interrupts
ignorePacket:
	clr	token
storeTokenAndReturn:
	sts	usbCurrentTok, token;[35]
doReturn:    
	ret
    
;----------------------------------------------------------------------------
; Processing of received packet (numbers in brackets are cycles after center of SE0)
;----------------------------------------------------------------------------
;This is the only non-error exit point for the software receiver loop
;we don't check any CRCs here because there is no time left.
se0:
	subi	cnt, USB_BUFSIZE	;[5]
	neg	cnt			;[6]
	sub	ZL, cnt			;[7]
	sbci	ZH, 0			;[8]
	ldi	x2, 1<<USB_INTR_PENDING_BIT ;[9]
	USB_STORE_PENDING(x2)		;[10] clear pending intr and check flag later. SE0 should be over.
;	ld	token, z		;[11]
	ld	token, z+		;[11] <-- critical change to get  Attiny10 work
	cpi	token, USBPID_DATA0	;[13]
	breq	handleData		;[14]
	cpi	token, USBPID_DATA1	;[15]
	breq	handleData		;[16]
	lds	shift, usbDeviceAddr	;[17]
;	ldd	x2, z+1			;[19] ADDR and 1 bit endpoint number
	ld	x2, z			;[19] <-- critical change to get  Attiny10 to work
	lsl	x2			;[21] shift out 1 bit endpoint number
	cpse	x2, shift		;[22]
	rjmp	ignorePacket		;[23]

	cpi	token, USBPID_IN	;[27]
	breq	handleIn		;[28]
	cpi	token, USBPID_SETUP	;[29]
	breq	handleSetupOrOut	;[30]
	cpi	token, USBPID_OUT	;[31]
	brne	ignorePacket		;[32] must be ack, nak or whatever
;	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.
handleSetupOrOut:               ;[32]

; always wait for data if SETUP or OUT was found.
; No timeout, however the bus can be recovered at the next transmission

	sts     usbCurrentTok, token;[xx]
waitmore:    
	USB_LOAD_PENDING(ZL)        ;[xx]
	sbrc	ZL, USB_INTR_PENDING_BIT;[xx] check whether data is already arriving
	 rjmp	waitForJ            ;[xx] save the pops and pushes -- a new interrupt is already pending
	rjmp	waitmore

handleData:
	lds	shift, usbCurrentTok	;[18]
	tst	shift			;[20]
	breq	doReturn		;[21]
	lds	x2, usbRxLen		;[22]
	tst	x2			;[24]
	brne	sendNakAndReti		;[25]
; 2006-03-11: The following two lines fix a problem where the device was not
; recognized if usbPoll() was called less frequently than once every 4 ms.

;   The commented out code is not needed with polled usb

;	cpi	cnt, 4			;[26] zero sized data packets are status phase only -- ignore and ack
;	brmi	sendAckAndReti		;[27] keep rx buffer clean -- we must not NAK next SETUP

	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
	rjmp	sendAckAndReti		;[38] 40 + 17 = 57 until SOP

handleIn:
;We don't send any data as long as the C code has not processed the current
;input data and potentially updated the output data. That's more efficient
;in terms of code size than clearing the tx buffers when a packet is received.
	lds	x1, usbRxLen		;[30]
	cpi	x1, 1			;[32] negative values are flow control, 0 means "buffer free"
	brge	sendNakAndReti		;[33] unprocessed input packet?
	ldi	x1, USBPID_NAK		;[34] prepare value for usbTxLen

	lds	cnt, usbTxLen		;[37]
	sbrc	cnt, 4			;[39] all handshake tokens have bit 4 set
	rjmp	sendCntAndReti		;[40] 42 + 16 = 58 until SOP
	sts	usbTxLen, x1		;[41] x1 == USBPID_NAK from above
usbSendTxBuf:
	ldi	ZL, lo8(usbTxBuf)	;[43]
	ldi	ZH, hi8(usbTxBuf)	;[44]
	rjmp	usbSendAndReti		;[45] 57 + 12 = 59 until SOP

; Comment about when to set usbTxLen to USBPID_NAK:
; We should set it back when we receive the ACK from the host. This would
; be simple to implement: One static variable which stores whether the last
; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
; ACK. However, we set it back immediately when we send the package,
; assuming that no error occurs and the host sends an ACK. We save one byte
; RAM this way and avoid potential problems with endless retries. The rest of
; the driver assumes error-free transfers anyway.

Detected encoding: ASCII (7 bit)2