COMMENT /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (C) Copyright Intel Corp., 1996 File: newloop.asm Universal Serial Bus 930 Test firmware Revision History --------------------------------------------- 0.3 08-07-96 Myngoc Le 0.2 05-27-96 Abdul Rahman Ismail 0.1 02-13-96 Joe DrAgony ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ INCLUDE "82930AA.inc" INCLUDE "swap.inc" INCLUDE "ONE_OH.INC" ;------------- External functions - process.c ;EXTERN _SetFeature:CODE ;EXTERN _ClearFeature:CODE ;EXTERN _GetStatus:CODE ;------------- Global variables. XDEF _EP1RxPtr, _EP1TxPtr, _EP1DataCount XDEF _EP2RxPtr, _EP2TxPtr, _EP2DataCount XDEF _EP3RxPtr, _EP3TxPtr, _EP3DataCount 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 Remote_WKup CSEG AT FF:0013H ; INT1# ; LJMP INT1_ISR LJMP Remote_WKup 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 SusRsm_ISR CSEG AT FF:0080H CopyRight: DB '(C) 1996 Copyright Intel Corporation' CSEG AT FF:0100H main: mov SP, #00h mov SPH, #05h ; Set the stack to start @ 00:0500h mov IE0, #00h ; Disable all interrupts mov P1, #33h mov DPXL, #0ffh ; Set DPXL to point at the FLASH device to access constants lCall INIT_VARIABLES ; Initialize the RAM space as required lCall INIT_USB ; Initialize the USB subsystem ljmp ActiveLoop ;Jump over the ISR stubs to the main loop. ;Interrupts EPx_ISR: RetI SOF_ISR: RetI SusRsm_ISR: RetI Remote_WKup: MOV P1, #20h ; clear Suspend LED jb GRSM, resume_l ; GSUS or GRSM flag. setb RWU ; Set remote_wakeup bit. clr GSUS ; Clear the suspend bit. RetI pw_down: MOV P1, #08h ; set LED for Suspend setb PD ; set Powerdown Mode bit to meet 500uA. resume_l: clr GSUS ; Clear Suspend bit clr GRSM ; Clear Resume bit MOV P1, #20h ; clear Suspend LED COMMENT *------------------------------------------------------------ Function name : ActiveLoop Brief Description : Monitors RX and TX on all EPs Regs preserved : No reg. is saved --------------------------------------------------------------------* SCOPE ActiveLoop: MOV IE0, #84h ; Enable INT1# interrupts CLR IT1 ; set INT1# level sensitive jb GRSM, resume_l ; Check for GRSM flag. jb GSUS, pw_down ; Check for GSUS 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: mov EPINDEX, #1 jnb RXFIF0,EP1_TX lCall ServiceEP1RX EP1_TX: mov EPINDEX, #1 jnb TXFIF1, doit1t ; If bit is not set then there is room jb TXFIF0, EP2_RX ; If this bit is also set then there is no room doit1t: lCall ServiceEP1TX EP2_RX: mov EPINDEX, #2 jnb RXFIF0,EP2_TX lCall ServiceEP2RX EP2_TX: mov EPINDEX, #2 jnb TXFIF1, doit2 ; If bit is not set then there is room jb TXFIF0, EP3_RX ; If this bit is also set then there is no room doit2: lCall ServiceEP2TX EP3_RX: mov EPINDEX, #3 jnb RXFIF0,EP3_TX lCall ServiceEP3RX EP3_TX: mov EPINDEX, #3 jnb TXFIF1, doit3 ; If bit is not set then there is room jb TXFIF0, EP_Done ; If this bit is also set then there is no room doit3: 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 SBI,#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 SBI, #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 ;; Setup the pointers in in mov R2, #00h mov in_rd_pntr, R2 ;Set buffer pointer to zero mov R2, #01h mov in_bytes_left, R2 ;point to count variable mov R2, MyConfigVal mov IN_BUFFERS, R2 mov R2, #01h mov SetupSeq , R2 ;Advance State Machine to next state lcall DoControlOutput ljmp EXIT_SETUP ; code for other types of bRequests CheckGetStatus: cmp R11, #GET_STATUS jne CheckGetInterface mov WR0, #0 ; preload with zero mov R2,bmRequestType anl R2, #3 ; Get the recipient bits cmp R2, #0 je GSDevice cmp R2, #1 je GSInterface GSEndpoint: ; We get here if this is a GetStatus to ; to and enpoint. Figure out which endpoint ; it is and then check to see if that endpoint ; is stalled push EPINDEX ; Save current value mov R2, wIndex anl R2, #3 ; Get epnumber mov EPINDEX, R2 ; and select it. ;; Now we have the correct EP number. We have to see if it is ;; and IN or an OUT mov R2, wIndex anl R2, #80h jne GS_IN_Endpoint GS_OUT_Endpoint: jnb RXSTL, GSEndpointDone mov R0, #1 ; Set the stall bit jmp GSEndpointDone GS_IN_Endpoint: jnb TXSTL, GSEndpointDone mov R0, #1 ; Set the stall bit GSEndpointDone: pop EPINDEX jmp GSFinish GSDevice: mov R0,#1 jmp GSFinish GSInterface: ;; Interface is always zero and since we already primed with that ;; we do nothing GSFinish: 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 ;; Setup the pointers in in mov R2, #00h mov in_rd_pntr, R2 ;Set buffer pointer to zero mov R2, #01h mov in_bytes_left, R2 ;point to count variable mov R2, MyInterfaceVal mov IN_BUFFERS, R2 mov R2, #01h mov SetupSeq , R2 ;Advance State Machine to next state lcall DoControlOutput ljmp EXIT_SETUP 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: ; mov R2, wValue mov MyConfigVal, R2 ajmp DO_SET_COMMAND_EXIT DO_SET_INTERFACE: ; mov R2, wValue mov MyInterfaceVal, R2 ajmp DO_SET_COMMAND_EXIT DO_CLEAR_FEATURE: DO_SET_FEATURE: mov R2, bmRequestType cmp R2, #2; Check to see if it for 'endpoint' jne DO_SET_COMMAND_EXIT; If not to endpoint then just finish mov WR2, wValue cmp WR2, #0 jne DO_SET_COMMAND_EXIT; Not something we understand push EPINDEX mov R2, wIndex ; Get the EP number anl R2, #3 ; Get epnumber mov EPINDEX, R2 ; and select it. ;; Now we have the correct EP number. We have to see if it is ;; and IN or an OUT mov R2, wIndex anl R2, #80h jne SF_IN_Endpoint SF_OUT_Endpoint: cmp R11,#SET_FEATURE jne SF_OUT_CLR setb RXSTL ; Set the stall bit jmp SFEndpointDone SF_OUT_CLR: clr RXSTL ; Clear the stall bit jmp SFEndpointDone SF_IN_Endpoint: cmp R11,#SET_FEATURE jne SF_IN_CLR setb TXSTL ; Set the stall bit jmp SFEndpointDone SF_IN_CLR: clr TXSTL ; Clear the stall bit jmp SFEndpointDone SFEndpointDone: pop EPINDEX 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 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: cmp R11, #STRING_DESCR je ?c23 ljmp EXIT_SETUP ; ********************** GET DESCRIPTOR, STRING ************ ?c23: mov WR30, #LOW16(SetupSeq) ;Update state machine mov R9, #1 mov @DR28, R9 mov WR28, #0ffh ;String is located in ROM ; First check to see if the index is zero. If ; so, then we treat this like a normal data ; buffer and not a string, since we need to ; return the language ID table cmp R10, #0 jne ?cs1 mov WR30, #LOW16(STRING0) lcall BufferControlData lcall DoControlOutput ljmp EXIT_SETUP ?cs1: cmp R10, #1 jne ?cs2 mov WR30, #LOW16(STRING1) jmp ?csms ?cs2: cmp R10, #2 jne ?cs3 mov WR30, #LOW16(STRING2) jmp ?csms ?cs3: cmp R10, #3 jne ?cs4 mov WR30, #LOW16(STRING3) jmp ?csms ?cs4: cmp R10, #4 jne ?cs5 mov WR30, #LOW16(STRING4) jmp ?csms ?cs5: cmp R10, #5 jne ?cs6 mov WR30, #LOW16(STRING5) jmp ?csms ?cs6: cmp R10, #6 jne ?cs0 mov WR30, #LOW16(STRING6) jmp ?csms ?cs0: mov WR30, #LOW16(STRING_END) ?csms: LCALL BufferStringData LCALL DoControlOutput ?c3: 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 SBI, #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: 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 SBI, #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: 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 SBI, #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 ?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 ; return setb RXIE ; Set ready to RX as enuf buffer sp ; now available. ?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: 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: 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 ####### ;################################################################### 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 ;################################################################### ;################### BufferControlData ############################ ;## Transfers the string data pointed to by DR28 into the IN Buffer. ;## The first byte in this data area is the length of the string. ;## The following 'length' bytes are the string itself. This routine ;## will load IN_BUFFERS with a string descriptor with the ASCII string ;## converted to a UNICODE string. ;################################################################### SCOPE BufferStringData: ;DR28 has address of data mov R6, #00h mov R7, @DR28 ; Ascii string length in R7 cmp R7, #0 je BSD_Ret push R7 ; To save for later add WR30, #01h ; increment pointer to first byte of string mov R9, #00h mov in_rd_pntr, R9 ;Set buffer pointer to zero ;for new transfer ;; Calculate that actual length of the descriptor. The equation is: ;; DescLength = 2 * (Ascii length) + 2 ;; The + 2 is for bLength and bDescriptorType add R7,R7 add R7,#2 mov WR26, #LOW16(IN_BUFFERS) ;; The first vale to go in IN_BUFFERS is the total length of the ;; string descriptor mov @WR26, R7 add WR26,#1 ;; The next value is the string descriptor encoding mov R9, #STRING_DESCR mov @WR26, R9 add WR26,#1 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 BSD_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. BSD_Continue: mov in_bytes_left, R7 ;Store Count ;; Now we can start moving the string itself. If you view a ;; unicode string as a sequence of 'words' (two byte ;; quantities), the low order byte of each word is a zero and ;; the upper order byte is the ascii character. So in the ;; loop below, we first put a zero in the buffer, followed by ;; the character from the string. ;; pop R7 ; Restore the string length. Note that we mov R8,#0 ; will always create the whole string ; descriptor even though only part of it may ; be returned. BSD_MoveMemory: mov @WR26, R8 add WR26, #01h mov R9, @DR28 ; Get data mov @WR26, R9 ; Store data add WR26, #01h add WR30, #01h djnz R7, BSD_MoveMemory BSD_Ret: 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. */ mov RXCON1,#84h ;/* Flush FIFO, sets Empty bit in RXFLG1, enable ARM. */ mov EPCON1,#0Fh; ;/* Enable receive and transmit on endpoint 1 */ setb RXSPM ; Turn on single packet mode mov EPINDEX, #02h mov TXCON2,#84h ;/* Flush FIFO, sets Empty bit in TXFLG2, enable ATM. */ mov RXCON2,#84h ;/* Flush FIFO, sets Empty bit in RXFLG2, enable ARM. */ mov EPCON2,#0Fh; ;/* Enable receive and transmit on endpoint 2 */ setb RXSPM ; Turn on single packet mode 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,#0Fh; ;/* Enable receive and transmit on endpoint 3 */ setb RXSPM ; Turn on single packet mode RET ; mov TXCON0,#84h ;/* Flush FIFO, sets Empty bit in TXFLG0, enable ATM. */ ; mov TXCON1,#84h ;/* Flush FIFO, sets Empty bit in TXFLG1, enable ATM. */ ; mov TXCON2,#84h ;/* Flush FIFO, sets Empty bit in TXFLG2, enable ATM. */ ; mov TXCON3,#84h ;/* Flush FIFO, sets Empty bit in TXFLG3, enable ATM. */ ; mov RXCON0,#84h ;/* Flush FIFO, sets Empty bit in RXFLG0, enable ARM. */ ; mov RXCON1,#84h ;/* Flush FIFO, sets Empty bit in RXFLG1, enable ARM. */ ; mov RXCON2,#84h ;/* Flush FIFO, sets Empty bit in RXFLG2, enable ARM. */ ; mov RXCON3,#84h ;/* Flush FIFO, sets Empty bit in RXFLG3, 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 EPCON1,#1Fh; ;/* Enable receive and transmit on endpoint 1 */ ; mov EPCON2,#1Fh; ;/* Enable receive and transmit on endpoint 2 */ ; mov EPCON3,#1Fh; ;/* Enable receive and transmit on endpoint 3 */ ; 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 IE0, #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 1099h ;product ID 9910h gDevice_bcdDevice: dw 3001h ;device version 1.30 gDevice_iManufacturer: db 1h ;These three fields are supposed gDevice_iProduct: db 2h ;to contain the index of strings gDevice_iSerialNumber: db 3h ;describing device. gDevice_bNumConfigurations: db 1 ;/*--------------- 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 4 ; gConfig_bmAttributes: db 040h gConfig_bmAttributes: db 060h ;support Remote_Wakeup gConfig_MaxPower: db 025 ;50ma ; /*------------- Initialize global Interface descriptor A--------------*/ gInterfaceDescriptorA: gInterfaceA_bLength: db gEndPoint1- gInterfaceDescriptorA gInterfaceA_bDescriptorType: db INTERFACE_DESCR gInterfaceA_bInterfaceNumber: db 0 gInterfaceA_bAlternateSetting: db 0 gInterfaceA_bNumEndpoints: db 6h gInterfaceA_bInterfaceClass: db 0DCh gInterfaceA_bInterfaceSubClass: db 10h gInterfaceA_bInterfaceProtocol: db 11h gInterfaceA_iInterface: db 5 ; /*------------- Initialize Endpoint 1 descriptor ---------------*/ gEndPoint1: gEP1_bLength: db 07h gEP1_bDescriptorType: db ENDPOINT_DESCR gEP1_bEndpointAddress: db 81h ;EP address 1, in gEP1_bmAtrributes: db 02h ;BULK gEP1_wMaxPacketSize: dw 4000h ;Max Packet 64 bytes gEP1_bInterval: db 0h ; /*------------- Initialize Endpoint 1B descriptor ---------------*/ gEndPoint1B: gEP1B_bLength: db 07h gEP1B_bDescriptorType: db ENDPOINT_DESCR gEP1B_bEndPointAddress: db 01h ;EP address 1,out gEP1B_bmAtrributes: db 02h ;BULK gEP1B_wMaxPacketSize: dw 4000h ;Max Packet 64 bytes gEP1B_bInterval: db 0h ; /*------------- Initialize Endpoint 2 descriptor ---------------*/ gEndPoint2: gEP2_bLength: db 07h gEP2_bDescriptorType: db ENDPOINT_DESCR gEP2_bEndPointAddress: db 82h ;EP address 2 gEP2_bmAtrributes: db 03h ;INTERUPT (int is always in) gEP2_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP2_bInterval: db 00ah ; /*------------- Initialize Endpoint 2 descriptor ---------------*/ gEndPoint2B: gEP2B_bLength: db 07h gEP2B_bDescriptorType: db ENDPOINT_DESCR gEP2B_bEndPointAddress: db 02h ;EP address 2, OUT gEP2B_bmAtrributes: db 02h ;BULK OUT gEP2B_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP2B_bInterval: db 00h ;Poll every 16mS ; /*------------- Initialize Endpoint 3 descriptor ---------------*/ gEndPoint3: gEP3_bLength: db 07h gEP3_bDescriptorType: db ENDPOINT_DESCR gEP3_bEndPointAddress: db 83h ;EP address 2 gEP3_bmAtrributes: db 02h ;BULK gEP3_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP3_bInterval: db 0h ; /*------------- Initialize Endpoint 3 descriptor ---------------*/ gEndPoint3B: gEP3B_bLength: db 07h gEP3B_bDescriptorType: db ENDPOINT_DESCR gEP3B_bEndPointAddress: db 03h ;EP address 2 gEP3B_bmAtrributes: db 02h ;BULK gEP3B_wMaxPacketSize: dw 0800h ;Max Packet 8 bytes gEP3B_bInterval: db 4h gEndDescriptorLabel: STRING0: db 04h ; Four for the BufferControlData routine db 04h ; Four bytes long db 03h ; String descriptor type db 09h ; This is the unicode identifier for English db 01h STRING1: db STRING2 - STRING1 - 1 db "Intel Architecture Labs (C) Intel 1996" STRING2: db STRING3 - STRING2 - 1 db "Standard Loopback with Suspend" STRING3: db STRING4 - STRING3 - 1 db "IAL-00001" STRING4: db STRING5 - STRING4 - 1 db "Single Configuration with one interface" STRING5: db STRING6 - STRING5 - 1 db "Standard Loopback Interface: Buffer length 1K" STRING6: db STRING_END - STRING6 - 1 STRING_END: db 00h 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 ; 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 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 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 1 org 00:D800h _EP1RxPtr: ds 2 _EP1TxPtr: ds 2 _EP1DataCount: ds 2 ;; ;; Data block for EP2. Contains buffer space and some management variables. ;; org 00:E000h EP_2_Buffer: ds 1 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 1 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 MyConfigVal: ds 1 MyInterfaceVal: 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