.include "tn861def.inc"
.DEF TEMP = R16
.DEF DUTYHI = R17
.DEF DUTYLO = R18
.DEF DUTY = R19
.DEF VOLT = R20
.DEF CURRENT = R21
.DEF TEMP2 = R24
.DEF TEMP3 = R25
.DEF TIME1 = R22
.DEF TIME2 = R23
.EQU CURRENT_LIMIT = 0x40 ;(0x41 = 400mA)
.EQU VOLTAGE_LIMIT = 0xDA ;(0xD5 = 4.176V)
.EQU CURRENT_END = 0x01 ;(0x07 = 42.89mA)
;(0x06 = 36.76mA)
;(0x05 = 30.64mA)
.EQU DUTY_HIGH_TIME= 0x50
.ORG 0x0000 rjmp RESET ; Reset Handler
;rjmp EXT_INT0 ; IRQ0 Handler
;rjmp PCINT ; PCINT Handler
;rjmp TIM1_COMPA ; Timer1 CompareA Handler
;rjmp TIM1_COMPB ; Timer1 CompareB Handler
;rjmp TIM1_OVF ; Timer1 Overflow Handler
;rjmp TIM0_OVF ; Timer0 Overflow Handler
;rjmp USI_START ; USI Start Handler
;rjmp USI_OVF ; USI Overflow Handler
;rjmp EE_RDY ; EEPROM Ready Handler
;rjmp ANA_COMP ; Analog Comparator Handler
;rjmp ADC ; ADC Conversion Handler
;.ORG 0x000C rjmp WDT ; WDT Interrupt Handler
;rjmp EXT_INT1 ; IRQ1 Handler
;rjmp TIM0_COMPA ; Timer0 CompareA Handler
;rjmp TIM0_COMPB ; Timer0 CompareB Handler
;rjmp TIM0_CAPT ; Timer0 Capture Event Handler
;rjmp TIM1_COMPD ; Timer1 CompareD Handler
;rjmp FAULT_PROTECTION ; Timer1 Fault Protection
RESET:
RCALL INIT
RCALL DELAY
START: RJMP CHG_CC
CHG_CC:
RCALL PWM ;START DUTY CYCLE PULSE (LOW %)
RCALL GET_CURRENT
CPI CURRENT,CURRENT_LIMIT;CHECK CURRENT FOR CURRENT LIMIT
BRLO UP1 ;IF LOWER, INCREASE CURRENT
BREQ CONTINUE1 ;IF AT LIMIT, DO NOTHING
BRSH DOWN1 ;IF TOO HIGH, DECREASE CURRENT
UP1: CPI DUTY,0xFF ;LIMIT MAX DUTY CYCLE TO FF (PREVENTS ROLL OVER)
BREQ ERROR ;NEW! IF DUTY CYCLE IS THIS HIGH, SOMETHING IS WEIRD
INC DUTY
RJMP CONTINUE1
DOWN1: DEC DUTY
RJMP CONTINUE1
CONTINUE1:
SBI PORTB,1
CBI PORTB,0 ;LIGHT UP LED RED FOR CC
RCALL GET_BATTVOLT
CPI VOLT,0x66 ;~2.0V
BRLO ERROR ;SOME IDIOT PUT A NON-LITHIUM BATTERY IN THE CHARGER!!
CPI VOLT,VOLTAGE_LIMIT;HAS BATTERY REACHED VOLTAGE LIMIT (~4.2v)
BRLO CHG_CC ;IF NO, STAY IN CONSTANT CURRENT STAGE
RJMP CHG_CV ;VOLTAGE LIMIT REACHED, GO TO CONTANT VOLTAGE
CHG_CV: SBI PORTB,0
CBI PORTB,1 ;LIGHT UP GREEN LED FOR CV
RCALL PWM
RCALL GET_BATTVOLT
CPI VOLT,VOLTAGE_LIMIT
BRSH VOLT_REG ;IF VOLTAGE TOO HIGH, DECREASE CURRENT A LITTLE
RJMP CHG_CV ;CONTINUE CHARGING IF VOLTAGE IS FINE
VOLT_REG:
DEC DUTY
RCALL GET_CURRENT
CPI CURRENT,CURRENT_END ;IF CURRENT IS LOWER THAN END CURRENT
BRLO CHG_DONE ;STOP CHARGING
RJMP CHG_CV ;OTHERWISE KEEP GOING
CHG_DONE:CBI PORTB,0
CBI PORTB,1 ;TURN OFF LED TO INDICATE DONE
CBI PORTB,6 ;TURN OFF MOSFET
SLEEP ;SLEEP (DRAWS ALMOST NO CURRENT)
RJMP CHG_DONE
ERROR:
CBI PORTB,6;TURN OFF MOSFET
SBI PORTB,0
CBI PORTB,1
RCALL DELAY
RCALL DELAY
RCALL DELAY
SBI PORTB,1
CBI PORTB,0
RCALL DELAY
RCALL DELAY
RCALL DELAY
RCALL GET_BATTVOLT
CPI VOLT,0x75
BRSH START
RJMP ERROR
;*******************************************************************
INIT:
LDI DUTY,0x01 ;START DUTY CYCLE LOW
SBI DDRB,0 ;MAKE LED PORTS AN OUTPUT
SBI DDRB,1
SBI DDRB,6 ;MAKE MOSFET OUTPUT
CBI PORTB,6 ;TURN MOSFET OFF
LDI TEMP,0x30
OUT ADMUX,TEMP
LDI TEMP,0x30 ;MAKE SLEEP=POWER DOWN
OUT MCUCR,TEMP
RET
GET_BATTVOLT: ;MAKES TWO READINGS TO MAKE SURE IT'S CORRECT
LDI TEMP,0x2D ;VCC AS REF, DIFFERENTIAL INPUT ON (PA5 +, ANND PA6 -)
OUT ADMUX,TEMP ;SET STUFF AGAIN
LDI TEMP,0x08 ;SET UP AS GAIN OF X1 AND THE MUX5 BIT FOR ABOVE
OUT ADCSRB,TEMP
LDI TEMP,0xC5
OUT ADCSRA,TEMP ;START A CONVERSION
CHK: SBIS ADCSRA,6 ;WAIT FOR END OF CONVERSION
RJMP CHKDONE
RJMP CHK
CHKDONE: ;DISCARD FIRST CONVERSION
LDI TEMP,0xC5
OUT ADCSRA,TEMP ;START A SECOND CONVERSION = NEEDED BECAUSE I CHANGED REFERENCES.
CHK4: SBIS ADCSRA,6 ;WAIT FOR END OF CONVERSION
RJMP CHKDONE4
RJMP CHK4
CHKDONE4:
IN VOLT,ADCH ;MOVE READING INTO BATT REG
RET
GET_CURRENT:
LDI TEMP3,0x0A
LDI TEMP,0x30
OUT ADMUX,TEMP ;SET UP DIFF ON PA6+ AND PA7- WITH GAIN OF 32X
LDI TEMP,0x48
OUT ADCSRB,TEMP ;SET UP GAIN OF 32X AND MUX5 OF ABOVE
LDI TEMP,0xC5
OUT ADCSRA,TEMP ;START A CONVERSION
CHK2: SBIS ADCSRA,6 ;WAIT FOR END OF CONVERSION
RJMP CHKDONE2
RJMP CHK2
CHKDONE2:
LDI TEMP,0xC5
OUT ADCSRA,TEMP ;START A SECOND CONVERSION
CHK3: SBIS ADCSRA,6 ;WAIT FOR END OF CONVERSION
RJMP CHKDONE3
RJMP CHK3
CHKDONE3:
; DEC TEMP3
; CPI TEMP3,0x01
; BRSH CHKDONE2 ;RUN 10 TIMES DANGIT! WHATS WRONG WITH THIS!?
;FINAL END
IN CURRENT,ADCH ;MOVE READING INTO BATT REG
RET
PWM:
LDI DUTYLO,0xFF
MOV DUTYHI,DUTY ;MOVE REQUESTED DUTY CYCLE INTO MEMORY FOR PWM HI
SUB DUTYLO,DUTYHI ;TAKE 255-REQUESTED DUTY CYCLE --> DUTYLO
LDI TEMP2,DUTY_HIGH_TIME;EX: 50% DUTY CYCLE = 127 255-127=128
;HIGH=127 LOW=128 --> TOTAL:255
PHIGH:
NOP ;GIVE MORE DUTY CYCLE HIGH
DEC TEMP2
CPI TEMP2,0x01
BRSH PHIGH
SBI PORTB,6
LDI TEMP2,DUTY_HIGH_TIME
DEC DUTYHI
CPI DUTYHI,0x00
BREQ PLOW
RJMP PHIGH
PLOW:CBI PORTB,6
DEC DUTYLO
CPI DUTYLO,0x00
BREQ PWMDONE
RJMP PLOW
PWMDONE:
RET
DELAY:
LDI TIME2,0xFF
LOOP2: LDI TIME1,0xFF
LOOP: DEC TIME1
CPI TIME1,0x00
BRNE LOOP
DEC TIME2
CPI TIME2,0x00
BRNE LOOP2
RET