$include (8051.mcu)

;  ------ uP POWER CONTROLLER ------
;  ------ 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)


RTCV          EQU NOT(4000-1)  ; (NOT((CLK_KHZ*4)/12) AND 0FFFFh)
INTV          EQU NOT(22000-1)  ; (NOT((CLK_KHZ*22)/12) AND 0FFFFh)


;  ------ Constantes ------

STACK	EQU 056H		;stack location
POW100	EQU 99		;max. power mode 1
POW10	EQU 10		;max. power mode 2
KEYDB	EQU 5		;key debounce delay    (x10mS)
KEYDA	EQU 70		;key autorepeat delay  (x10mS)
KEYARR	EQU 15		;autorepeat rate       (x10mS)
KEYFARR	EQU 7		;fast autorepeat rate  (x10mS)
ARCOUNT	EQU 10		;autorepeat to fast autorepeat count

;  ------ Debugger variables ------


;  ------ Ports ------

SEG_A	EQU P1.2		;indicators segment A
SEG_B	EQU P1.3		;indicators segment B
SEG_C	EQU P1.4		;indicators segment C
SEG_D	EQU P1.5		;indicators segment D
SEG_E	EQU P1.6		;indicators segment E
SEG_F	EQU P1.7		;indicators segment F
SEG_G	EQU P3.7		;indicators segment G
SEG_H	EQU T1		;indicators segment H (1XX)

SCAN0	EQU TXD		;display scan line 1
SCAN1	EQU RXD		;display scan line 2
JUMPER	EQU SEG_H	;jumper

KEY_UP	EQU T0		;UP   key
KEY_DN	EQU INT1		;DOWN key

PWM	EQU INT0		;PWM out

;  ------ Variables ------

;  Bit addressing memory

PRESS	EQU 20h.0	;keyboard press bit
SIGN	EQU 021H		;mains sign
PHASE	EQU 022H		;PWM phase
POWER	EQU 023H		;power level
DELTA	EQU 024H		;PWM_100 internal variable
KEYDBT	EQU 025H		;key debounce timer
KEYTM	EQU 026H		;key timer
PREV	EQU 027H		;previous key code
MAXPOW	EQU 028H		;max. power value
REPCNT	EQU 029H		;repeat counter

;  ------ Vectors Area ------

	ORG 0000H	;reset vector

;  ------ Main Program ------

	MOV SP,#STACK	;stack init
	MOV MAXPOW,#POW100
	JB JUMPER,M100
	MOV MAXPOW,#POW10
M100:     CLR PRESS		;clear keyboard press bit
	CLR A
	MOV PREV,A
	MOV SIGN,A
	MOV POWER,A
	MOV DPTR, #FONT

	MOV A,MAXPOW
	MOV PHASE,A
	CLR C
	RRC A
	CPL A
	INC A
	MOV DELTA,A

	CLR TR0
	CLR TR1
	CLR TF0
	MOV TMOD,#11H    	;timer 0 and timer 1 init
	MOV TH0,#HIGH(INTV)	;indication timer load
	MOV TL0,#LOW(INTV)
	SETB TR0		;timer start

;======== Comparator out check ========

MAIN:
;#IFDEF ASYNCEN
;	JB TF0,PWM0	;jump if no mains pulses
;#ELSE
	JB TF0,PWM2	;jump if no mains pulses
;#ENDIF
	MOV A,P3		;comparator out check
	XRL A,SIGN
	JNB ACC.6,MAIN	;loop if same mains sign

	XRL SIGN,#0FFH	;change sign

;======== PWM out control ========

PWM0:	MOV A,POWER
	ADD A,DELTA
	MOV DELTA,A
	MOV C,ACC.7
	
  cpl c
	MOV PWM,C
	cpl c
	
	JC PWM1
	SUBB A,MAXPOW
	MOV DELTA,A
PWM1:     DJNZ PHASE,PWM2
	MOV A,MAXPOW
	MOV PHASE,A
	CLR C
	RRC A
	CPL A
	INC A
	MOV DELTA,A

;======== Indicate 1s ========

PWM2:     CLR TR0
	MOV TH0,#HIGH(RTCV)	;indication timer load
	MOV TL0,#LOW(RTCV)
	CLR  TF0
	SETB TR0		;timer start
	MOV A,POWER
	MOV B,#10
	DIV AB		;A=10s, B=1s
	MOV A,B
	MOVC A,@A+DPTR
	ACALL IND
	SETB SCAN1
	CLR  SCAN0	;indicate 1s

;======== Keyboard check ========

	MOV C,KEY_UP	;keyboard check
	ANL C,KEY_DN
	JC  NP		;jump if no press
	MOV A,#0FFH
	MOV C,KEY_UP
	RLC A
	MOV C,KEY_DN
	RLC A
	CPL A		;ACC.1 - UP, ACC.0 - DN
	MOV R0,A
	XRL A,PREV
	JNZ ND
	MOV A,KEYDBT
	JZ DOV
	DEC KEYDBT
	SJMP W1		;jump if debounce delay is not over
DOV:	CJNE R0,#1,NDN
	ACALL DO_DN	;DOWN pressed
NDN:	CJNE R0,#2,NUP
	ACALL DO_UP	;UP pressed
NUP:	CJNE R0,#3,NUD
	ACALL DO_UD	;UP+DOWN pressed
NUD:	SETB PRESS
	SJMP W1
ND:	MOV PREV,R0
NP:	CLR PRESS
	MOV KEYDBT,#KEYDB	;debounce timer load
W1:	JNB  TF0,$

;======== PWM out off ========

;#IFNDEF UNLIMOUT
;	SETB PWM		;PWM out off
;#ENDIF

;======== Indicate 10s ========

	CLR TR0
	MOV TH0, #HIGH(RTCV)	;indication timer load
	MOV TL0,#LOW(RTCV)
	CLR  TF0
	SETB TR0		;timer start
	MOV A,POWER
	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 ========

	MOV A,KEYTM
	JZ W2
	DEC KEYTM		;advance key timer
W2:	JNB  TF0,$

;======== Indication off ========

	CLR TR0
	MOV TH0,#HIGH(RTCV)	;indication timer load
	MOV TL0,#LOW(RTCV)
	CLR  TF0
	SETB TR0		;timer start
	SETB SCAN0
	SETB SCAN1	;indication off
	AJMP MAIN		;main loop

;  ------ Subroutines Area ------

;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.
	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.
	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
	SJMP UD_RET
DO_MAX:	MOV POWER,MAXPOW	;load MAX power
UD_RET:   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

	END






