; This module initializes the microcontroller then executes MAIN forever

;



Reset:

	MOV	SP, #235		; Initialize the Stack at top of internal memory

	MOV	PageReg, #7FH		; Needed to use MOVX @Ri



	MOV	R0, #LOW(USBControl)	; Simulate a disconnect

	MOVX	A, @R0

	ANL	A, #11110011b		; Clear DISCON, DISCOE

	MOVX	@R0, A

	CALL	Wait100msec   		; Give the host time to react

	MOVX	A, @R0			; Reconnect with this new identity

	ORL	A, #00000110b           ; Set DISCOE to enable pullup resistor

	MOVX	@R0, A	 		; Set RENUM so that 8051 handles USB requests

	CLR	A

	MOV	FLAGS, A		; Start in Default state

InitializeIOSystem:			; This example uses only I2C signals

					; No initialization is required

InitializeInterruptSystem:		; First initialize the USB level

	MOV	R0, #LOW(IN07IEN)

	MOVX	@R0, A			; Disable interrupts from IN Endpoints 0-7

	INC	R0

	MOVX	@R0, A			; Disable interrupts from OUT Endpoints 0-7

	INC	R0

	MOV	A, #00000011b

	MOVX	@R0, A			; Enable (Resume, Suspend,) SOF and SUDAV INTs

	INC	R0

	MOV	A, #00000001b

	MOVX	@R0, A	     		; Enable Auto Vectoring for USB interrupts

	MOV	R0, #LOW(OUT07IRQ)

	MOV	A, #0FFH

	MOVX	@R0, A			; Clear out any pending interrupts

	                                ; Now enable the main level

	MOV	EIE, #00000001b		; Enable INT2 = USB Interrupt (only) 		

        MOV	EI, #11000000b		; Enable interrupt subsystem (and Ser1 for Dscope)

 

; Initialization Complete.

; 

MAIN:

	NOP				; Not much of a main loop for this example

	JMP	MAIN			; All actions are initiated by interrupts

; We are a slave, we wait to be told what to do



Wait100msec:

	MOV	Temp, #100

Wait1msec:				; A delay loop

	MOV	DPTR, #-1200		

More:	INC	DPTR			; 3 cycles

	MOV	A, DPL                  ; + 2

	ORL	A, DPH                  ; + 2

	JNZ	More                    ; + 3 = 10 cycles x 1200 = 1msec

	DJNZ	Temp, Wait1msec

	RET



Wait4Stop:				; Make sure the STOP from a previous

	MOVX	A, @R0			; I2C transaction has completed

	JB	ACC.6, Wait4Stop

	RET

SendI2Caddress:				; Send the first byte to I2C bus

	CALL	Wait4Stop

	MOV	A, #10000000b		; Set the START bit

	MOVX	@R0, A			; I2C engine now primed

SendI2Cdatabyte:

	MOVX	A, @DPTR		; Get data and . . .

	MOVX	@R1, A			; . . . send using I2C engine

Wait4Done:

	MOVX	A, @R0

	JNB	ACC.0, Wait4Done	; Wait for the data to be transmitted

	RET



ProcessOutputReport:		  	; A Report has just been received

; The report is two bytes long

; Byte 1, Bits[7:1] = an I2C Address, Bit[0] = direction (0 = Write)

; Byte 2 = DataByte if byte 1 specifies a write

	MOV	R0, #LOW(I2CControl)	; Initialize the pointers to be used

	MOV	R1, #LOW(I2CData)

	MOV	DPTR, #EP0OutBuffer	; Point to the Report

	CALL	SendI2Caddress

	MOVX	A, @DPTR		; Retrieve Report Byte 1

	JB	ACC.0, I2C_Read

I2C_Write:

	INC	DPTR			; Point to data byte to write

	CALL	SendI2Cdatabyte

	MOV	A, #01000000b		; Set the STOP bit

	MOVX	@R0, A

	RET

I2C_Read:

	MOV	A, #00100000b		; Set the LASTRD bit

	MOVX	@R0, A

	MOVX	A, @R1			; Dummy read of I2C_Data

	CALL	Wait4Done

	MOV	A, #01000000b		; Set the STOP bit

	MOVX	@R0, A                  ; Immediately follow with . . .

	MOVX	A, @R1			; . . . read the I2C bus data

					; Fall into CreateInputReport

CreateInputReport:

; The report is only one byte long in this example

; It contains the byte read from the I2C bus 

	MOV	DPTR, #EP1InBuffer	; Point to the buffer 

	MOVX	@DPTR, A		; Update the Report

	MOV	DPTR, #IN1ByteCount

	MOV	A, #1

	MOVX	@DPTR, A		; Endpoint 1 now 'armed', next IN will get data

	RET