; 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