;******************************************************************************* ;** ;** A Simple client code for iWire bus (only LCD display driver) ;** ;** Written by Rick Huang, Copyright (C) 2003 ;** Revision YYYY/MM/DD ;** Rev 1 2003/10/20 - Initial Release ;** Rev 2 2003/11/03 - Change the width of Id and Vs pulse(Not used for LCD) ;** Rev 3 2003/11/06 - Moved trigger output to PB3, add temperature func ;** ---- 2003/11/14 - Source split, remove driver and add LCD support ;** Rev S.1. 2003/11/14 - Change the code to drive LCD and 1wire bus only ;** Rev S.2. 2003/11/24 - Add command 0x24 and 0x25, fixed bug in 0x22 ;** ;** ==Commands Available== ;** Cmd# Var1 Var2 Function ;** 0x20 None None Initialize and clear the LCD display ;** 0x21 None None Write welcome message on LCD display ;** 0x22 None Pos Change the cursor position to Pos ;** 0x23 None Data Write a single character in Data to LCD ;** 0x24 None None Return the cursor position to home position ;** 0x25 None Cmd Execute any command in Cmd ;** ;** 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 ;******************************************************************************* include __config _XT_OSC & _WDT_OFF & _LVP_OFF & _BODEN_ON & _MCLRE_OFF & _PWRTE_ON ;***************************************************************** ;** Variables TempW EQU 20h CounterA EQU 21h CounterB EQU 22h wAddr EQU 23h wCmd EQU 24h wDataH EQU 25h wDataL EQU 26h lAddr EQU 27h lCmd EQU 28h lDataH EQU 29h lDataL EQU 2ah lDebug EQU 2bh MyAddr EQU 2ch DataH EQU 2dh DataL EQU 2eh IntCount EQU 2fh ;Not used for LCD version iWireIE EQU 30h ;Not used for LCD version LCDtemp EQU 31h LCDxfer EQU 32h ;** Note: ;** Not all code use defined value, any change to pin assignment ;** the code must be adjusted too. #define _ID PORTA, 0 ; #define _VS PORTA, 4 #define _TRIG PORTB, 3 #define _DIN PORTB, 7 ; Incoming data from 1wire bus #define _DOUT PORTB, 6 ; Outgoing data to the 1wire bus #define _DE PORTB, 0 ; Debug port #define _TC77CS PORTB, 4 ; CE for temperature sensor ;***************************************************************** ;** Program code here goto Start ORG 4 ;waiting for <0004> ;interrupt vector ;***************************************************************** ;** Interrupt entry point movfw TempW ;***************************************************************** ;** Starts the counting cycle here, ;** 120mS cycle ;** Clock is 4Mhz, instruction cycle is 1uS ;** Interrupt is not used for the LCD version ;** ISR is written here as an example on how to generate ;** a precise pulse, can be adapted for timer application ;** The interrupt cycle is 10mS, divided into 12 slots ;** Slot 0 is time-critical with gurantee service delay ;** Slot 1~11 is not time critical movlw 0f0h movwf TMR1L movlw 0d8h movwf TMR1H decfsz IntCount, F goto ExitInt incf IntCount, F ; Set to 1 btfss iWireIE, 0 ; Actually, need 12 cycles of 10mS each goto RunInt ; However, need to disable iWire at the bcf iWireIE, 0 ; last 10mS to preserv timing. goto ExitInt RunInt: movlw d'11' movwf IntCount movlw b'00010001' ; 199999 Set both Idata and Vsel high movwf PORTA ; 0 <--- KEY bcf _TRIG ; 1 movlw d'99' ; 2 movwf CounterA ; 3 wLoop1: nop ; * +1 nop ; * +2 decfsz CounterA, F ; * +3 goto wLoop1 ; * +5 nop ; 498 movlw b'00000001' ; 499 Set port B data. DO NOT USE bcf movwf PORTA ; 500 <--- KEY movlw d'3' ; 501 movwf CounterA ; 502 wLoop2: decfsz CounterA, F ; * +1 goto wLoop2 ; * +3 nop ; 511 nop ; 512 nop ; 513 bsf _TRIG ; 514 bcf _TRIG ; 515 <--- KEY ;**************************** bsf iWireIE, 0 ; Enable iWire again ExitInt: bcf PIR1, TMR1IF retfie ;***************************************************************** ;* RA0 - Idata, active high ;* RA4 - Vsel, active high ;* RB3 - Trigger ;* RB0 - Reserved for interrupt ;* RB1 - Sync Data port ;* RB2 - Sync Clock port ;* RB4 - CS for Temperature sensor ;* RB6 - DOUT for 1wire bus ;* RB7 - DIN for 1wire bus ;******************** Program Starts here Start: bsf STATUS, RP0 movlw b'10000000' ;LCD use, disable serial port 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' movwf CMCON bcf _ID bcf _VS bcf _DOUT bsf _TC77CS ;********************** Setup USRT (LCD, disable serial) bsf STATUS, RP0 movlw d'0' ;1Mhz for 4MHz Clock movwf SPBRG movlw b'10010111' ;Sync 8-bit @ High speed ;movwf TXSTA bcf STATUS, RP0 movlw b'10000000' ; serial port ;movwf RCSTA ; Not setting serial port enable flag ;********************* Enable timer 1 movlw b'00000001' movwf T1CON movlw 0f0h movwf TMR1L movlw 0d8h movwf TMR1H ; Set timer to overflow in 10000 counts ;********************* Disable timer 1 interrupt movlw d'11' movwf IntCount bsf STATUS, RP0 bsf PIR1, TMR1IE bcf STATUS, RP0 bcf PIR1, TMR1IF bsf INTCON, PEIE bcf INTCON, GIE ;Disable all interrupt bsf iWireIE, 0 ;************************************************** ;*** The following code ;*** Captures the data off the iWire bus and execute ;*** the commands or send back data CaptureData: movlw 01h movwf MyAddr ;Set Address to 0 movlw 8h movwf lAddr movwf lCmd movwf lDataH movwf lDataL movwf lDebug movfw MyAddr ; <- W contains MyAddr bcf _DE TooLong: WaitHigh: btfss _DIN goto WaitHigh TooShort: btfsc _DIN ; 1 goto TooShort ; 2 btfsc _DIN ; 3 goto TooShort ; 4 btfsc _DIN ; 5 goto TooShort ; 6 btfsc _DIN ; 7 goto TooShort ; 8 btfsc _DIN ; 9 goto TooShort ; 10 btfsc _DIN ; 11 goto Accept ; 12 btfsc _DIN ; 13 goto Accept ; 14 btfsc _DIN ; 15 goto Accept ; 16 btfsc _DIN ; 17 goto Accept ; 18 btfsc _DIN ; 19 goto Accept ; 20 btfsc _DIN ; 21 goto Accept ; 22 goto TooLong ;*** Captured the start bit and sync to the timing Accept: bcf STATUS, C AddrLoop: btfsc _DIN ; Addr 1 bsf STATUS, C ; Addr 2 rlf wAddr, F ; Addr 3 bcf STATUS, C ; Addr 4 decfsz lAddr, F ; Addr 5 goto AddrLoop ; Addr 6 + 1 ; Send ACK (First) xorwf wAddr, W ; Addr 7 btfss STATUS, Z ; 1 goto CaptureData ; 2 <- Not my ID, return bsf _DOUT ; 3 Hold Ack low for 7 cycles nop ; 4 nop ; 5 nop ; 6 nop ; 7 nop ; 1 <- Second ACK nop ; 2 bcf _DOUT ; 3 End Ack a bit early, rest is buffer zone nop ; 4 nop ; 5 nop ; 6 bcf STATUS, C ; 7 CmdLoop: btfsc _DIN ; Cmd 1 - 8 bits bsf STATUS, C ; Cmd 2 rlf wCmd, F ; Cmd 3 bcf STATUS, C ; Cmd 4 decfsz lCmd, F ; Cmd 5 goto CmdLoop ; Cmd 6 + 1 btfsc wCmd, 7 ; Cmd 7 goto WriteData ; Send data instead of receving bcf STATUS, C ; 2 extra cycle here DHLoop: 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 DHLoop ; DH 6 + 1 bcf STATUS, C ; DH 7 DLLoop: 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 DLLoop ; DL 6 + 1 movfw wDataH movwf DataH movfw wDataL movwf DataL goto DoneCapture WriteData: rlf wDataH, F ; DH WDHLoop: 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 WDHLoop ; DH 6 + 1 rlf wDataL, F ; DH 7 WDLLoop: 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 WDLLoop ; DL 6 + 1 nop ; DL 7 bcf _DOUT ;******************** Decode and run commands DoneCapture: movlw 10h xorwf wCmd, W btfsc STATUS, Z goto runGetTemp movlw 20h xorwf wCmd, W btfsc STATUS, Z goto ResetLCD movlw 21h xorwf wCmd, W btfsc STATUS, Z goto SaySomething movlw 22h xorwf wCmd, W btfsc STATUS, Z goto LocateLCD movlw 23h xorwf wCmd, W btfsc STATUS, Z goto SendByteLCD movlw 24h xorwf wCmd, W btfsc STATUS, Z goto ReturnHomeLCD movlw 25h xorwf wCmd, W btfsc STATUS, Z goto CommandLCD goto CaptureData ;******************** Command codes: runGetTemp: ; 0x10 get temperature from TC77 chip call ReadTemp ; Not functional for LCD version goto CaptureData ResetLCD: call LCDinit goto CaptureData LocateLCD: movfw wDataL call LCDLocate goto CaptureData SendByteLCD: movfw wDataL call LCDchar goto CaptureData ReturnHomeLCD: call LCDHome goto CaptureData CommandLCD: movfw wDataL call LCDcmd goto CaptureData SaySomething: ; "Welcome!" message movlw 'W' call LCDchar movlw 'e' call LCDchar movlw 'l' call LCDchar movlw 'c' call LCDchar movlw 'o' call LCDchar movlw 'm' call LCDchar movlw 'e' call LCDchar movlw '!' call LCDchar goto CaptureData ;***************************************************************** ;** ** LCD Routines ** ;** Written by Rick Huang, Copyright (C) 2001 ;** ResetLCD ;** Initialization ;** LCD function on port R/B ;** PB0 - D0 ;** PB1 - D1 PB4 - RS ;** PB2 - D2 PB5 - E ;** PB3 - D3 ;** LCDtemp 0ch LCDxfer 0eh ;** LCDchar 0dh LCDinit: ;initialize port/LCDscreen ;Delay to let LCD wake up call Delay164 call Delay164 movlw 03h movwf PORTB 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 PORTB 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 PORTB bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer ;lower 4 bits next andlw 0fh movwf PORTB 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 iorlw 10h movwf PORTB bsf PORTB, 5 ;Set Enable nop bcf PORTB, 5 ;Toggle call Delay40 movfw LCDxfer ;lower 4 bits next andlw 0fh iorlw 10h movwf PORTB 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 ;***************************************************************** ;** ReadTemp - Read Temperature from TC77 temperature sensor ;** Written by Rick Huang, Copyright (C) 2003 ;** Output placed in wDataH and wDataL ;** Utilizing USART feature of PIC16F87X and PIC16F62X ;** SI, SO - connected together to SI/O or SDATA ;** SCK - connected to SCK ;** /CE - Connected to _TC77CS ;** It is possible to communicate with multiple sensors on ;** a single SPI bus ReadTemp: bcf _TC77CS btfsc PIR1, RCIF movfw RCREG ; Empty buffer bsf RCSTA, SREN ; Receive 1st byte RTWait1: btfsc RCSTA, SREN goto RTWait1 movfw RCREG movwf wDataH bsf RCSTA, SREN ; Receive 2nd byte RTWait2: btfsc RCSTA, SREN goto RTWait2 movfw RCREG movwf wDataL clrf DataH clrf DataL bsf _TC77CS rrf wDataH, F ; Bit 12 rlf DataH, F rrf wDataH, F rlf DataH, F rrf wDataH, F rlf DataH, F rrf wDataH, F rlf DataH, F rrf wDataH, F rlf DataH, F ; Bit 8 rrf wDataH, F rlf DataL, F ; Bit 7 rrf wDataH, F rlf DataL, F ; 6 rrf wDataH, F rlf DataL, F ; 5 rrf wDataL, F rlf DataL, F ; 4 rrf wDataL, F rlf DataL, F ; 3 rrf wDataL, F rlf DataL, F ; 2 rrf wDataL, F rlf DataL, F ; 1 rrf wDataL, F rlf DataL, F ; 0 movfw DataH movwf wDataH movfw DataL movwf wDataL return end