;**********************************************************************
;   This file is a basic code template for assembly code generation   *
;   on the PIC16F685. This file contains the basic code               *
;   building blocks to build upon.                                    *  
;                                                                     *
;   Refer to the MPASM User's Guide for additional information on     *
;   features of the assembler (Document DS33014).                     *
;                                                                     *
;   Refer to the respective PIC data sheet for additional             *
;   information on the instruction set.                               *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:	    WIFi_charger_cntrl.asm                      *
;    Date: 2012/01/04                                                 *
;    File Version:3                                                   *
;    revision date 2/1/2013                                                                *
;    Author:zs2r                                                      *
;    Company:                                                         *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P16F685.INC                                      *
;                                                                     *
;**********************************************************************
; Notes:                                                              *
;          Pinout:-1,Vdd, +5V                                         *
;	        2,RA5, N/C				    *
;	        3,RA4, N/C				    *	
;                  4,RA3, serial programmer                           *
;                  5,RC5, load connect/disconnect                     *
;                  6,RC4, solar panel connect/disconnect              *
;                  7,RC3, V in scale to  load current		    *
;                  8,RC6, push button			    *
;                  9,RC7, push button			    *
;                  10,RB7, LCD data d3			    *
;                  11,RB6, LCD data d2			    *	
;                  12,RB5, LCD data d1			    *
;                  13,RB4, LCD data d0			    * 
;                  14,RC2, LCD enable			    * 
;	        15,RC1, LCD RS			    *
;	        16,RC0, V in scale to solar panel current value    *	
;	        17,RA2, V in scale to battery pd		    *	
;	        18,RA1, serial programmer clock		    *
;	        19,RA0, serial programmer data		    *
;	        20,Vss ground 			    *
;						    *
;						    *	
;**********************************************************************
;Configuration notes
;_FCMEN_ON                    EQU     H'3FFF' failsafe clock monitor on
;_FCMEN_OFF                   EQU     H'37FF' failsafe clock monitor off
;_IESO_ON                     EQU     H'3FFF' Internal/External Switchover bit (Two-Speed Startup mode enabled).on
;_IESO_OFF                    EQU     H'3BFF' Internal/External Switchover bit (Two-Speed Startup mode enabled).off
;_BOR_ON                      EQU     H'3FFF' Brown out reset on
;_BOR_NSLEEP                  EQU     H'3EFF'
;_BOR_SBODEN                  EQU     H'3DFF'
;_BOR_OFF                     EQU     H'3CFF' Brown out reset off
;_CPD_ON                      EQU     H'3F7F' code protection data on
;_CPD_OFF                     EQU     H'3FFF' code protection data off
;_CP_ON                       EQU     H'3FBF' code protection on
;_CP_OFF                      EQU     H'3FFF' code protection off
;_MCLRE_ON                    EQU     H'3FFF' master clear on pin on
;_MCLRE_OFF                   EQU     H'3FDF' MCLRE pin now input
;_PWRTE_OFF                   EQU     H'3FFF' power up timer off
;_PWRTE_ON                    EQU     H'3FEF' power up timer
;_WDT_ON                      EQU     H'3FFF' watchdog timer on
;_WDT_OFF                     EQU     H'3FF7' watchdog timer off
;_LP_OSC                      EQU     H'3FF8' low freq osc.+/- 32kHz low gain amp
;_XT_OSC                      EQU     H'3FF9' medium gain resonators
;_HS_OSC                      EQU     H'3FFA' high speed oscillator
;_EC_OSC                      EQU     H'3FFB' external clock
;_INTRC_OSC_NOCLKOUT          EQU     H'3FFC'
;_INTRC_OSC_CLKOUT            EQU     H'3FFD'
;_EXTRC_OSC_NOCLKOUT          EQU     H'3FFE'
;_EXTRC_OSC_CLKOUT            EQU     H'3FFF'
;_INTOSCIO                    EQU     H'3FFC' internal osc
;_INTOSC                      EQU     H'3FFD' internal osc
;_EXTRCIO                     EQU     H'3FFE' external RC with IO on osc2/clockout
;_EXTRC                       EQU     H'3FFF' external RC
;
;*******************************************************************************************************************************

	list		p=16f685		; list directive to define processor
	#include	<P16F685.inc>		; processor specific variable definitions
	
	__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF


; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.






;***** VARIABLE DEFINITIONS
w_temp		EQU	0x7D			; variable used for context saving
status_temp	EQU	0x7E			; variable used for context saving
pclath_temp	EQU	0x7F			; variable used for context saving

inside		equ	     H'0020'       ;general delay
insidev		equ	     H'0021'       ;general delay
middle		equ	     H'0022'       ;general delay
middlev		equ	     H'0023'       ;general delay
outside		equ	     H'0024'       ;general delay
outsidev		equ	     H'0025'       ;general delay
time		equ	     H'0026'       ;general delay
timeo		equ	     H'0027'       ;general delay
timev		equ	     H'0028'       ;general delay 
atod		equ	     H'0029'       ;A to D result 		
flags		equ	     H'0030'
battV		equ	     H'0031'
currentS		equ	     H'0032'       ;current from solar panel		
V_tens		equ	     H'0033'       ;battV in decimal	
V_units		equ	     H'0034'
V_tenths		equ	     H'0035'
I_units		equ	     H'0036'       ;I in decimal
I_tenths		equ	     H'0037'
I_hths		equ	     H'0038'
temp1		equ	     H'0039'     
offset		equ	     H'0040'       ;displaycount
dispadd		equ	     H'0041'
datafile		equ	     H'0042'
counter		equ	     H'0043'       ;setup 
counter1		equ	     H'0044'
currentL		equ	     H'0045'       ;current to load			



#define		charge_flag	flags,0
#define		load_flag		flags,1
#define		iflag		flags,2
#define		writeflag		flags,3

#define		dispe		PORTC,2
#define		regselect		PORTC,1
;**********************************************************************
	ORG		0x000		; processor reset vector
  	goto		initialise		; go to beginning of program


	ORG		0x004		; interrupt vector location
	movwf		w_temp		; save off current W register contents
	movf		STATUS,w		; move status register into W register
	movwf		status_temp	; save off contents of STATUS register
	movf		PCLATH,w		; move pclath register into W register
	movwf		pclath_temp	; save off contents of PCLATH register


; isr code can go here or be located as a call subroutine elsewhere

	movf		pclath_temp,w	; retrieve copy of PCLATH register
	movwf		PCLATH		; restore pre-isr PCLATH register contents	
	movf		status_temp,w	; retrieve copy of STATUS register
	movwf		STATUS		; restore pre-isr STATUS register contents
	swapf		w_temp,f
	swapf		w_temp,w		; restore pre-isr W register contents
	retfie				; return from interrupt






initialise
              ;setup          set/clear all neccessary special function bits
  
          banksel       TRISA
          movlw         b'00111111'   
          movwf         TRISA                 ;ra0(19), ra1(18),ra3(4) inputs,reserved for programing,ra2(17)is analogue input
          movlw         b'00000000'
          movwf         TRISB                 ;rb output data to LCD        
          movlw         b'11001001'
          movwf         TRISC                 ;rc0,3,6 & rc7 inputs others output.
          clrf          INTCON                 ; global interrupts disabled
          movlw         b'10000000'
          movwf         OPTION_REG             ;porta&b pull ups disabled

          banksel       ANSEL
          movlw         b'00010100'
          movwf         ANSEL                 ;ra2(17), rc0(16) now set for analogue input
          clrf          ANSELH 
          banksel       counter
; use 4MHz internal clock i.e. default setting
	banksel		OSCCON
	movlw		b'01100001'
	movwf		OSCCON
	banksel		counter  		;back to bank 0

	clrf	flags

	
;Initialise the LCD display and put it in 4 bit data transfer mode.pin read/write wired low    
	movlw	.3
	movwf	counter
	bcf	regselect	 
	;bcf	readnotw	 
	bcf	dispe
	bsf	writeflag
displaysetup
	
	call	delay15ms
	movlw	b'00110000'	;8bit mode
	movwf	datafile
	call	writeinstr
	decfsz	counter,f
	goto	displaysetup	;send 8 bit command at least 3 times
	movlw	b'00100000'	;This instruction puts it in 4 bit mode
	movwf	datafile
	call	writeinstr
	bcf	writeflag
	movlw	b'00101000'	;select 2 lines 5x7 dots
	movwf	datafile
	call	writeinstr
	bcf	writeflag
	call	cleardisp  	;now display is in 4 bit mode, 2 lines and 5x7 
	movlw	b'00001100'	;characters display on, cursor & blink off
	movwf	datafile
	call	writeinstr
	bcf	writeflag
	movlw	b'00000110'	;incr.cursor automatically although invisible
	movwf	datafile
	call	writeinstr
	bcf	writeflag
	clrf	dispadd
	call	setadd
                                  ;display is now ready and character memory set
                                  ;to first character on line 1


main	



	call 		find_V
	call		set_flags
	btfsc		charge_flag
	call		charger_on
	btfss		charge_flag
	call		charger_off
	btfsc		load_flag
	call		load_on
	btfss		load_flag
	call		load_off
	btfss                 PORTC,6
	call		send_log
	btfss		PORTC,7
	call		set_display	;will alternate display current charging/load 
	call		show 		;battery volts on top line,charging/load current bottom line.
	goto		main

;##############################################################################################################	
;find V for battery and current
find_V
           ;set a/d converter
	;hardware set to put 1/4 of battery pd (voltage) on pin17, RA2, so have 0 -20V voltmeter
	
           banksel         ADCON1
           movlw           b'00010000'              ;a/d conversion clock = clock /8
           movwf           ADCON1
           banksel         ADCON0
           movlw           b'00001011'              ;left justify,Vdd as ref V,an2 (ra2) as input,  a/d turned on
           movwf           ADCON0
           call            delayd1s                 ;acquisition  time .1s arbitary but sure to be long enough R source < 10k
           bsf             ADCON0,GO                ;start conversion
           btfsc           ADCON0,GO                ;is conversion done?
           goto            $-1                      ;no!  test again
           banksel         ADRESH                   ;ADRESH is in bank0
           movf            ADRESH,w
           movwf           battV                    ;will only use 8 most sig bits, ignore ADRESL

;V for current from solar panel

           ;hardware set to put 0 - 5V on pin16, RC0, to represent a current of 0 - 5 amperes.

           banksel         ADCON1
           movlw           b'00010000'              ;a/d conversion clock = clock /8
           movwf           ADCON1
           banksel         ADCON0
           movlw           b'00010011'              ;left justify,Vdd as ref V,an4 (rc0) as input,  a/d turned on
           movwf           ADCON0
           call            delayd1s                 ;acquisition  time .1s arbitary but sure to be long enough R source < 10k
           bsf             ADCON0,GO                ;start conversion
           btfsc           ADCON0,GO                ;is conversion done?
           goto            $-1                      ;no!  test again
           banksel         ADRESH                   ;ADRESH is in bank0
           movf            ADRESH,w
           movwf           currentS                  ;will only use 8 most sig bits, ignore ADRESL

	      


;V for current to load
	;hardware set to put 0 - 5V on pin16, RC3, to represent a current of 0 - 5 amperes.

           banksel         ADCON1
           movlw           b'00010000'              ;a/d conversion clock = clock /8
           movwf           ADCON1
           banksel         ADCON0
           movlw           b'00011111'              ;left justify,Vdd as ref V,an7 (rc3) as input,  a/d turned on
           movwf           ADCON0
           call            delayd1s                 ;acquisition  time .1s arbitary but sure to be long enough R source < 10k
           bsf             ADCON0,GO                ;start conversion
           btfsc           ADCON0,GO                ;is conversion done?
           goto            $-1                      ;no!  test again
           banksel         ADRESH                   ;ADRESH is in bank0
           movf            ADRESH,w
           movwf           currentL                  ;will only use 8 most sig bits, ignore ADRESL

	      
	return


delayd1s			;4MHz clock
         movlw       .7
         movwf       outside
         movlw       .14
         movwf       middle
         movlw       .254
         movwf       inside
         call        delay
         return
;##########################################################################################################


set_flags
	

	movlw	.135
	subwf	battV,0
	btfss	STATUS,C			;is battV < 13.5V
	bsf	charge_flag		;yes 
	btfss	STATUS,C			;no, check again
	goto	$+5			;yes to load check 
	movlw	.140
	subwf	battV,0
	btfsc	STATUS,C			;is battV > = 14V
	bcf	charge_flag		;yes
	nop				;no


	movlw	.120
	subwf	battV,0
	btfsc	STATUS,C			;is battV >= 12,0V
	bsf	load_flag			;yes
	btfsc	STATUS,C			;no
	goto	$+5
	movlw	.110
	subwf	battV,0
	btfss	STATUS,C			;is battV < 11,0V
	bcf	load_flag			;yes
	nop				;no

	return

;##########################################################################################################
;will alternate the state of the iflag each this routine is called
set_display

	btfsc	iflag
	goto	ciflag
	bsf	iflag
	return
ciflag
	bcf	iflag
	return

;##########################################################################################################


charger_on
	btfsc	PORTC,4
	return
	bsf	PORTC,4
	return

;############################################################################################################


charger_off
	btfss	PORTC,4
	return
	bcf	PORTC,4
	return

;###########################################################################################################


load_on
	btfsc	PORTC,5
	return
	bsf	PORTC,5
	return
	
;############################################################################################################3

load_off
	btfss	PORTC,5
	return
	bcf	PORTC,5
	return	

;############################################################################################################
; For voltmeter display 0 to 25.5 volts. A to D file (battV) 0 to 255 so each increment of 1 is 0.1V on display.
; For the ammeter display 0 to 5.1 amps. A to D file (current) 0 to 255 so each increment of 1 is 0.02A on display

show
; modify battV to get 3 digits V_tens,V_units and V_tenths
	clrf	V_tens
	clrf	V_units
	clrf	V_tenths
	movf	battV,w


tens	movwf	temp1
	bcf	STATUS,C
	movlw   	.100
         	subwf	temp1,0
	btfsc	STATUS,C		;a/d value <100?
	incf       V_tens,f		;no
           btfsc      STATUS,C		;yes
           goto	tens		;no
         	movf	temp1,w		;yes


units	movwf	temp1	
	bcf	STATUS,C
	movlw	.10
	subwf	temp1,0		
	btfsc	STATUS,C		;a/d value <10?
	incf	V_units,f		;no
	btfsc	STATUS,C		;yes
	goto	units		;no
	movf	temp1,w		;yes

tenths	movwf	temp1
	bcf	STATUS,C
	movlw	.1
	subwf	temp1,0	
	btfsc	STATUS,C		;a/d value < 1?
	incf	V_tenths,f		;no
	btfsc	STATUS,C		;yes
	goto	tenths		;no
	movf	temp1,w		;yes

;now batt_V in 3 digits V_tens,V_units and V_tenths max 25.5V
	clrf	dispadd
	call	setadd

	movf	V_tens,w
	call	displaynumber
	movf	V_units,w
	call	displaynumber
	movlw	'.'
	movwf	datafile
 	call	writedata
	bcf	writeflag
	movf	V_tenths,w
	call	displaynumber

	movlw      'V'
	movwf	datafile	
 	call	writedata
	bcf	writeflag

	
;modify current to give 3 digits 0 to 5.10A in increments of .02A file 0 to 255


	

	clrf	I_units
	clrf	I_tenths
	clrf	I_hths
	btfsc	iflag
	goto	$+3
	movf       currentS,w
	goto	$+2
	movf	currentL,w
;subwf
;subtracts W register from register ‘f’. If ‘d’ is  
;‘0’, the result is stored in the W
;register. If ‘d’ is ‘1’, the result is
;stored back in register ‘f’.
;C = 0 W > f
;C = 1 W = f


I_u	movwf	temp1
	bcf	STATUS,C
	movlw	.50
	subwf	temp1,0
	btfsc	STATUS,C		;battV>=50 ? (ie 1.00A) , 
	incf	I_units,f		;yes  C= 1 if battV >=50
	btfsc	STATUS,C		;no   C = 0 if battV<50
	goto	I_u
	movf	temp1,w

I_t	movwf	temp1	
	bcf	STATUS,C
	movlw	.5
	subwf	temp1,0
	btfsc	STATUS,C		;>10
	incf	I_tenths,f		;yes
	btfsc	STATUS,C		;no
	goto	I_t
	movf	temp1,w

I_h	movwf	temp1
	bcf	STATUS,C
	movlw	.1
	subwf	temp1,0
	btfsc	STATUS,C
	incf	I_hths,f
	btfsc	STATUS,C
	goto	I_h
 	rlf	I_hths,f		; now in increments of .02


	movlw	.40		;now on line 2 of display
	movwf	dispadd
	call	setadd

	movf	I_units,w
	call	displaynumber
	movlw	'.'
	movwf	datafile
 	call	writedata
	bcf	writeflag
	movf	I_tenths,w
	call	displaynumber	
	movf	I_hths,w
	call	displaynumber
	movlw      'A'
	movwf	datafile
 	call	writedata
	bcf	writeflag
	movlw      ' '
	movwf	datafile
 	call	writedata
	bcf	writeflag
	movlw      ' '
	movwf	datafile
 	call	writedata
	bcf	writeflag
	btfsc	iflag
	goto 	write_s
	movlw      'S'
	movwf	datafile
 	call	writedata
	bcf	writeflag
           return
write_s
	movlw      'L'
	movwf	datafile
 	call	writedata
	bcf	writeflag
	return
;####################################################################################################

displaynumber	
		movwf	offset		;move the value from w to 'offset' (w normally contains 
		incf	offset,f   	;the digit value as loaded in above)
		movlw	low display	;for use in the look-up table to convert                 
		addwf	offset,f	           ;from binary to ASCII.   This method used allow
		movlw	high display	;crossing of memory page
		btfsc	STATUS,C
		addlw	.1
		movwf	PCLATH
		movf	offset,w
		call	display		;call the look up table
		movwf	datafile
		call	writedata		;write ASCII to the display. Remember display
		bcf	writeflag		;automatically steps to next character as set up

		return
;###################################################################################################
;sets the lcd character address to the value in dispadd	
setadd				
	movf	dispadd,w
	movwf	datafile
	bsf 	datafile,7
	call	writeinstr
	bcf 	writeflag
	return


		

;##############################################################################
;get ascii code for numbers
;ASCII look up table for numbers	
display	
	movwf	PCL
	retlw	b'00110000'
	retlw	b'00110001'
	retlw	b'00110010'
	retlw	b'00110011'
	retlw	b'00110100'
	retlw	b'00110101'
	retlw	b'00110110'
	retlw	b'00110111'
	retlw	b'00111000'
	retlw	b'00111001'
	retlw	'.'
	retlw	' '
	retlw	'?'
	retlw	'?'
	retlw	'?'


writedata			;to the LCD

	bsf	regselect
	;bcf	readnotw
	bsf	dispe
	movf	datafile,w
	movwf	PORTB
	nop
	nop
	nop
	nop
	bcf	dispe	
	call	delay15ms     ;this delay is a little longer than in the original(2,2,12)
	btfsc	writeflag
	return
	swapf	datafile,f
	bsf	writeflag
	goto	writedata
	

writeinstr			;instruction to the LCD
	bcf	regselect
	;bcf	readnotw
	bsf	dispe
	movf	datafile,w
	movwf	PORTB
	nop
	nop
	nop
	nop
	bcf	dispe	
	call	delay15ms      ;see note under write data
	btfsc	writeflag
	return
	swapf	datafile,f
	bsf	writeflag
	goto	writeinstr

;#########################################################################################################
;name says it all
cleardisp
	movlw	b'00000001'	;clear display
	movwf	datafile
	call	writeinstr
	bcf	writeflag
	call	delay15ms
	return	
;###############################################################################################################
delay1s
	 movlw       .14
         movwf       outside
         movlw       .17
         movwf       middle
         movlw       .247
         movwf       inside
         call        delay
         return

	
;#############################################################################################################

;General purpose delay routine. Pass to it parameters inside, middle and 
;outside to alter the delay
delay
	movf	outside,w
	movwf	outsidev
outsideloop
	movf	middle,w
	movwf	middlev
middleloop
	movf	inside,w
	movwf	insidev
insideloop
	clrwdt
	decfsz	insidev,f
	goto	insideloop
	decfsz	middlev,f
	goto	middleloop
	decfsz	outsidev,f
	goto	outsideloop
	return
;##############################################################################################################

delay15ms
			;4MHz clock
         movlw       .3
         movwf       outside
         movlw       .6
         movwf       middle
         movlw       .207
         movwf       inside
         call        delay
         return


;##############################################################################################################3


send_log

	nop
	return
;##############################################################################################################


	ORG	0x2100				; data EEPROM location
	DE	1,2,3,4				; define first four EEPROM locations as 1, 2, 3, and 4




	END                       ; directive 'end of program'

