;******************************************************************************* ;** ;** Master controller for the test system ;** ;** Written by Rick Huang, Copyright (C) 2003 ;** Revision YYYY/MM/DD ;** Rev 1. 2003/04/24 - Initial release ;** Rev 1.1 2003/10/-- - Adapted with 1wire bus ;** Rev 2 2003/12/16 - Updated with LCD controller ;** Rev 2.1 2003/12/22 - Add WDT support code, ;** corrected a bug that cause the program crash when overflow occures ;** during serial transmission ;** Rev 2.2 2004/06/21 - Correct a bug in the RcvHex that fail to check the ;** availability of the serialTX buffer ;** ;** Command Functions ;** '1' Initialize local LCD display ;** '2' Send Command to local Display ;** '3' Send String to Local Display ESC to break ;** '4' Hex test - echo any hex input ;** '7' Send command and data on iWire bus - Format: ;** 7 ;** '8' Send string on iWire bus - break when ESC is detected ;** 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 _XT_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 wAddr EQU 23h ; wXX is word storage wCmd EQU 24h wDataH EQU 25h wDataL EQU 26h lAddr EQU 27h ; lXX is loop counter lCmd EQU 28h lDataH EQU 29h lDataL EQU 2ah Zero EQU 2bh ; Zero is 0x00 SerData EQU 2ch Temp EQU 2dh Output EQU 2eh Counter EQU 2fh LCDtemp EQU 30h LCDxfer EQU 31h #define _DIN PORTB, 7 ; Incoming data from 1wire bus #define _DOUT PORTB, 6 ; Outgoing data to the 1wire bus #define _MUX PORTB, 5 ; Select the multiplexer #define _DE PORTB, 4 ; Debug port ;***************************************************************** ;** 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" ;***************************************************************** ;******************** 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'12' ;19200 for 4MHz 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 ;----------------------- 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 InitLocLCD ;Initialize local LCD display movlw '2' xorwf SerData, W btfsc STATUS, Z goto LocSendCommand ;SendCommend to display movlw '3' xorwf SerData, W btfsc STATUS, Z goto LocSendString ;Send String to Display movlw '4' xorwf SerData, W btfsc STATUS, Z goto HexTest ;Testing HEX routine movlw '5' xorwf SerData, W btfsc STATUS, Z goto DummyNow ;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 ;Send packet for iWire bus movlw '8' xorwf SerData, W btfsc STATUS, Z goto CmdSendString ;Send String for iWire bus 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 HexTest: call RcvHex ;Command 4: Hex test movfw Output call SendHex call NewLine goto WaitMore CmdSendPacket7: call RcvHex ;Command 7: Send iWire packet movfw Output movwf wAddr ;Receive address call RcvHex movfw Output movwf wCmd ;Receive command call RcvHex movfw Output movwf wDataH ;Receive higher byte of data call RcvHex movfw Output movwf wDataL ;Receive lower byte of data call SendPacket btfss STATUS, C ;if C is set, there are no target slave device goto NoError movlw NoAckMsg call SendString goto WaitMore NoError: movfw wDataH ;Display return value if there is no error call SendHex movfw wDataL call SendHex call NewLine goto WaitMore CmdSendString: ;Command 8: Send ASCII string call RcvHex movfw Output movwf wAddr ;Receive address Again: btfss PIR1, RCIF goto Again movfw RCREG movwf wDataL movwf TXREG ; Send it back out movlw 23h movwf wCmd ; Use command 0x23 to send a character at a time movlw 1bh xorwf wDataL, W btfsc STATUS, Z goto ExitSendString ; If ESC is pressed, exit the routine call SendPacket goto Again ExitSendString: call NewLine ; ESC character mess up the first newline call NewLine goto WaitMore InitLocLCD: ; Command 2, initialize local display call LCDinit call NewLine goto WaitMore LocSendString: LAgain: btfss PIR1, RCIF goto LAgain movfw RCREG movwf wDataL movlw 1bh xorwf wDataL, W btfsc STATUS, Z goto LExitSendString ; If ESC is pressed, exit the routine movfw wDataL movwf TXREG ; Send it back out call LCDchar goto LAgain LExitSendString: call NewLine ; ESC character mess up the first newline goto WaitMore LocSendCommand call RcvHex ;Command 7: Send iWire packet movfw Output call LCDcmd call NewLine goto WaitMore ;***************************** SUBROUTINE ;----------------------------------------------------------------- ; 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 RcvHexWait1: btfss PIR1, TXIF ;Wait till buffer is empty goto RcvHexWait1 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 RcvHexWait2: btfss PIR1, TXIF ;Wait till buffer is empty goto RcvHexWait2 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 ;----------------------------------------------------------------- ; 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 ;----------------------------------------------------------------- ; Space, send a space character into serial port ; Input: None SSpace: btfss PIR1, TXIF ;Wait till buffer is empty goto SSpace movlw ' ' movwf TXREG return ;----------------------------------------------------------------- ; Schar, send a character into serial port Schar: btfss PIR1, TXIF ;Wait for buffer goto Schar movwf TXREG return ;******************************************************** ;** SendPacket, send and receive data packet though 1wire bus ;** Note: Timing is critical, Observer timing marker when changing ;** the code. ;** Input: wAddr - Network address ;** wCmd - Command (0~79 - Output, 80 ~ ff - Input) ;** wDataH - First data byte ;** wDataL - Second data byte ;** Output: wDataH, wDataL ;** Internal used variable: ;** lAddr, lCmd, lDataH, lDataL - counting latch ;** Error condition: ;** STATUS, C is set - No ACK from slave device ;** STATUS, C is clear - No error ;** ;********************** Test code, Send an packet SendPacket: movlw 08h movwf lAddr movwf lCmd movwf lDataH movwf lDataL bsf _DOUT ; ATTN, last 15 cycles nop ; 1 nop ; 2 nop ; 3 nop ; 4 nop ; 5 nop ; 6 nop ; 7 nop ; 8 nop ; 9 nop ; 10 nop ; 11 nop ; 12 nop ; 13 nop ; 14 bcf _DOUT ; End of ATTN, Pad 2 cycle for safty rlf wAddr, F ; P1 - Moved from next data cycle AddrLoop: bcf _DOUT ; Addr 1 - 8 bits - P2 btfss STATUS, C ; Addr 2 bsf _DOUT ; Addr 3 rlf wAddr, F ; Addr 4 decfsz lAddr, F ; Addr 5 goto AddrLoop ; Addr 6 + 1 nop ; Pad 1 due to no goto bcf _DOUT ; #1Ack 1 nop ; #1Ack 2 nop ; #1Ack 3 nop ; #1Ack 4 nop ; #1Ack 5 nop ; #1Ack 6 nop ; #1Ack 7 nop ; #2Ack 1 bcf _DOUT ; #2Ack 2 btfsc _DIN ; #2Ack 3 <- sample here goto NoAck ; #2Ack 4 nop ; #2Ack 5 nop ; #2Ack 6 rlf wCmd, F ; #2Act 7 CmdLoop: bcf _DOUT ; Cmd 1 - 8 bits btfss STATUS, C ; Cmd 2 bsf _DOUT ; Cmd 3 rlf wCmd, F ; Cmd 4 decfsz lCmd, F ; Cmd 5 goto CmdLoop ; Cmd 6 + 1 rlf wDataH, F ; Cmd 7 btfsc wCmd, 7 goto ReadData ; Read instead of write DHLoop: bcf _DOUT ; DH 1 - 8 bits btfss STATUS, C ; DH 2 bsf _DOUT ; DH 3 rlf wDataH, F ; DH 4 decfsz lDataH, F ; DH 5 goto DHLoop ; DH 6 + 1 rlf wDataL, F ; DH 7 DLLoop: bcf _DOUT ; DL 1 - 8 bits btfss STATUS, C ; DL 2 bsf _DOUT ; DL 3 rlf wDataL, F ; DL 4 decfsz lDataL, F ; DL 5 goto DLLoop ; DL 6 + 1 nop ; DL 7 bsf _DOUT ; Timing Marker bcf _DOUT bcf STATUS, C return NoAck: bsf STATUS, C return ReadData: bcf _DOUT bcf STATUS, C nop ; 1 - Read and write swich sync, req. 7 cycles nop ; 2 nop ; 3 nop ; 4 nop ; 5 nop ; 6 nop ; 7 RDHLoop: btfsc _DIN ; DH 1 - 8 bits bsf STATUS, C ; DH 2 rlf wDataH, F ; DH 3 bcf STATUS, C ; DH 4 decfsz lDataH, F ; DH 5 goto RDHLoop ; DH 6 + 1 bcf STATUS, C ; DH 7 RDLLoop: btfsc _DIN ; DL 1 - 8 bits bsf STATUS, C ; DL 2 rlf wDataL, F ; DL 3 bcf STATUS, C ; DL 4 decfsz lDataL, F ; DL 5 goto RDLLoop ; DL 6 + 1 bcf STATUS, C return ;***************************************************************** ;** ** LCD Routines ** ;** Written by Rick Huang, Copyright (C) 2001 ;** ResetLCD ;** Initialization ;** LCD function on port R/B R/A ;** PA0 - D0 ;** PA1 - D1 PB4 - RS ;** PA2 - D2 PB5 - E ;** PA3 - D3 ;** LCDtemp 0ch LCDxfer 0eh ;** LCDchar 0dh LCDinit: ;initialize port/LCDscreen ;Delay to let LCD wake up call Delay164 call Delay164 movlw 03h movwf PORTA bsf PORTB, 5 bcf PORTB, 5 call Delay164 call Delay164 call Delay164 call Delay164 bsf PORTB, 5 bcf PORTB, 5 call Delay164 ;8bit at this point bsf PORTB, 5 bcf PORTB, 5 call Delay40 ;4bit I/O movlw 02h movwf PORTA bsf PORTB, 5 bcf PORTB, 5 call Delay164 movlw 28h call LCDcom call Delay40 movlw 10h ;Cursor move left call LCDcom call Delay40 movlw 0fh ;Display/Cursor/Binker on call LCDcom call Delay40 movlw 06h ;Cursor increase call LCDcom call Delay40 movlw 02h ;Return cursor call LCDcom call Delay164 movlw 01h ;Clear Screen call LCDcom call Delay164 call Delay164 movlw 28h call LCDcom call Delay164 return ;***************************************************************** ;** 40us Delay set for 6Mhz clock cycle Delay40: movlw 16h ;Need 60 instructions movwf LCDtemp ;60/3 = 20 cycles delay40_0: decfsz LCDtemp, F goto delay40_0 return ;***************************************************************** ;** 1.64ms Delay set for 6Mhz clock Delay164: movlw 0cch ;Need 2448 instructions ;2448 / 3 = 816 cycles / 4 = 204 sets movwf LCDtemp ;Set 1 delay164_0: decfsz LCDtemp, F goto delay164_0 movwf LCDtemp ;Set 2 delay164_1: decfsz LCDtemp, F goto delay164_1 movwf LCDtemp ;Set 3 delay164_2: decfsz LCDtemp, F goto delay164_2 movwf LCDtemp ;Set 4 delay164_3: decfsz LCDtemp, F goto delay164_3 return ;***************************************************************** ;** LCD Communication code LCDcom: ;send LCD command LCDcmd: movwf LCDxfer swapf LCDxfer, W ;upper 4 bits first bcf PORTB, 4 andlw 0fh movwf PORTA bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer ;lower 4 bits next andlw 0fh movwf PORTA bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer return ;***************************************************************** LCDchar: ;send LCD character movwf LCDxfer swapf LCDxfer, W ;upper 4 bits first bsf PORTB, 4 andlw 0fh movwf PORTA bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer ;lower 4 bits next andlw 0fh movwf PORTA bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer return ;***************************************************************** ;** Set curser location LCDLocate: iorlw 080h call LCDcom return LCDHome: movlw 02h call LCDcom return end