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 R9 push EPINDEX ;??????? Some test code. Remove when finished testing. mov R7, TestVal ; cmp R7, #0 jne ?around ;??????? ;; Put the counter on to see something working mov R8, SOFH anl R8, #07h mov P1, R8 ?around: ;; FOr testing only ; push R8 ; lcall _SetLEDs ; pop R8 ;; End for testing only clr ASOF ;??????? Some test code. Remove when finished testing. ; mov R7, TestVal ; ; cmp R7, #0 ; je SOF_ISR_exit ;??????? ; jmp SOF_ISR_exit jmp ISO_REC ;; 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 R9 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 ;------------------------------------------------------------------ ; ISO receive portion ;------------------------------------------------------------------ ISO_REC: mov EPINDEX,#1 call handle_ISO_OUT mov EPINDEX,#2 call handle_ISO_OUT mov EPINDEX,#3 call handle_ISO_OUT mov R8, ISO_out_err cmp R8, #0 je SOF_ISR_exit ;; Here is where we send something back. Let's use EP3 just so things ;; don't go in order. What gets sent back is three bytes. The first two bytes ;; is the current Frame Number. The third byte is a bitmap indicating which ;; EP had a break in the ISO stream. Bit0->EP1, Bit1->EP2, Bit2->EP3. ;; Note that ISO_out_err has the appropriate pattern loaded into it. ;; First, see if there is any room in the TX fifo push EPINDEX mov EPINDEX, #3 mov R7, TXFLG anl R7, #0C0h ; Check if both bits are set cmp R7, #0C0h je report_exit ; and if so, we can't report now ;; If we get here, then there was room for the report mov R9, SOFL mov R8, SOFH anl R8, #07h ; Only the bottom three bits count sub WR8, #1 mov TXDAT, R9 mov TXDAT, R8 mov R8, ISO_out_err mov TXDAT, R8 mov TXCNTL, #3 ; Sending three bytes report_exit: pop EPINDEX mov R8, #0 mov ISO_out_err,R8 ; Always clear ISO_out_err jmp SOF_ISR_exit ;;; SPecial test stuff ; report_exit1: ; mov R7, ISO_out_err ; mov P1,R7 ; jmp $ ;;; ;------------------------------------------------------------------ ;; This routine checks the state of the currently selected FIFO. ;; If it is not empty, then it takes out one packet, and marks ;; the EP as running. If it is empty, and it was previously ;; running, then it marks the EP as not running, and sets the ;; appropriate bit in ISO_out_err. ;------------------------------------------------------------------ handle_ISO_OUT: push DR28 ;; First get DR28 to be pointing to the appropriate EPrunning ;; variable. It is needed in several places. mov WR28,#0 ; Access in page 00h mov WR30,#LOW16(EP1running)-1; Offset of EP1running var minus 1 ; We add EPINDEX to it to get ; the proper offset mov WR6, #0 mov R7, EPINDEX add WR30, WR6 mov R7, RXFLG ; Get the receive flags anl R7, #0C0h ; Mask of to RXFIF bits only je hio_not_running ; and if so jump to handle this ;; If we get here, then there was something in the FIFO. We need ;; to empty the FIFO, and then mark the EP as running. Let's mark ;; the EP as running first. mov R7, #1 mov @DR28, R7 ;; Now empty the FIFO mov R7, RXCNTL cmp R7, #0 je hio_done_with_fifo ; If it was a zero length packet then done hio_empty_fifo: mov R8, RXDAT djnz R7, hio_empty_fifo hio_done_with_fifo: setb RXFFRC ; Mark the read as complete jmp hio_return hio_not_running: ;; We get here if we discover that the FIFO is empty. If the ;; EP was previously running, this is a problem and should be ;; marked in ISO_out_err. Otherwise it is normal ;; DR28 holds the address the correnct EPrunning variable ;; Check to see if it was previously running mov R8, @DR28 cmp R8, #0 je hio_return ;;; ; mov WR6, WR30 ; mov P1,R6 ; jmp $ ;;; ;; If we get there, then the EP was previously running, so there ;; was a gap. Reset the EPrunning variable, and set the appropriate ;; bit in ISO_out_err mov R7, #0 mov @DR28, R7 ;; We can directly OR in EPINDEX if it isn't equal to 3 mov R7, ISO_out_err mov R8, EPINDEX cmp R8, #3 je hio_EP3 ;; Directly OR it in orl R7, EPINDEX jmp hio_seterr hio_EP3: orl R7, #4 ; If EPINDEX is = 3, then set bit 2 hio_seterr: mov ISO_out_err, R7 hio_return: pop DR28 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 ;????????? ; SPecial test code here. mov TestVal, R12 push R7 push EPINDEX mov EPINDEX, #3 mov R7, TXFLG anl R7, #0c0h srl R7 srl R7 mov P1, R7 pop EPINDEX pop R7 jmp SI_leave1 ;????????? 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 SI_leave1: 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 R10, #1 mov @DR28, R10 mov WR28, #0ffh; ;Located in ROM mov WR30, #LOW16(CONFIGURATION_DESCRIPTOR); 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 TXCON,#84h ;/* Flush FIFO, sets Empty bit in TXFLG1, enable ATM. */ mov RXCON,#84h ;/* Flush FIFO, sets Empty bit in RXFLG1, enable ARM. */ setb RXISO ; Make it an ISO endpoint mov EPCON,#0Ch; ;/* Receive only */ mov EPINDEX, #02h mov TXCON,#84h ;/* Flush FIFO, sets Empty bit in TXFLG2, enable ATM. */ mov RXCON,#84h ;/* Flush FIFO, sets Empty bit in RXFLG2, enable ARM. */ setb RXISO ; Make it an ISO endpoint mov EPCON,#0Ch; ;/* Receive only */ mov EPINDEX, #03h mov TXCON,#84h ;/* Flush FIFO, sets Empty bit in TXFLG3, enable ATM. */ mov RXCON,#84h ;/* Flush FIFO, sets Empty bit in RXFLG3, enable ARM. */ setb RXISO ; Make it an ISO endpoint mov EPCON,#0Fh; ;/* Both endpoints enables */ 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 9298h ; gDevice_bcdDevice: dw 5001h ;device version 1.50 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 gEndDescriptorLabel-gConfig_bLength ; ^^^^ Used by packet transfer routines. gConfig_bLength: db 09h gConfig_bDescriptorType: db CONFIG_DESCR gConfig_bTotalLength: db gEndDescriptorLabel-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 04h gInterface_bInterfaceClass: db 0DCh gInterface_bInterfaceSubClass: db 50h gInterface_bInterfaceProtocol: db 80h gInterface_iInterface: db 0 ; /*------------- Initialize Endpoint 1 descriptor ---------------*/ gEndPoint1: gEP_bLength: db 07h gEP_bDescriptorType: db ENDPOINT_DESCR gEP_bEndpointAddress: db 01h ;EP address 1, out gEP_bmAtrributes: db 01h ;ISOC gEP_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ gEndPoint2: gEPB_bLength: db 07h gEPB_bDescriptorType: db ENDPOINT_DESCR gEPB_bEndPointAddress: db 02h ;EP address 2, out gEPB_bmAtrributes: db 01h ;ISOC gEPB_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEPB_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ gEndPoint3: gEP3_bLength: db 07h gEP3_bDescriptorType: db ENDPOINT_DESCR gEP3_bEndPointAddress: db 03h ;EP address 2, out gEP3_bmAtrributes: db 01h ;ISOC gEP3_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP3_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ gEndPoint4: gEP4_bLength: db 07h gEP4_bDescriptorType: db ENDPOINT_DESCR gEP4_bEndPointAddress: db 83h ;EP address 3, in gEP4_bmAtrributes: db 03h ;interrupt gEP4_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP4_bInterval: db 10h gEndDescriptorLabel: SCOPE INIT_VARIABLES: ;Init SETUP VARIABLES 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 WR10, #00h ; mov WR30, #LOW16(_EP1RxPtr); mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; add WR30, #02h ; mov @DR28, WR10 ; ;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 ; ; Clear out the EPxrunning variables mov WR30, #LOW16(EP1running); mov @DR28, WR10 ; add WR30, #01h ;EP2 mov @DR28, WR10 ; add WR30, #01h ;EP3 mov @DR28, WR10 ; add WR30, #01h ;ISO_out_err mov @DR28, WR10 ; add WR30, #01h ;TestVal mov @DR28, WR10 ; 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 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 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 EP1running: ds 1 EP2running: ds 1 EP3running: ds 1 ISO_out_err: ds 1 TestVal: 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 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 org 00:B000h ; IN_BUFFERS: org 00:C000h ; OUT_BUFFERS: END