$NOMOD51
$include (C8051F98x.inc)     
            
HUMI_NOM		EQU 61		; calibration values
TEMP_NOM		EQU 284
CS_NOM		EQU 2365

RTC0CN_Local 	EQU 0x80		; default SmaRTClock cfg. value
PMU0CF_Snapshot 	EQU R5
Period_low		EQU 0xFE		; 0 for 1 sek
Period_high		EQU 0xFF		; 0x80 for 1 sek
Light_TH		EQU 0x10		; ambient light intensity threschold


	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
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

	ORG 	0x50
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				; 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	ADC_Setup			; initialize hardware
	acall	CS0_Setup

	mov	Counter, #1			; initialize conversion counter
	mov	Status,  #3			; request circ buffers initialization
	sjmp	measure

loop: 					; MAIN LOOP
	acall	LPM   			; enter sleep until next alarm
	mov	A, PMU0CF_Snapshot
	anl	A, #RTCAWK			; RTC_Alarm ?
	jz	loop				; NO - back to sleep	

measure:					; YES - do measurements
	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

	acall	display_OFF			; NO - disable LCD oscillator 
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
	setb	P0.0				; turn on LCD oscillator
	sjmp	measure			; back to the main loop

;-------------------PROCEDURES-------------------------------------------
Ports_Setup:
	mov  	P0MDIN,    #0xE9		; analog input on P0[2:1] & P0.4 	
	mov  	P0MDOUT,   #0xE9		; push-pull out on P0.0, P0.3, P0[7:5]
	mov  	P1MDIN,    #0xFF		; digital I/O on P1
    	mov  	P1MDOUT,   #0x7F		; digital input on P1.7
    	mov  	P0SKIP,    #0xFF		; I/O function on P0
    	mov  	P1SKIP,    #0xFF		; I/O function on P1
    	mov   XBR2,      #0x40		; enable XBar and weak pull-ups	
	mov	P0, 	     #0x17
	mov	P1, 	     #0x90		; 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 SmaRTClock 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	P1.7, $			; 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	RTC0ADR, #(0x10 OR RTC0CN)	; enable SmaRTClock
	mov	RTC0DAT, #(RTC0CN_Local OR RTC0TR)  

	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

;-----------------------------------------------------------------------
CS0_Setup:
	mov	CS0CN,   #0x80		; enable Capacitive Sense module CS0
	mov	CS0CF,   #0x00		; accumulate no samples
	mov	CS0MD1,  #0x00		; gain = 1x
	mov	CS0MD2,  #0x28		; set 12-bit resolution, discharge time 3 usec 
	mov	CS0MX,   #0x02		; select channel P0.2
	mov	CS0THH,  #0x00		; set-up digital comparator
	mov	CS0THL,  #0xFF		; for waking up the CPU from SUSPEND
	mov	CS0CN,   #0x00		; turn the module off
	ret

;-----------------------------------------------------------------------
getLight:
	mov	ADC0MX, #1			; select P0.1 as ADC input
	mov	REF0CN, #0x18           ; enable high-speed ref
	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 reference

	clr	C
	mov	A, ADC0L			; get conversion result
	subb	A, #Light_TH
	mov	A, ADC0H
	subb	A, #0
	ret

;-----------------------------------------------------------------------
display_OFF:
	mov	A, #0x0A			; turn off display
	mov	DPTR, #table7seg		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get blank code 
	mov	P1, A
	nop
	nop
	nop
	setb	P0.6				; latch it into all digits
	setb	P0.7
	nop
	nop
	nop
	clr	P0.6
	clr	P0.7
	clr	P0.0				; stop LCD oscillator
	setb	P1.4				; clear units symbol
	setb	P1.5
	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, #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 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 midified since the
	swap	A				; last add
	mov	B, A
	anl	A, 0xF0
	add	A, R2
	mov	R2, A
	mov	A, B				
	anl	A, #0x0F
	mov	R3, A

process_TEMP:
	mov	B, #165			; multiply ADC by 165 (2 bytes x 1 byte)
	mov	A, R2
	mul	AB
	mov	R2, B
	mov	B, #165
	mov	A, R3
	mul	AB
	add	A, R2				; A = lower byte, B = higher byte
	mov	R2, A
 	mov	temp_lo, A
      mov  	A, B
      addc	A,  #0
	mov	R3, A				; R3:R2 = ADC_temp * 165 / 256
 	mov	temp_hi, A

	mov	A, R2				; subtract 50*4-2 = 198 and round off
	add	A, #0x3A			; 198 = 0xFF3A
	mov	R2, A
	mov	A, R3
	addc	A, #0xFF
	mov	R3, A				; R3:R2 = ADC_temp * 165 / 256 - 200

	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 * 165 / 1024 - 50

	mov	A, R3				; check computed data range	
	jnb	ACC.7, $+6			; if R3:R2 < 0, set R2=0
	clr	A
	sjmp	display_TEMP		

	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	B, #10
	div	AB				; A = tens of temp, B = units of temp
	cjne	A, #0, $+5			; skip over the next instruction
	 mov	A, #10			; load blank code
	mov	DPTR, #table7seg		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig1
	mov	P1, A
	nop
	nop
	nop
	setb	P0.7				; latch in the first digit
	nop
	nop
	nop
	clr	P0.7
	
	mov	A, B
	movc	A, @A+DPTR			; get code of dig2
	mov	P1, A
	nop
	nop
	nop
	setb	P0.6				; latch in the second digit
	nop
	nop
	nop
	clr	P0.6

	setb	P1.4				; display units (degrees C)
	clr	P1.5				
	ret

;-----------------------------------------------------------------------
getHumi:
	mov	CS0CN, #0x88		; enable Capacitive Sense module CS0
	nop
	orl	CS0CN, #0x10		; start conversion
	acall	wait4CS0			; enter SUSPEND mode till the end of conversion        	
	mov	CS0CN, #0x00		; power-off CS0 module

	mov	A, CS0DL			; shift CS value 4 bits to the left 
	swap	A				; needed for 12-bit CS0 resolution
	anl	A, #0x0F
	mov	R2, A				; R2 = lower nibble
	mov	A, CS0DH
	swap	A
	mov	B, A
	anl	A, #0xF0
	orl	A, R2
	mov	R2, A
	mov	A, B
	anl	A, #0x0F
	mov	R3, A				; R3:R2 = shifted CS value

	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 midified since the
	swap	A				; last add
	mov	B, A
	anl	A, 0xF0
	add	A, R2
	mov	R2, A
	mov	A, B				
	anl	A, #0x0F
	mov	R3, A				; R3:R2 is averaged humi index

process_HUMI:
	clr	C				; subtract ADC offset
	mov	A, R2
	subb	A, #(CS_NOM MOD 256)
	mov	R2, A
	mov	A, R3
	subb	A, #(CS_NOM / 256)
	mov	AUX, A			; AUX:R2 = adc - a2 (can be negative)

	mov	A, R2				; compute humi*125
	mov	B, #125			; result is at most 16 bits	
	mul	AB
	mov	R2, B
	mov	A, AUX
	mov	B, #125
	mul	AB
	add	A, R2				
	mov	R2, A
	mov	A, B				; A:R2 = humi*125 unsigned
	jnb 	AUX.7, $+5			; examine the sign bit
	add	A, #-125			; A:R2 = humi*125 signed
	mov	R3, A				; R3:R2 (adc - a2) / 256

	clr	C
	mov	A, temp_lo			; thermo compensation
	subb	A, #(TEMP_NOM MOD 256)
	mov	temp_lo, A
	mov	A, temp_hi
	subb	A, #(TEMP_NOM / 256)
	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

	mov	A, temp_lo			; add temperature correction
	add	A, R2				; to the humidity value
	mov	R2, A
	mov	A, temp_hi
	addc	A, R3
	mov	R3, A	

	mov	A, R2	
	add	A, #2				; rounding off
	mov	R2, A 
	mov	A, R3 
	addc	A, #0				; A:R2 = signed rounded off product / 256	

	mov	C, ACC.7			; get the sign bit
	rrc	A				; A = humi*125/512 (signed)
	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	A, R3				; check computed data range	
	jnb	ACC.7, $+6			; if R3:R2 < 0, set R2=0
	clr	A
	sjmp	display_HUMI		

	clr	C				; if R3:R2 > 99, set R2=99 
	mov	A, R2
	subb	A, #100
	mov	A, R3
	subb	A, #0
	jc	display_HUMI
	mov	R2, #99	

display_HUMI:
	mov	A, R2
	mov	B, #10			; A = RH in %
	div	AB

	mov	DPTR, #table7seg		; initialize 7-seg table pointer
	movc	A, @A+DPTR			; get code of dig1

	mov	P1, A
	nop
	nop
	nop
	setb	P0.7				; latch in the first digit
	nop
	nop
	nop
	clr	P0.7
	
	mov	A, B
	movc	A, @A+DPTR			; get code of dig2
	mov	P1, A
	nop
	nop
	nop
	setb	P0.6				; latch in the second digit
	nop
	nop
	nop
	clr	P0.6

	clr	P1.4				; display units (H)
	clr	P1.5
	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_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      

;-----------------------------------------------------------------------
wait4CS0: 
	anl	FLSCL,  #NOT(BYPASS)	; clear the one-shot bypass bit
	mov	PMU0FL, #CS0WK		; enable wake-up from CS0 module
	mov	PMU0CF, #(SUSPEND OR RSTWK) 	; wakeup sources
	nop   				; device is now awake
   	nop
	nop
	nop
  
	orl	FLSCL, #BYPASS		; set the one-shot bypass bit
	mov	PMU0CF_Snapshot, PMU0CF	; capture the wake-up source
   	mov 	PMU0CF, #CLEAR		; clear all wake-up source flags
	mov	PMU0FL, #0x00		
   
	mov	A, PMU0CF_Snapshot	; reset pin Wakeup ?
	anl	A, #RSTWK
	jnz	debug_delay2		
	ret					; NO - exit

debug_delay2:
	mov	A, #0x5			; YES - make a 20 usec delay		
	dec	A				; 1 cycle
	nop					; 1 cycle
	jnz	$-2				; 2 cycles    
	ret      

;========================================================================
table7seg:					; 7-seg LCD table
	DB	0x00 + 0xB0			; code for 0
	DB	0x08 + 0xB0			; code for 1
	DB	0x02 + 0xB0			; code for 2
	DB	0x0A + 0xB0			; code for 3
	DB	0x01 + 0xB0			; code for 4
	DB	0x09 + 0xB0			; code for 5
	DB	0x03 + 0xB0			; code for 6
	DB	0x0B + 0xB0			; code for 7
	DB	0x04 + 0xB0			; code for 8
	DB	0x0C + 0xB0			; code for 9
	DB	0x0F + 0xB0			; blank	

END