; ------ uP POWER CONTROLLER WITH AUTO MODE ------ ; ------ Processor AT89C2051 24PC ------ ;#DEFINE DEBUG ;Debugger on/off ;#DEFINE ASYNCEN ;enables out pin in asynchronous mode ;#DEFINE UNLIMOUT ;unlimited out pulse length (else 4 MS) #INCLUDE "LIBREG.ASM" ;8051 SFR set #INCLUDE "LIBMAC.ASM" ;macros set CLK_KHZ = 12000 ;OSC frequency, KHZ RTC_MS = 22 ;initial mains pulse wait time, MS #INCLUDE "LIBRTC.ASM" ;calculate RTCV INTV .EQU RTCV ;INTV <- RTCV RTC_MS = 4 ;indication scan rate, MS #INCLUDE "LIBRTC.ASM" ;calculate RTCV #IFDEF DEBUG #INCLUDE "LIBDEF.ASM" #ENDIF ; ------ Constantes ------ STACK .EQU 056H ;stack location MAXPOW .EQU 100 ;max. power level K .EQU 3 ;auto regulation loop gain KEYDB .EQU 5 ;key debounce delay (x10mS) KEYDA .EQU 70 ;key autorepeat delay (x10mS) KEYARR .EQU 10 ;autorepeat rate (x10mS) KEYFARR .EQU 10 ;fast autorepeat rate (x10mS) AUDEL .EQU 150 ;auto off delay (x10mS) ARCOUNT .EQU 10 ;autorepeat count to change rate ; ------ Debugger variables ------ #IFDEF DEBUG DBGVA .EQU STACK-1 ;debugger variable address in internal memory DBGVV .EQU STACK ;debugger variable value in internal memory DBGA .EQU 0FFH ;debugger address in external memory #ENDIF ; ------ Ports ------ SEG_A .EQU P1.0 ;indicators segment A SEG_B .EQU P1.1 ;indicators segment B SEG_C .EQU P1.2 ;indicators segment C SEG_D .EQU P1.3 ;indicators segment D SEG_E .EQU P1.4 ;indicators segment E SEG_F .EQU P1.5 ;indicators segment F SEG_G .EQU P1.6 ;indicators segment G SEG_H .EQU P1.7 ;indicators segment H (1XX) SCAN0 .EQU TXD ;display scan line 1 SCAN1 .EQU RXD ;display scan line 2 RETL .EQU P3.7 ;keyboard return line SYNC .EQU INT0 ;mains pulses PWM .EQU INT1 ;PWM out REF .EQU T0 ;ref. PWM out COMP .EQU T1 ;comparator out ; ------ Variables ------ ; Bit addressing memory PRESS .EQU M_20H.0 ;keyboard press bit AUTO .EQU M_20H.1 ;auto mode REG_F .EQU M_20H.2 ;regulation fail SIGN .EQU 021H ;mains sign PHASE .EQU 022H ;PWM phase POWER .EQU 023H ;power level PWOUT .EQU 024H ;output power level PWLOW .EQU 025H ;output power level low byte DELTA .EQU 026H ;PWM routine internal variable DEOUT .EQU 027H ;PWM routine internal variable KEYDBT .EQU 028H ;key debounce timer KEYTM .EQU 029H ;key timer COD .EQU 02AH ;key code PREV .EQU 02BH ;previous key code REPCNT .EQU 02CH ;repeat counter FLT .EQU 02DH ;digital filter data CNTR .EQU 02EH ;program counter CNTR.0 .EQU M_2EH.0 ;20mS CNTR.1 .EQU M_2EH.1 ;40mS CNTR.2 .EQU M_2EH.2 ;80mS CNTR.3 .EQU M_2EH.3 ;160mS CNTR.4 .EQU M_2EH.4 ;360mS CNTR.5 .EQU M_2EH.5 ;640mS CNTR.6 .EQU M_2EH.6 ;1.28S CNTR.7 .EQU M_2EH.7 ;2.56S ; ------ Vectors Area ------ .ORG 0000H ;reset vector ; ------ Main Program ------ MOV SP,#STACK ;stack init #IFDEF DEBUG DEBUGINIT ;debug init #ENDIF CLR PRESS ;clear keyboard press bit CLR AUTO CLR REG_F MOV DPTR,#FONT CLR A MOV COD,A MOV PREV,A MOV SIGN,A MOV FLT,A MOV CNTR,A MOV POWER,A MOV PWOUT,A MOV PWLOW,A MOV PHASE,#MAXPOW MOV DELTA,#-(MAXPOW/2) MOV DEOUT,#-(MAXPOW/2) CLR TR0 CLR TR1 CLR TF0 MOV TMOD,#11H ;timer 0 and timer 1 init MOV TH0,#HI(INTV) ;indication timer load MOV TL0,#LO(INTV) SETB TR0 ;timer start ;======== Comparator out check ======== MAIN: #IFDEF ASYNCEN JB TF0,PWM0 ;jump if no mains pulses #ELSE JB TF0,PWM3 ;jump if no mains pulses #ENDIF MOV C,SYNC ;SYNC pulse check RLC A XRL A,SIGN JNB ACC.0,MAIN ;loop if same mains sign XRL SIGN,#0FFH ;change sign ;======== PWM out control ======== PWM0: MOV A,PWOUT ADD A,DEOUT MOV DEOUT,A MOV C,ACC.7 MOV PWM,C JC PWM1 SUBB A,#MAXPOW MOV DEOUT,A PWM1: MOV A,POWER ADD A,DELTA MOV DELTA,A MOV C,ACC.7 CPL C MOV REF,C JNC PWM2 SUBB A,#MAXPOW MOV DELTA,A PWM2: CLR TR0 MOV TH0,#HI(RTCV) ;indication timer load MOV TL0,#LO(RTCV) CLR TF0 SETB TR0 ;timer start DJNZ PHASE,PWM3 MOV PHASE,#MAXPOW MOV DELTA,#-(MAXPOW/2) MOV DEOUT,#-(MAXPOW/2) LCALL UPDATE ;update PWOUT ;======== Indicate 1s ======== PWM3: MOV R0,COD MOV A,POWER ;indicate POWER... CJNE R0,#4,PM3 MOV A,PWOUT ;or PWOUT PM3: MOV B,#10 DIV AB ;A=10s, B=1s MOV A,B MOVC A,@A+DPTR MOV C,CNTR.5 ;load blink bit ORL C,/REG_F ;check for regulation fail ANL C,AUTO CPL C MOV ACC.7,C ;led AUTO on/off ACALL IND SETB SCAN1 CLR SCAN0 ;indicate 1s ;======== Control functions processing ======== MOV R0,COD MOV A,R0 JZ W1 CJNE R0,#2,NDN ACALL DO_DN ;DOWN pressed NDN: CJNE R0,#1,NUP ACALL DO_UP ;UP pressed NUP: CJNE R0,#3,NUD ACALL DO_UD ;UP+DOWN pressed NUD: CJNE R0,#5,NAP ACALL DO_AP ;AUTO+UP pressed NAP: CJNE R0,#6,NAN ACALL DO_AN ;AUTO+DOWN pressed NAN: SETB PRESS W1: JNB TF0,$ ;======== PWM out off ======== CLR TR0 MOV TH0,#HI(RTCV) ;indication timer load MOV TL0,#LO(RTCV) CLR TF0 SETB TR0 ;timer start #IFNDEF UNLIMOUT SETB PWM ;PWM out off #ENDIF ;======== Comparator out digital filtering ======== MOV C,COMP ;C <- COMP (input 1-bit data) CLR A ;convert 1-bit to 8-bit signed RLC A RL A DEC A ADD A,FLT ;FLT = FLT + A MOV FLT,A ;FLT - output of filter tap ;======== Indicate 10s ======== IND10: MOV R0,COD MOV A,POWER ;indicate POWER... CJNE R0,#4,PM4 MOV A,PWOUT ;or PWOUT PM4: MOV B,#10 DIV AB ;A=10s, B=1s JNZ NZ MOV A,#0DH ;blank code NZ: MOVC A,@A+DPTR ACALL IND SETB SCAN0 CLR SCAN1 ;indicate 10s ;======== Program timer check ======== INC CNTR MOV A,KEYTM JZ W2 DEC KEYTM ;advance key timer W2: JNB TF0,$ ;======== Indication off ======== CLR TR0 MOV TH0,#HI(RTCV) ;indication timer load MOV TL0,#LO(RTCV) CLR TF0 SETB TR0 ;timer start SETB SCAN0 SETB SCAN1 ;indication off ;======== Keyboard check ======== MOV P1,#11111110B ;P1.0 = 0 MOV C,RETL ;return line check RLC A ;A << P1.0 MOV P1,#11111101B ;P1.1 = 0 MOV C,RETL ;return line check RLC A ;A << P1.1 MOV P1,#11111011B ;P1.2 = 0 MOV C,RETL ;return line check RLC A ;A << P1.2 CPL A ANL A,#7 ;ACC.2 - UP, ACC.1 - DN, ACC.0 - AUTO JZ NP ;jump if no press MOV R0,A XRL A,PREV JNZ ND ;jump if codes are differ MOV A,KEYDBT ;the same code, debounce timer check JZ DOV DEC KEYDBT SJMP NR ;jump if debounce delay is not over DOV: MOV COD,R0 ;COD load SJMP NS ND: MOV PREV,R0 NP: MOV KEYDBT,#KEYDB ;debounce timer load NR: CLR PRESS MOV COD,#0 ;load unused code NS: AJMP MAIN ;main loop ; ------ Subroutines Area ------ ;AUTO+UP key processing: DO_AP: JB PRESS,AP_RET ;jump if key hold SETB AUTO ;auto on AP_RET: RET ;AUTO+DOWN key processing: DO_AN: JB PRESS,AN_RET ;jump if key hold MOV PWOUT,POWER ;auto off, copy PWOUT <- POWER CLR AUTO AN_RET: RET ;UP key processing: DO_UP: JB PRESS,UPH ;jump if key hold MOV KEYTM,#KEYDA ;first press, autorepeat delay load MOV REPCNT,#0 ;autorepeat counter clear SJMP UP_DO UPH: MOV A,KEYTM ;KEYTM check JNZ UP_RET CLR C MOV KEYTM,#KEYARR ;load normal repeat rate MOV A,REPCNT SUBB A,#ARCOUNT ;REPCNT check JC UP_DO ;jump if REPCNT < ARCOUNT MOV KEYTM,#KEYFARR ;load fast repeat rate UP_DO: MOV A,POWER XRL A,#MAXPOW JZ UP_RET ;jump if limit INC POWER ;power inc. MOV PWOUT,POWER ;initial out power: copy PWOUT <- POWER INC REPCNT ;autorepeat counter inc. UP_RET: RET ;DOWN key processing: DO_DN: JB PRESS,DNH ;jump if key hold MOV KEYTM,#KEYDA ;first press, autorepeat delay load MOV REPCNT,#0 ;autorepeat counter clear SJMP DN_DO DNH: MOV A,KEYTM ;KEYTM check JNZ DN_RET CLR C MOV KEYTM,#KEYARR ;load normal repeat rate MOV A,REPCNT SUBB A,#ARCOUNT ;REPCNT check JC DN_DO ;jump if REPCNT < ARCOUNT MOV KEYTM,#KEYFARR ;load fast repeat rate DN_DO: MOV A,POWER JZ DN_RET ;jump if limit DEC POWER ;power dec. MOV PWOUT,POWER ;initial out power: copy PWOUT <- POWER INC REPCNT ;autorepeat counter inc. DN_RET: RET ;UP+DOWN key processing: DO_UD: JB PRESS,UD_RET ;no hold mode MOV A,POWER JZ DO_MAX MOV POWER,#0 ;load MIN power MOV PWOUT,#0 SJMP UD_RET DO_MAX: MOV POWER,#MAXPOW ;load MAX power MOV PWOUT,#MAXPOW UD_RET: RET ;Update power ;Input: DELH,DELL, bit AUTO ;Out: DELH,DELL=0, PWOUT,PWLOW UPDATE: CLR REG_F ;regulation fail clear MOV A,POWER JZ DON JNB AUTO,DON ;manual mode, PWOUT=POWER MOV A,FLT RLC A MOV F0,C ;save signum JNC POS ;jump if > 0 MOV A,FLT CPL A INC A POS: MOV B,#K ;A = ABS(FLT), B = K MUL AB JB F0,MIN ADD A,PWLOW ;PWOUT,PWLOW + A x B MOV PWLOW,A MOV A,PWOUT ADDC A,B JC PL1 CJNE A,#MAXPOW,PL2 PL2: JC DON PL1: MOV A,#MAXPOW MOV PWLOW,#0 SETB REG_F ;regulation fail (limit) SJMP DON MIN: CLR C ;PWOUT,PWLOW - A x B XCH A,PWLOW SUBB A,PWLOW MOV PWLOW,A MOV A,PWOUT SUBB A,B JNC DON CLR A MOV PWLOW,#0 DON: MOV PWOUT,A ;update PWOUT MOV FLT,#0 ;new filter cycle RET ;Segments on/off ;Input: A - segments copy, ACC.0 - A, ACC.1 - B, ... IND: RRC A MOV SEG_A,C RRC A MOV SEG_B,C RRC A MOV SEG_C,C RRC A MOV SEG_D,C RRC A MOV SEG_E,C RRC A MOV SEG_F,C RRC A MOV SEG_G,C RRC A MOV SEG_H,C RET ;Font table ; SGFEDCBA FONT .DB 11000000B ;code 00H, character 0 .DB 11111001B ;code 01H, character 1 .DB 10100100B ;code 02H, character 2 .DB 10110000B ;code 03H, character 3 .DB 10011001B ;code 04H, character 4 .DB 10010010B ;code 05H, character 5 .DB 10000010B ;code 06H, character 6 .DB 11111000B ;code 07H, character 7 .DB 10000000B ;code 08H, character 8 .DB 10010000B ;code 09H, character 9 .DB 01000000B ;code 0AH, character 10 .DB 01111001B ;code 0BH, character 11 .DB 00100100B ;code 0CH, character 12 .DB 11111111B ;code 0DH, character blank #IFDEF DEBUG #INCLUDE "LIBDBG.ASM" #ENDIF .END