COMMENT /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (C) Copyright Intel Corp., 1996 File: LOOPBACK&ISO&SUSRSM.asm Universal Serial Bus 930 Test firmware Revision History --------------------------------------------- 0.3 09-12-96 Myngoc Le 0.2 05-27-96 Abdul Rahman Ismail 0.1 02-13-96 Joe DrAgony ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ INCLUDE "swap.INC" INCLUDE "82930aa.INC" INCLUDE "ONE_OH.INC" ;------------- External functions - process.c ;EXTERN _SetFeature:CODE ;EXTERN _ClearFeature:CODE ;EXTERN _GetStatus:CODE ;EXTERN _SetLEDs:CODE EXTERN _SetInterface:CODE PUBLIC _TestThing PUBLIC _SOF_Init_FIFOs ;------------- Global variables. XDEF _EP1RxPtr, _EP1TxPtr, _EP1DataCount XDEF _EP2RxPtr, _EP2TxPtr, _EP2DataCount XDEF _EP3RxPtr, _EP3TxPtr, _EP3DataCount XDEF _gbMPSEndPoint1 XDEF _gbMPSEndPoint2 DEFINE CCB_SEGMENT, SPACE=CODE, ORG=0ff7ff8H SEGMENT CCB_SEGMENT ; CCB0 ; - WSA1# WSA0# XALE# RD1 RD0 PAGE# SRC ; CCB1 ; - - - INTR - WSB1# WSB0# EMAP# db 092h ; D2 Original Binary Mode-Paged Mode db 0F1h ; F7 Normal ;TO DO ; Change Packet Transfer to use Words not bytes. FIFO_SIZE equ 8 CSEG AT FF:0000H LJMP main CSEG AT FF:0003H ; INT0# ; LJMP INT0_ISR LJMP RWK_ISR CSEG AT FF:0013H ; INT1# ; LJMP INT1_ISR LJMP RWK_ISR CSEG AT FF:0043H ; Any SOF (ISO Endpoint) LJMP SOF_ISR CSEG AT FF:004BH ; USB Function (FTXDx,FRXDx)x=0,1,2,3 LJMP EPx_ISR CSEG AT FF:0053H ;USB Global Suspend/Resume LJMP Sus_ISR CSEG AT FF:0100H main: mov SP, #00h mov SPH, #05h ; Set the stack to start @ 00:0500h mov DPXL, #0ffh ; Set DPXL to point at the FLASH device to access constants mov IEN0, #00h ; Disable all interrupts mov P1, #3Ch lCall INIT_VARIABLES ; Initialize the RAM space as required mov P1, #66h lCall INIT_USB ; Initialize the USB subsystem mov P1, #0CCh mov R8, #8 ; same as 00:gEP_wMaxPacketSize mov 00:_gbMPSEndPoint1, R8 mov R8, #8 ; same as 00:gEPB_wMaxPacketSize mov 00:_gbMPSEndPoint2, R8 call _SOF_Init_FIFOs mov P1, #099h MOV IEN0, #84h ; Enable Global Interrupts MOV IEN1, #07h ; Enable USB Interrupts CLR IT1 ; set INT1# to level sensitive setb SOFIE ; Enable SOF interrupts ljmp ActiveLoop ;Jump over the ISR stubs to the main loop. ;Interrupts EPx_ISR: RetI _TestThing: mov R8, SOFH anl R8, #07h mov P1, R8 ret SOF_ISR: push R7 push R8 push EPINDEX ;; Put the counter on to see something working mov R8, SOFH ; mov R8, _gbMPSEndPoint1 anl R8, #07h mov P1, R8 ;; FOr testing only ; push R8 ; lcall _SetLEDs ; pop R8 ;; End for testing only clr ASOF ; jmp SOF_ISR_exit ; ### for test only ;; First check to see if there were any overflows. If so, then ;; Just re-init the fifos and start over. This should never happen ;; for transmits mov EPINDEX, #1 jnb TXOVF, ?SOF_Check_EP2 clr TXOVF call _SOF_Init_FIFOs jmp SOF_ISR_exit ?SOF_Check_EP2: mov EPINDEX, #2 jnb TXOVF, ?SOF_Check_FIFOs clr TXOVF call _SOF_Init_FIFOs jmp SOF_ISR_exit ?SOF_Check_FIFOs: mov R8, SOFL ; preload R8 with the right value mov EPINDEX, #1 mov R7, TXFLG anl R7, #0C0h ; Check if both bits are set cmp R7, #0C0h je ?SOF_Check_FIFO2 ; and if so, skip to next mov R7,_gbMPSEndPoint1 call SOF_Load_FIFO ?SOF_Check_FIFO2: mov EPINDEX, #2 mov R7, TXFLG anl R7, #0C0h ; Check if both bits are set cmp R7, #0C0h je SOF_ISR_exit ; and if so, no room so return mov R7,_gbMPSEndPoint2 call SOF_Load_FIFO SOF_ISR_exit: pop EPINDEX pop R8 pop R7 RetI ;; This routine will init the FIFOs for both pipes. _SOF_Init_FIFOs: push R8 push R7 push EPINDEX mov EPINDEX, #1 setb TXCLR mov R8, #0 mov R7, 00: _gbMPSEndPoint1 call SOF_Load_FIFO mov R8, #1 call SOF_Load_FIFO mov EPINDEX, #2 setb TXCLR mov R8, #0 mov R7, 00: _gbMPSEndPoint2 call SOF_Load_FIFO mov R8, #1 call SOF_Load_FIFO pop EPINDEX pop R7 pop R8 ret ;; This routine assumes that R7 holds the number of bytes to write ;; into the FIFO, and that R8 holds the value, and that EPINDEX is ;; setup properly. Registers are preserved. SOF_Load_FIFO: push R7 ?Fill_SOF_FIFO: mov TXDAT, R8 djnz R7, ?Fill_SOF_FIFO pop R7 mov TXCNTL, R7 Ret ;------------------------------------------------------------------ ;------------------------------------------------------------------ RWK_ISR: MOV P1, #20h ; clear Suspend LED reti Sus_ISR: jb GRSM, Resume_l ; MOV P1, #08h ; set LED for Suspend setb PD ; set Powerdown Mode bit to meet 500uA. jb GRSM,Resume_l ; jump if GRSM flag. setb RWU ; Set remote_wakeup bit. clr GSUS ; Clear the suspend bit. reti Resume_l: ; jb GSUS, Sus_ISR ; clr GRSM ; Clear Resume bit MOV P1, #20h ; reset Suspend LED, turn on resume LED reti COMMENT *------------------------------------------------------------ Function name : ActiveLoop Brief Description : Monitors RX and TX on all EPs Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ActiveLoop: ; jb GRSM, resume_l ; jump if Global Resume flag. ; jb GSUS, pw_down ; jump if Global Suspend flag. ; mov R8, SOFH ; mov P1, R8 ; clr SOFH.6 EP0_RX: jnb FRXD0, EP0_TX mov EPINDEX, #0 lCall OUT_TOKEN1 ; 82930 has received a packet from HC EP0_TX: jnb FTXD0, EP1_RX mov EPINDEX, #0 lCall IN_TOKEN ; 82930 has sent a packet to HC EP1_RX: ; jnb FRXD1, EP1_TX ; mov EPINDEX, #1 ; lCall ServiceEP1RX ; lCall PrimeEP1Fifo EP1_TX: ; jnb FTXD1, EP2_RX ; mov EPINDEX, #1 ; lCall ServiceEP1TX EP2_RX: ; jnb FRXD2, EP2_TX ; mov EPINDEX, #2 ; lCall ServiceEP2RX ; lCall PrimeEP2Fifo EP2_TX: ; jnb FTXD2, EP3_RX ; mov EPINDEX, #2 ; lCall ServiceEP2TX EP3_RX: ; jnb FRXD3, EP3_TX ; mov EPINDEX, #3 ; lCall ServiceEP3RX ; lCall PrimeEP3Fifo EP3_TX: ; jnb FTXD3, EP_Done ; mov EPINDEX, #3 ; lCall ServiceEP3TX EP_Done: ljmp ActiveLoop SCOPE ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; This is the block that services EP0 events. ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ;####################### FAKE INTERUPT ROUTINE ####################### ; ; SetupSeq Meaning ; 0 No Setup command pending. Any out received is treated as a ; DeviceRequest. Later steppings will actually detect a SETUP ; packet and set a status flag telling us SETUP was received. ; ; 1 DeviceRequest Received, Processing Get Request. An IN Will ; transfer data. An Out will end the transfer and set ; SetupSeq to 0 ; ; 2 DeviceRequest Received, Processing Set Request. An OUT Will ; transfer data to the buffer. An IN will end the transfer and ; set SetupSeq to 0 ; ; 3 Done bit SetRequest. Ignore all data sent until an IN ; Used for Set Address ; This block of code deals with Endpoint 0 getting a transmit event interrupt. OUT_TOKEN1: anl FIFLG, #EP0_RX_CLR ; Clear the interrupt bit. ;Check sequence bit for the state that we are in. mov WR28, #00 ; point to page 00 mov WR30, #LOW16(SetupSeq) mov R11, @DR28 cmp R11, #0 ; Is this a setup packet?? jne ?l1 ; If not, then deal with the data phase. lcall SETUP_TOKEN ; If yes, then parse the setup command. ljmp ?lx ; Return to caller. ; If this is not a setup command then it must be one of two things ; 0 or more data packets for a set command (Seq=2) or an ; status result if Seq=1 ?l1: cmp R11, #1 ; Is this the status phase of a "GET" command? jne ?l2 ; No, so check next SETB RXCON0.4 ;Update receive FIFO state SETB TXCON0.7 ;Flush the Transmit FIFOS CLR EPCON0.1 ;disable Tx Output on EP0. Respond to "IN" ;with "NAK" mov WR30,#LOW16(SetupSeq) ;Update the state machine-Expect a setup token mov r11,#0 mov @DR28, R11 sjmp ?lx ;jb RXSTAT0.6, ?l1 ; If not SETUP then must be a standard out ?l2: cmp R11, #2 ; Are we processing a Control Write, i.e. Set Descr... jne ?l3 lcall OUT_TOKEN ; If we are continue to read in the data. SJMP ?lx ?l3: cmp R11, #3 ;If 3, then we are done setting the address and ;all outs are to be ignored until an IN terminates ;the control transfer jne ?l4 SETB RXCON0.4 ;Clear the receive FIFO sjmp ?lx ?l4: ?lx: ret SCOPE ;##################################################################### ;#################### IN TOKEN ###################################### ;##################################################################### ; SetupSeq Meaning ; 0 No Setup command pending. Any out received is a DeviceRequest ; ; 1 DeviceRequest Received, Processing Get Request. An IN Will ; transfer data. An Out will end the transfer and set ; SetupSeq to 0 ; ; 2 DeviceRequest Received, Processing Set Request. An OUT Will ; transfer data to the buffer. An IN will end the transfer and ; set SetupSeq to 0 ; ; 3 Done SetADDRESS Request. Ignore all data sent until an IN ; Used for Set Address ; ; ; For in tokens we can do 2 things. ; ; If SetupSeq = 2,3 then a IN will terminate the control transfer. SCOPE IN_TOKEN: anl FIFLG, #EP0_TX_CLR ; clear the interrupt bit mov R11, 00:SetupSeq ; read state variable cmp R11, #02h ; Should this be the end to a setup sequence? jne InTokenCheckSA ; If no,check for end of set address ?StatusPhaseDone: mov R11, #00h mov 00:SetupSeq, R11 ; Set state var. to expect setup. jmp ?Return InTokenCheckSA: cmp R11, #03h ; Prev. Setup was SetAddress??? jne ?SendDataBack mov R10, 00:new_addr mov FADDR, R10 mov R11, #00h mov 00:SetupSeq, R11 jmp ?Return ?SendDataBack: cmp R11, #01h jne ?Return lCall DoControlOutput ?Return: Ret SCOPE ;***************** SETUP_TOKEN ************************* ;***** Gets and saves SETUP DATA ************************ ;****************************************************** ;Procedure that takes SETUP data from the FIFO, Puts it in memory ;and then updates writes it to the fifo. SETUP_TOKEN: MOV WR28, #0 ; USE DR28 for our data pointer mov WR30, #LOW16(COMMAND_BUFFER) mov R8, RXCNT0 ; Use R8 for our count register mov @DR28, R8 ; Store the count in the buffer add WR30, #1 ; Increment mem pointer orl R8, R8 ; Set flags je ?k2 ; Zero length SETUP, error out.... ;(KLS) clr EDOVW ; Release the SETUP Fifo to be read. ; Read FIFO loop ?k1: mov R11, RXDAT0 ; Read byte from FIFO into R11 mov @DR28, R11 ; Store it in the buffer ADD WR30, #1 ; Increment the pointer sub R8, #1 ; Decrement the counter jne ?k1 ; Read until FIFO empty setb RXCON0.4 ; Set FFRC bit to update RX FIFO state ;(KLS) clr RXSETUP ; Release the FIFO to no longer NAK data. sjmp PROCESS_SETUP ?k2: ;Should never get a zero length setup. setb RXCON0.4 ;Clear the fifo LJMP EXIT_SETUP ;leave. SCOPE ;***************** PROCESS_SETUP ********************** ;***** PROCESS THE SETUP ****************************** ;****************************************************** SCOPE PROCESS_SETUP: ;Compare bmRequest Type ;If it's it 1xxxxxxb - Get Descriptor/Get Configuration ;If it's it 0xxxxxxb - Set Address/Configuration/Set Feature/Clear Feature. mov WR28, #0 mov WR30, #LOW16(bmRequestType) mov R11, @DR28 anl R11, #80h; Get/Set ?? jne DO_GET_COMMAND LJMP DO_SET_COMMAND ;=================================================== ; Routines to process a get descriptor/configuration ;=================================================== DO_GET_COMMAND: ;Is this a get_config or a Get_Descrip. mov WR30, #LOW16(bRequest) mov R11, @DR28 cmp R11, #GET_DESCRIPTOR jne CheckGetConfig ljmp GET_DESCR_Request ;Go get Descriptor (Device & Config) CheckGetConfig: cmp R11, #GET_CONFIGURATION jne CheckGetStatus ljmp GET_CONFIG_Request ;Go get config request ; code for other types of bRequests CheckGetStatus: cmp R11, #GET_STATUS jne CheckGetInterface mov WR12, wIndex SWAP_BYTES R12,R13,R14 push WR12 ;wIndex mov R12, bmRequestType push R12 ;bmRequestType ; lCall _GetStatus ;Go get status sub SPX, #03h ; WR0 contains the result returned from GetStatus ; need to swap the bytes to make it little endian for the bus SWAP_BYTES R0, R1, R2 mov R2, #01h mov SetupSeq , R2 ;Advance State Machine to next state lCall SetStatusData lCall DoControlOutput ;primes fifo ljmp EXIT_SETUP CheckGetInterface: cmp R11, #GET_INTERFACE jne CheckSynchFrame ljmp GET_CONFIG_Request ;Go get config request CheckSynchFrame: cmp R11, #SYCH_FRAME jne GetCommandExit ljmp GET_CONFIG_Request ;Go get config request GetCommandExit: ljmp EXIT_SETUP ;=================================================== ; Routines to process a set descriptor/configuration ;=================================================== DO_SET_COMMAND: mov WR30, #LOW16(bRequest) mov R11, @DR28 cmp R11, #SET_DESCRIPTOR ; Was this a Set_Descriptor? jne ?CheckSetConfig jmp DO_SET_DESCRIPTOR ?CheckSetConfig: cmp R11, #SET_CONFIGURATION ; Was this a Set_Configuration? jne ?CheckSetInterface jmp DO_SET_CONFIGURATION ?CheckSetInterface: cmp R11, #SET_INTERFACE ; Was this a Set_Interface? jne ?CheckClearFeature jmp DO_SET_INTERFACE ?CheckClearFeature: cmp R11, #CLEAR_FEATURE jne ?CheckSetAddress jmp DO_CLEAR_FEATURE ?CheckSetAddress: cmp R11, #SET_ADDRESS ; Was this a Set_Address? jne ?CheckSetFeature jmp DO_SET_ADDRESS ?CheckSetFeature: cmp R11, #SET_FEATURE ; Was this a Set_Feature? jne ?CheckExit jmp DO_SET_FEATURE ?CheckExit: ajmp DO_SET_COMMAND_EXIT DO_SET_DESCRIPTOR: ; ajmp DO_SET_COMMAND_EXIT DO_SET_CONFIGURATION: ; ajmp DO_SET_COMMAND_EXIT DO_SET_INTERFACE: ; ;###################################################################### ;; This stuff was originally here to call into C. It doesn't ;; work easily so it is booted ;###################################################################### ; push DR28 ; These push'es are here to protect what ; push WR26 ; gets used by the C-code that is called ; push WR14 ; below ; ; mov WR12, wIndex ; SWAP_BYTES R12, R13, R14 ; push WR12 ; ; mov WR12, wValue ; SWAP_BYTES R12, R13, R14 ; push WR12 ; ; lCall _SetInterface ; sub SPX, #04h ; ; pop WR14 ; pop WR26 ; pop DR28 ;###################################################################### ;###################################################################### mov WR12, wValue ; Loads the 'word' value R12 actually holds ; what we want cmp R12,#0 jne ?SI1 mov R8, #8 ; Alt setting 0 - MPS1=8 MPS2=8 mov _gbMPSEndPoint1,R8 mov R8, #8 mov _gbMPSEndPoint2,R8 jmp SI_leave ?SI1: cmp R12,#1 jne ?SI2 mov R8, #32 ; Alt setting 1 - MPS1=32 MPS2=4 mov _gbMPSEndPoint1,R8 mov R8, #4 mov _gbMPSEndPoint2,R8 jmp SI_leave ?SI2: cmp R12,#2 jne ?SI3 mov R8, #64 ; Alt setting 2 - MPS1=64 MPS2=2 mov _gbMPSEndPoint1,R8 mov R8, #2 mov _gbMPSEndPoint2,R8 jmp SI_leave ?SI3: cmp R12,#3 jne ?SI4 mov R8, #128 ; Alt setting 3 - MPS1=128 MPS2=1 mov _gbMPSEndPoint1,R8 mov R8, #1 mov _gbMPSEndPoint2,R8 jmp SI_leave ?SI4: cmp R12,#4 jne ?SI5 mov R8, #53 ; Alt setting 4 - MPS1=53 MPS2=3 mov _gbMPSEndPoint1,R8 mov R8, #3 mov _gbMPSEndPoint2,R8 jmp SI_leave ?SI5: cmp R12,#5 jne SI_leave mov R8, #103 ; Alt setting 5 - MPS1=103 MPS2=7 mov _gbMPSEndPoint1,R8 mov R8, #7 mov _gbMPSEndPoint2,R8 SI_leave: clr SOFIE ; Disable SOF interrupts call _SOF_Init_FIFOs ; Set the FIFOs back to startup setb SOFIE ; Enable SOF interrupts mov WR30, #LOW16(SetupSeq) mov R10, #2 ; This was a Set with do data phase. mov @DR28, R10 ;Set state to look for status phase. ajmp DO_SET_COMMAND_EXIT DO_CLEAR_FEATURE: mov WR12, wIndex SWAP_BYTES R12, R13, R14 push WR12 mov WR12, wValue SWAP_BYTES R12, R13, R14 push WR12 mov R12, bmRequestType push R12 ; LCall _ClearFeature sub SPX, #05h jmp DO_SET_COMMAND_EXIT DO_SET_FEATURE: mov WR12, wIndex SWAP_BYTES R12, R13, R14 push WR12 mov WR12, wValue SWAP_BYTES R12, R13, R14 push WR12 mov R12, bmRequestType push R12 ; LCall _SetFeature sub SPX, #05h mov WR30, #LOW16(SetupSeq) mov R10, #2 ; This was a Set Address command. mov @DR28, R10 ;Set state to look for status phase. jmp DO_SET_COMMAND_EXIT DO_SET_ADDRESS: mov WR30, #LOW16(wValue) ; Get the address from wValue and store it. mov WR8, @DR28 ; It doesn't actually get changed until the mov WR30, #LOW16(new_addr) ;status phase completes successfully. mov @DR28, R8 mov WR30, #LOW16(SetupSeq) mov R10, #3 ; This was a Set Address command. mov @DR28, R10 ;Set state to look for status phase. ajmp DO_SET_COMMAND_EXIT DO_SET_COMMAND_EXIT: mov EPINDEX, #0 mov TXCNT0, #0 ; Prime FIFO for response to status phase setb EPCON0.1 ; Set the Tx output enable bit. ajmp EXIT_SETUP ; ********************** GET DESCRIPTOR ******************* GET_DESCR_Request: mov WR30, #LOW16(wValue) mov WR10, @DR28 cmp R11, #DEVICE_DESCR ;Low Byte in Rll jne ?c1 ; ********************** GET DESCRIPTOR, DEVICE ******************* mov WR30, #LOW16(SetupSeq) ;Advance State Machine to next state mov R10, #1 ;Set state to doing a "GET" command mov @DR28, R10 ; mov WR28, #0ffh; ; Located in ROM->Page=0ff mov WR30, #LOW16(DEVICE_DESCRIPTOR); LCALL BufferControlData LCALL DoControlOutput ljmp EXIT_SETUP ?c1: cmp R11, #CONFIG_DESCR jne ?c2 ; ********************** GET DESCRIPTOR, CONFIGURATION ************ mov WR30, #LOW16(SetupSeq) ;Update state machine mov R9, #1 mov @DR28, R9 mov WR28, #0ffh; ;Located in ROM mov WR30, #LOW16(CONFIGURATION_DESCRIPTOR); cmp R10, #1 jne ?c45 mov WR30, #LOW16(CONFIGURATION_DESCRIPTOR2); ?c45: LCALL BufferControlData LCALL DoControlOutput ljmp EXIT_SETUP ?c2: ljmp EXIT_SETUP GET_CONFIG_Request: EXIT_SETUP: ret SCOPE ;***************** OUT_TOKEN ************************* ;***** Gets and saves OUT DATA ************************ ;****************************************************** ;Program that takes data from the FIFO, Puts it in memory ;and then updates writes it to the fifo. OUT_TOKEN: ; Get the data and place it in the in_buffers anl FIFLG, #EP0_RX_CLR ; Clear the bit MOV WR24, #0 ; USE DR24 mov WR26, #LOW16(OUT_BUFFERS) mov R8, RXCNT0 ; Read count of bytes rec'd into R8 mov @DR24, R8 ; Store the count in the OUT_BUFFERS space. add WR26, #1 ; Increment mem pointer orl R8, R8 ; Set flags je ?k2 ?k1: mov R7, RXDAT0 ; Read loop mov @DR24, R7 ADD WR26, #1 sub R8, #1 jne ?k1 ?k2: setb RXCON0.4 ; Clear the fifo ; We now have the data in the buffer. ; Transmit it to the xmit fifo ret COMMENT *------------------------------------------------------------ Function name : ServiceEP1RX Brief Description : Copies data recd. on EP 1 and stores the same in : a buffer. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP1RX: anl FIFLG, #EP1_RX_CLR ; Clear the interrupt bit jb RXACK, ?GoodReceive ; If R_ACK set then a good reception jmp ?Return ; else leave ?GoodReceive: mov R6, #00h mov R7, RXCNT1 ; Get the no. of bytes recd. cmp R7, #00h ; Check whether a null data packet was recd. je ?NullPacketRecd ; mov WR10, _EP1RxPtr ; Get offset of next free location in the buffer mov WR30, #EP_1_Buffer ; get address of start of buffer. add WR30, WR10 ; get to next free locaion. add WR10, WR6 anl WR10, #RINGBUFFMASK ; do modulo 800h rollover mov _EP1RxPtr, WR10 ; update the RXPtr offset in buffer. mov WR10, _EP1DataCount ; get current data count add WR10, WR6 ; add no. of bytes recd. mov _EP1DataCount, WR10 ; update the data count ?CopyDataToBuffer: mov R12, RXDAT1 ; Read data from FIFO mov @WR30, R12 ; store in data buffer inc WR30, #01h ; incr. ptr into buffer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?CopyDataToBuffer ?ReadyForAnotherRX: add WR10, #EP1MAXPACKET ; The next packet can ba a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is < than the total buffer sapce, return jl ?NullPacketRecd clr RXIE ; Set not ready to RX till a enuf space is available. ?NullPacketRecd: setb RXFFRC ; signal FIFO read complete to trigger ARM ; logic for FIFO management ?Return: Ret COMMENT *------------------------------------------------------------ Function name : ServiceEP1TX Brief Description : Deals with a transmit event on endpoint 1 It : checks to be sure a FIFO is available. It then : checks for data availability. If the no. of bytes : of data is greater than the MaxPacket size, then : MaxPacket bytes are sent. Otherwise all the : available data is sent. In either case the data : count and TxPtr are adjusted after the move. : It can be called as the result of a Tx or an Rx : interrupt. If its a Tx interrupt it enters at : ServiceEP1TX. If its from an Rx interrupt it : enters at PrimeEP1Fifo. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP1TX: anl FIFLG, #EP1_TX_CLR ; Clear the interrupt bit. PrimeEP1Fifo: jnb TXFIF1, ?FifoAvailable ; Make sure a fifo is available jnb TXFIF0, ?FifoAvailable ; Make sure a fifo is available jmp ?Return ?FifoAvailable: mov WR6, _EP1DataCount ; Get data count in WR6 cmp WR6, #00h ; is data count == 0? jne ?Continue jmp ?Return ?Continue: cmp WR6, #EP1MAXPACKET ; cmp with MPS jl ?LessThanMPS ?MoreThanMPS: mov WR6, #EP1MAXPACKET ; Set NoOfBytes to transfer to MPS ?LessThanMPS: mov WR10, _EP1TxPtr ; Get offset of first full location ; in the endpoint buffer mov WR30, #EP_1_Buffer ; set WR30 back to buffer start add WR30, WR10 ; get to first full location add WR10, WR6 anl WR10, #RINGWORDMASK ; do modulo 800h rollover mov _EP1TxPtr, WR10 mov WR10, _EP1DataCount sub WR10, WR6 mov _EP1DataCount, WR10 push R7 ?ArmTXFifo: mov R12, @WR30 ; Read data from buffer mov TXDAT1, R12 ; store in Tx FIFO inc WR30, #01h ; inc. the pointer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?ArmTXFifo pop R7 mov TXCNT1, R7 ; Write the transmit count ?ReadyForRX: jb RXIE , ?Return ?RXWasDisabled: add WR10, #EP1MAXPACKET ; The next packet can be a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is > than the total buffer sapce jg ?Return ; return setb RXIE ; Set ready to RX as enuf buffer space is ; now available. ?Return: Ret COMMENT *------------------------------------------------------------ Function name : ServiceEP2RX Brief Description : Copies data recd. on EP 2 and stores the same in : a buffer. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP2RX: anl FIFLG, #EP2_RX_CLR ; Clear the interrupt bit jb RXACK, ?GoodReceive ; If R_ACK set then a good reception jmp ?Return ; else leave ?GoodReceive: mov R6, #00h mov R7, RXCNT2 ; Get the no. of bytes recd. cmp R7, #00h ; Check whether a null data packet was recd. je ?NullPacketRecd ; mov WR10, _EP2RxPtr ; Get offset of next free location in the buffer mov WR30, #EP_2_Buffer ; get address of start of buffer. add WR30, WR10 ; get to next free locaion. add WR10, WR6 anl WR10, #RINGBUFFMASK ; do modulo 800h rollover mov _EP2RxPtr, WR10 ; update the RXPtr offset in buffer. mov WR10, _EP2DataCount ; get current data count add WR10, WR6 ; add no. of bytes recd. mov _EP2DataCount, WR10 ; update the data count ?CopyDataToBuffer: mov R12, RXDAT2 ; Read data from FIFO mov @WR30, R12 ; store in data buffer inc WR30, #01h ; incr. ptr into buffer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?CopyDataToBuffer ?ReadyForAnotherRX: add WR10, #EP2MAXPACKET ; The next packet can ba a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is < than the total buffer sapce, return jl ?NullPacketRecd clr RXIE ; Set not ready to RX till a enuf space is available. ?NullPacketRecd: setb RXFFRC ; signal FIFO read complete to trigger ARM ; logic for FIFO management ?Return: Ret COMMENT *------------------------------------------------------------ Function name : ServiceEP2TX Brief Description : Deals with a transmit event on endpoint 1 It : checks to be sure a FIFO is available. It then : checks for data availability. If the no. of bytes : of data is greater than the MaxPacket size, then : MaxPacket bytes are sent. Otherwise all the : available data is sent. In either case the data : count and TxPtr are adjusted after the move. : It can be called as the result of a Tx or an Rx : interrupt. If its a Tx interrupt it enters at : ServiceEP2TX. If its from an Rx interrupt it : enters at PrimeEP2Fifo. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP2TX: anl FIFLG, #EP2_TX_CLR ; Clear the interrupt bit. PrimeEP2Fifo: jnb TXFIF1 , ?FifoAvailable ; Make sure a fifo is available jnb TXFIF0 , ?FifoAvailable ; Make sure a fifo is available jmp ?Return ?FifoAvailable: mov WR6, _EP2DataCount ; Get data count in WR6 cmp WR6, #00h ; is data count == 0? jne ?Continue jmp ?Return ?Continue: cmp WR6, #EP2MAXPACKET ; cmp with MPS jl ?LessThanMPS ?MoreThanMPS: mov WR6, #EP2MAXPACKET ; Set NoOfBytes to transfer to MPS ?LessThanMPS: mov WR10, _EP2TxPtr ; Get offset of first full location ; in the endpoint buffer mov WR30, #EP_2_Buffer ; set WR30 back to buffer start add WR30, WR10 ; get to first full location add WR10, WR6 anl WR10, #RINGWORDMASK ; do modulo 800h rollover mov _EP2TxPtr, WR10 mov WR10, _EP2DataCount sub WR10, WR6 mov _EP2DataCount, WR10 push R7 ?ArmTXFifo: mov R12, @WR30 ; Read data from buffer mov TXDAT2, R12 ; store in Tx FIFO inc WR30, #01h ; inc. the pointer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?ArmTXFifo pop R7 mov TXCNT2, R7 ; Write the transmit count ?ReadyForRX: jb RXIE, ?Return_3 ?RXWasDisabled: add WR10, #EP2MAXPACKET ; The next packet can be a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is > than the total buffer sapce jg ?Return_3 ; return setb RXIE ; Set ready to RX as enuf buffer sp ; now available. ?Return_3: mov R11, TXFLG anl R11, #0C0h jZ ?Return jmp ServiceEP2TX ?Return: Ret COMMENT *------------------------------------------------------------ Function name : ServiceEP3RX Brief Description : Copies data recd. on EP 3 and stores the same in : a buffer. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP3RX: anl FIFLG, #EP3_RX_CLR ; Clear the interrupt bit jb RXACK, ?GoodReceive ; If R_ACK set then a good reception jmp ?Return ; else leave ?GoodReceive: mov R6, #00h mov R7, RXCNT3 ; Get the no. of bytes recd. cmp R7, #00h ; Check whether a null data packet was recd. je ?NullPacketRecd ; mov WR10, _EP3RxPtr ; Get offset of next free location in the buffer mov WR30, #EP_3_Buffer ; get address of start of buffer. add WR30, WR10 ; get to next free locaion. add WR10, WR6 anl WR10, #RINGBUFFMASK ; do modulo 800h rollover mov _EP3RxPtr, WR10 ; update the RXPtr offset in buffer. mov WR10, _EP3DataCount ; get current data count add WR10, WR6 ; add no. of bytes recd. mov _EP3DataCount, WR10 ; update the data count ?CopyDataToBuffer: mov R12, RXDAT3 ; Read data from FIFO mov @WR30, R12 ; store in data buffer inc WR30, #01h ; incr. ptr into buffer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?CopyDataToBuffer ?ReadyForAnotherRX: add WR10, #EP3MAXPACKET ; The next packet can ba a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is < than the total buffer sapce, return jl ?NullPacketRecd clr RXIE ; Set not ready to RX till a enuf space is available. ?NullPacketRecd: setb RXFFRC ; signal FIFO read complete to trigger ARM ; logic for FIFO management ?Return: Ret COMMENT *------------------------------------------------------------ Function name : ServiceEP3TX Brief Description : Deals with a transmit event on endpoint 1 It : checks to be sure a FIFO is available. It then : checks for data availability. If the no. of bytes : of data is greater than the MaxPacket size, then : MaxPacket bytes are sent. Otherwise all the : available data is sent. In either case the data : count and TxPtr are adjusted after the move. : It can be called as the result of a Tx or an Rx : interrupt. If its a Tx interrupt it enters at : ServiceEP3TX. If its from an Rx interrupt it : enters at PrimeEP3Fifo. Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ServiceEP3TX: anl FIFLG, #EP3_TX_CLR ; Clear the interrupt bit. PrimeEP3Fifo: jnb TXFIF1, ?FifoAvailable ; Make sure a fifo is available jnb TXFIF0, ?FifoAvailable ; Make sure a fifo is available jmp ?Return ?FifoAvailable: mov WR6, _EP3DataCount ; Get data count in WR6 cmp WR6, #00h ; is data count == 0? jne ?Continue jmp ?Return ?Continue: cmp WR6, #EP3MAXPACKET ; cmp with MPS jl ?LessThanMPS ?MoreThanMPS: mov WR6, #EP3MAXPACKET ; Set NoOfBytes to transfer to MPS ?LessThanMPS: mov WR10, _EP3TxPtr ; Get offset of first full location ; in the endpoint buffer mov WR30, #EP_3_Buffer ; set WR30 back to buffer start add WR30, WR10 ; get to first full location add WR10, WR6 anl WR10, #RINGWORDMASK ; do modulo 800h rollover mov _EP3TxPtr, WR10 mov WR10, _EP3DataCount sub WR10, WR6 mov _EP3DataCount, WR10 push R7 ?ArmTXFifo: mov R12, @WR30 ; Read data from buffer mov TXDAT3, R12 ; store in Tx FIFO inc WR30, #01h ; inc. the pointer anl WR30, #RINGBUFFMASK ; do modulo 800h rollover djnz R7, ?ArmTXFifo pop R7 mov TXCNT3, R7 ; Write the transmit count ?ReadyForRX: jb RXIE , ?Return ?RXWasDisabled: add WR10, #EP3MAXPACKET ; The next packet can be a max of MPS cmp WR10, #RINGBUFFSIZE ; If this is > than the total buffer sapce jg ?Return ; return setb RXIE ; Set ready to RX as enuf buffer space is ; now available. ?Return: Ret SCOPE ;################################################################### ;################### BufferControlData ############################ ;## Transfers the data pointed to by DR28 into the IN Buffer ####### ;## Also assumes that the first byte pointed to by DR28 is the ##### ;## number of bytes to be moved, immediately followed by the data ## ;################################################################### SCOPE BufferControlData: ;DR28 has address of data mov R6, #00h mov R7, @DR28 ; Move Count add WR30, #01h ; increment pointer to first byte of data mov R9, #00h mov in_rd_pntr, R9 ;Set buffer pointer to zero ;for new transfer mov WR10, wLength ; cmp no of bytes asked for with the SWAP_BYTES R10,R11,R12 ; no. of bytes that the descriptor cmp WR6, WR10 ; contains. jle ?Continue mov WR6, WR10 ; If the no. of bytes in the descriptor ; is greater than the no. of bytes asked for ; send back only the no. of bytes as per ; the Setup packet. ?Continue: mov in_bytes_left, R7 ;Store Count mov WR26, #LOW16(IN_BUFFERS) ?MoveMemory: mov R9, @DR28 ; Get data mov @WR26, R9 ; Store data add WR26, #01h add WR30, #01h djnz R7, ?MoveMemory Ret ; --------------------------------------------------------- ; ; ; --------------------------------------------------------- SetStatusData: mov R2, #00h mov in_rd_pntr, R2 ;Set buffer pointer to zero mov R2, #02h mov in_bytes_left, R2 ;point to count variable mov WR26, #LOW16(IN_BUFFERS) mov @WR26, WR0 Ret ;################################################################### ;################# DoControlOutput ################################## ;################################################################### SCOPE DoControlOutput: clr EPCON0.1 ; Set it up so that data is not Xmitted ; while were are filling up the fifo. mov R10, in_bytes_left cmp R10, #00h ;check for none jne CntlDataAvail ;if ther is data do normal flow mov R8, #00h ;if none, do null packet ljmp ControlArmTx CntlDataAvail: mov WR26, #LOW16(IN_BUFFERS) ;Get the address of the first char mov R12, #00h ;set up a word value for add since mov R13, in_rd_pntr ;this is just a byte value. add WR26, WR12 ;Add the read_pointer to the buffer location mov R8, #00h ;initialize FIFO full counter push R10 ;save starting bytes avail count ?WriteToFifo: mov R11, @WR26 ;Get the data mov TXDAT0, R11 ;write it into the FIFO add WR26, #01h ;Increment buffer pointer add R8,#01h ;Increment FIFO count sub R10, #01h ;Are we done with the buffer je ControlTxUpd cmp R8, #FIFO_SIZE ;FIFO FULL? jne ?WriteToFifo ControlTxUpd: pop R10 ;restore starting count mov R12, in_rd_pntr ;Get the offset into IN_BUFFER add R12, R8 ;add amount we consumed mov in_rd_pntr, R12 ;store the new offset sub R10, R8 ;subtract amount we just consumed mov in_bytes_left, R10 ;store new count ControlArmTx: mov TXCNT0, R8 ;Write count into TXCNT register setb EPCON0.1 ;Enable data transmit ?Return: Ret SCOPE ;***************************************************** ;***************** INIT_USB ************************* ;***************************************************** INIT_USB: ;(KLS) mov EPINDEX, #00h mov TXCON0,#84h ;/* Flush FIFO, sets Empty bit in TXFLG0, enable ATM. */ mov RXCON0,#84h ;/* Flush FIFO, sets Empty bit in RXFLG0, enable ARM. */ ; Enable endpoint 0 as a control endpoint. We need to set the ; Transmit Endpoint enable, Receive Endpoint enable, and the ; Receive Input enable. We do not set the Transmit Output enable ; until we have determined what type of response we need to send ; back, i.e., NULL packet for status phase or data for a "GET" ; command. mov EPCON0,#2Dh; ; The non-zero endpoints are being enabled here just so they will ; NAK any tokens sent to them. This is really not correct, since ; by the spec they should not respond at all until the host has ; set a configuration for this endpoint. We will set the Receive ; Endpoint enable and Transmit Endpoint enable bits for these guys ; but not the input and output enables. mov EPINDEX, #01h mov TXCON1,#84h ;/* Flush FIFO, sets Empty bit in TXFLG1, enable ATM. */ setb TXISO ; Make it an ISO endpoint mov RXCON1,#84h ;/* Flush FIFO, sets Empty bit in RXFLG1, enable ARM. */ mov EPCON1,#03h; ;/* Transmit only */ mov EPINDEX, #02h mov TXCON2,#84h ;/* Flush FIFO, sets Empty bit in TXFLG2, enable ATM. */ setb TXISO ; Make it an ISO endpoint mov RXCON2,#84h ;/* Flush FIFO, sets Empty bit in RXFLG2, enable ARM. */ mov EPCON2,#03h; ;/* Transmit only */ mov EPINDEX, #03h mov TXCON3,#84h ;/* Flush FIFO, sets Empty bit in TXFLG3, enable ATM. */ mov RXCON3,#84h ;/* Flush FIFO, sets Empty bit in RXFLG3, enable ARM. */ mov EPCON3,#00h; ;/* Off */ RET SCOPE ;***************************************************** ;***************** INIT_UART ************************* ;***************************************************** INIT_UART: mov SCON, #050h ;Timer 2 is being used to generate baud rates. mov RCAP2L, #0D9h ; USB EVAL 9600 ?==? 9600/19200 16-bit reload value for baud mov RCAP2H, #0FFh ; mov T2CON, #034h ; Set TIMER 2 into baud rate generator WORKS(A) clr TI ; Clear Transmit interrupt ;; mov IEN0, #0 ; KILL ALL INTERUPTS LCALL Lng_Delay mov SBUF, #00 LCALL Lng_Delay ret ;************************************************************************ ;************* DEVICE DESCRIPTOR **************************************** ;************************************************************************ ; ; NOTE!!!!! '251 is a Big Endian machine. Words and DWords are stored with the ; LSB in the numerically higher address. ; DEVICE_DESCRIPTOR: gDLength: db 012h ;Used by packet transfer routines. gDevice_bLength: db 012h gDevice_bDescriptorType: db DEVICE_DESCR gDevice_bcdUSB: dw 0001h ; Version 1.00 compliant gDevice_bDeviceClass: db 0DCh gDevice_bDeviceSubClass: db 00h gDevice_bDeviceProtocol: db 00h gDevice_wMaxPacketSize0: db 08h ;8 byte max for EP0 gDevice_widVendor: dw 8680h ;Intel Vendor ID (8086) gDevice_widProduct: dw 9098h ;product ID 9876h gDevice_bcdDevice: dw 3001h ;device version 1.30 gDevice_iManufacturer: db 0h ;These three fields are supposed gDevice_iProduct: db 0h ;to contain the index of strings gDevice_iSerialNumber: db 0h ;describing device. gDevice_bNumConfigurations: db 01h ;/*--------------- Initialize global Config descriptor ----------------*/ CONFIGURATION_DESCRIPTOR: gCLength: db gEndDescriptor1Label-gConfig_bLength ; ^^^^ Used by packet transfer routines. gConfig_bLength: db 09h gConfig_bDescriptorType: db CONFIG_DESCR gConfig_bTotalLength: db gEndDescriptor1Label-gConfig_bLength ; gConfig_bCorrection: db 0 gConfig_bNumInterfaces: db 1 ; NUM_OF_INTERFACES; gConfig_bConfigurationValue: db 1 gConfig_iConfiguration: db 0 gConfig_bmAttributes: db 040h gConfig_MaxPower: db 025h ;50ma ; /*------------- Initialize global Interface descriptor ---------------*/ gInterfaceDescriptor: gInterface_bLength: db 09h gInterface_bDescriptorType: db INTERFACE_DESCR gInterface_bInterfaceNumber: db 00h gInterface_bAlternateSetting: db 00h gInterface_bNumEndpoints: db 02h gInterface_bInterfaceClass: db 0DCh gInterface_bInterfaceSubClass: db 50h gInterface_bInterfaceProtocol: db 10h gInterface_iInterface: db 0 ; /*------------- Initialize Endpoint 1 descriptor ---------------*/ gEndPoint: gEP_bLength: db 07h gEP_bDescriptorType: db ENDPOINT_DESCR gEP_bEndpointAddress: db 81h ;EP address 1, in gEP_bmAtrributes: db 01h ;ISOC gEP_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ gEndPointB: gEPB_bLength: db 07h gEPB_bDescriptorType: db ENDPOINT_DESCR gEPB_bEndPointAddress: db 82h ;EP address 2, in gEPB_bmAtrributes: db 01h ;ISOC gEPB_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEPB_bInterval: db 0h ; /*------------- Initialize Alternate Interface descriptor 1---------------*/ gAltXface1Descriptor: gAltXface1_bLength: db 09h gAltXface1_bDescriptorType: db INTERFACE_DESCR gAltXface1_bInterfaceNumber: db 0h gAltXface1_bAlternateSetting: db 01h gAltXface1_bNumEndpoints: db 2h gAltXface1_bInterfaceClass: db 0DCh gAltXface1_bInterfaceSubClass: db 50h gAltXface1_bInterfaceProtocol: db 00h gAltXface1_iInterface: db 0 ; /*------------- Initialize Endpoints in Alternate interface 1 ---------------*/ gEndPointAX1: gEPAX1_bLength: db 07h gEPAX1_bDescriptorType: db ENDPOINT_DESCR gEPAX1_bEndpointAddress: db 81h ;EP address 1, in gEPAX1_bmAtrributes: db 01h ;ISOC gEPAX1_wMaxPacketSize: dw 2000h ;Max Packet 32 bytes gEPAX1_bInterval: db 0h gEndPointAX1B: gEPAX1B_bLength: db 07h gEPAX1B_bDescriptorType: db ENDPOINT_DESCR gEPAX1B_bEndPointAddress: db 81h ;EP address 2,in gEPAX1B_bmAtrributes: db 01h ;ISOC gEPAX1B_wMaxPacketSize: dw 0400h ;Max Packet 4 bytes gEPAX1B_bInterval: db 0h ; /*------------- Initialize Alternate Interface descriptor 2---------------*/ gAltXface2Descriptor: gAltXface2_bLength: db 09h gAltXface2_bDescriptorType: db INTERFACE_DESCR gAltXface2_bInterfaceNumber: db 00h gAltXface2_bAlternateSetting: db 02h gAltXface2_bNumEndpoints: db 2h gAltXface2_bInterfaceClass: db 0DCh gAltXface2_bInterfaceSubClass: db 50h gAltXface2_bInterfaceProtocol: db 00h gAltXface2_iInterface: db 0 ; /*------------- Initialize Endpoints in Alternate interface 2 ---------------*/ gEndPointAX2: gEPAX2_bLength: db 07h gEPAX2_bDescriptorType: db ENDPOINT_DESCR gEPAX2_bEndpointAddress: db 81h ;EP address 1, in gEPAX2_bmAtrributes: db 01h ;ISOC gEPAX2_wMaxPacketSize: dw 4000h ;Max Packet 64 bytes gEPAX2_bInterval: db 0h gEndPointAX2B: gEPAX2B_bLength: db 07h gEPAX2B_bDescriptorType: db ENDPOINT_DESCR gEPAX2B_bEndPointAddress: db 81h ;EP address 2,in gEPAX2B_bmAtrributes: db 01h ;ISOC gEPAX2B_wMaxPacketSize: dw 0200h ;Max Packet 2 bytes gEPAX2B_bInterval: db 0h ; /*------------- Initialize Alternate Interface descriptor 3---------------*/ gAltXface3Descriptor: gAltXface3_bLength: db 09h gAltXface3_bDescriptorType: db INTERFACE_DESCR gAltXface3_bInterfaceNumber: db 00h gAltXface3_bAlternateSetting: db 03h gAltXface3_bNumEndpoints: db 2h gAltXface3_bInterfaceClass: db 0DCh gAltXface3_bInterfaceSubClass: db 50h gAltXface3_bInterfaceProtocol: db 00h gAltXface3_iInterface: db 0 ; /*------------- Initialize Endpoints in Alternate interface 3 ---------------*/ gEndPointAX3: gEPAX3_bLength: db 07h gEPAX3_bDescriptorType: db ENDPOINT_DESCR gEPAX3_bEndpointAddress: db 81h ;EP address 1, in gEPAX3_bmAtrributes: db 01h ;ISOC gEPAX3_wMaxPacketSize: dw 8000h ;Max Packet 128 bytes gEPAX3_bInterval: db 0h gEndPointAX3B: gEPAX3B_bLength: db 07h gEPAX3B_bDescriptorType: db ENDPOINT_DESCR gEPAX3B_bEndPointAddress: db 81h ;EP address 2,in gEPAX3B_bmAtrributes: db 01h ;ISOC gEPAX3B_wMaxPacketSize: dw 0100h ;Max Packet 1 bytes gEPAX3B_bInterval: db 0h ; /*------------- Initialize Alternate Interface descriptor 4---------------*/ gAltXface4Descriptor: gAltXface4_bLength: db 09h gAltXface4_bDescriptorType: db INTERFACE_DESCR gAltXface4_bInterfaceNumber: db 00h gAltXface4_bAlternateSetting: db 04h gAltXface4_bNumEndpoints: db 2h gAltXface4_bInterfaceClass: db 0DCh gAltXface4_bInterfaceSubClass: db 50h gAltXface4_bInterfaceProtocol: db 00h gAltXface4_iInterface: db 0 ; /*------------- Initialize Endpoints in Alternate interface 4 ---------------*/ gEndPointAX4: gEPAX4_bLength: db 07h gEPAX4_bDescriptorType: db ENDPOINT_DESCR gEPAX4_bEndpointAddress: db 81h ;EP address 1, in gEPAX4_bmAtrributes: db 01h ;ISOC gEPAX4_wMaxPacketSize: dw 3500h ;Max Packet 53 bytes gEPAX4_bInterval: db 0h gEndPointAX4B: gEPAX4B_bLength: db 07h gEPAX4B_bDescriptorType: db ENDPOINT_DESCR gEPAX4B_bEndPointAddress: db 81h ;EP address 2,in gEPAX4B_bmAtrributes: db 01h ;ISOC gEPAX4B_wMaxPacketSize: dw 0300h ;Max Packet 3 bytes gEPAX4B_bInterval: db 0h ; /*------------- Initialize Alternate Interface descriptor 3---------------*/ gAltXface5Descriptor: gAltXface5_bLength: db 09h gAltXface5_bDescriptorType: db INTERFACE_DESCR gAltXface5_bInterfaceNumber: db 00h gAltXface5_bAlternateSetting: db 05h gAltXface5_bNumEndpoints: db 2h gAltXface5_bInterfaceClass: db 0DCh gAltXface5_bInterfaceSubClass: db 50h gAltXface5_bInterfaceProtocol: db 00h gAltXface5_iInterface: db 0 ; /*------------- Initialize Endpoints in Alternate interface 3 ---------------*/ gEndPointAX5: gEPAX5_bLength: db 07h gEPAX5_bDescriptorType: db ENDPOINT_DESCR gEPAX5_bEndpointAddress: db 81h ;EP address 1, in gEPAX5_bmAtrributes: db 01h ;ISOC gEPAX5_wMaxPacketSize: dw 6700h ;Max Packet 103 bytes gEPAX5_bInterval: db 0h gEndPointAX5B: gEPAX5B_bLength: db 07h gEPAX5B_bDescriptorType: db ENDPOINT_DESCR gEPAX5B_bEndPointAddress: db 81h ;EP address 2,in gEPAX5B_bmAtrributes: db 01h ;ISOC gEPAX5B_wMaxPacketSize: dw 0700h ;Max Packet 7 bytes gEPAX5B_bInterval: db 0h gEndDescriptor1Label: ;/*--------------- Initialize global Config descriptor ----------------*/ CONFIGURATION_DESCRIPTOR2: g2CLength: db g2EndDescriptor2Label-g2Config_bLength ; ^^^^ Used by packet transfer routines. g2Config_bLength: db 09h g2Config_bDescriptorType: db CONFIG_DESCR g2Config_bTotalLength: db g2EndDescriptor2Label-g2Config_bLength ; g2Config_bCorrection: db 0 g2Config_bNumInterfaces: db 1 ; NUM_OF_INTERFACES; g2Config_bConfigurationValue: db 1 g2Config_iConfiguration: db 0 g2Config_bmAttributes: db 040h g2Config_MaxPower: db 025h ;50ma ; /*------------- Initialize global Interface descriptor ---------------*/ g2InterfaceDescriptor: g2Interface_bLength: db 09h g2Interface_bDescriptorType: db INTERFACE_DESCR g2Interface_bInterfaceNumber: db 00h g2Interface_bAlternateSetting: db 00h g2Interface_bNumEndpoints: db 02h g2Interface_bInterfaceClass: db 0DCh g2Interface_bInterfaceSubClass: db 50h g2Interface_bInterfaceProtocol: db 10h g2Interface_iInterface: db 0 ; /*------------- Initialize Endpoint 1 descriptor ---------------*/ g2EndPoint: g2EP_bLength: db 07h g2EP_bDescriptorType: db ENDPOINT_DESCR g2EP_bEndpointAddress: db 81h ;EP address 1, in g2EP_bmAtrributes: db 01h ;ISOC g2EP_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes g2EP_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ g2EndPointB: g2EPB_bLength: db 07h g2EPB_bDescriptorType: db ENDPOINT_DESCR g2EPB_bEndPointAddress: db 82h ;EP address 2, in g2EPB_bmAtrributes: db 01h ;ISOC g2EPB_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes g2EPB_bInterval: db 0h ; /*------------- Initialize Interface descriptor 1---------------*/ g2AltXface1Descriptor: g2AltXface1_bLength: db 09h g2AltXface1_bDescriptorType: db INTERFACE_DESCR g2AltXface1_bInterfaceNumber: db 1h g2AltXface1_bAlternateSetting: db 00h g2AltXface1_bNumEndpoints: db 2h g2AltXface1_bInterfaceClass: db 0DCh g2AltXface1_bInterfaceSubClass: db 50h g2AltXface1_bInterfaceProtocol: db 00h g2AltXface1_iInterface: db 0 ; /*------------- Initialize Endpoints in interface 1 ---------------*/ g2EndPointAX1: g2EPAX1_bLength: db 07h g2EPAX1_bDescriptorType: db ENDPOINT_DESCR g2EPAX1_bEndpointAddress: db 81h ;EP address 1, in g2EPAX1_bmAtrributes: db 01h ;ISOC g2EPAX1_wMaxPacketSize: dw 2000h ;Max Packet 32 bytes g2EPAX1_bInterval: db 0h g2EndPointAX1B: g2EPAX1B_bLength: db 07h g2EPAX1B_bDescriptorType: db ENDPOINT_DESCR g2EPAX1B_bEndPointAddress: db 81h ;EP address 2,in g2EPAX1B_bmAtrributes: db 01h ;ISOC g2EPAX1B_wMaxPacketSize: dw 0400h ;Max Packet 4 bytes g2EPAX1B_bInterval: db 0h ; /*------------- Initialize Interface descriptor 2---------------*/ g2AltXface2Descriptor: g2AltXface2_bLength: db 09h g2AltXface2_bDescriptorType: db INTERFACE_DESCR g2AltXface2_bInterfaceNumber: db 02h g2AltXface2_bAlternateSetting: db 00h g2AltXface2_bNumEndpoints: db 2h g2AltXface2_bInterfaceClass: db 0DCh g2AltXface2_bInterfaceSubClass: db 50h g2AltXface2_bInterfaceProtocol: db 00h g2AltXface2_iInterface: db 0 ; /*------------- Initialize Endpoints in interface 2 ---------------*/ g2EndPointAX2: g2EPAX2_bLength: db 07h g2EPAX2_bDescriptorType: db ENDPOINT_DESCR g2EPAX2_bEndpointAddress: db 81h ;EP address 1, in g2EPAX2_bmAtrributes: db 01h ;ISOC g2EPAX2_wMaxPacketSize: dw 4000h ;Max Packet 64 bytes g2EPAX2_bInterval: db 0h g2EndPointAX2B: g2EPAX2B_bLength: db 07h g2EPAX2B_bDescriptorType: db ENDPOINT_DESCR g2EPAX2B_bEndPointAddress: db 81h ;EP address 2,in g2EPAX2B_bmAtrributes: db 01h ;ISOC g2EPAX2B_wMaxPacketSize: dw 0200h ;Max Packet 2 bytes g2EPAX2B_bInterval: db 0h ; /*------------- Initialize Interface descriptor 3---------------*/ g2AltXface3Descriptor: g2AltXface3_bLength: db 09h g2AltXface3_bDescriptorType: db INTERFACE_DESCR g2AltXface3_bInterfaceNumber: db 03h g2AltXface3_bAlternateSetting: db 00h g2AltXface3_bNumEndpoints: db 2h g2AltXface3_bInterfaceClass: db 0DCh g2AltXface3_bInterfaceSubClass: db 50h g2AltXface3_bInterfaceProtocol: db 00h g2AltXface3_iInterface: db 0 ; /*------------- Initialize Endpoints in interface 3 ---------------*/ g2EndPointAX3: g2EPAX3_bLength: db 07h g2EPAX3_bDescriptorType: db ENDPOINT_DESCR g2EPAX3_bEndpointAddress: db 81h ;EP address 1, in g2EPAX3_bmAtrributes: db 01h ;ISOC g2EPAX3_wMaxPacketSize: dw 8000h ;Max Packet 128 bytes g2EPAX3_bInterval: db 0h g2EndPointAX3B: g2EPAX3B_bLength: db 07h g2EPAX3B_bDescriptorType: db ENDPOINT_DESCR g2EPAX3B_bEndPointAddress: db 81h ;EP address 2,in g2EPAX3B_bmAtrributes: db 01h ;ISOC g2EPAX3B_wMaxPacketSize: dw 0100h ;Max Packet 1 bytes g2EPAX3B_bInterval: db 0h ; /*------------- Initialize Interface descriptor 4---------------*/ g2AltXface4Descriptor: g2AltXface4_bLength: db 09h g2AltXface4_bDescriptorType: db INTERFACE_DESCR g2AltXface4_bInterfaceNumber: db 04h g2AltXface4_bAlternateSetting: db 00h g2AltXface4_bNumEndpoints: db 2h g2AltXface4_bInterfaceClass: db 0DCh g2AltXface4_bInterfaceSubClass: db 50h g2AltXface4_bInterfaceProtocol: db 00h g2AltXface4_iInterface: db 0 ; /*------------- Initialize Endpoints in interface 4 ---------------*/ g2EndPointAX4: g2EPAX4_bLength: db 07h g2EPAX4_bDescriptorType: db ENDPOINT_DESCR g2EPAX4_bEndpointAddress: db 81h ;EP address 1, in g2EPAX4_bmAtrributes: db 01h ;ISOC g2EPAX4_wMaxPacketSize: dw 3500h ;Max Packet 53 bytes g2EPAX4_bInterval: db 0h g2EndPointAX4B: g2EPAX4B_bLength: db 07h g2EPAX4B_bDescriptorType: db ENDPOINT_DESCR g2EPAX4B_bEndPointAddress: db 81h ;EP address 2,in g2EPAX4B_bmAtrributes: db 01h ;ISOC g2EPAX4B_wMaxPacketSize: dw 0300h ;Max Packet 3 bytes g2EPAX4B_bInterval: db 0h ; /*------------- Initialize Interface descriptor 5---------------*/ g2AltXface5Descriptor: g2AltXface5_bLength: db 09h g2AltXface5_bDescriptorType: db INTERFACE_DESCR g2AltXface5_bInterfaceNumber: db 05h g2AltXface5_bAlternateSetting: db 00h g2AltXface5_bNumEndpoints: db 2h g2AltXface5_bInterfaceClass: db 0DCh g2AltXface5_bInterfaceSubClass: db 50h g2AltXface5_bInterfaceProtocol: db 00h g2AltXface5_iInterface: db 0 ; /*------------- Initialize Endpoints in interface 5 ---------------*/ g2EndPointAX5: g2EPAX5_bLength: db 07h g2EPAX5_bDescriptorType: db ENDPOINT_DESCR g2EPAX5_bEndpointAddress: db 81h ;EP address 1, in g2EPAX5_bmAtrributes: db 01h ;ISOC g2EPAX5_wMaxPacketSize: dw 6700h ;Max Packet 103 bytes g2EPAX5_bInterval: db 0h g2EndPointAX5B: g2EPAX5B_bLength: db 07h g2EPAX5B_bDescriptorType: db ENDPOINT_DESCR g2EPAX5B_bEndPointAddress: db 81h ;EP address 2,in g2EPAX5B_bmAtrributes: db 01h ;ISOC g2EPAX5B_wMaxPacketSize: dw 0700h ;Max Packet 7 bytes g2EPAX5B_bInterval: db 0h g2EndDescriptor2Label: SCOPE INIT_VARIABLES: ;Init SETUP VARIABLES ;;; mov P1,#080h ;;; mov R11,#0 ; Zero out R11 to represent initial state mov WR28,#0 ; Access in page 00h mov WR30,#LOW16(SetupSeq) ; Offset of SetupSeq var mov @DR28,R11 ; Initial state is wait for SETUP ;;; mov P1,#090h ;;; ; mov WR10, #00h ; mov WR30, #LOW16(_EP1RxPtr); mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; ;;; mov P1,#0A0h ;;; ;initialize the buffer variables for mov WR30, #LOW16(_EP2RxPtr);the three endpoints mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; ; mov WR30, #LOW16(_EP3RxPtr); mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; ;;; mov P1,#0B0h ;;; mov WR20,#0 mov WR22, #low16(out_var_table) mov WR10, #0 mov WR8,#0 ?l1: mov @DR20,R11 ;This loop zeroes out the 64 byte area add WR22,#1 ;at out_var_table. I'm not sure why. add R8,#1 cmp R8,#64 jne ?l1 ;Zero out the output buffer area. ;;; mov P1,#0C0h ;;; mov WR20, #0 mov WR22, #low16(OUT_BUFFERS) mov WR10, #0 mov WR8,#0 ?l2: mov @DR20,R11 add WR22,#1 add WR8,#1 ; cmp WR8,#1000 cmp WR8,#10h jne ?l2 ;;; mov P1,#0D0h ;;; mov WR10, #00h mov WR22, #LOW16(DATA_PENDING) mov @DR20, R10 mov WR22, #LOW16(DIRECTION_ERROR_COUNT) mov @DR20, R10 mov WR22, #LOW16(PENDING_START_TIME) mov @DR20, WR10 ;;; mov P1,#0E0h ;;; RET SCOPE Lng_Delay: push WR24 push WR26 MOV WR24, #082H JMP DE2 Delay_X: ;MOV P1,DPXL push WR24 ;5 states push WR26 ;5 states MOV WR24, #001H ;3 states DE1: MOV WR26, #004FFH ;3 states cfffh original ;0fff works DE2: DEC WR26, #1 ;2 states CMP WR26, #00H ;4 states JNE DE2 ;5 states T ; 2 states NT DEC WR24, #1 ;2 states CMP WR24, #00H ;4 states JNE DE1 ;5 states T ; 2 states NT POP WR26 ;5 states POP WR24 ;5 states QUICK1: RET ; ;############################################################# ;####### RAM MEMORY MAP ###################################### ;############################################################# ; org 00:0000h ;0-4ff Reserved ; org 00:0500h ; Variables ; org 00:0600h ; Variables for the IN token buffers ;; ;; Data block for EP1. Contains buffer space and some management variables. ;; define OUR_DATA_SEG, SPACE=pdata segment OUR_DATA_SEG org 00:D000h EP_1_Buffer: ds 10h org 00:D800h _EP1RxPtr: ds 2 _EP1TxPtr: ds 2 _EP1DataCount: ds 2 _gbMPSEndPoint1: ds 1 _gbMPSEndPoint2: ds 1 Critical: ds 1 ;; ;; Data block for EP2. Contains buffer space and some management variables. ;; org 00:E000h EP_2_Buffer: ds 10h org 00:E800h _EP2RxPtr: ds 2 _EP2TxPtr: ds 2 _EP2DataCount: ds 2 ;; ;; Data block for EP3. Contains buffer space and some management variables. ;; org 00:F000h EP_3_Buffer: ds 10h org 00:F800h _EP3RxPtr: ds 2 _EP3TxPtr: ds 2 _EP3DataCount: ds 2 org 00:9000h SETUP_VARS: SetupSeq: ds 1 heart_pat: ds 1 heart_bt0: ds 2 heart_bt1: ds 2 new_addr: ds 1 org 00:9100h COMMAND_BUFFER: ds 1 ; Byte Count StandardDeviceRequest: bmRequestType: ds 1 bRequest: ds 1 wValue: ds 2 wIndex: ds 2 wLength: ds 2 ; define OUR_DATA_SEG, SPACE=data, ORG=00:A000h ; segment OUR_DATA_SEG org 00:A000h out_var_table: out_cur_buf: ds 2 out_cnt: ds 2 in_var_table: in_rd_pntr: ds 1 in_bytes_left: ds 1 in_FIFO_size: ds 1 in_FIFO_empty: ds 1 DATA_PENDING: ds 1 PENDING_START_TIME: ds 2 DIRECTION_ERROR_COUNT: ds 1 org 00:B000h ; IN_BUFFERS: org 00:C000h ; OUT_BUFFERS: END