$NOMOD51
$include (C8051F930.inc)      
 
HUMI_NOM		EQU 63		; calibration values: humidity
TEMP_NOM		EQU 22		; calibration value:  temperature (C)
N_NOM			EQU 0x12A6		; calibration value:  oscillator period 
		
PMU0CF_Snapshot 	EQU R5
Period_low		EQU LOW(1000)	; settings for 35 msec timeout  
Period_high		EQU HIGH(1000)	 
Period_dark_low	EQU 0xFE		; setting for the light check period
Period_dark_high	EQU 0xFF						
Light_TH		EQU 0x10		; ambient light intensity threschold
T_0			EQU TEMP_NOM*4

	DSEG 	AT 0x20			; data segment in direct addressable space
Status:	DS 1				; status bits for circular buffer
Counter:	DS 1				; counter for the # of measurements
DB_counter:	DS 1				; calibration counter
AUX:		DS 1				; auxilary temporary bit-addressable storage

	ORG	0x30
bufTemp: 	DS 16				; circular buffer for temperature (8x 2-byte entries)
tempAve_lo:	DS 1				; storage for temperature average sum
tempAve_hi:	DS 1
temp_lo:	DS 1				; temp value 
temp_hi:	DS 1
LCD_cnt:	DS 1				; counter for LCD cycles

	ORG 	0x50
bufHumi:	DS 16				; curcular buffer for humidity
humiAve_lo: DS 1				; storage for humidity average sum
humiAve_hi: DS 1
humi_lo:	DS 1
humi_hi:	DS 1

	CSEG 	AT 0				; interrupt vectors
	ljmp 	Main  			; reset

	ORG	0x2B				; Timer2 ISR
	anl	TMR2CN, #0x3F		; clear Timer2 interrupt flags
	reti

	ORG	0xB3				; code section right after the int. vectors
	USING    0                    ; specify register bank 

main:       
	anl   PCA0MD, #NOT(0x40)      ; disable the WDT
	mov	SP, #0x79			; setup stack in indirect storage area

	acall	Ports_Setup
	acall	Clock_Setup
	acall	Debug_Trap			; debug trap !!!

	acall	RTC_Setup			; initialize oscillators
	acall	DCDC_Setup			
	acall	ADC_Setup			; initialize hardware
	acall	Comparator_Setup

	mov	Counter, #1			; initialize conversion counter
	mov	DB_counter, #0
	mov	Status,  #3			; request circ buffers initialization
	mov	AUX, #0
	mov	LCD_cnt, #1
	sjmp	measure

loop: 					; MAIN LOOP
	mov	PMU0CF, #(SLEEP OR RTCAWK) ; set wakeup sources
	nop   				; device is now awake
  	nop
	nop
	nop
	mov 	PMU0CF, #CLEAR
			
	mov	A, #0xE0			; toggle LCD pins
	xrl	P0, A
	mov	A, #0xFF
	xrl	P1, A
	mov	A, #0x7F
	xrl	P2, A

measure:
	djnz	LCD_cnt, loop		; time to perform measurement?
	mov	LCD_cnt, #60		; YES - restore counter
	acall	getTempHumi			; update temp & Humi values on display
;	sjmp	loop				; uncomment this line if no light sensor present

	mov	A, Counter			
	cjne	A, #0, loop			; time to check light? 
	acall getLight			; YES - is light ON ?		
	jnc	loop				; YES - continue the main loop

	mov	P0, #0x13			; NO - display off
	mov	P1, #0x00
	mov	P2, #0x00
	mov	R6, #Period_dark_low	; reassign RTC clock to 2 sek
	mov	R7, #Period_dark_high	; wake-up time
	acall	ALARM_Setup

wait4light:					; and check for light periodically
	acall	LPM				; sleep till the next light test
	acall	getLight			; is it dark yet ?
	jc	wait4light			; YES - keep waiting

	mov	Status,  #3			; NO - request circ buffers initialization
	mov	LCD_cnt, #1			; make immediate measurement
	mov	R6, #Period_low		; reassign RTC clock to its regular
	mov	R7, #Period_high		; wake-up time
	acall	ALARM_Setup
	sjmp	measure			; back to the main loop

;-------------------PROCEDURES-------------------------------------------
Ports_Setup:
	mov  	P0MDIN,    #0xEC		; analog input on P0.0, P0.1, P0.4	
	mov  	P0MDOUT,   #0xEC		; push-pull out on P0.2, P0.3, P0[7:5]
	mov  	P1MDIN,    #0xFF		; digital I/O on P1
    	mov  	P1MDOUT,   #0xFF		; digital input on P1.7
	mov  	P2MDIN,    #0xFF		; digital I/O on P2
    	mov  	P2MDOUT,   #0x7F		; digital input on P2
	mov  	P0SKIP,    #0xFF		; I/O function on P0
    	mov  	P1SKIP,    #0xFF		; I/O function on P1
    	mov  	P2SKIP,    #0xFF		; I/O function on P2
    	mov   XBR2,      #0x40		; enable XBar and weak pull-ups
	mov	P0, 	     #0x13
	mov	P1,        #0x60		
	mov	P2,        #0x00		; initialize port pins	
	ret

;-----------------------------------------------------------------------
Clock_Setup:
	mov	RTC0KEY, #0xA5		; unlock RTC interface
	mov	RTC0KEY, #0xF1
	mov	RTC0ADR, #(0x10 OR RTC0PIN)	
	mov	RTC0DAT, #0xE7		; self oscillate mode
	nop
	mov	RTC0ADR, #(0x10 OR RTC0XCN)	
	mov	RTC0DAT, #0x00		; disable double bias
	nop
	mov	RTC0ADR, #(0x10 OR RTC0XCF)	
	mov	RTC0DAT, #0x80		; set 4 pF load capacitor
	nop

   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; enable SmaRTClock
	mov	RTC0DAT, #(RTC0EN OR RTC0TR)  

	mov 	RSTSRC,  #0x00		; disable MCD and VDD monitor
	mov	OSCICN,  #0x0F		; disable internal precision oscillator
	mov	OSCXCN,  #0			; disable external oscillator
	mov	REG0CN,  #0			; disable precision oscillator bias
	mov	CLKSEL,  #0x14
	anl	FLSCL,   #NOT(BYPASS)	; set the one-shot bypass bit
	mov	FLWR,	   #0x01		; write dummy value
	mov	A, CLKSEL			; wait for the divider setting to be applied
	anl	A, #0x80		
	jz	$-4	

	mov	CLKSEL,  #0x03		; select SmaRTClock with 1:1 clock divider
	mov	CKCON,   #0x12		; set Timer2 system clock
	ret

;-----------------------------------------------------------------------
Debug_Trap:
	mov	R2, #0xFF
	mov	A,  #0xFF

del_loop:					; nested loops for approx. 10 sec delay
	dec	A
	nop
	nop
	jnz	$-3

	mov	A, R2
	dec	A
	mov	R2, A
	jnz	del_loop	

	mov	CLKSEL, #0x04		; select LPO with 1:1 clock divider
	orl	FLSCL,  #BYPASS		; set the one-shot bypass bit
	mov	FLWR,	  #0x01		; write dummy value
	mov	A, CLKSEL			; wait for the divider setting to be applied
	anl	A, #0x80		
	jz	$-4

	mov 	PMU0CF, #CLEAR
	ret

;-----------------------------------------------------------------------
RTC_Setup:
	mov 	RTC0ADR, #(0x10 + CAPTURE0)	; clear RTC timer
	mov 	RTC0DAT, #0				; autoincrement address
	nop						; feature does not work!
	mov 	RTC0ADR, #(0x10 + CAPTURE1)
	mov 	RTC0DAT, #0
	nop
	mov 	RTC0ADR, #(0x10 + CAPTURE2)
	mov 	RTC0DAT, #0
	nop
	mov 	RTC0ADR, #(0x10 + CAPTURE3)
	mov 	RTC0DAT, #0
	nop
	mov	RTC0ADR, #RTC0CN		; set timer value
	mov	RTC0DAT, #(RTC0EN OR RTC0SET) 
	nop
	mov 	RTC0ADR, #(0x90 OR RTC0CN)
	nop
	nop
	nop
	mov 	A, RTC0DAT			
	anl	A, #RTC0SET			; verify that timer is set
	jnz	$-10

   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; enable SmaRTClock
	mov	RTC0DAT, #(RTC0EN OR RTC0TR)  

	mov	R6, #Period_low
	mov	R7, #Period_high
ALARM_Setup:
   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; disable alarm while
   	mov	RTC0DAT, #(RTC0EN AND NOT(RTC0AEN)) ; updating the regs      
   	nop
	mov 	RTC0ADR, #(0x10 OR ALARM0)	; load alarm regs       
	mov   RTC0DAT, R6
	nop
	mov 	RTC0ADR, #(0x10 OR ALARM1)
	mov	RTC0DAT, R7
	nop
	mov 	RTC0ADR, #(0x10 OR ALARM2)
	mov	RTC0DAT, #0 
	nop
	mov 	RTC0ADR, #(0x10 OR ALARM3)
	mov	RTC0DAT, #0
	nop
   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; enable SmaRTClock
	mov	RTC0DAT, #(RTC0EN OR RTC0TR OR RTC0AEN OR ALRM)  
	ret

;-----------------------------------------------------------------------
DCDC_Setup:
	mov	DC0CN, #0xE5		; set 2.7 V output
	mov	DC0CF, #0x63		; float in sleep, LPO as clock source
	ret

;-----------------------------------------------------------------------
ADC_Setup:
   	mov	ADC0CN, #0			; ADC0 disabled, Burst Mode disabled 
	mov 	ADC0CF, #0x11 		; SAR clock = 6.6MHz, gain = 1
   	mov	ADC0AC, #0              ; right-justify results
	ret

;-----------------------------------------------------------------------
Comparator_Setup:
	mov  	CPT0CN, #0x80		; enable comparator
	clr	A
	djnz	ACC, $			; short delay
   	anl  	CPT0CN, #0xCF		; clear comparator flags
    	mov  	CPT0MX, #0x0C		; capacitive touch sense mode
    	mov  	CPT0MD, #0x83		; power mode 3
	anl	CPT0CN, #0x7F		; disable comparator
	ret

;-----------------------------------------------------------------------
getLight:
	mov	ADC0MX, #0x00		; select P0.0 as ADC input
	mov	REF0CN, #0x18           ; enable high-speed ref
	mov	ADC0CN, #0x80		; enable ADC

	mov	A, #40			; 10 usec delay		
	dec	A				; 1 cycle
	nop					; 1 cycle
	nop					; 1 cycle
	jnz	$-3				; 2 cycles

	orl	ADC0CN, #0x10		; start conversion
	nop
	nop	
	mov	A, ADC0CN			; poll BUSY flag
	anl	A, #0x10
	jnz	$-5    	

	mov	ADC0CN, #0			; turn off ADC
	mov	REF0CN, #0			; turn off reference

	clr	C
	mov	A, ADC0L			; get conversion result
	subb	A, #Light_TH
	mov	A, ADC0H
	subb	A, #0
	ret

;-----------------------------------------------------------------------
getTempHumi:
	inc	Counter
	jnb	Counter.0, getTemp
	ajmp	getHUMI

getTemp:
	setb	P0.3				; turn sensor on
	mov	R6, #0x20			; use RTC clock to perform a
	mov	R7, #0x00			; 1 msec delay, which is needed
	acall	ALARM_Setup			; for sensor to set up
	acall	LPM   			; enter sleep mode until next alarm
	nop
	mov	R6, #Period_low		; reassign RTC clock to its regular
	mov	R7, #Period_high		; wake-up time
	acall	ALARM_Setup

	mov	ADC0MX, #4			; select P0.4 as ADC input
	mov	REF0CN, #0x18           ; enable high-speed ref
	mov	ADC0CN, #0x80		; enable ADC

	mov	A, #40			; 10 usec delay		
	dec	A				; 1 cycle
	nop					; 1 cycle
	nop					; 1 cycle
	jnz	$-3				; 2 cycles

	orl	ADC0CN, #0x10		; start conversion
	nop
	nop	
	mov	A, ADC0CN			; poll BUSY flag
	anl	A, #0x10
	jnz	$-5    	

	mov	ADC0CN, #0			; turn off ADC
	mov	REF0CN, #0			; turn off reference
	clr	P0.3				; turn off sensor
	mov	R2, ADC0L			; save ADC values in registers
	mov	R3, ADC0H
		
	jnb	Status.0, average_TEMP	; init circ buffer ?
	clr	Status.0			; YES
	mov	R0, #bufTemp		; initialize buffer pointer		
	mov	bufTemp+0, R2		; fill the buffer with
	mov	bufTemp+2, R2		; temp reading (lower byte)
	mov	bufTemp+4, R2
	mov	bufTemp+6, R2
	mov	bufTemp+8, R2
	mov	bufTemp+10, R2
	mov	bufTemp+12, R2
	mov	bufTemp+14, R2
	
	mov	bufTemp+1, R3		; fill the buffer with 
	mov	bufTemp+3, R3		; temp reading (upper byte)
	mov	bufTemp+5, R3
	mov	bufTemp+7, R3
	mov	bufTemp+9, R3
	mov	bufTemp+11, R3
	mov	bufTemp+13, R3
	mov	bufTemp+15, R3	
	
	mov	A, R2
	mov	B, #8				; compose the average sum by
	mul	AB				; multilpying current temp by 8
	mov	tempAve_lo, A
	mov	tempAve_hi, B
	mov	B, #8
	mov	A, ADC0H
	mul	AB
	add	A, tempAve_hi
	mov	tempAve_hi, A
	ajmp	process_TEMP

average_TEMP:
	mov	A, tempAve_lo		; subtract the oldest temp value
	clr	C				; in circular buffer from the 
	subb	A, @R0			; average temp sum
	mov	tempAve_lo, A
	inc	R0				; advance pointer to higher-order byte
	mov	A, tempAve_hi
	subb	A, @R0
	mov	tempAve_hi, A
	
	dec	R0
	mov	@R0, ADC0L			; save new temp in circular buffer
	inc	R0				; update circ buffer pointer
	mov	@R0, ADC0H
	inc	R0
	cjne	R0, #0x40, $+5		; jump over the next instruction
	 mov	R0, #0x30			; take pointer R0 mod 16

	mov	A, tempAve_lo		; update average temp sum
	add	A, ADC0L
	mov	tempAve_lo, A
	mov	A, tempAve_hi
	addc	A, ADC0H
	mov	tempAve_hi, A		; at this point C = 0

	mov	A, tempAve_lo		; average temp sum (div. by 8)	
	rlc	A				; for that we multiply it by 2 
	swap	A				; and swap the nibbles
	anl	A, #0x0F
	mov	R2, A				; R2 contains the lower nibble
	mov	A, tempAve_hi
	rlc	A				; C is not modified since the
	swap	A				; last add
	mov	B, A
	anl	A, #0xF0
	add	A, R2
	mov	R2, A
	mov	A, B				
	anl	A, #0x0F
      	jnb   	ACC.3, at1
      	orl   	A, #0xF0
at1:	mov	R3, A

process_TEMP:
	mov	A, R2				; compute R5:R4 = R3:R2 / 32
	swap	A				; first shift R3:R2 4 bits to the right
	anl	A, #0x0F			; by swapping the nibbles
	mov	R4, A
	mov	A, R3
	swap	A
	mov	R5, A
	anl	A, #0xF0
	add	A, R4
	mov	R4, A
	mov	A, R5
	anl	A, #0x0F
      	jnb   	ACC.3, at2
      	orl   	A, #0xF0
	
at2:	mov	C, ACC.7
	rrc	A
	mov	R5, A
	mov	A, R4
	rrc	A
	mov	R4, A				; R5:R4 = R3:R2 / 32 (unsigned)

	add	A, R2
	mov	R2, A
	mov	A, R5
	addc	A, R3
	mov	R3, A				; R3:R2 = 264*ADC_temp / 256

	clr	C
	mov	A, R2
	subb	A, #LOW(269)
	mov	R2, A
	mov	temp_lo, A
	mov	A, R3
	subb	A, #HIGH(269)
	mov	R3, A
	mov	temp_hi, A

	mov	C, ACC.7			; divide R3:R2 by 4 (signed) 
	rrc	A
	mov	R3, A
	mov	A, R2
	rrc	A
	mov	R2, A
	mov	A, R3
	mov	C, ACC.7
	rrc	A
	mov	R3, A
	mov	A, R2
	rrc	A				
	mov	R2, A				; R3:R2 = ADC_temp * 264 / 1024 - 67.84

	mov	A, R3				; check computed data range	
	jnb	ACC.7, pte4			; if R3:R2 < 0, then
	mov	A, R2				; 2-complement negative temp
	cpl	A
	inc	A				; A = |temp|
	cjne	A, #10, pte1	
	sjmp	pte2
pte1:	jc	pte3
pte2:	mov	A, #0x10			; too low temp - display "--"
pte3:	mov	B, A				; digit 2 or "-" sign
	mov	P1, #0x60			; display the degree symbol
	mov	A, #0x10			; display the "-" sign
	ajmp	dn2

pte4:	clr	C				; if R3:R2 > 99, set R2=99 
	mov	A, R2
	subb	A, #100
	mov	A, R3
	subb	A, #0
	jc	display_TEMP
	mov	R2, #99			
	
display_TEMP:				; display value in R2
	mov	A, R2
	mov	P1, #0x60			; display the degree symbol
	ajmp	display_Number

;-----------------------------------------------------------------------
getHumi:
	mov  	CPT0CN, #0x80		; enable comparator
	mov	A, #10			; 2 usec delay		
	djnz	ACC, $			; 4 cycles

	anl	FLSCL,  #NOT(BYPASS)	; enable flash one-shot bypass mode
	mov	FLWR,	  #0x01		; write dummy value
	mov	TMR2CN, #0x16		; enable capture of comparator events
	mov	IE,	  #0xA0		; enable Timer2 interrupt
	mov	PCON,   #0x01		; enter idle mode
	mov	humi_lo, TMR2RLL		; get first comparator capture
	mov	humi_hi, TMR2RLH
	mov	PCON,	  #0x01		; wait for the comparator period end
	mov	IE,	  #0x00		; disable interrupts
	orl	FLSCL,  #BYPASS		; disable flash one-shot bypass mode
	mov	FLWR,	  #0x01		; write dummy value	
	mov	TMR2CN, #0x00		; disable Timer2
	anl	CPT0CN, #0x7F		; disable comparator	 

	clr	C
	mov	A, TMR2RLL			; compute the time stamp difference
	subb	A, humi_lo			; and take its absolute value
	mov	R2, A
	mov	A, TMR2RLH
	subb	A, humi_hi
	mov	R3, A
	jnb	ACC.7, abs
	setb 	C				; compute the absolute value
	mov	A, R2
	addc	A, #0xFF
	mov	R2, A
	mov	A, R3
	addc	A, #0xFF
	mov	R3, A

abs:	
	jnb	Status.1, average_HUMI	; init circ buffer ?
	clr	Status.1			; YES
	mov	R1, #bufHumi		; initialize buffer pointer
	mov	bufHumi, R2			; fill the buffer with the
	mov	bufHumi+2, R2		; humi reading (lower byte)
	mov	bufHumi+4, R2
	mov	bufHumi+6, R2
	mov	bufHumi+8, R2
	mov	bufHumi+10, R2
	mov	bufHumi+12, R2
	mov	bufHumi+14, R2

	mov	bufHumi+1, R3		; fill the buffer with the
	mov	bufHumi+3, R3		; humi reading (higher byte)
	mov	bufHumi+5, R3
	mov	bufHumi+7, R3
	mov	bufHumi+9, R3
	mov	bufHumi+11, R3
	mov	bufHumi+13, R3
	mov	bufHumi+15, R3

	mov	A, R2
	mov	B, #8				; compute the average sum by
	mul	AB				; multilpying R3:R2 by 8
	mov	humiAve_lo, A		; value in R3:R2 remains unchanged
	mov	humiAve_hi, B
	mov	B, #8
	mov	A, R3
	mul	AB
	add	A, humiAve_hi
	mov	humiAve_hi, A
	ajmp	process_HUMI

average_HUMI:
	mov	A, humiAve_lo		; subtract the oldest humi value
	clr	C				; in circular buffer from the 
	subb	A, @R1			; average humi sum
	mov	humiAve_lo, A
	inc	R1				; advance pointer to the higher-order byte
	mov	A, humiAve_hi
	subb	A, @R1
	mov	humiAve_hi, A
	
	dec	R1
	mov	@R1, 2			; save new humi in circular buffer
	inc	R1				; update circ buffer pointer
	mov	@R1, 3			; 2 is direct acces to R2 address, 3 is for R3
	inc	R1
	cjne	R1, #0x60, $+5		; jump over the next instruction
	 mov	R1, #0x50			; take pointer R0 mod 16

	mov	A, humiAve_lo		; update average temp sum
	add	A, R2
	mov	humiAve_lo, A
	mov	A, humiAve_hi
	addc	A, R3
	mov	humiAve_hi, A		; at this point C = 0

	mov	A, humiAve_lo		; average humi sum (div. by 8)	
	rlc	A				; for that we multiply it by 2 
	swap	A				; and swap the nibbles
	anl	A, #0x0F
	mov	R2, A				; R2 contains the lower nibble
	mov	A, humiAve_hi
	rlc	A				; C is not modified since the
	swap	A				; last add
	mov	B, A
	anl	A, #0xF0
	orl	A, R2
	mov	R2, A
	mov	A, B				
	anl	A, #0x0F
	mov	ACC.4, C
	mov	R3, A				; R3:R2 is averaged oscillator period N

process_HUMI:
;	ajmp	calibrate_HUMI		; uncomment this libe for calibration
	clr	C
	mov	A, R2				; subtract N_NOM (16-bit operation)
	subb	A, #LOW(N_NOM)
	mov	R2, A
	mov	A, R3
	subb	A, #HIGH(N_NOM)
	mov	R3, A

	mov	A, R2				; compute (N - N_NOM)*65
	mov	B, #65			; result is at most 16 bits	
	mul	AB
	mov	R2, B
	mov	A, R3
	mov	B, #65
	mul	AB
	add	A, R2				
	mov	R2, A
	mov	A, B				; A:R2 = humi*65 unsigned
	mov	AUX, R3
	jnb 	AUX.7, $+5			; examine the sign bit
	add	A, #-65			; A:R2 = humi*32 signed
	mov	R3, A				; R3:R2 (N - N_NOM) * 65/ 256

	clr	C
	mov	A, temp_lo			; thermo compensation
	subb	A, #LOW(T_0)
	mov	temp_lo, A
	mov	A, temp_hi
	subb	A, #HIGH(T_0)
	mov	AUX, A			; AUX:temp_lo = (T - T_NOM)*4

	mov	A, temp_lo			; compute temp*34 = (T - T_NOM)*136
	mov	B, #34			; result is at most 16 bits	
	mul	AB
	mov	temp_lo, B
	mov	A, AUX
	mov	B, #34
	mul	AB
	add	A, temp_lo			
	mov	temp_lo, A
	mov	A, B				
	jnb 	AUX.7, $+5			; examine the sign bit
	add	A, #-34	
	mov	temp_hi, A			; temp = (T - T_NOM)*136 / 256 signed

	setb	C
	mov	A, temp_lo			; add temperature correction
	addc	A, R2				; to the humidity value
	mov	R2, A				; and rounding off 1
	mov	A, temp_hi
	addc	A, R3
	mov	R3, A	

	mov	C, ACC.7			; get the sign bit
	rrc	A				; divide by 2 (16-bit operation)
	mov	R3, A
	mov	A, R2
	rrc	A
	add	A, #HUMI_NOM		; A = RH in %
	mov	R2, A
	mov	A, R3
	addc	A, #0
	mov	R3, A				; R3:R2 = RH in %

	mov	P1, #0xC0			; display unit 'H'

	mov	A, R3				; check computed data range	
	jnb	ACC.7, $+6			; if R3:R2 < 0, set R2=0
	clr	A
	sjmp	display_Number		

	clr	C				; if R3:R2 > 99, set R2=99 
	mov	A, R2
	subb	A, #100
	mov	A, R3
	subb	A, #0
	mov	A, R2	
	jc	display_Number
	mov	A, #99	

display_Number:				; display number in ACC
	mov	B, #10			
	div	AB				; A=1st digit, B=2nd digit

dn2:
	mov	R4, A				; A *= 3
	add	A, ACC
	add	A, R4
	mov	R4, A				; A = R4 = table offset of the 1st digit

	mov	DPTR, #table7seg1		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig1
	mov	P0, #0x13			; preserve analog input pins status
	orl	P0, A
	
	inc	R4				; update table offset
	mov	A, R4
	movc	A, @A+DPTR			; get table value
	orl	P1, A				; send it to the LCD

	inc	R4				; update table pointer
	mov	A, R4	
	movc	A, @A+DPTR			; get table value
	anl	P2, #0x08
	orl	P2, A				; send it to the LCD

	mov	A, B				; load 2nd digit to ACC
	add	A, ACC			; A *= 2
	mov	R4, A				; A = R4 = table offset of the 2nd digit 

	mov	DPTR, #table7seg2		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig2
	orl	P1, A				; set it to the LCD
	
	inc	R4				; update table pointer
	mov	A, R4
	movc	A, @A+DPTR			; get table value
	orl	P2, A				; send it to the LCD
	ret

;-----------------------------------------------------------------------
calibrate_HUMI:				; calibration: display HEX value
	mov	A, R2				; of the oscillator period
	jb	DB_counter.0, cal2	
	mov	A, R3				; display high-order byte
	dec	Counter

cal2:
	inc	DB_counter
	mov	B, A
	swap	A
	anl	A, #0x0F
	anl	B, #0x0F
	mov	P1, #0x00
	ajmp	dn2

;-----------------------------------------------------------------------
LPM:  
	mov	PMU0CF, #(SLEEP OR RSTWK OR RTCAWK) ; wakeup sources
	nop   				; device is now awake
   	nop
	nop
	nop

	mov	PMU0CF_Snapshot, PMU0CF	; capture the wake-up source
   	mov 	PMU0CF, #CLEAR		; clear all wake-up source flags

	mov	RTC0ADR, #(0x90 OR RTC0CN); capture RTC events that occured
	nop					; while PMU0CF was being cleared
	nop
	nop	
	mov	A, RTC0DAT			; RTC0CN_snapshot	
	anl	A, #ALRM
	orl	A, PMU0CF_Snapshot	; add it to the old flags
	mov	PMU0CF_Snapshot, A
   
	mov	A, PMU0CF_Snapshot	; reset pin Wakeup ?
	anl	A, #RSTWK
	jnz	debug_delay1		
	ret					; NO - exit

debug_delay1:
	mov	A, #0x5			; YES - make a 20 usec delay		
	dec	A				; 1 cycle
	nop					; 1 cycle
	jnz	$-2				; 2 cycles    
	ret      

;========================================================================
table7seg1: ; P0    P1    P2		; 7-seg LCD table for the first digit
;	DB	0xC0, 0x01, 0x70		; codes for 0
	DB	0x00, 0x00, 0x00		; do not show the leading 0
	DB	0x00, 0x01, 0x10		; codes for 1
	DB	0xA0, 0x01, 0x60		; codes for 2
	DB	0xA0, 0x01, 0x30		; codes for 3
	DB	0x60, 0x01, 0x10		; codes for 4
	DB	0xE0, 0x00, 0x30		; codes for 5
	DB	0xE0, 0x00, 0x70		; codes for 6
	DB	0x80, 0x01, 0x10		; codes for 7
	DB	0xE0, 0x01, 0x70		; codes for 8
	DB	0xE0, 0x01, 0x30		; codes for 9
	DB	0xE0, 0x01, 0x50		; codes for A
	DB	0x60, 0x00, 0x70		; codes for b
	DB	0xC0, 0x00, 0x60		; codes for C
	DB	0x20, 0x01, 0x70		; codes for d
	DB	0xE0, 0x00, 0x60		; codes for E
	DB	0xE0, 0x00, 0x40		; codes for F
	DB	0x20, 0x00, 0x00		; codes for -

table7seg2: ; P1    P2			; 7-seg LCD table for the second digit
	DB	0x1C, 0x07			; codes for 0
	DB	0x10, 0x01			; codes for 1
	DB	0x1A, 0x06			; codes for 2
	DB	0x1A, 0x03			; codes for 3
	DB	0x16, 0x01			; codes for 4
	DB	0x0E, 0x03			; codes for 5
	DB	0x0E, 0x07			; codes for 6
	DB	0x18, 0x01			; codes for 7
	DB	0x1E, 0x07			; codes for 8
	DB	0x1E, 0x03			; codes for 9	
	DB	0x1E, 0x05			; codes for A
	DB	0x06, 0x07			; codes for b
	DB	0x0C, 0x06			; codes for C
	DB	0x12, 0x07			; codes for d
	DB	0x0E, 0x06			; codes for E
	DB	0x0E, 0x04			; codes for F
	DB	0x02, 0x00			; codes for -

END