$NOMOD51
$include (C8051F98x.inc)         
        
RTC0CN_Local 	EQU 0x80		; default SmaRTClock cfg. value
PMU0CF_Snapshot 	EQU R5
Period_low		EQU 0xFE		; 0x00 for 1 sek
Period_high		EQU 0xFF		; 0x80 for 1 sek

	DSEG 	AT 0x30			; data segment in direct addressable space
bufTemp: 	DS 8				; circular buffer for temperature
tempAve_lo:	DS 1				; storage for temperature average sum
tempAve_hi:	DS 1
temp:		DS 1				; temp value 

	ORG 	0x40
bufHumi:	DS 16				; curcular buffer for humidity
humiAve_lo: DS 1				; storage for humidity average sum
humiAve_hi: DS 1

	CSEG 	AT 0				; interrupt vectors
	ljmp 	Main  			; reset

	ORG	0xB3
	USING    0                    ; specify register bank 

main:       
	anl   PCA0MD, #NOT(0x40)      ; disable the WDT
	mov	SP, #0x79			; setup stack

	acall	Ports_Setup
	acall	Clock_Setup
	acall	Debug_Trap			; debug trap !!!

	acall	RTC_Setup
	acall	ADC_Setup

	mov 	PMU0CF, #CLEAR
	setb	P0.5				; turn on LCD oscillator

loop: 					; MAIN LOOP
	acall	LPM   			; enter sleep until next alarm
	anl 	P0, #NOT(0x06)		; disable latches
	mov	A, PMU0CF_Snapshot
	anl	A, #RTCAWK			; RTC_Alarm ?
	jz	loop				; NO - back to sleep	

measure:					; YES - do measurements
	acall	getTempOffset		; update temp offset values on display
	sjmp	loop


;-------------------PROCEDURES-------------------------------------------
Ports_Setup:
	mov  	P0MDIN,    #0xF7		; analog input on P0.3 	
	mov  	P0MDOUT,   #0x76		; push-pull out on P0[2:1] and P0[6:4]
	mov  	P1MDIN,    #0xFC		; comparator input on P1[1:0]
    	mov  	P1MDOUT,   #0xFC		; push-pull out on P1[7:2]
    	mov  	P0SKIP,    #0xBF		; I/O function on P0[5:0], P0.7
    	mov  	P1SKIP,    #0xFF		; I/O function on P1[7:0]
	mov  	XBR0,      #0x20
    	mov   XBR2,      #0x40		; enable XBar and weak pull-ups
	mov	P0, 	     #0x29
	mov	P1, 	     #3		; initialize port pins
	ret

;-----------------------------------------------------------------------
Clock_Setup:
	mov	RTC0ADR, #(0x10 OR RTC0XCN)	
	mov	RTC0DAT, #RTC0AEN		; enable LFO
	nop
   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; enable SmaRTClock
	mov	RTC0DAT, #(RTC0CN_Local OR RTC0TR)  

	mov	SFRPAGE, #0xF		; switch to SFR page 0xF
	mov	PMU0MD,  #0			; enable POR supply monitor
	mov	SFRPAGE, #0			; switch to default SFT page
	mov 	RSTSRC,  #0x06		; enable MCD and VDD monitor
	anl	OSCICN,  #NOT(0x80)	; disable internal precision oscillator
	mov	REG0CN,  #0			; disable precision oscillator bias
	mov	OSCXCN,  #0			; disable external oscillator
	mov	CLKSEL,  #0x03		; select LFO with 1:1 clock divider
	mov	A, CLKSEL			; wait for the divider setting to be applied
	anl	A, #0x80		
	jz	$-4		
	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	

	jnb	P0.0, $			; additional debug trap !!!

	mov	CLKSEL, #0x04		; select LPO with 1:1 clock divider
	orl	FLSCL, #BYPASS		; set the one-shot bypass bit
	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, #(RTC0CN_Local 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	R6, #Period_low
	mov	R7, #Period_high
ALARM_Setup:
   	mov	RTC0ADR, #(0x10 OR RTC0CN)	; disable alarm while
   	mov	RTC0DAT, #(RTC0CN_Local 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, #(RTC0CN_Local OR RTC0TR OR RTC0AEN OR ALRM)  
	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

;-----------------------------------------------------------------------
getTempOffset:
   	mov	ADC0MX, #0x1B		; temp sensor as ADC input
	mov	REF0CN, #0x1C           ; enable high-speed ref, enable temp sensor
	mov	ADC0CN, #0x80		; enable ADC

	mov	A, #10			; 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 sensor and ref

	mov	A, #0x0A
	mov	DPTR, #table7seg1		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig1
	mov	P1, A
	nop
	nop
	nop
	setb	P0.1				; latch in the first digit
	nop
	nop
	nop
	clr	P0.1

	mov	B, #-1
do_loop:
	inc	B
	mov	A, ADC0L   
	clr	C
	subb	A, #100
	mov	ADC0L, A   
	mov	A, ADC0H
	subb	A, #0
	mov	ADC0H, A
	jnc	do_loop
         
      mov 	A, ADC0L
	add	A, #100
	xch	A, B
	
	mov	DPTR, #table7seg2		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig2
	mov	P1, A
	nop
	nop
	nop
	setb	P0.2				; latch in the second digit
	nop
	nop
	nop
	clr	P0.2

      xch   A, B
      mov   B, #10
      div   AB

	mov	DPTR, #table7seg1		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig2
	mov	P1, A
	nop
	nop
	nop
	setb	P1.6				; latch in the third digit
	nop
	nop
	nop
	clr	P1.6

	mov	A, B				; extract second digit
	mov	DPTR, #table7seg2		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig2
	mov	P1, A
	nop
	nop
	nop
	setb	P1.7				; latch in the fourth digit	
	nop
	nop
	nop
	clr	P1.7
	ret

;-----------------------------------------------------------------------
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_delay		
	ret					; NO - exit

debug_delay:
	mov	A, #0x5			; YES - make a 20 usec delay		
	dec	A				; 1 cycle
	nop					; 1 cycle
	jnz	$-2				; 2 cycles    
	ret      

;========================================================================
table7seg1:					; 7-seg LCD table for left digits
	DB	0 + 3				; code for 0
	DB	0x20 + 3			; code for 1
	DB	0x08 + 3			; code for 2
	DB	0x28 + 3			; code for 3
	DB	0x04 + 3			; code for 4
	DB	0x24 + 3			; code for 5
	DB	0x0C + 3			; code for 6
	DB	0x2C + 3			; code for 7
	DB	0x10 + 3			; code for 8
	DB	0x30 + 3			; code for 9
	DB	0x3C + 3			; blank	
							
table7seg2:					; 7-seg LCD table for right digits
	DB	0 + 3				; code for 0
	DB	0x04 + 3			; code for 1
	DB	0x10 + 3			; code for 2
	DB	0x14 + 3			; code for 3
	DB	0x20 + 3			; code for 4
	DB	0x24 + 3			; code for 5
	DB	0x30 + 3			; code for 6
	DB	0x34 + 3			; code for 7
	DB	0x08 + 3			; code for 8
	DB	0x0C + 3			; code for 9
	DB	0x3C + 3			; blank	


END