Timer.A51
; This module services the real time interrupt
; It is also responsible for the "real world" buttons and lights
;
; CHANGE SINCE THE BOOK TEXT WAS FINALIZED: Idle_Time is used by the Operating System
; to override the report times defined in the Endpoint Descriptor.  A device driver
; will modify Idle_Time to change the reporting characteristics of a HID device.
; During initialization the OS sets Idle_Time = 0 which turns reporting OFF unless
; a change is detected; an application that starts to poll a HID device will appear
; to hang. While it is possible to write extra PCHost application code to re-enable
; Idle_Time is it simpler to defeat this mechanism by IGNORRING the Idle_Time value.
;
; Get a Real Time interrupt every One millisecond (using SOF interrupt)
;
; HID devices work on a 4 millisecond timer
; We have one task
;	a) Strobe the LEDs (only one is ever really on, saves power)
ServiceTimerRoutine:
	DJNZ	Msec_counter, Done	; Only need to check every 4msec
	MOV	Msec_counter, #4	; Reinitialize
;
; LED task
; Light the next LED in sequence
	MOV	A, LEDStrobe		; Get the current enabling pattern
	RL	A
	MOV	LEDStrobe, A		; Save for next time
	ANL	A, LEDValue		; Get the LED image
	CALL 	WriteLEDs		; Update the real world
;
; Create an Input Report from the Buttons value
; This will be continually overwritten while the PCHost is not polling for data
	CALL	ReadButtons
	JMP	CreateInputReport	; RETurn via CreateInputReport

; Talk to the "real world" buttons and lights
ReadButtons:
	MOV	DPTR, #PortB_Pins
	MOVX	A, @DPTR
	ANL	A, #0F0H		; Get upper nibble
	MOV	Temp, A
	INC	DPTR			; Point to PortC_Pins
	MOVX	A, @DPTR
	ANL	A, #0FH			; Get lower nibble
	ORL	A, Temp			; Merge both halves together
	RET	
WriteLEDs:
	CPL	A			; 0 = LED on
	MOV	DPTR, #PortA_Out
	MOVX	@DPTR, A
Done:	RET