;******************************************************************************* ;** ;** Testing out USB application, I/O chip is NSC USBN9603/4, using serial I/O ;** ;** Written by Rick Huang, Copyright (C) 2004 ;** Revision YYYY/MM/DD ;** Rev 1. 2004/01/30 - Initial release, code base adapted from 1wire base master code ;** Rev 2. 2004/02/08 - Updated to include all standard device requests ;** Rev 3. 2004/09/23 - Fully implement initialization code ;** ;** Command Functions ;** '1' Write/Read register ;** '2' Write register, first byte address, second data ;** '3' Read only ;** '4' Hex test - echo any hex input ;** '5' Main USB loop, initial and start the message pump ;** '7' ;** '8' ;** ;** ;** This program is free software; you can redistribute it and/or modify ;** it under the terms of the GNU General Public License as published by ;** the Free Software Foundation; either version 2 of the License, or ;** (at your option) any later version. ;** ;** This program is distributed in the hope that it will be useful, ;** but WITHOUT ANY WARRANTY; without even the implied warranty of ;** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;** GNU General Public License for more details. ;** ;** You should have received a copy of the GNU General Public License ;** along with this program; if not, write to the Free Software ;** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ;******************************************************************************* ;**************************************************************************** ;** NOTE: Disable the WDT when debugging the code, however, make sure ;** the WDT is enabled when putting the system into lift time test ;** The timeout for WDT is about 2 seconds with 128:1 prescaler ;**************************************************************************** include __config _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_ON & _MCLRE_OFF & _PWRTE_ON ;***************************************************************** ;** Variables TempW EQU 20h ; ISR use, not utilized CounterA EQU 21h CounterB EQU 22h MAEV EQU 23h ALT EQU 24h TXEV EQU 25h RXEV EQU 26h WARN EQU 27h RXS0 EQU 28h NAKEV EQU 29h Zero EQU 2bh SerData EQU 2ch Temp EQU 2dh Output EQU 2eh Counter EQU 2fh S_bmRequestT EQU 30h S_bRequest EQU 31h wValueL EQU 32h wValueH EQU 33h wIndexL EQU 34h wIndexH EQU 35h wLengthL EQU 36h wLengthH EQU 37h Lookup EQU 38h Toggle EQU 39h TX0length EQU 3ah DescripSel EQU 3bh Configuration EQU 3ch RX1length EQU 3dh TXnum EQU 3eh TX0stat EQU 40h TX0TimeOut EQU 41h OutOfData EQU 42h EP0WaitT EQU 43h RealDesLen EQU 44h OverSize EQU 45h DataBuff EQU 0a0h ; Continuous data buffer for 80 bytes #define _SI PORTB, 7 ; Incoming data #define _SO PORTB, 6 ; Outgoing data #define _CS PORTB, 5 ; Chip Select #define _SK PORTB, 4 ; Serial Clock ;***************************************************************** ;** Program code here goto Start ORG 4 ;waiting for <0004> ;interrupt vector ;goto Interrupt ORG 5 ;***************************** DATA StringStart: PWelcomeMsg: addwf PCL, F DT "Welcome!" DT H'0d', H'0a', H'00' PCommandMsg: DT "Command Error?" DT H'0d', H'0a', H'00' PParameterMsg: DT "Parameter Error?" DT H'0d', H'0a', H'00' PNoAckMsg: DT "Missing Ack" DT H'0d', H'0a', H'00' StringEnd: WelcomeMsg EQU 0 CommandMsg EQU PCommandMsg - 1 - 5 ; 5 is the offset where the ParameterMsg EQU PParameterMsg - 1 - 5 ; Strings start NoAckMsg EQU PNoAckMsg - 1 - 5 HexTable: addwf PCL, F DT "0123456789ABCDEF" DescriptorOffset: addwf PCL, F nop ;Device descriptor 0 DNE DT DevDescripter - DescripterEnt -1 DT ConfDescripter - DescripterEnt -1 DT StringDesZero - DescripterEnt -1 StringOffset: addwf PCL, F DT StringDesZero - DescripterEnt -1 DT ManufacStr - DescripterEnt -1 DT ProductStr - DescripterEnt -1 DT SerialNumStr - DescripterEnt -1 DescripterEnt: addwf PCL, F DevDescripter: DT D'18', H'01' ; Length, TYPE-DEVICE DT H'10', H'01' ; Version DT H'FF', H'FF', H'FF' ; Class, SubClass, Protocol DT D'8' ; Max packet = 8byte DT H'47', H'05' ; Fake Cypress EZ-USB DT H'31', H'21' DT H'21', H'00' ; Release number, 0021 for now DT H'01' ; Manufacture string # DT H'02' ; Product string # DT H'03' ; Serial Number string # DT H'01' ; # of configuration ConfDescripter: DT D'9', H'02' ; Length, TYPE-CONFIG DT D'32', H'00' ; Total Length DT H'01', H'01' ; Num Interface, ConfValue DT H'00' ; String Description string # DT H'80', H'32' ; No Wakeup, Bus Power, 100mA power IntDescriptor: DT D'9', H'04' ; Length, TYPE-INTERFACE DT H'00', H'00' ; Index, Alternate setting DT H'02', H'ff' ; # of EP, Class DT H'ff', H'ff' ; subclass, protocal DT H'00' ; String description # EP1IDescriptor: DT D'7', H'05' ; Length, TYPE-ENDPOINT DT H'81', H'02' ; IN-01, Bulk DT H'40', H'00' ; Max size - 64 bytes DT H'00' ; Pulling interval, DNE EP1ODescriptor: DT D'7', H'05' ; Length, TYPE-ENDPOINT DT H'01', H'02' ; OUT-01, Bulk DT H'40', H'00' ; Max size - 64 bytes DT H'00' ; Pulling interval, DNE StringDesZero: DT d'4', H'03' ; Length, TYPE-STRING DT H'09', H'04' ; Code ENGLISH ManufacStr: DT ProductStr-ManufacStr ; Length DT H'03' ; TYPE-STRING DT 'M', 0, 'y', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0 ProductStr: DT SerialNumStr-ProductStr ; Length DT H'03' ; TYPE-STRING DT 'U', 0, 'S', 0, 'B', 0, ' ', 0 DT 'T', 0, 'e', 0, 's', 0, 't', 0 SerialNumStr: DT EndDes-SerialNumStr ; Length DT H'03' ; TYPE-STRING DT 'T', 0, '0', 0, '0', 0, '0', 0 EndDes: ;-------------------------------- No more data to send, mark it bsf OutOfData, 0 return ;***************************************************************** ;******************** Program Starts here Start: ;********************* Setup WDT clrwdt bsf STATUS, RP0 movlw b'00001111' ;Prescaler to WDT, 1:128 movwf OPTION_REG clrwdt ;********************* Setting up environment movlw b'10000010' ;Serial port in too movwf TRISB ;Set port B I/O clrf TRISA ;Set port A to all output bcf STATUS, RP0 clrf PORTA ;********************** Disable 16f628 specific features movlw b'00000111' ;Disable the analog section movwf CMCON ;********************** Setup UART first bsf STATUS, RP0 movlw d'10' ;115200 for 20MHz Clock, High speed movwf SPBRG ;The only rate with low mismatch movlw b'10100111' ;Async 8-bit @ High speed movwf TXSTA bcf STATUS, RP0 movlw b'10110000' ;Enable serial port movwf RCSTA clrf Zero movlw WelcomeMsg ;Display welcome string on startup call SendString ;*********************** Setup I/O port bsf _CS bcf _SK clrf TXnum ;----------------------- Wait for command WaitMore: clrwdt btfsc RCSTA, OERR goto ClearError btfss PIR1, RCIF goto WaitMore movfw RCREG movwf SerData movwf TXREG ;Send it back out call SSpace movlw '1' ;Decode command xorwf SerData, W btfsc STATUS, Z goto Cmd1SendMW ;Send and receive data from MW bus movlw '2' xorwf SerData, W btfsc STATUS, Z goto Cmd2WriteMW ;Write data into register movlw '3' xorwf SerData, W btfsc STATUS, Z goto Cmd3BurstR ;Burst read data movlw '4' xorwf SerData, W btfsc STATUS, Z goto HexTest ;Testing HEX routine movlw '5' xorwf SerData, W btfsc STATUS, Z goto Cmd5Initialize ;Not in use movlw '6' xorwf SerData, W btfsc STATUS, Z goto DummyNow ;Not in use movlw '7' xorwf SerData, W btfsc STATUS, Z goto CmdSendPacket7 ;Not in use movlw '8' xorwf SerData, W btfsc STATUS, Z goto CmdSendString ;Not in use DummyNow: ;For all command not in use movlw CommandMsg call SendString ;Send error command message goto WaitMore ;********************* Clear receving overrun error ClearError: movfw RCREG movfw RCREG bcf RCSTA, CREN bsf RCSTA, CREN goto WaitMore ;---------------------- Commands execution Cmd1SendMW: ;Command 1: Send and receive MW data call RcvHex movfw Output bcf _CS call MWSend bsf _CS call SendHex call NewLine goto WaitMore Cmd2WriteMW: ;Command 2: Write MW data call RcvHex movlw 80h xorwf Output, W bcf _CS call MWSend call RcvHex movfw Output call MWSend bsf _CS call SendHex call NewLine goto WaitMore Cmd3BurstR: ;Command 3: Read the buffer call RcvHex movfw Output bcf _CS call MWSend call MWSend bsf _CS call SendHex call NewLine goto WaitMore HexTest: call RcvHex ;Command 4: Hex test movfw Output call SendHex call NewLine goto WaitMore ;******************************* USB function starts here Cmd5Initialize: ;Use this function to enter USB setup bcf _CS ;*Before start main loop, reset processor movlw 80h call MWSend ;MainControl movlw b'1000101' ;VGE, Int on high, no NAT soft reset call MWSend movlw 80h call MWSend ;MainControl movlw b'1000100' ;VGE, Int on high, no NAT yet call MWSend bsf _CS call Delay_1ms ;Wait for regulator to stabalize bcf _CS ;*Set different message mask movlw 89h call MWSend ;Alt mask movlw b'01000000' ;Only check RESET for now call MWSend movlw 8dh call MWSend ;Receive mask movlw b'00000011' ;Only check for data incoming at EP0 call MWSend movlw 8bh call MWSend ;Transmit mask movlw b'00000011' ;Only check for data outgoing at EP0 call MWSend movlw 8fh call MWSend ;NAK Event mask movlw b'00000001' ;Only check for data outgoing at EP0 call MWSend bsf _CS bcf _CS movlw 0a0h call MWSend ;Set EPC0 to 00(no DEF address) movlw 00h call MWSend movlw 84h call MWSend ;Set FAR to 80(accept default address) movlw 80h call MWSend ;Turn on NAT, USB ready to receve data movlw 80h call MWSend ;MainControl movlw b'10001100' ;VGE, Int on high, NAT high call MWSend bsf _CS USBMainLoop: ;*Start USB cycle, main loop btfss PIR1, RCIF ;If buffer is not empty, key has been hit goto Continue_Run ;If not, continue the loop movfw RCREG movwf TXREG ;Exit the USB main cycle if user hit a key movlw 1bh xorwf RCREG, W btfsc STATUS, Z ;ESC to exit, if not sent a packet goto WaitMore call EP1_SendTestPacket Continue_Run: bcf _CS ;*Check the main event register, take action if needed movlw 06h call MWSend ;Read MainEvent movlw 40h call MWSend ;Call again to read buffer bsf _CS movwf MAEV btfsc MAEV, 0 ;WARN goto procWARN btfsc MAEV, 1 ;ALT goto procALT btfsc MAEV, 2 ;TX_EV goto procTX_EV btfsc MAEV, 4 goto procNAK_EV btfsc MAEV, 6 ;RX_EV goto procRX_EV goto USBMainLoop ;Loop return ;------------------------------- 2nd level routines procWARN: ;Warning movlw 'W' call SendChar bcf _CS movlw 10h call MWSend ;Read WARN Event movlw 40h call MWSend ;Call again to read buffer bsf _CS movwf WARN goto USBMainLoop procALT: movlw 'A' call SendChar bcf _CS movlw 08h call MWSend ;Read ALT Event movlw 40h call MWSend ;Call again to read buffer bsf _CS movwf ALT call SendHex call SSpace btfsc ALT, 6 ;Only decode reset now call ProcReset goto USBMainLoop procTX_EV: movlw 'T' call SendChar bcf _CS movlw 0ah call MWSend ;Read TXEV Event movlw 40h call MWSend ;Call again to read buffer movwf TXEV bsf _CS call SSpace btfsc TXEV, 0 call procEP0TX ;Again, control pipe btfsc TXEV, 1 call procEP1TX ;EP1 check for finished transfer goto USBMainLoop procNAK_EV: movlw 'N' call SendChar bcf _CS movlw 0eh call MWSend ;Read TXEV Event movlw 40h call MWSend ;Call again to read buffer bsf _CS movwf NAKEV call SendHex call SSpace btfsc TXEV, 1 call procEP1NAK goto USBMainLoop procRX_EV: movlw 'R' call SendChar bcf _CS movlw 0ch call MWSend ;Read RXEV Event movlw 40h call MWSend ;Call again to read buffer movwf RXEV bsf _CS call SSpace btfsc RXEV, 0 call procEP0RX ;Check for control pipe btfsc RXEV, 1 call procEP1RX ;EP1 check for incoming data goto USBMainLoop ;------------------------------- 3rd level function ** ALT ** ProcReset: movlw 'r' call SendChar bcf _CS movlw 85h call MWSend ;Set NFS to 00(reset) movlw 00h call MWSend movlw 84h call MWSend ;Set Address to 00 movlw 80h call MWSend bsf _CS call Delay_100us ;Wait 100uS before re-enable bcf _CS movlw 85h call MWSend ;Set NFS to 02(Operation) movlw 02h ;Set back to operational mode call MWSend movlw 0a8h ;EPC1 call MWSend movlw b'00010000' ;EP1TX, enabled call MWSend movlw 0ach ;EPC2 call MWSend movlw b'00010001' ;EP1RX, enabled call MWSend movlw 0afh ;RXC1 call MWSend movlw b'00001001' ;Enable RX and flush buffer call MWSend bsf _CS return ;------------------------------- 3rd level function ** RX ** procEP0RX: movlw 'f' call SendChar movlw '0' call SendChar movlw '-' call SendChar bcf _CS movlw 26h ;RXS0 - EP0 status call MWSend ; movlw 40h call MWSend ;Read bsf _CS movwf RXS0 call SendHex call SSpace btfsc RXS0, 6 ;Chect for setup packet call ProcSetupPacket return procEP1RX: movlw 'f' call SendChar movlw '1' call SendChar movlw '-' call SendChar call NewLine bcf _CS EP1ReReadLength: movlw '(' call SendChar movlw 2eh ;RXS1 - EP1 status call MWSend ; movlw 40h ;Read status call MWSend movwf RX1length call SendHex movlw ')' call SendChar movlw 0fh andwf RX1length, F btfsc STATUS, Z goto FinishedReadEP1 ;If length is 0, read is finished EP1CountRead: movlw 2dh ;RXD1 - EP1 data call MWSend ; movlw 40h call MWSend ;Read call SendChar ;Send out the received data out to serial decfsz RX1length, F goto EP1CountRead goto EP1ReReadLength FinishedReadEP1: movlw 0afh ;RXC1 - EP1 Control call MWSend movlw b'00001001' ;Re-enable receive call MWSend bsf _CS call NewLine return ;------------------------------- procEP1NAK: movlw 'n' call SendChar movlw '1' call SendChar call EP1_SendTestPacket return ;------------------------------- 3rd level function ** TX ** procEP0TX: ;**EP0** Part of the enumeration process movlw 't' call SendChar movlw '0' call SendChar bcf _CS movlw 22h ;TXS0 - EP0 TX status call MWSend ; movlw 40h call MWSend ;Read to clear the int flag bsf _CS movf TX0length, F ;Check if there are more data to send btfsc STATUS, Z goto TXNoMoreData return TXNoMoreData: ;Re-enable RX if there are no more data to send bcf _CS ;This completes the ACK stage of the setup packeta movlw 0a7h ;RXC0 - EP0 RX control call MWSend ; movlw 01h call MWSend ;RX enable bsf _CS return ;**EP1** procEP1TX: movlw 't' call SendChar movlw '1' call SendChar bcf _CS movlw 2ah ;TXS1 - EP1 TX status call MWSend ; movlw 40h call MWSend ;Read to clear the int flag bsf _CS movlw b'00000100' xorwf Toggle, F ;Switch PID return ;------------------------------- 4th level function ** EP0 ** ProcSetupPacket: movlw 'Z' call SendChar movlw 0fh andwf RXS0, F ;Check for the length of the data movfw RXS0 call SendHex movlw '-' call SendChar movlw b'00000100' movwf Toggle ;Reset Toggle value when SETUP is received movlw S_bmRequestT movwf FSR bcf _CS PSP_loop: movlw 25h ;RXD0 - EP0 data call MWSend ; movlw 40h ;Read only call MWSend ;Read movwf INDF call SendHex ;Read and dump all data call SSpace incf FSR, F decfsz RXS0, F goto PSP_loop bsf _CS call NewLine movlw d'0' ;Get status, DEV, INT, EP xorwf S_bRequest, W btfsc STATUS, Z goto GET_STATUS movlw d'1' ;Clear feature, DEV, INT, EP xorwf S_bRequest, W btfsc STATUS, Z goto CLEAR_FEATURE movlw d'3' ;Set feature, DEV, INT, EP xorwf S_bRequest, W btfsc STATUS, Z goto SET_FEATURE movlw d'5' ;Code process address xorwf S_bRequest, W btfsc STATUS, Z goto SET_ADDRESS movlw d'6' ;Code get configuration xorwf S_bRequest, W btfsc STATUS, Z goto GET_DESCRIPTOR movlw d'7' ;Set descriptor xorwf S_bRequest, W ;No action, return zero length btfsc STATUS, Z goto SET_DESCRIPTOR movlw d'8' xorwf S_bRequest, W btfsc STATUS, Z goto GET_CONFIGURATION movlw d'9' ;Set configuration xorwf S_bRequest, W ;Only one configuration, so btfsc STATUS, Z ;do nothing goto SET_CONFIGURATION movlw d'10' xorwf S_bRequest, W btfsc STATUS, Z goto GET_INTERFACE movlw d'11' xorwf S_bRequest, W btfsc STATUS, Z goto SET_INTERFACE movlw d'12' xorwf S_bRequest, W btfsc STATUS, Z goto SYNCH_FRAME ;All other command are not supported ;Complete by sending STALL for other command bcf _CS movlw 0a0h ;EPC0 - EP0 control call MWSend movlw 80h call MWSend ;write STALL movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit packet iorwf Toggle, W ;Combine with toggle information call MWSend movlw 0a7h call MWSend movlw 01h call MWSend ;Enable OUT token for STALL handshake call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID bsf _CS return ;bRequest 0 GET_STATUS: movlw 'g' call SendChar movlw 'S' call SendChar movlw 02h ;Endpoint xorwf S_bmRequestT, W btfsc STATUS, Z goto get_status_ep get_status_ep: bcf _CS ;Send two 0x00 bytes movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer clrw call MWSend movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer clrw call MWSend movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit two empty bytes iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend movlw b'00000100' xorwf Toggle, F ;Switch PID bsf _CS return CLEAR_FEATURE: movlw 'c' call SendChar movlw 'F' call SendChar movlw 02h ;Endpoint xorwf S_bmRequestT, W btfsc STATUS, Z goto clear_feature_ep clear_feature_ep: bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend movlw b'00000100' xorwf Toggle, F ;Switch PID movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return SET_FEATURE: movlw 's' call SendChar movlw 'F' call SendChar movlw 02h ;Endpoint xorwf S_bmRequestT, W btfsc STATUS, Z goto set_feature_ep set_feature_ep: bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend movlw b'00000100' xorwf Toggle, F ;Switch PID movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return SET_ADDRESS: movlw 's' call SendChar movlw 'A' call SendChar bcf _CS movlw 0a0h ;EPC0 - EP0 control call MWSend ; movlw 40h call MWSend ;write Default address movlw 084h ;FAR call MWSend ; movfw wValueL iorlw 80h call MWSend ;write Current address movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit a zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID bcf _CS movlw 0a0h ;EPC0 - EP0 control call MWSend ; movlw 00h call MWSend ;set to the new address bsf _CS return GET_DESCRIPTOR: movlw 'g' call SendChar movlw 'D' call SendChar clrf OutOfData clrf OverSize movfw wValueH call DescriptorOffset movwf DescripSel movlw 03h xorwf wValueH, W btfsc STATUS, Z goto GetStringDesc goto GetOtherDesc GetStringDesc: movfw wValueL ;user the first byte, which is length call StringOffset call DescripterEnt ;Firt byte of the descriptor is the length ;Check which one is smaller, send the smaller one movwf RealDesLen subwf wLengthL, W ;wLength - RealLength movfw RealDesLen btfsc STATUS, C ;If carry, wLength > RealLength movwf wLengthL ;Reset the length of string to get movfw wValueL call StringOffset movwf DescripSel goto NormalDesProcess ;**************________*_*_*_*_*_*_*_ GetOtherDesc: movlw 02h xorwf wValueH, W ;Check if is asking for Configuration Descriptor btfss STATUS, Z goto NotConfigurationDes movfw wValueH call DescriptorOffset movwf DescripSel ;Add 2 to get the total length incf DescripSel, F incf DescripSel, W call DescripterEnt ;Get the total length at address 2 goto FromConfigDes NotConfigurationDes: movfw wValueH ;user the first byte, which is length call DescriptorOffset call DescripterEnt ;Firt byte of the descriptor is the length ;Check which one is smaller, send the smaller one FromConfigDes: movwf RealDesLen subwf wLengthL, W ;wLength - RealLength movfw RealDesLen btfss STATUS, C ;If carry, wLength > RealLength goto SizeIsRight ;Reset the length of string to get bsf OverSize, 0 ;Mark as oversized, require a zero packet at the end movwf wLengthL SizeIsRight: movfw wValueH call DescriptorOffset movwf DescripSel goto NormalDesProcess NormalDesProcess: clrf CounterB movlw d'8' movwf CounterA ;Breakup to 8 byte at a time send_conf_loop: movfw CounterB addwf DescripSel, W ;Add to the offset call DescripterEnt ;Transmit descripter movwf Lookup btfsc OutOfData, 0 ;See if the all the data is read goto OutOfData2Send ;If no data left, set the send command bcf _CS movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer movfw Lookup call MWSend bsf _CS movfw Lookup call SendHex call SSpace incf CounterB, F movfw wLengthL xorwf CounterB, W btfss STATUS, Z goto sendMoreData OutOfData2Send: bcf _CS ;No more data, send them out movlw 0a3h call MWSend ;TXC0 - Transmit Data Command movlw 01h ;Transmit iorwf Toggle, W ;Combine with toggle information call MWSend bsf _CS clrf TX0length ;Clear TX transmission length, re-enable receive call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID btfss OverSize, 0 ;If host requested too much data, have to indicate goto NotOverSized ;end of string by sending a smaller than FIFO packet decfsz CounterA, F ;If the packet is already smaller goto NotOverSized ;No need to send 0 length packet SendZeroLength: bcf _CS ;OverSized, send a zero length packet movlw 0a3h call MWSend ;TXC0 - Transmit Data Command movlw 01h ;Transmit iorwf Toggle, W ;Combine with toggle information call MWSend bsf _CS clrf TX0length ;Clear TX transmission length, re-enable receive call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID NotOverSized: bcf _CS movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return ; when TX is done sendMoreData: decfsz CounterA, F goto send_conf_loop movlw '-' call SendChar ;Since the FIFO is only 8 byte size bcf _CS ;No more FIFO, send them out movlw 0a3h call MWSend ;TXD0 - Transmit Data buffer movlw 01h ;Transmit iorwf Toggle, W ;Combine with toggle information call MWSend bsf _CS movlw d'8' movwf CounterA ;Breakup to 8 byte at a time call EP0_WaitSend btfss TX0stat, 5 ;Check to see if the TX is done goto TX0DesTimedOut ;Return if transmission is time-out movlw b'00000100' xorwf Toggle, F ;Switch PID goto send_conf_loop ;Continue if pack is sent TX0DesTimedOut: return SET_DESCRIPTOR: movlw 's' call SendChar movlw 'D' call SendChar bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID bsf _CS return GET_CONFIGURATION: movlw 'g' call SendChar movlw 'C' call SendChar bcf _CS movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer movfw Configuration call MWSend movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer movlw 00h call MWSend movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return SET_CONFIGURATION: movlw 's' call SendChar movlw 'C' call SendChar movfw wValueL movwf Configuration bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit a zero length packet, PID1 iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID ;Setup config 1-EP1 support IN/OUT movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS call EP1_SendTestPacket ;Send a test packet return GET_INTERFACE: movlw 'g' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit a zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return SET_INTERFACE movlw 's' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit a zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend bsf _CS call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID bcf _CS movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return SYNCH_FRAME: movlw 's' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 01h ;Transmit a zero length packet iorwf Toggle, W ;Combine with toggle information call MWSend bsf _CS call EP0_WaitSend ;Wait until the packet is sent movlw b'00000100' xorwf Toggle, F ;Switch PID bcf _CS movlw 0a7h call MWSend movlw 01h call MWSend ;Send ACK packet bsf _CS return ;******************************************************************* ;** EP0_WaitSend - Wait until the data in the transmission buffer ;** is sent EP0_WaitSend: movlw 0x20 movwf TX0TimeOut EP0_WaitSendLoop: bcf _CS movlw '>' ;Mark reading status (DEBUG) call SendChar movlw 08h call MWSend ;TXD0 - Transmit Data buffer movlw 40h call MWSend ;Read the status call SendHex ;Display result movlw 023h call MWSend ;TXD0 - Transmit Data buffer movlw 40h call MWSend ;Read the status bsf _CS movwf EP0WaitT decf TX0TimeOut, F ;>255 = timeout btfsc STATUS, Z goto EP0TX0TimeOut btfsc EP0WaitT, 0 ;Check to makesure TX is complete goto EP0_WaitSendLoop EP0TX0TimeOut: movlw '*' ;Before exit, read TX status call SendChar bcf _CS movlw 022h call MWSend ;Read TX status TXS0 movlw 40h call MWSend ;Read the status movwf TX0stat ;Store status bsf _CS return EP1_SendTestPacket: incf TXnum, F bcf _CS movlw 0a9h call MWSend ;TXD1 - Transmit Data buffer movlw 'T' call MWSend ;Data movlw 0a9h call MWSend ;TXD1 - Transmit Data buffer movlw 'E' call MWSend ;Data movlw 0a9h call MWSend ;TXD1 - Transmit Data buffer movlw 'S' call MWSend ; movlw 0a9h call MWSend ; movlw 'T' call MWSend ; movlw 0a9h call MWSend ; movfw TXnum call MWSend ; movlw 0abh call MWSend ; movlw b'00000011' iorwf Toggle, W call MWSend ;Set to send bsf _CS return ;************************************** Finish USB routine CmdSendPacket7: call RcvHex ;Command 7: movlw NoAckMsg call SendString goto WaitMore CmdSendString: ;Command 8: Send ASCII string Again: btfss PIR1, RCIF goto Again movfw RCREG movwf TXREG ; Send it back out movlw 1bh xorwf RCREG, W btfsc STATUS, Z goto ExitSendString ; If ESC is pressed, exit the routine goto Again ExitSendString: call NewLine ; ESC character mess up the first newline call NewLine goto WaitMore LocSendCommand goto WaitMore ;***************************** SUBROUTINE ;----------------------------------------------------------------- ; MWsend, send a single byte out of Microwire port ; Input: data stored in W ; Output: data stored in W MWSend: movwf Temp movlw d'8' movwf Counter ;8 cycles MWSendLoop1: btfsc Temp, 7 bsf _SO btfss Temp, 7 ;Send MSB first bcf _SO ;Clear if bit is low bsf _SK ;Shift bit in rlf Temp, F ;Rotate first bsf Temp, 0 btfss _SI bcf Temp, 0 ;Data is read and stored in Temp bcf _SK ;Shift bit out decfsz Counter, F goto MWSendLoop1 movfw Temp return ;----------------------------------------------------------------- ; SendHex, Send a single byte out of serial port, hex format ; Input: data stored in W SendHex: movwf Temp swapf Temp, W andlw 00fh call HexTable HexWaitLoop1: btfss PIR1, TXIF ;Wait till buffer is empty goto HexWaitLoop1 movwf TXREG movf Temp, W andlw 00fh call HexTable HexWaitLoop2: btfss PIR1, TXIF ;Wait till buffer is empty goto HexWaitLoop2 movwf TXREG return ;----------------------------------------------------------------- ; RcvHex, Receive a single byte from serial port in hex format ; Output: data stored in Output RcvHex: btfss PIR1, RCIF goto RcvHex movfw RCREG movwf SerData movwf TXREG ; Send it back out movlw 30h subwf SerData, F movlw 10h subwf SerData, W ; F - W btfsc STATUS, C ; Positive means letter input goto Letter1 RtnLetter1: swapf SerData, W movwf Output RcvHexLoop: btfss PIR1, RCIF goto RcvHexLoop movfw RCREG movwf SerData movwf TXREG ; Send it back out movlw 30h subwf SerData, F movlw 10h subwf SerData, W ; F - W btfsc STATUS, C ; Positive means letter input goto Letter2 RtnLetter2: movfw SerData iorwf Output, F call SSpace return Letter1: movlw 07h subwf SerData, F movlw 10h subwf SerData, W btfsc STATUS, C ; Positive means bad input goto Letter1E goto RtnLetter1 Letter1E: movlw d'32' subwf SerData, F goto RtnLetter1 Letter2: movlw 07h subwf SerData, F movlw 10h subwf SerData, W btfsc STATUS, C ; Positive means bad input goto Letter2E goto RtnLetter2 Letter2E: movlw d'32' subwf SerData, F goto RtnLetter2 ;----------------------------------------------------------------- ; LongDelay, 15 cycles, 3ins/cycle 22.5uS for 8Mhz clock long_delay: movlw d'15' movwf Counter long_delay_L: decfsz Counter, F goto long_delay_L return ;----------------------------------------------------------------- ; Delay_1ms, 5000 cycles, actual is 4590 cycle, 0.918mS for 20Mhz clock Delay_1ms: movlw d'6' movwf CounterA Delay_1ms_loop_O: Delay_1ms_loop_I: decfsz CounterB, F goto Delay_1ms_loop_I decfsz CounterA, F goto Delay_1ms_loop_O return ;----------------------------------------------------------------- ; Delay_100us, 500 cycles, actual is 498 cycle, 99.6uS for 20Mhz clock Delay_100us: movlw d'166' movwf CounterA Delay_100us_loop: decfsz CounterA, F goto Delay_100us_loop return ;----------------------------------------------------------------- ; SendString, send the string out to serial port ; Input: String location in W SendString: movwf Counter SendLoop: btfss PIR1, TXIF ;Wait till buffer is empty goto SendLoop call StringStart iorwf Zero, W btfsc STATUS, Z ;Zero is the end of string return movwf TXREG incf Counter, F movfw Counter goto SendLoop ;----------------------------------------------------------------- ; NewLine, send s newline character into serial port ; Input: None NewLine: btfss PIR1, TXIF ;Wait till buffer is empty goto NewLine movlw 0dh movwf TXREG movlw 0ah NewLineLoop: btfss PIR1, TXIF ;Wait till buffer is empty goto NewLineLoop movwf TXREG return ;----------------------------------------------------------------- ; SSpace, send a space character into serial port ; Input: None SSpace: btfss PIR1, TXIF ;Wait till buffer is empty goto SSpace movlw ' ' movwf TXREG return ;----------------------------------------------------------------- ; SendChar, send a single character into serial port SendChar: btfss PIR1, TXIF ;Wait till buffer is empty goto SendChar movwf TXREG return ;***************************************************************** ; Subede wasure de, kokoni iru end