;**********************************************************************
;                                                                     *
;    Filename:	    sunboi1.asm                                       *
;    Date:          02-10-2007                                        *
;    File Version:  Display unit for sunboiler                        *
;                   PCB:    Displayunit LZB (Luigjes ZonneBoiler)     *
;  					processor: PIC16F913                              *
;					SET VELLEMAN PROGRAMMER TO: PIC16F876             * 
;    Author:                                                          *
;                                							          *
;**********************************************************************
; NOTES
;
; - Incoming serial data from sunboiler will be displayed on LCD
; - PIC16F913, clock frequency: 4 MHz ,= 1MHz internal clock oscillator 
; - EA-DOGM162 Display-routines from German internet forum.....
; - Bestand gehaald van forum: http://www.mikrocontroller.net/topic/19480
;   Wolfram Hildebrandt
;   
; - 
; - Display shows COL: ...   PMP: OFF
; -               BOI: ...   HRS: ....
; -Collectortemparature    Pump On or off
; -Boilertemperature       Number of hours run
; 
; Received strings from ATAG-Luigjes HR zonnegascombi:
;
; Luigjes Delta-T <CR>
; Col:... Boi: .. <CR>
; PMP:...         <CR>
; ...-YCOL...-YBOI<CR>
; PMP: ..... UREN <CR>
;
;
; ; - WDT enabled 
;
;
; PIC ports used:
;
; RC0-3 outputs: drives LCD D4-D7 (4 bit parallel data transfer, LCD model= EA DOGM162)
; RC6 = UART-Tx for transmitting serial data to sunboiler (optional) TRANSMITTING NOT POSSIBLE!!
; No serial data is transmitted; RC6=highimpedance, RC5 connected to RC6 to make line low/high

; RC7 = UART-Rx for receiving serial data from sunboiler


; RA0 = RS Display
; RA1 = R/W Display
; RA2 = E  Display
; RB4 = LED backlight 1 via 220R resistor ; set = on
; RB5 = LED backlight 2 via 220R resistor ; set = on

; inputs: 

; RB2 = key - pushbutton (optional)
; RB7 = only used for ICSP PGD
; RB6 = only used for ICSP PGC



;**********************************************************************
 list	p=16f913, R=DEC ; using decimal system
	
	
	#include "p16f913.inc"
	;#include <c:\program files\microchip\MPASM Suite\p16f685.inc>
	;;	#include <c:\velleman\Include_files\p16F627.inc>
	;#include <c:\program files\microchip\MPASM Suite\picmac1.inc>
;	#include "picmac1.inc"
	
	

		__CONFIG  _DEBUG_OFF & _FCMEN_OFF & _IESO_OFF & _BOD_ON & _CPD_OFF & _CP_OFF &  _PWRTE_ON & _WDT_ON &   _MCLRE_OFF &  _INTRC_OSC_NOCLKOUT


	cblock 	0x20 			; start of general purpose registers
		

        loops
        loops2
        command
        counter
        temp
        dataL            ; used in UART communication routine
        BOI_1            ; sign that comes before boiler temp
        BOI_MSD          ; first digit of boiler temperature
        BOI_LSD          ; second digit of boiler temperature
        COL_1            ; sign that comes before collector temp 
        COL_MSD          ; first digit of collector temperature
        COL_LSD          ; second digit of collector temperature
        PMP_1            ; first digit of pump
        PMP_2            ; second digit of pump
        PMP_3            ; third digit of pump
        HRS_1            ; first digit of hours
        HRS_2            ; second digit of hours 
        HRS_3            ; third digit of hours
        HRS_4            ; fourth digit of hours
        temp_data        ; temporary storage of received character
        COUNT1			 ; Used by delay routines
			        	 ; and "prescaler flush"
	    COUNT2			 ; Timing (100ms)
        FLAG             ;
		STATUS_TEMP      ; for temporary storage of STATUS contence during interrupt
		W_TEMP           ; for temporary storage of w-contence during interrupt
		VALUE				; to get value from table
		count1 				; used in delay routine
		counta 				; used in delay routine 
		countb
		count
		dcnt0				; delay counter 0
		dcnt1				; delay counter 1
		dcnt2				; delay counter 2
		
        counter2             ; to keep track of when character 16 has been received
        EOS_FLAG            ; End Of  String FLAG
        CHR1
        CHR2
        CHR3
        CHR4
        CHR5
        CHR6
        CHR7
        CHR8
        CHR9
        CHR10
        CHR11
        CHR12
        CHR13
        CHR14
        CHR15
        CHR16
        CHR17
        CHR18
        CHR19
        CHR20
        CHR21
        CHR22
        CHR23
        CHR24
        CHR25
        CHR26
        CHR27
        CHR28
        CHR29
        CHR30
        CHR31
        CHR32
        CHR33
        CHR34
        CHR35
        CHR36

	endc

	
#define RS		PORTA,0		; line RS to LCD
#define E   	PORTA,2		; line E to LCD
#define RW  	PORTA,1		; line R/W to LCD
#define LED_BL1 PORTB,5     ; backlight led1
#define LED_BL2 PORTB,4     ; backlight led2
D4  		EQU	0			; line D4 to LCD
D5			EQU	1			; line D5 to LCD
D6			EQU	2			; line D6 to LCD
D7  		EQU	3			; line D7 to LCD
pushbutton  EQU 2			;


vectors		ORG 0x000
 			goto	 INIT
			nop
			nop
			nop
			goto 	INTERRUPT          


		ORG 0x005

; ***************************************************************************

INIT										; initialisation starts here	
		
    		movlw	OSCCON
			movwf	FSR
			movlw	b'11100111' 			; internal oscillator, 4 MHz
			movwf	INDF
			
			movlw	T1CON					; 
			movwf	FSR						; 
			movlw	b'00110000'				; timer 1 OFF, prescaler 1:8
			movwf	INDF					; 
		
			movlw	PORTB		
			movwf	FSR
			movlw 	b'00000000'				; 
			movwf	INDF

         	movlw	PORTC		
			movwf	FSR
			movlw 	b'01000000'				; RC6 = 1 (Tx)
			movwf	INDF

			movlw	T2CON					; Timer 2 off
			movwf	FSR						; 
			clrw
			movwf	INDF					; 	

    		movlw	OPTION_REG  			; bit7 zero ;  WPUB on
			movwf	FSR						; 
			movlw   b'01111111'
			movwf	INDF					; 			
	
        	movlw	WPUB					; portB2 WPU on
			movwf	FSR						; 
			movlw   b'00000100'
			movwf	INDF					; 	

	    	movlw	TRISA					; port A
			movwf	FSR						; all
			movlw	b'00000000'				; out-
			movwf	INDF					; puts 

			movlw	TRISB		
			movwf	FSR
			movlw 	b'00000100' 			; pb2 input
			movwf	INDF

			movlw	TRISC		
			movwf	FSR
			movlw 	b'11000000'				; pc0-5 output, PC6 input!! 
			movwf	INDF                    ; pc7 = input Rx
			
					
    		BCF STATUS,RP0 ;Bank 0
            BCF STATUS,RP1 ;
            CLRF PORTA ;Init PORTA
            BSF STATUS,RP0 ;Bank 1
            BCF STATUS,RP1 ;
            MOVLW 07h ;Set RA<2:0> to 
            MOVWF CMCON0 ;digital I/O
            CLRF ANSEL ;Make all PORTA I/O
            MOVLW b'11110000' ;Set RA<7:4> as inputs
            MOVWF TRISA ;and set RA<3:0>
                    ; as outputs
        

     		BANKSEL LCDCON
			clrw
			movwf	LCDCON

			BANKSEL WDTCON
			movlw	b'00010001'				;  enable WDT; 1:8192 ( 40 sec)
			movwf	WDTCON

     	    BCF STATUS,RP0 ;Bank 0
			BCF STATUS,RP1 ;
      

       
;***************
init_lcd
;***************
    bsf     LED_BL1        ; light backlight led1
    bsf     LED_BL2        ; light backlight led2
    movlw	.40            ; wait for 
	movwf	loops          ; LCD 
	call	WAIT           ; to startup


	movlw	B'00000011'
	movwf	command
	call	send_n_chk
	movlw	.2
	movwf	loops
	call	WAIT

	movlw	B'00000011'
	movwf	command
	call	send_n_chk
	call	delay_30us

	movlw	B'00000011'
	movwf	command
	call	send_n_chk
	call	delay_30us

	call	check_busy
	movlw	B'00000010'
	movwf	command
	call	send_n_chk				; function set
	call	delay_30us

	movlw	B'10010010'
	movwf	command
	call	send_command			; function set
	call	delay_30us
	

	movlw	B'11000001'
	movwf	command		        	; bias
	call	send_command
	call	delay_30us

	movlw	B'00100101'
	movwf	command			        ; power control
	call	send_command
	call	delay_30us

	movlw	B'10010110'
	movwf	command			        ; follower control
	call	send_command
	call	delay_30us

	movlw	B'11110111'             ; changed; was B'01000111'
	movwf	command			        ; contrast
	call	send_command
	call	delay_30us

	movlw	B'11000000'
	movwf	command			        ; display on
	call	send_command
	call	delay_30us

	movlw	B'00010000'
	movwf	command		        	; display clear, home
	call	send_command
	call	delay_30us

	movlw	B'01100000'
	movwf	command			        ; entry mode
	call	send_command
	call	delay_30us


; --------------------------------------------- 
; UART---SET BAUD RATE TO COMMUNICATE WITH ATAG 
; --------------------------------------------- 
; Boot Baud Rate = 9600, No Parity, 1 Stop Bit 
;       
        bsf   STATUS,RP0        ; Bank1
        movlw b'00011001'         ; 0x19=9600 bps  
        movwf SPBRG 
        movlw  b'00000100'       ; brgh = high (2) 
        movwf TXSTA             ; DISABLE Async Transmission, set brgh 

        bcf STATUS,RP0          ; RAM PAGE 0 

        movlw b'10010000'       ; enable Async Reception 
        movwf RCSTA 
; 	
; ------------------------------------ 
; PROVIDE A SETTLING TIME FOR START UP 
; ------------------------------------ 
; 
        clrf dataL 
settle  decfsz dataL,F 
        goto settle 

        movf RCREG,W 
        movf RCREG,W 
        movf RCREG,W            ; flush receive buffer 
  
        clrf   PIR1     

; set interrupts vor UART receiver     
	    movlw	PIE1					; 
  		movwf	FSR						; set
		movlw   b'00100000'             ; RCIE
		movwf	INDF					; 	
       
        bsf INTCON,PEIE
        bsf INTCON,GIE
        
    
        movLW   CHR1         ; init pointer; get address of string1
        movwf FSR               ; and put in FSR  

;**********************************************************************************	  
;*********************************************************************************
;MAIN PROGRAM
;*********************************************************************************

MAIN		

; 1 Mhz intern
; ea dogm 162 display
 
; PORTC:   D7-4 = PC3-0    
; steuerleitungen an  PORTA      


port_display	equ		PORTC
tris_display	equ		TRISC

;**********************************************************************************

show 
	
	movLw	'C'
	movwf	command
	call	send_data
	movLw	'O'
	movwf	command
	call	send_data
	movLw	'L'
	movwf	command
	call	send_data
	movLw	':'
	movwf	command
	call	send_data
	movfw	COL_1
	movwf	command
	call	send_data
	movfw	COL_MSD
	movwf	command
	call	send_data
	movfw	COL_LSD
	movwf	command
	call	send_data
	movLw	b'11011111'
	movwf	command
	call	send_data
	movLw	'C'
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	'P'
	movwf	command
	call	send_data
	movLw	'O'
	movwf	command
	call	send_data
	movLw	':'
	movwf	command
	call	send_data
	movfw	PMP_1
	movwf	command
	call	send_data
	movfw	PMP_2
	movwf	command
	call	send_data
	movfw	PMP_3
	movwf	command
	call	send_data

	movlw	B'00001100'
	movwf	command			; second line
	call	send_command
	call	delay_30us


	movLw	'B'
	movwf	command
	call	send_data
	movLw	'O'
	movwf	command
	call	send_data
	movLw	'I'
	movwf	command
	call	send_data
	movLw	':'
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
    movfw	BOI_MSD
	movwf	command
	call	send_data
	movfw	BOI_LSD
	movwf	command
	call	send_data
	movLw	b'11011111'  ; degree
	movwf	command
	call	send_data
	movLw	'C'
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	'U'
	movwf	command
	call	send_data
	movLw	'R'
	movwf	command
	call	send_data
	movLw	':'
	movwf	command
	call	send_data
	movfw	HRS_2
	movwf	command
	call	send_data
	movfw	HRS_3
	movwf	command
	call	send_data
	movfw	HRS_4
	movwf	command
	call	send_data
	movlw	B'00001000'
	movwf	command			; back to line 1
	call	send_command
	call	delay_30us
 
    bsf   PORTC,5           ; RC5 is connected to RC6 and will
    call  WAIT              ; be set to give pulse to switch-line
    bcf   PORTC,5
    call  WAIT
    call  WAIT
    call  WAIT
    call  WAIT

;*****************************************************
; Find out which infoline has been send and store info
;*****************************************************

test    btfss   EOS_FLAG,0      ; wait until string is complete
        goto    test
        movlw   CHR1         ; reset pointer
        movwf   FSR
        movf RCREG,W 
        movf RCREG,W 
        movf RCREG,W            ; flush receive buffer 
   

        movf    CHR1,w
        sublw   b'01000011'     ; C (dec67)
        btfss   STATUS,Z        ; is first chr a "C" 
        goto    next1           ; no
       ;; bsf     FLAG,2          ; set flag line2(=Col:.... Boi:....)
        movf    CHR5,w
        movwf   COL_1
        movf    CHR6,w
        movwf   COL_MSD
        movf    CHR7,w
        movwf   COL_LSD


        movf    CHR13,w
        movwf   BOI_1
        movf    CHR14,w
        movwf   BOI_MSD
        movf    CHR15,w
        movwf   BOI_LSD


next1   movf    CHR1,w
        sublw   b'01001100'     ; L (dec76)
        btfss   STATUS,Z        ; is first chr a "L" 
        goto    next2           ; no
      ;;  bsf     FLAG,1          ; set flag line1(=Luigjes Delta-T)
 

next2   movf    CHR14,w
        sublw   b'00100000'     ; <space> (dec32)
        btfss   STATUS,Z        ; is fourteenth chr a "space" 
        goto    next3           ; no
      ;;  bsf     FLAG,3          ; set flag line3(=PMP:UIT        )
     
        movf    CHR5,w
        movwf   PMP_1
        movf    CHR6,w
        movwf   PMP_2
        movf    CHR7,w
        movwf   PMP_3

        
next3   movf    CHR5,w
        sublw   b'01011001'     ; Y (dec89)
        btfss   STATUS,Z        ; is fifth chr a "Y" 
        goto    next4           ; no
      ;;  bsf     FLAG,4          ; set flag line4(=....YCOL....YBOI)


next4   movf    CHR12,w
        sublw   b'01010101'     ; U (dec85)
        btfss   STATUS,Z        ; is twelfth chr a "U" 
        goto    next5           ; no      
      ;;  bsf     FLAG,5          ; set flag line5(=PMP:......UREN )

        movf    CHR7,w
        movwf   HRS_1
        movf    CHR8,w
        movwf   HRS_2
        movf    CHR9,w
        movwf   HRS_3
        movf    CHR10,w
        movwf   HRS_4
       

next5   clrwdt                 ; reset watchdogtimer
        bcf      EOS_FLAG,0    ; reset flag
 
        btfsc  PORTB,2         ; test pushbutton
    	goto	show           ; not pushed...


; If pushbutton is pushed, incoming lines wil be displayed
; unchanged,  a new line every 2 seconds until watchdog ends this...
 
showline   movlw	B'00001000'     ; set display to  
	       movwf	command			; first line
	       call	send_command
	       call	delay_30us
    
    bsf   PORTC,5           ; RC5 is connected to RC6 and will
    call  WAIT              ; be set to give pulse to switch-line
    bcf   PORTC,5
   
	movfw	CHR1
	movwf	command
	call	send_data
	movfw	CHR2
	movwf	command
	call	send_data
	movfw	CHR3
	movwf	command
	call	send_data
	movfw	CHR4
	movwf	command
	call	send_data
	movfw	CHR5
	movwf	command
	call	send_data
    movfw	CHR6
	movwf	command
	call	send_data
	movfw	CHR7
	movwf	command
	call	send_data
	movfw	CHR8
	movwf	command
	call	send_data
	movfw	CHR9
	movwf	command
	call	send_data
	movfw	CHR10
	movwf	command
	call	send_data
	movfw	CHR11
	movwf	command
	call	send_data
	movfw	CHR12
	movwf	command
	call	send_data
	movfw	CHR13
	movwf	command
	call	send_data
	movfw	CHR14
	movwf	command
	call	send_data
	movfw	CHR15
	movwf	command
	call	send_data
	movfw	CHR16
	movwf	command
	call	send_data
	movlw	B'00001100'     ; set LCD to
	movwf	command			; line 2
	call	send_command
	call	delay_30us
 	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data

	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movLw	' '
	movwf	command
	call	send_data
	movlw	B'00001000'     ; LCD
	movwf	command			; back to line 1
	call	send_command
	call	delay_30us
   
    call  WAIT              ; delay
    call  WAIT              ; to 
    call  WAIT              ; show
    call  WAIT              ; new
    call  WAIT              ; infoline
    call  WAIT              ; every  
    call  WAIT              ; 2 
    call  WAIT              ; seconds
    call  WAIT
    call  WAIT
    call  WAIT
    call  WAIT
    call  WAIT
    call  WAIT
    call  WAIT

    btfss   PORTB,2         ; test pushbutton
    goto    show
    goto    showline


;-----------------------------------------------------------
; LCD Subroutine send_data
;***********************************************************
send_data
	call	check_busy

    rrf    command,1            ; bit 7-4
    rrf    command,1            ; have to be
    rrf    command,1            ; shifted to
    rrf    command,1            ; place 3-0


	movlw	0x0F                ; clear MS nibble
	andwf	command,0 
	movwf	port_display        ; and sent to display
 
	bsf		RS
	bcf		RW
	bsf		E
	nop                         ; important, this time is
	nop							; needed for the display to write register !!
	bcf		E

	rrf	command,1	            ; shift 5 times
	rrf	command,1               ; so result is again
	rrf	command,1               ; equal 
	rrf	command,1               ; to
    rrf command,1               ; original
	movlw	0x0F                ; clear MS nibble
	andwf	command,0 
	movwf	port_display        ; and sent to display

	bsf		RS
	bcf		RW
	bsf		E
	nop
	nop
	bcf		E

	retlw	.0
;-----------------------------------------------------------
;LCD Subroutine send_command
;**********************************************************
send_command
	call	check_busy

	movlw	0x0F
	andwf	command,0 
	movwf	port_display

	bcf		RS
	bcf		RW
	bsf		E
	nop
	nop
	bcf		E

	swapf	command,1

send_n_chk
	movlw	0x0F               ;  
	andwf	command,0 
	movwf	port_display

	bcf		RS
	bcf		RW
	bsf		E
	nop
	nop
	bcf		E

	retlw	.0
;-----------------------------------------------------------
; LCD Subroutine check_busy
;*********************************************************
check_busy
	bsf     STATUS,5
    movlw	0x0F
	movwf	tris_display
    bcf     STATUS,5
chk	
	bcf		RS
	bsf		RW
	bsf		E
	nop
	nop
	movf	port_display, w
	movwf	temp
	bcf		E 
	nop
	nop

	bsf		E
	nop
	nop
	bcf		E 

	btfsc	temp, 3
	goto	chk

    bsf     STATUS,5
	movlw	0x00
	movwf	tris_display
    bcf     STATUS,5
	retlw	.0
;**********************************************************
; LCD Wait-loop subroutines
; Warteschleife 1 ms für einen 4MHz-PIC-Takt
;**********************************************************
WAIT

Wai
        movlw   .110           ; Zeitkonstante für 1ms
        movwf   loops2
Wai2    nop                    ; 
        nop
        nop
        nop
        nop
        nop
        decfsz  loops2, F      ; 1 ms vorbei?
        goto    Wai2           ; nein, noch nicht
                               ;
        decfsz  loops, F       ; 250 ms vorbei?
        goto    Wai            ; nein, noch nicht
        retlw   .0             ; das Warten hat ein Ende 



delay_30us
    	movlw	.10
	    movwf	counter
del	    decfsz	counter,f			; 1 Befehl
	    goto	del					; 2 Befehle

	    retlw	.0


; End of LCD communication block


;*********************************************************************************
; UART

;*********************************************************************************
; 
; ------------------------------------------------------------ 
; INTERRUPT ROUTINE RECEIVE CHARACTER FROM UART AND STORE IN W 
; ------------------------------------------------------------
;  
; 
INTERRUPT   	movwf	W_TEMP      ; save
				swapf	STATUS,W    ; contence
				clrf	STATUS      ; of
				movwf	STATUS_TEMP	; STATUS and W
   
        clrf    STATUS
        movf    RCREG,W         ; move received data in W 
        movwf   temp_data       ; store received character

        clrf    PIR1            ; reset flag

        subLW   b'0001101'      ; is received character a CR ?
        btfsc   STATUS,Z        ;
        goto    base_data       ; yes, so go reset pointer
        goto    next            ; no, next character
next    movf    temp_data,w     ; get received character
        movwf   INDF            ; and store into RAM
        incf    counter2,1      ; set counter 1 higher
        incf    FSR,1           ; set pointer 1 higher for next chr
        movf    counter2,w      ; check if end of string 
        sublw   .16             ; when number of bytes is received, end of datastring
        btfsc   STATUS,Z        ; 
        bsf     EOS_FLAG,0      ; set flag End Of String
       
        movf     RCREG,W        ; flush receive buffer 
        goto     STOP

base_data   movLW   CHR1        ; get address of string1
            movwf FSR           ; and put in FSR  
            clrf   counter2     ; reset counter


STOP	SWAPF	STATUS_TEMP,W   ; restore
		MOVWF	STATUS          ; old contence
		SWAPF	W_TEMP,F        ; of STATUS and
		SWAPF	W_TEMP,W        ; W
		RETFIE					; Done 

;**********************************************************************************
   
        END 



;**********************************************************************************
;**********************************************************************************

