
;	Lithium Ion Battery Charger
;	Charges (Raw) unprotected cells
;	12/05 Luhan Monat

;	device	pic12f675,intrc_osc,pwrte_on,mclre_on

#include <p12f675.inc>

;__config	_INTRC_OSC_NOCLKOUT & _PWRTE_ON & _MCLRE_ON & _WDT_OFF & _BODEN_OFF & _CP_OFF & _CPD_OFF

__config	0x01A4

	radix dec

	cblock	20h

flag:	1
temp:	1
ddata:	1
count:	1
htime:	1		;power on time
ltime:	1		;power off time
battv:	1		;battery volts
batta:	1		;battery amps
hi:	1
lo:	1
timer:	2
dfact:	3
digit:	1
dela:	1
	endc

#define BVOLT	GPIO,1		;battery top voltage
#define BAMP	GPIO,0		;battery current sense
#define LED	GPIO,4		;LED indicator
#define PWR	GPIO,5		;power control

#define SOUT	LED
#define BUG	GPIO,2

	org	0
	
	goto	start
	
	org	4
	
	retfie

	
start	bsf	STATUS,RP0
	movlw	000011b		;set gp io directions
	movwf	TRISIO
	movlw	127
	movwf	OSCCAL
	movlw	00010011b	;clk/8, ad0,1
	movwf	ANSEL
	bcf	STATUS,RP0
	movlw	7
	movwf	CMCON		;enable digital lines
	bsf	PWR		;power off
 	bsf	LED		;led off
 
	call	getvolt
	call	getvolt
	movlw	70
	call	delay
	call	clamp		;kill stray charge
	call	testb		;test for battery
	movlw	40
	call	delay
	call	charge
	goto	chend	

; loop time = 900ms
; 5 hrs = 20,000 loops

charge	movlw	high(20000)
	movwf	timer
	movlw	low(20000)
	movwf	timer+1

___2	call	getamp		;read charge current pulse
	movf	batta,w		;result?
	call	pwidth
	xorlw	0		;check for zero
	btfsc	STATUS,Z
	return			;done.
	call	setpwr
	call	ppulse
	call	ppulse
	call	ppulse
	call	ppulse
	call	ppulse
	call	chktim		;count down timer
	btfss	STATUS,Z		;done?
	goto	___2		;no.
	goto	toerr		;yes - timed out

; count down timer+1,/timer returnurn Z on done.

chktim	movf	timer
	btfsc	STATUS,Z
	decf	timer+1
	decf	timer
	movf	timer,w
	iorwf	timer+1,w
	return
	

testb	call	getvolt		;is battery present
	movf	battv,w		;get voltage
	addlw	10		;too high?
	btfsc	STATUS,C
	goto	hverr
	movf	battv,w
	addlw	240		;battery present?
	btfss	STATUS,C
	goto	nperr
	movf	battv,w
	addlw	160		;too low?
	btfss	STATUS,C
	goto	lverr
	return


; discharge stray voltage at battery clips

clamp	bcf	BVOLT		;line low
	bsf	STATUS,RP0
	bcf	BVOLT		;line is out
	bcf	ANSEL,1		;line is digital
	bcf	STATUS,RP0
	movlw	20		;clear any charge
	call	delay
	bsf	STATUS,RP0
	bsf	BVOLT		;line is input
	bsf	ANSEL,1		;line is analog
	bcf	STATUS,RP0
	return
	
	
chend	movlw	1
	goto	hold	
toerr	movlw	2
	goto	hold
nperr	movlw	3
	goto	hold
lverr	movlw	4
	goto	hold
hverr	movlw	5
	goto	hold


; turn off power and flash value in W

hold	bsf	PWR		;power off
	movwf	temp
_2	movf	temp,w
	movwf	count
_4	bcf	LED
	movlw	25
	call	delay
	bsf	LED
	movlw	50
	call	delay
	decfsz	count
	goto	_4
	movlw	70
	call	delay
	goto	_2


sign	movlw	10
	movwf	count
__2	bcf	LED		;led on
	movlw	20
	call	delay
	bsf	LED		;led off
	movlw	20
	call	delay
	decfsz	count
	goto	__2
	return
		

eval	call	getamp
	call	serout
	movlw	50
	call	delay
	goto	eval
		

test	bsf	LED
	call	ppulse
	bcf	LED
	movlw	20
	call	setpwr
	call	ppulse
	goto	test

; set power pulse delay values via 'w'

setpwr	movwf	htime		;high time
	sublw	0		;residual time
	movwf	ltime
	return


; generate power pulse

ppulse	movlw	250
	movwf	count		;set main loop count
_blip	movf	htime,w
	movwf	temp
	bcf	PWR		;engage power
	bcf	LED
_b2	decfsz	temp
	goto	_b2
	bsf	PWR		;end power pulse
	bsf	LED
	movf	ltime,w
	movwf	temp
_b4	decfsz	temp		;remaining time
	goto	_b4
	decfsz	count
	goto	_blip
	return


getvolt	bsf	PWR		;turn off charge
	call	volts
	movwf	battv		;save data
	return

getamp	bcf	PWR		;turn on charge
	call	amps
	movwf	batta		;save data
	bsf	PWR		;turn off charge
	return


; read battery voltage and current

amps	movlw	81h		;right just, chan=0, a/d on
	movwf	ADCON0
	nop			; need to settle?
	bsf	ADCON0,1	;start conversion
_wt	btfsc	ADCON0,1	;ready?
	goto	_wt		;no.
	bsf	STATUS,RP0
	movf	ADRESL,w	;read lower quadrant
	bcf	STATUS,RP0
	return

volts	movlw	05h		;left just, chan=1, a/d on
	movwf	ADCON0
	bsf	ADCON0,1	;start conversion
__wt	btfsc	ADCON0,1	;ready?
	goto	__wt		;no.
	movf	ADRESH,w
	return	
	

delay	movwf	dfact+2
_dz	movwf	dfact+1
_dy	movwf	dfact
_dx	decfsz	dfact
	goto	_dx
	decfsz	dfact+1
	goto	_dy
	decfsz	dfact+2
	goto	_dz
	return


	
serout	movwf	temp
	clrf	count
	bsf	count,3
	bcf	SOUT		;start bit
	nop
	nop
	nop
	nop
_s2	nop
	call	fbit
	rrf	temp
	btfss	STATUS,C
	bcf	SOUT
	btfsc	STATUS,C
	bsf	SOUT
	decfsz	count
	goto	_s2
	call	fbit
	bsf	SOUT		;stop bit
	call	fbit
	call	fbit
	return

; 9600 baud at 20mhz clock
	
fbit	movlw	136
	goto	fhbit
hbit	movlw	1	
fhbit	movwf	dela
_f2	decfsz	dela
	goto	_f2
	return

pwidth	clrf	PCLATH
	bsf	PCLATH,0	;100h
	movwf	temp
	rrf	temp
	rrf	temp
	movf	temp,w
	andlw	3fh		;devide by 4
	movwf	PCL

	org	100h

_0	dt	  0,  0,  0,255,255, 250,245,240
_40	dt	235,228,215,200,185, 170,155,140,125,110
_80	dt	107,103, 99, 95, 90,  85,  83, 81, 79, 77
_120 dt	 60, 40, 40, 40, 40,  40,  40, 40, 40, 40
	dt	 40, 40, 40, 40, 40,  40,  40, 40, 40, 40
	
	end
