;******************************************************************************* ;** ;** 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 ;** ;** ;** 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 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 EP0Toggle EQU 39h TX0length EQU 3ah DescripSel EQU 3bh Configuration EQU 3ch RX1length EQU 3dh TXnum EQU 3eh EP1Toggle EQU 3fh 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'00', 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: ;***************************************************************** ;******************** 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'10000101' ;VGE, Int on high, no NAT soft reset call MWSend movlw 80h call MWSend ;MainControl movlw b'10000100' ;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 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 movlw 'N' call SendChar 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 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, 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 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 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 call MWSend ;Call again to read buffer bsf _CS movwf TXEV call SendHex call SSpace btfsc TXEV, 0 call procEP0TX ;Again, control pipe btfsc TXEV, 1 call procEP1TX ;EP1 check for finished transfer goto USBMainLoop procRX_EV: movlw 'R' call SendChar bcf _CS movlw 0ch call MWSend ;Read RXEV Event call MWSend ;Call again to read buffer bsf _CS movwf RXEV call SendHex 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 bsf _CS return ;------------------------------- 3rd level function ** RX ** procEP0RX: movlw 'f' call SendChar movlw '0' call SendChar bcf _CS movlw 26h ;RXS0 - EP0 status call MWSend ; 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 call NewLine bcf _CS EP1ReReadLength: movlw 2eh ;RXS1 - EP1 status call MWSend ; movlw 40h ;Shift data, don't read call MWSend ;Read movwf RX1length call SendHex call SSpace 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 ;------------------------------- 3rd level function ** TX ** procEP0TX: ;**EP0** movlw 't' call SendChar movlw '0' call SendChar bcf _CS movlw 22h ;TXS0 - EP0 TX status call MWSend ; 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 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 ; call MWSend ;Read to clear the int flag bsf _CS call SendHex call SSpace 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 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 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 movlw 0a0h ;EPC0 - EP0 control call MWSend movlw 80h call MWSend ;write stall movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit packet, PD1 call MWSend bsf _CS call EP0_WaitSend ;Wait until the packet is sent 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 05h ;Transmit two empty packet, PD1 call MWSend 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 05h ;Transmit zero length packet, PD1 call MWSend 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 05h ;Transmit zero length packet, PD1 call MWSend 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 05h ;Transmit a zero length packet, PID1 call MWSend call EP0_WaitSend ;Wait until the packet is sent 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 'C' call SendChar movfw wValueH call DescriptorOffset movwf DescripSel movlw 03h xorwf wValueH, W btfsc STATUS, Z goto GetStringDesc goto NormalDesProcess GetStringDesc: movlw 0ffh xorwf wLengthL, W btfss STATUS, Z goto NormalStringLen ;String length unknown, reset movfw wValueL ;user the first byte, which is length call StringOffset call DescripterEnt movwf wLengthL ;Reset the length of string to get NormalStringLen: movfw wValueL call StringOffset movwf DescripSel NormalDesProcess: movlw b'00000100' movwf EP0Toggle clrf CounterB movlw d'8' movwf CounterA ;Breakup to 8 byte at a time bcf _CS movlw 0a7h call MWSend movlw 08h call MWSend ;Flush RX buffer to make room for TX bsf _CS send_conf_loop: bcf _CS movlw 0a1h call MWSend ;TXD0 - Transmit Data buffer movfw CounterB addwf DescripSel, W ;Add to the offset call DescripterEnt ;Transmit descripter movwf Lookup call MWSend bsf _CS movfw Lookup call SendHex call SSpace incf CounterB, F movfw wLengthL xorwf CounterB, W btfss STATUS, Z goto sendMoreData bcf _CS ;No more data, send them out movlw 0a3h call MWSend ;TXD0 - Transmit Data buffer movlw 01h ;Transmit iorwf EP0Toggle, W call MWSend bsf _CS clrf TX0length ;Clear TX transmission length, re-enable receive return ; when TX is done sendMoreData: decfsz CounterA, F goto send_conf_loop movlw '-' call SendChar bcf _CS ;No more FIFO, send them out movlw 0a3h call MWSend ;TXD0 - Transmit Data buffer movlw 01h ;Transmit iorwf EP0Toggle, W call MWSend bsf _CS movlw d'8' movwf CounterA ;Breakup to 8 byte at a time movlw b'00000100' xorwf EP0Toggle, F ;Switch PID call EP0_WaitSend goto send_conf_loop SET_DESCRIPTOR: movlw 's' call SendChar movlw 'D' call SendChar bcf _CS movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit zero length packet, PD1 call MWSend bsf _CS return GET_CONFIGURATION: movlw 'g' call SendChar movlw 'C' call SendChar 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 05h ;Transmit, PID1 call MWSend return SET_CONFIGURATION: movlw 's' call SendChar movlw 'C' call SendChar movfw wValueL movwf Configuration movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit a zero length packet, PID1 call MWSend ;Setup config 1-EP1 support IN/OUT bcf _CS movlw 0a8h ;EPC1 call MWSend movlw b'00010001' ;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 clrf EP1Toggle call EP1_SendTestPacket ;Send a test packet return GET_INTERFACE: movlw 'g' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit a zero length packet, PID1 call MWSend return SET_INTERFACE movlw 's' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit a zero length packet, PID1 call MWSend return SYNCH_FRAME: movlw 's' call SendChar movlw 'I' call SendChar movfw wValueL movwf Configuration movlw 0a3h call MWSend ;TXC0 - Transmit EP0 movlw 05h ;Transmit a zero length packet, PID1 call MWSend return ;******************************************************************* ;** EP0_WaitSend - Wait until the data in the transmission buffer ;** is sent EP0_WaitSend: bcf _CS ;No more data, send them out movlw 023h call MWSend ;TXD0 - Transmit Data buffer call MWSend ;Read the status bsf _CS movwf Temp btfsc Temp, 0 goto EP0_WaitSend return EP1_SendTestPacket: incf TXnum, F bcf _CS ;No more data, send them out 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 ;Read the status movlw 0a9h call MWSend ;Data movlw 'T' call MWSend ;Read the status movlw 0a9h call MWSend ;Data movfw TXnum call MWSend ;Read the status movlw 0abh call MWSend ;TXD1 - Transmit Data buffer movlw b'00000011' iorwf EP1Toggle, W call MWSend ;Set to send bsf _CS movlw b'00000100' xorwf EP1Toggle, F ;Change the toggle for the next packet 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