usbInit
;Oszillator: 48MHz vom INTOSC mittels 3x PLL)
banksel OSCCON ;Bank 1
movlwf 0xFC,OSCCON
;Warte bis PLL stabil
_wosc comf OSCSTAT,w
andlw (1<<PLLRDY)|(1<<HFIOFR)|(1<<HFIOFS)
brnz _wosc
;„active clock tuning“ aktivieren, Voraussetzung für USB Full-Speed ohne Quarz
banksel ACTCON ; Bank 7
movlwf (1<<ACTSRC)|(1<<ACTEN),ACTCON ; source = USB
;USB initialisieren
call usbReset
;Busverbindung herstellen
banksel UCON ;Bank 29
clrf UCON
bsf UCON,USBEN ; enable USB module and wait until ready
ret return
usbPoll
banksel UIR ;Bank 29
btfsc UIR,URSTIF ;USB-Reset?
goto usbReset ; if so, reset the USB interface
btfss UIR,TRNIF
return ;nichts zu tun
movfwf USTAT,FSR1H ;Status retten
bcf UIR,TRNIF ;Interruptflag löschen
banksel 0
andlw 0x78 ;Endpoint !=0 ?
skpz
return
; Handles a control transfer on endpoint 0.
; args: BSR=0, FSR1H=USTAT
; clobbers: W, FSR1H
btfsc FSR1H,DIR
bra usbE0I ;In-Transfer
; it's an OUT or SETUP transfer
movfw E0O_STA ; All non-PID bits are zero here because SETUP comes with DATA0
xorlw 13<<2 ; 13=PID_SETUP — is it a SETUP packet?
brnz usbE0O ;Out-Transfer
call handleSetup
banksel 0
movwf SETUPDAT_CNT
incfsz WREG,w
bra _setup_complete
bra _usb_ctrl_invalid
handleSetup
; Handles a SETUP control transfer on endpoint 0.
assume 0
clrf E0O_STA ; let start with DATA1
clrf E0I_STA ; let start with DATA1
;Die Datenrichtung ist später noch wichtig, deshalb hier aufheben
bcf USB_STATE,7
btfsc bmRequestType,7 ; is this device->host?
bsf USB_STATE,7 ; if so, this is a control read
movfw bmRequestType
xorlw 0xC0
brz _ivd ;0xC0 = in, vendor, device
decf bRequest,w
brz _get_report ;1 = GET_REPORT
; is it Set Address?
addlw 1-5 ;5 = SET_ADDRESS
brnz _osdn5
bsf USB_STATE,5 ;Adresse (später) setzen!
retlw 0
_osdn5 decfsz WREG,w ;6 = GET_DESCRIPTOR
bra _no_usb_get_descriptor
; Handles a Get Descriptor request.
; check descriptor type
decfsz wValueH,w ;1 = Device-Deskriptor
bra _isdn1
movlwf2 DEVICE_DESC,FSR0
retlw 18
_isdn1 decfsz WREG,w ;2 = Config-Deskriptor
bra _isdn2
movlwf2 CONFIG_DESC,FSR0
retlw CONFIG_DESC_LEN ; length includes all subordinate descriptors
_isdn2 decfsz WREG,w ;3 = String-Deskriptor
bra _isdn3
movlw wValueL
sublw STRING_DESC_N ;w = wValueL - 6
skpb
retlw -1 ;Falscher Index
movlwf2 STRING_DESC,FSR0
incf wValueL,f
bra _sdf
_sdl moviw FSR0
addwf FSR0L,f
skpnc
incf FSR0H,f
_sdf loop wValueL,_sdl
moviw FSR0
return
_isdn3 addlw 3-15 ;15 = BOS-Deskriptor
skpz
retlw -1
movlwf2 BOS_DESC,FSR0
retlw BOS_DESC_LEN
_no_usb_get_descriptor
; is it Get Configuration?
decf WREG,w
decfsz WREG,w ;8 = GET_CONFIG
bra _no_usb_get_configuration
; Handles a Get Configuration request.
; BSR=0
; load a pointer to either a 0 or a 1 in ROM
movlw low CONST0
btfsc USB_STATE,0 ;konfiguriert?
movlw low CONST1
movwf FSR0L
movlwf high CONST0,FSR0H
retlw 1
_no_usb_get_configuration
decfsz WREG,w ;9 = SET_CONFIG oder SET_REPORT
retlw -1
movfw bmRequestType
brnz _set_report
; Handles a Set Configuration request.
; BSR=0
movfwf wValueL,USB_STATE ; should be 0 or 1
; Initializes the buffers for the CDC endpoints (1 OUT, 1 IN, and 2 IN).
; clobbers: W, BSR=0
movlwf 1<<DTS|1<<DTSEN,E1I_STA ; USB NAK and toggle bit set: Send first packet as DATA0
retlw 0
_get_report
movfw bmRequestType
skpnz
retlw -1
movlwf2 report,FSR0
retlw 4
_set_report
movfw wValueL ;Report-ID
brz _prep_report0
xorlw 99 ;Magische Report-ID 99 (dezimal)?
skpz
retlw -1 ;nein, Fehler (STALL)
banksel PCON ;Bank1
bsf PCON,NOT_POR ;Kein Power-On-Reset
bcf PCON,NOT_RMCLR ;Reset-Ursache !MCLR vorgaukeln
reset ;Reset ausführen: Zum Urlader
_prep_report0
movlwf2 report,FSR0
retlw 4
_ivd ;In Vendor Device
decfsz bRequest,w
bra _ivdn1
movlwf2 URL_DESC,FSR0
retlw URL_DESC_LEN
_ivdn1
decfsz WREG,w
retlw -1
movlwf2 MSOS20_DESC,FSR0
retlw MSOS20_DESC_LEN
_setup_complete
movfwf2 FSR0,SETUPDAT_PTR
; If requested length is shorter, transfer less than descriptor size
tstf wLengthH
brnz _sc ; more than 255 bytes requested (Windows 7: 0x109)
movfw SETUPDAT_CNT
subwf wLengthL,w ; W = wLengthL - SETUPDAT_CNT (headroom)
skpnb ; if W >= 0, no need to adjust
addwf SETUPDAT_CNT,f ; SETUPDAT_CNT += wLengthL - SETUPDAT_CNT
_sc
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel 0
btfss bmRequestType,7
bra _cwrite
; this is a control read; prepare the IN endpoint for the data stage
; and the OUT endpoint for the status stage
call ep0_send_in ; read data into IN buffer
_e0ExpectOut
movlw 1<<DTS|1<<DTSEN ; make OUT buffer ready for status stage
; value in W is used to specify the EP0 OUT flags
_armbfs call arm_e0o_w
; Send next packet to Endpoint 0 In, size already set to E0I_CNT
arm_e0i
comf E0I_STA,w ; toggle DTS
andlw 1<<DTS
iorlw 1<<DTSEN
arm_e0i_w ; W specifies STAT flags
movwf E0I_STA
bsf E0I_STA,UOWN
return
; this is a control write: prepare the IN endpoint for the status stage
; and the OUT endpoint for the next SETUP transaction
_cwrite bcf E0I_STA,UOWN ; ensure we have ownership of the buffer
clrf E0I_CNT ; we'll be sending a zero-length packet
tstf SETUPDAT_CNT
brnz _e0ExpectOut
movlw 1<<DTSEN|1<<BSTALL ; make OUT buffer ready for next SETUP packet
bra _armbfs ; arm OUT and IN buffers
; Finishes a rejected SETUP transaction: the endpoints are stalled
_usb_ctrl_invalid
banksel UCON
bcf UCON,PKTDIS ; reenable packet processing
banksel 0
movlw 1<<DTSEN|1<<BSTALL
call arm_e0i_w
arm_ep0_out_stall ;for next SETUP
movlw 1<<DTSEN|1<<BSTALL
bra arm_e0o_w
;Wenn EP0-IN-Transfer beendet:
;* Control Read: Weitere Deskriptordaten senden
;* Control Write: Acknowledge-Paket war erfolgreich, ggf. USB-Adresse setzen
usbE0I btfss USB_STATE,7 ; is this a control read or write?
bra _check_for_pending_address
; fetch more data and re-arm the IN endpoint
call ep0_send_in
bra arm_e0i ; arm the IN buffer
; if this is the status stage of a Set Address request, assign the address here.
; The OUT buffer has already been armed for the next SETUP.
_check_for_pending_address
btfss USB_STATE,5 ;Adresse setzen?
return
bcf USB_STATE,5 ;passiert jetzt
movfw wValueL ;Endpoint-Puffer ist noch mit SETUP-Daten gefüllt
banksel UADDR
movwf UADDR
return
;Wenn EP0-OUT-Transfer beendet:
;* Control Read: Acknowledge-Paket
;* Control Write: (Weiteres) Datenpaket
usbE0O btfsc USB_STATE,7
bra _e0oe
tstf SETUPDAT_CNT
brz _e0oe
movfwf2 SETUPDAT_PTR,FSR0
movlwf2 E0_BUF,FSR1
_e0oc tstf E0O_CNT
brz _e0od
decf E0O_CNT,f
moviw FSR1++ ;EP0-Daten
movwi FSR0++ ;in RAM kopieren
loop SETUPDAT_CNT,_e0oc
_e0od movfwf2 FSR0,SETUPDAT_PTR
_e0oe comf E0O_STA,w ;DTS kippen
andlw 1<<DTS
iorlw 1<<DTSEN
arm_e0o_w ; W specifies STAT flags
movwf E0O_STA
movlwf 1<<E0_SSH,E0O_CNT ; reset the buffer count
bsf E0O_STA,UOWN ; arm the OUT endpoint
return
; Reads descriptor data from SETUPDAT_PTR, copies it to the EP0 IN buffer,
; and decrements SETUPDAT_CNT.
; Cannot simply point EP0_ADDR to flash as it is not accessible by USB SIE
; args: BSR=0
; returns: SETUPDAT_PTR advanced
; SETUPDAT_CNT decremented
; clobbers: W, FSR0, FSR1
ep0_send_in
clrf E0I_CNT ; initialize transfer length to 0
tstf SETUPDAT_CNT ; do nothing if there are 0 bytes to send
skpnz
return
movfwf2 SETUPDAT_PTR,FSR0 ; set up source pointer
movlwf2 E0_BUF,FSR1
; byte copy loop
_bcopy btfsc E0I_CNT,E0_SSH ; 8 Bytes full?
bra _bcdone
moviw FSR0++
movwi FSR1++
incf E0I_CNT,f ; increase number of bytes copied
loop SETUPDAT_CNT,_bcopy
; write back the updated source pointer
_bcdone movfwf2 FSR0,SETUPDAT_PTR
return
;WebUSB-Transmitpuffer EP1IN absenden
;PE: E1ISTA.UOWN gelöscht
; EP1IN-Puffer gefüllt (mit 4..8 Byte)
; E1I_CNT = Füllstand
;VR: W,BSR=0
e1i_tx
banksel 0
comf E1I_STA,w ;DataToggle
andlw 1<<DTS
iorlw 1<<DTSEN ;0↕001000
movwf E1I_STA
bsf E1I_STA,UOWN ;Puffer an SIE übergeben
return
; Initializes the USB system and resets all associated registers.
; clobbers: W,BSR=0,FSR0,FSR1L
usbReset
; clear USB registers
banksel UIR ; Bank 29
clrf UIR
; set configuration
movlwf (1<<UPUEN)|(1<<FSEN),UCFG ; enable pullups, full speed, no ping-pong buffering
;movlwf (1<<TRNIE)|(1<<URSTIE),UIE ; TODO: Need interrupts for CPU wakeup later
; clear all BDT entries, variables, and buffers
clrf FSR0H
movlwf 0x20,FSR0L ; BDT starts at 0x2000 aka 0x20, clear all Bank0 variables except RxBuf
movwf CL ; use 0x20 as loop count
clrw
_ramclr movwi FSR0++
loop CL,_ramclr
; reset ping-pong buffers and address
banksel UCON ; Bank 29: All about USB
bsf UCON,PPBRST
clrf UADDR
bcf UCON,PKTDIS ; enable packet processing
bcf UCON,PPBRST ; clear ping-pong buffer reset flag
; flush pending transactions
_tflush btfss UIR,TRNIF
bra _initep
bcf UIR,TRNIF
call ret ; need at least 6 cycles before checking TRNIF again
bra _tflush
; initialize endpoints:
; 0 für control
; 1 in für WebUSB (vergleichbar mit HID)
_initep movlwf 1<<EPHSHK|1<<EPOUTEN|1<<EPINEN,UEP0
movlwf 1<<EPHSHK|1<<EPCONDIS|1<<EPOUTEN|1<<EPINEN,UEP1
; initialize endpoint buffers and counts
banksel 0
movlwf2 LIN_E0_BUF,E0O_ADR ; set endpoint 0 address low
movlwf2 LIN_E0_BUF,E0I_ADR
movlwf2 LIN_E1I_BUF,E1I_ADR ; set endpoint 1 IN address low
goto arm_ep0_out_stall
| Vorgefundene Kodierung: UTF-8 | 0
|