A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 1 DOS MACRO ASSEMBLER A51 V5.28m OBJECT MODULE PLACED IN RB.OBJ ASSEMBLER INVOKED BY: C:\ANCHOR\KEIL2K\BIN\A51.EXE RB.A51 RB(0) DB EP LOC OBJ LINE SOURCE 1 NAME ReaderBoard 2 3 $INCLUDE(../Declare.A51) =1 4 ; This module declares the variables and constants used in the examples =1 5 ; It is common to all of the examples =1 6 ; =1 7 ; Declare Special Function Registers used 00A8 =1 8 EI DATA 0A8H 00E8 =1 9 EIE DATA 0E8H ; EZ-USB specific 0091 =1 10 EXIF DATA 091H ; EZ-USB specific 00D8 =1 11 EICON DATA 0D8H ; EZ-USB specific 0092 =1 12 PageReg DATA 092H ; EZ-USB specific, used with MOVX @Ri 0086 =1 13 DPS DATA 086H ; EZ-USB specific, used with dual data pointers =1 14 ; =1 15 ; "External" memory locations used, EZ-USB specific =1 16 ; Note that most of these variables are in Page 7FH 7FE8 =1 17 SETUPDAT EQU 07FE8H 7FD4 =1 18 SUDPTR EQU 07FD4H 7FB4 =1 19 EP0Control EQU 07FB4H 7F00 =1 20 EP0InBuffer EQU 07F00H 7EC0 =1 21 EP0OutBuffer EQU 07EC0H ; Not in Page 7FH 7E80 =1 22 EP1InBuffer EQU 07E80H ; Not in Page 7FH 7FB5 =1 23 IN0ByteCount EQU 07FB5H 7FC5 =1 24 Out0ByteCount EQU 07FC5H 7FB7 =1 25 IN1ByteCount EQU 07FB7H 7FAC =1 26 IN07IEN EQU 07FACH 7FA9 =1 27 IN07IRQ EQU 07FA9H 7FAD =1 28 OUT07IEN EQU 07FADH 7FAA =1 29 OUT07IRQ EQU 07FAAH 7FAE =1 30 USBIEN EQU 07FAEH 7FAB =1 31 USBIRQ EQU 07FABH 7FD6 =1 32 USBControl EQU 07FD6H 7FA6 =1 33 I2CData EQU 07FA6H 7FA5 =1 34 I2CControl EQU 07FA5H 7F93 =1 35 PortA_Config EQU 07F93H 7F94 =1 36 PortB_Config EQU 07F94H 7F95 =1 37 PortC_Config EQU 07F95H 7F96 =1 38 PortA_OUT EQU 07F96H 7F97 =1 39 PortB_OUT EQU 07F97H 7F98 =1 40 PortC_OUT EQU 07F98H 7F99 =1 41 PortA_PINS EQU 07F99H 7F9A =1 42 PortB_PINS EQU 07F9AH 7F9B =1 43 PortC_PINS EQU 07F9BH 7F9C =1 44 PortA_OE EQU 07F9CH 7F9D =1 45 PortB_OE EQU 07F9DH 7F9E =1 46 PortC_OE EQU 07F9EH =1 47 ; =1 48 ; Byte Variables =1 49 ---- =1 50 DSEG AT 20H 0020 =1 51 FLAGS: DS 1 ; This register is bit-addressable =1 52 ; Bit Variables 0000 =1 53 Configured EQU FLAGS.0 ; Is this device configured 0001 =1 54 STALL EQU FLAGS.1 ; Need to STALL endpoint 0 0002 =1 55 SendData EQU FLAGS.2 ; Need to send data to PC Host 0003 =1 56 IsDescriptor EQU FLAGS.3 ; Enable a shortcut reply =1 57 ; 0021 =1 58 MonitorSpace: DS 1FH ; Used by Dscope A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 2 0040 =1 59 Temp: DS 1 ; A temporary working register 0041 =1 60 Idle_Time: DS 1 ; The time the PC host wants us to wait 0042 =1 61 Expired_Time: DS 1 ; A downcounter for timed Reports 0043 =1 62 ReplyBuffer: DS 3 ; First byte is Count 0046 =1 63 CurrentConfiguration: 0046 =1 64 DS 1 ; Some examples support > 1 configurations =1 65 ; =1 66 ; Declare the specific variables used by each of the examples 0047 =1 67 Overlay EQU $ 0047 =1 68 Old_Buttons: DS 1 ; Used by BAL: stores current button position 0048 =1 69 LEDstrobe: DS 1 ; Used by BAL: strobe one LED on at a time 0049 =1 70 LEDvalue: DS 1 ; Used by BAL: stores current LED value 004A =1 71 Msec_Counter: DS 1 ; Used by BAL: counts up to 4 msec =1 72 0047 =1 73 ORG Overlay ; Overlay the variables (only one set in use at any one tim e) 0047 =1 74 I2CDataByte: DS 1 ; Used by I2C: keep a local copy of data read from I2C bus =1 75 0047 =1 76 ORG Overlay 0047 =1 77 LightValues: DS 6 ; Used by LP: local buffer for light brightness =1 78 0047 =1 79 ORG Overlay 0047 =1 80 CurrentPosition:DS 1 ; Used by Stepper: motor has 16 stable positions 0048 =1 81 MotorControl: DS 3 ; Used by Stepper: direction, Low(count) and High(count) =1 82 0047 =1 83 ORG Overlay 0047 =1 84 LimitValues: DS 12 ; Used by Temps: local buffer for limits =1 85 0047 =1 86 ORG Overlay 0047 =1 87 ButtonsValue: DS 1 ; Used by RB: buttons are read each full scan 0048 =1 88 DisplayPosition:DS 1 ; Used by RB: holds current display position 0049 =1 89 LEDBuffer: DS 42 ; Used by RB: local buffer for reader board =1 90 =1 91 ; 92 $INCLUDE(../Vectors.A51) =1 93 ; This module is common to all of the examples. =1 94 ; It contains all of the interrupt vector declarations and =1 95 ; the first level interrupt servicing (register save, call subroutine, =1 96 ; clear interrupt source, restore registers, return) =1 97 ; Suspend and Resume are handled totally in this module =1 98 ; =1 99 ; A Reset sends us to Program space location 0 ---- =1 100 CSEG AT 0 ; Code space =1 101 USING 0 ; Reset forces Register Bank 0 0000 020362 =1 102 LJMP Reset =1 103 ; =1 104 ; The interrupt vector table is also located here =1 105 ; EZ-USB has two levels of USB interrupts: =1 106 ; 1-the main level is described in this table (at ORG 43H) =1 107 ; 2-there are 21 sources of USB interrupts and these are described in USB_ISR =1 108 ; This means that two levels of acknowledgement and clearing will be required =1 109 ; LJMP INT0_ISR ; Features not used are commented out =1 110 ; ORG 0BH =1 111 ; LJMP Timer0_ISR =1 112 ; ORG 13H =1 113 ; LJMP INT1_ISR =1 114 ; ORG 1BH =1 115 ; LJMP Timer1_ISR =1 116 ; ORG 23H =1 117 ; LJMP UART0_ISR =1 118 ; ORG 2BH =1 119 ; LJMP Timer2_ISR =1 120 ; ORG 33H =1 121 ; LJMP WakeUp_ISR =1 122 ; ORG 3BH =1 123 ; LJMP UART1_ISR A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 3 0043 =1 124 ORG 43H 0043 020100 =1 125 LJMP USB_ISR ; Auto Vector will replace byte 45H =1 126 ; ORG 4BH =1 127 ; LJMP I2C_ISR =1 128 ; ORG 53H =1 129 ; LJMP INT4_ISR =1 130 ; ORG 5BH =1 131 ; LJMP INT5_ISR =1 132 ; ORG 63H =1 133 ; LJMP INT6_ISR =1 134 00E0 =1 135 ORG 0E0H ; Keep out of the way of dScope monitor =1 136 ; If you are not using dScope then this memory hole =1 137 ; may be used for useful routines. 0100 =1 138 ORG 100H 0100 02013C =1 139 USB_ISR:LJMP SUDAV_ISR 0103 00 =1 140 DB 0 ; Pad entries to 4 bytes 0104 020158 =1 141 LJMP SOF_ISR 0107 00 =1 142 DB 0 0108 020118 =1 143 LJMP SUTOK_ISR 010B 00 =1 144 DB 0 010C 020129 =1 145 LJMP Suspend_ISR 010F 00 =1 146 DB 0 0110 020120 =1 147 LJMP USBReset_ISR 0113 00 =1 148 DB 0 0114 020118 =1 149 LJMP Reserved 0117 00 =1 150 DB 0 =1 151 ; LJMP EP0In_ISR ; Endpoint Interrupts are not used in these examples =1 152 ; DB 0 ; Comment out features not used =1 153 ; LJMP EP0Out_ISR =1 154 ; DB 0 =1 155 ; LJMP EP1In_ISR =1 156 ; DB 0 =1 157 ; LJMP EP1Out_ISR =1 158 ; DB 0 =1 159 ; LJMP EP2In_ISR =1 160 ; DB 0 =1 161 ; LJMP EP2Out_ISR =1 162 ; DB 0 =1 163 ; LJMP EP3In_ISR =1 164 ; DB 0 =1 165 ; LJMP EP3Out_ISR =1 166 ; DB 0 =1 167 ; LJMP EP4In_ISR =1 168 ; DB 0 =1 169 ; LJMP EP4Out_ISR =1 170 ; DB 0 =1 171 ; LJMP EP5In_ISR =1 172 ; DB 0 =1 173 ; LJMP EP5Out_ISR =1 174 ; DB 0 =1 175 ; LJMP EP6In_ISR =1 176 ; DB 0 =1 177 ; LJMP EP6Out_ISR =1 178 ; DB 0 =1 179 ; LJMP EP7In_ISR =1 180 ; DB 0 =1 181 ; LJMP EP7Out_ISR =1 182 ; End of Interrupt Vector tables =1 183 =1 184 ; When a feature is used insert the required interrupt processing here =1 185 ; The example use only used Endpoints 0 and 1 and also SOF for timing 0118 =1 186 Reserved: 0118 =1 187 INT0_ISR: 0118 =1 188 Timer0_ISR: 0118 =1 189 INT1_ISR: A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 4 0118 =1 190 Timer1_ISR: 0118 =1 191 UART0_ISR: 0118 =1 192 Timer2_ISR: 0118 =1 193 UART1_ISR: 0118 =1 194 I2C_ISR: 0118 =1 195 INT4_ISR: 0118 =1 196 INT5_ISR: 0118 =1 197 INT6_ISR: 0118 =1 198 SUTOK_ISR: 0118 =1 199 EP0In_ISR: 0118 =1 200 EP0Out_ISR: 0118 =1 201 EP1In_ISR: 0118 =1 202 EP1Out_ISR: 0118 =1 203 EP2In_ISR: 0118 =1 204 EP2Out_ISR: 0118 =1 205 EP3In_ISR: 0118 =1 206 EP3Out_ISR: 0118 =1 207 EP4In_ISR: 0118 =1 208 EP4Out_ISR: 0118 =1 209 EP5In_ISR: 0118 =1 210 EP5Out_ISR: 0118 =1 211 EP6In_ISR: 0118 =1 212 EP6Out_ISR: 0118 =1 213 EP7In_ISR : 0118 =1 214 EP7Out_ISR: 0118 =1 215 Not_Used: ; Should not get any of these 0118 32 =1 216 RETI =1 217 0119 =1 218 ClearINT2: ; Tell the hardware that we're done 0119 E591 =1 219 MOV A, EXIF 011B C2E4 =1 220 CLR ACC.4 ; Clear the Interrupt 2 bit 011D F591 =1 221 MOV EXIF, A 011F 22 =1 222 RET =1 223 0120 =1 224 USBReset_ISR: ; Bus has been Reset, move to DEFAULT state 0120 C0E0 =1 225 PUSH ACC 0122 C200 =1 226 CLR Configured 0124 3119 =1 227 CALL ClearINT2 =1 228 ; No need to clear source of interrupt 0126 D0E0 =1 229 POP ACC 0128 32 =1 230 RETI =1 231 0129 =1 232 Suspend_ISR: ; SIE detected an Idle bus 0129 C0E0 =1 233 PUSH ACC 012B E587 =1 234 MOV A, PCON 012D 4401 =1 235 ORL A, #1 012F F587 =1 236 MOV PCON, A ; Go to sleep! 0131 00 =1 237 NOP 0132 00 =1 238 NOP ; Wake up here due to a USBResume 0133 00 =1 239 NOP 0134 3119 =1 240 CALL ClearINT2 0136 D0E0 =1 241 POP ACC 0138 32 =1 242 RETI =1 243 0139 =1 244 WakeUp_ISR: ; Not using external WAKEUP in these examples =1 245 ; So this must be due to a USBResume 0139 C2DC =1 246 CLR EICON.4 ; Clear the wakeup interrupt source 013B 32 =1 247 RETI =1 248 013C =1 249 SUDAV_ISR: ; A Setup packet has been received 013C C0D0 =1 250 PUSH PSW ; Save Registers before the service routine 013E C0E0 =1 251 PUSH ACC 0140 C082 =1 252 PUSH DPL 0142 C083 =1 253 PUSH DPH 0144 120169 =1 254 CALL ServiceSetupPacket 0147 3119 =1 255 CALL ClearINT2 A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 5 =1 256 ; Clear the source of the interrupt 0149 7401 =1 257 MOV A, #00000001b 014B 907FAB =1 258 ExitISR:MOV DPTR, #USBIRQ 014E F0 =1 259 MOVX @DPTR, A 014F D083 =1 260 POP DPH ; Restore Registers 0151 D082 =1 261 POP DPL 0153 D0E0 =1 262 POP ACC 0155 D0D0 =1 263 POP PSW 0157 32 =1 264 RETI =1 265 0158 =1 266 SOF_ISR: ; A Start-Of-Frame packet has been received 0158 C0D0 =1 267 PUSH PSW ; Save Registers before the service routine 015A C0E0 =1 268 PUSH ACC 015C C082 =1 269 PUSH DPL 015E C083 =1 270 PUSH DPH 0160 1205FA =1 271 CALL ServiceTimerRoutine 0163 3119 =1 272 CALL ClearINT2 =1 273 ; Clear the source of the interrupt 0165 7402 =1 274 MOV A, #00000010b 0167 80E2 =1 275 JMP ExitISR =1 276 =1 277 278 $INCLUDE(../USB_INT.A51) =1 279 ; This module is common to all of the examples. =1 280 ; It services USB Requests from the SIE. =1 281 ; Interpretation of the Output Reports is handled by MAIN =1 282 ; ---- =1 283 CSEG 0169 =1 284 ServiceSetupPacket: 0169 907FE8 =1 285 MOV DPTR, #SETUPDAT ; Point to Setup Packet data 016C E0 =1 286 MOVX A, @DPTR ; Get the RequestType 016D A2E7 =1 287 MOV C, ACC.7 ; Bit 7 = 1 means IO device needs to send data to P C Host 016F 9202 =1 288 MOV SendData, C 0171 545C =1 289 ANL A, #01011100b ; IF RequestType[6.4.3.2] = 1 THEN goto BadRequest 0173 7051 =1 290 JNZ BadRequest 0175 E0 =1 291 MOVX A, @DPTR ; IF RequestType[1&0] = 1 THEN goto BadRequest 0176 A2E0 =1 292 MOV C, ACC.0 0178 82E1 =1 293 ANL C, ACC.1 017A 404A =1 294 JC BadRequest 017C 30E502 =1 295 JNB ACC.5, NotB5 ; IF RequestType[5] = 1 THEN RequestType[1,0] = [1, 1] 017F 7403 =1 296 MOV A, #00000011b 0181 5403 =1 297 NotB5: ANL A, #00000011b ; Set CommandIndex[5,4] = RequestType[1,0] 0183 C4 =1 298 SWAP A 0184 F540 =1 299 MOV Temp, A ; Save HI nibble of CommandIndex =1 300 ; Set CommandIndex[3,0] = Request[3,0] 0186 A3 =1 301 INC DPTR ; Point to Request 0187 E0 =1 302 MOVX A, @DPTR 0188 540F =1 303 ANL A, #00001111b ; Only 13 are defined today, handle in table 018A 4540 =1 304 ORL A, Temp 018C 1201D5 =1 305 CALL CorrectSubroutine ; goto CommandTable(CommandIndex) =1 306 ; Returns STALL=1 if a stall is required 018F 200134 =1 307 JB STALL, BadRequest 0192 300218 =1 308 JNB SendData, HandShake 0195 200320 =1 309 JB IsDescriptor, LoadSUDPTR; EZ-USB has a short cut for descriptors =1 310 ; Send data in ReplyBuffer 0198 907F02 =1 311 MOV DPTR, #EP0InBuffer+2 019B 7846 =1 312 MOV R0, #ReplyBuffer+3 019D 754003 =1 313 MOV Temp, #3 ; Copy maximum byte count 01A0 E6 =1 314 CopyRB: MOV A, @R0 01A1 F0 =1 315 MOVX @DPTR, A 01A2 1582 =1 316 DEC DPL 01A4 18 =1 317 DEC R0 01A5 D540F8 =1 318 DJNZ Temp, CopyRB 01A8 E6 =1 319 MOV A, @R0 ; Get real byte count A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 6 01A9 =1 320 SendEP0InBuffer: 01A9 907FB5 =1 321 MOV DPTR, #In0ByteCount 01AC =1 322 StartXfer: 01AC F0 =1 323 MOVX @DPTR, A ; This write initiates the transfer 01AD =1 324 HandShake: ; Handshake with host 01AD 754002 =1 325 MOV Temp, #00000010b ; Set HSNAK to tell the SIE that we're done 01B0 =1 326 SetEP0Control: 01B0 907FB4 =1 327 MOV DPTR, #EP0Control 01B3 E0 =1 328 MOVX A, @DPTR 01B4 4540 =1 329 ORL A, Temp 01B6 F0 =1 330 MOVX @DPTR, A 01B7 22 =1 331 RET 01B8 =1 332 LoadSUDPTR: ; Send the data pointed to by DPTR 01B8 858240 =1 333 MOV Temp, DPL 01BB E583 =1 334 MOV A, DPH 01BD 907FD4 =1 335 MOV DPTR, #SUDPTR 01C0 F0 =1 336 MOVX @DPTR, A 01C1 E540 =1 337 MOV A, Temp 01C3 A3 =1 338 INC DPTR 01C4 80E6 =1 339 JMP StartXfer 01C6 =1 340 BadRequest: ; Invalid Request was received 01C6 754003 =1 341 MOV Temp, #00000011b ; Set EP0STALL and HSNAK 01C9 80E5 =1 342 JMP SetEP0Control =1 343 01CB =1 344 NextDPTR: ; Returns (DPTR + byte DPTR is pointing to) 01CB E0 =1 345 MOVX A, @DPTR 01CC =1 346 BumpDPTR: ; Returns (DPTR + ACC) 01CC 2582 =1 347 ADD A, DPL 01CE F582 =1 348 MOV DPL, A 01D0 5002 =1 349 JNC Skip 01D2 0583 =1 350 INC DPH ; Need 16 bit arithmetic here 01D4 22 =1 351 Skip: RET =1 352 01D5 =1 353 CorrectSubroutine: ; Jump to the subroutine that DPTR is pointing to 01D5 9001FA =1 354 MOV DPTR, #CommandTable 01D8 31CC =1 355 CALL BumpDPTR ; Point to entry 01DA E0 =1 356 MOVX A, @DPTR ; Get the offset 01DB 9001FA =1 357 MOV DPTR, #CommandTable 01DE 31CC =1 358 CALL BumpDPTR ; Get the routine address 01E0 C082 =1 359 PUSH DPL ; Create a RETURN address on stack 01E2 C083 =1 360 PUSH DPH ; Note: JMP @A+DPTR not used since A, DPTR needed 01E4 7845 =1 361 MOV R0, #ReplyBuffer+2 01E6 E4 =1 362 CLR A 01E7 F6 =1 363 MOV @R0, A ; Clear ReplyBuffer 01E8 18 =1 364 DEC R0 01E9 F6 =1 365 MOV @R0, A 01EA 18 =1 366 DEC R0 01EB 7601 =1 367 MOV @R0, #1 ; Default non-descriptor reply 01ED 907FEA =1 368 MOV DPTR, #SETUPDAT+2 ; Point to LOW(wValue) 01F0 E0 =1 369 MOVX A, @DPTR ; Many of the routines need these 01F1 F5F0 =1 370 MOV B, A ; LOW(wValue) in B 01F3 A3 =1 371 INC DPTR 01F4 E0 =1 372 MOVX A, @DPTR ; HIGH(wValue) in A 01F5 C201 =1 373 CLR STALL 01F7 C203 =1 374 CLR IsDescriptor 01F9 22 =1 375 RET ; Go to service routine =1 376 =1 377 ; Since the table only contains byte offsets, it is important that all these routines are =1 378 ; within one page (100H) of CommandTable =1 379 ; 01FA =1 380 CommandTable: =1 381 ; First 16 commands are for the Device 01FA 6D =1 382 DB Device_Get_Status - CommandTable 01FB 40 =1 383 DB Device_Clear_Feature - CommandTable 01FC 40 =1 384 DB Invalid - CommandTable 01FD 40 =1 385 DB Device_Set_Feature - CommandTable A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 7 01FE 40 =1 386 DB Invalid - CommandTable 01FF 40 =1 387 DB Invalid - CommandTable ; SIE implements Device_Set_Address 0200 81 =1 388 DB Get_Descriptor - CommandTable 0201 40 =1 389 DB Set_Descriptor - CommandTable 0202 6A =1 390 DB Get_Configuration - CommandTable 0203 74 =1 391 DB Set_Configuration - CommandTable 0204 40 =1 392 DB Invalid - CommandTable 0205 40 =1 393 DB Invalid - CommandTable 0206 40 =1 394 DB Invalid - CommandTable 0207 40 =1 395 DB Invalid - CommandTable 0208 40 =1 396 DB Invalid - CommandTable 0209 40 =1 397 DB Invalid - CommandTable =1 398 ; Next 16 commands are for the Interface 020A 71 =1 399 DB Interface_Get_Status - CommandTable 020B 40 =1 400 DB Interface_Clear_Feature - CommandTable 020C 40 =1 401 DB Invalid - CommandTable 020D 40 =1 402 DB Interface_Set_Feature - CommandTable 020E 40 =1 403 DB Invalid - CommandTable 020F 40 =1 404 DB Invalid - CommandTable 0210 A5 =1 405 DB Get_Class_Descriptor - CommandTable 0211 40 =1 406 DB Set_Class_Descriptor - CommandTable 0212 40 =1 407 DB Invalid - CommandTable 0213 40 =1 408 DB Invalid - CommandTable 0214 40 =1 409 DB Get_Interface - CommandTable 0215 40 =1 410 DB Set_Interface - CommandTable 0216 40 =1 411 DB Invalid - CommandTable 0217 40 =1 412 DB Invalid - CommandTable 0218 40 =1 413 DB Invalid - CommandTable 0219 40 =1 414 DB Invalid - CommandTable =1 415 ; Next 16 commands are for the Endpoint 021A 71 =1 416 DB Endpoint_Get_Status - CommandTable 021B 42 =1 417 DB Endpoint_Clear_Feature - CommandTable 021C 40 =1 418 DB Invalid - CommandTable 021D 40 =1 419 DB Endpoint_Set_Feature - CommandTable 021E 40 =1 420 DB Invalid - CommandTable 021F 40 =1 421 DB Invalid - CommandTable 0220 40 =1 422 DB Invalid - CommandTable 0221 40 =1 423 DB Invalid - CommandTable 0222 40 =1 424 DB Invalid - CommandTable 0223 40 =1 425 DB Invalid - CommandTable 0224 40 =1 426 DB Invalid - CommandTable 0225 40 =1 427 DB Invalid - CommandTable 0226 40 =1 428 DB Endpoint_Sync_Frame - CommandTable 0227 40 =1 429 DB Invalid - CommandTable 0228 40 =1 430 DB Invalid - CommandTable 0229 40 =1 431 DB Invalid - CommandTable =1 432 ; Next 16 commands are Class Requests 022A 40 =1 433 DB Invalid - CommandTable 022B 56 =1 434 DB Get_Report - CommandTable 022C 63 =1 435 DB Get_Idle - CommandTable 022D 40 =1 436 DB Get_Protocol - CommandTable 022E 40 =1 437 DB Invalid - CommandTable 022F 40 =1 438 DB Invalid - CommandTable 0230 40 =1 439 DB Invalid - CommandTable 0231 40 =1 440 DB Invalid - CommandTable 0232 40 =1 441 DB Invalid - CommandTable 0233 43 =1 442 DB Set_Report - CommandTable 0234 5D =1 443 DB Set_Idle - CommandTable 0235 40 =1 444 DB Set_Protocol - CommandTable 0236 40 =1 445 DB Invalid - CommandTable 0237 40 =1 446 DB Invalid - CommandTable 0238 40 =1 447 DB Invalid - CommandTable 0239 40 =1 448 DB Invalid - CommandTable =1 449 ; =1 450 ; Many requests are INVALID for this example 023A =1 451 Get_Protocol: ; We are not a Boot device A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 8 023A =1 452 Set_Protocol: ; We are not a Boot device 023A =1 453 Set_Descriptor: ; Our Descriptors are static 023A =1 454 Set_Class_Descriptor: ; Our Descriptors are static 023A =1 455 Set_Interface: ; We only have one Interface 023A =1 456 Get_Interface: ; We do not have an Alternate setting 023A =1 457 Device_Set_Feature: ; We have no features that can be set or cleared 023A =1 458 Interface_Set_Feature: ; We have no features that can be set or cleared 023A =1 459 Endpoint_Set_Feature: ; We have no features that can be set or cleared 023A =1 460 Device_Clear_Feature: ; We have no features that can be set or cleared 023A =1 461 Interface_Clear_Feature: ; We have no features that can be set or cleared 023A =1 462 Endpoint_Sync_Frame: ; We are not an Isonchronous device =1 463 023A =1 464 Invalid: ; Invalid Request made, STALL the Endpoint 023A D201 =1 465 SETB STALL =1 466 ; 023C =1 467 Endpoint_Clear_Feature: ; We have no features that can be set or cleared =1 468 ; 023C 22 =1 469 Reply: RET =1 470 023D =1 471 Set_Report: ; Host wants to sent us a Report. =1 472 ; The ONLY case in this example where host sends data to us 023D 3000FA =1 473 JNB Configured, Invalid ; Need to be Configured to do this command 0240 907FC5 =1 474 MOV DPTR, #Out0ByteCount ; Enable EP0OutBuffer to receive data 0243 F0 =1 475 MOVX @DPTR, A ; Any value will do 0244 907FAA =1 476 MOV DPTR, #OUT07IRQ ; Wait for valid data in EP0OutBuffer 0247 E0 =1 477 Wait4D: MOVX A, @DPTR 0248 5401 =1 478 ANL A, #00000001b 024A 60FB =1 479 JZ Wait4D 024C F0 =1 480 MOVX @DPTR, A ; Clear the interrupt 024D 0203CA =1 481 JMP ProcessOutputReport ; RETurn via this subroutine 0250 =1 482 Get_Report: ; Host wants a Report 0250 3000E7 =1 483 JNB Configured, Invalid ; Need to be Configured to do this command 0253 08 =1 484 INC R0 ; Point to ReplyBuffer(1) 0254 7618 =1 485 MOV @R0, #18H ; Reply with a recognizable (arbitary) value 0256 22 =1 486 RET 0257 =1 487 Set_Idle: ; Host wants to tell us how often we should talk 0257 3000E0 =1 488 JNB Configured, Invalid ; Need to be Configured to do this command 025A F541 =1 489 MOV Idle_Time, A 025C 22 =1 490 RET ; Handshake with host 025D =1 491 Get_Idle: ; Host must have forgotten what he told us to do 025D 3000DA =1 492 JNB Configured, Invalid ; Need to be Configured to do this command 0260 08 =1 493 INC R0 ; Point to ReplyBuffer(1) 0261 A641 =1 494 MOV @R0, Idle_Time 0263 22 =1 495 RET 0264 =1 496 Get_Configuration: 0264 3000D5 =1 497 JNB Configured, Reply =1 498 ; If configured return a 1 (via Device_Get_Status) 0267 =1 499 Device_Get_Status: ; Only two bits of Device Status are defined 0267 08 =1 500 INC R0 ; Point to ReplyBuffer(1) 0268 7601 =1 501 MOV @R0, #1 ; Bit 1=Remote Wakeup(=0), Bit 0=Self Powered(=1) 026A 22 =1 502 RET =1 503 026B =1 504 Interface_Get_Status: ; Interface Status is currently defined as 0 026B =1 505 Endpoint_Get_Status: 026B 7602 =1 506 MOV @R0, #2 026D 22 =1 507 RET 026E =1 508 Set_Configuration: ; Valid values are 0 and 1 026E E5F0 =1 509 MOV A, B ; Get LOW(wValue) 0270 6006 =1 510 JZ Deconfigured 0272 14 =1 511 DEC A 0273 70C5 =1 512 JNZ Invalid 0275 D200 =1 513 SETB Configured 0277 22 =1 514 RET 0278 =1 515 Deconfigured: 0278 C200 =1 516 CLR Configured 027A 22 =1 517 RET A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 9 027B =1 518 Get_Descriptor: ; Host wants to know who/what we are 027B D203 =1 519 SETB IsDescriptor 027D 14 =1 520 DEC A ; Valid Values are 1, 2 and 3 027E 9002C5 =1 521 MOV DPTR, #DeviceDescriptor 0281 60B9 =1 522 JZ Reply 0283 14 =1 523 DEC A 0284 9002D7 =1 524 MOV DPTR, #ConfigurationDescriptor 0287 60B3 =1 525 JZ Reply 0289 14 =1 526 DEC A 028A 70AE =1 527 JNZ Invalid =1 528 ; Request is for a String Descriptor 028C 900316 =1 529 MOV DPTR, #String0 ; Point to String 0 028F E5F0 =1 530 MOV A, B ; Get String Index 0291 =1 531 NextString: 0291 601E =1 532 JZ FixUpthenReply 0293 F540 =1 533 MOV Temp, A ; Save String Index 0295 31CB =1 534 CALL NextDPTR 0297 E0 =1 535 MOVX A, @DPTR ; Get the String Length (= 0 means we're at Backsto p) 0298 60A0 =1 536 JZ Invalid ; Asked for a string I don't have 029A E540 =1 537 MOV A, Temp 029C 14 =1 538 DEC A 029D 80F2 =1 539 JMP NextString ; Check if we are there yet 029F =1 540 Get_Class_Descriptor: ; Valid values are 21H, 22H, 23H for Class Request 029F D203 =1 541 SETB IsDescriptor 02A1 C3 =1 542 CLR C 02A2 9421 =1 543 SUBB A, #21H 02A4 9002E9 =1 544 MOV DPTR, #HIDDescriptor 02A7 6093 =1 545 JZ Reply 02A9 14 =1 546 DEC A 02AA 9002F9 =1 547 MOV DPTR, #ReportDescriptor 02AD 608D =1 548 JZ Reply =1 549 ; DEC A ; This example does not use Physical Descriptors =1 550 ; JZ Send_Physical_Descriptor 02AF 8089 =1 551 JMP Invalid =1 552 ; =1 553 ; Error check: this MUST be on within a page of CommandTable 00B7 =1 554 WithinSamePage EQU $ - CommandTable =1 555 ; 02B1 =1 556 FixUpthenReply: ; EZ-USB Rev D has a String Descriptor bug =1 557 ; Need to fill the IN0BUF (@ 7F00H) myself 02B1 E0 =1 558 MOVX A, @DPTR ; Get the string length 02B2 FF =1 559 MOV R7, A ; Save counter 02B3 F5F0 =1 560 MOV B, A 02B5 7800 =1 561 MOV R0, #LOW(EP0InBuffer) ; PageReg = 7FH = HIGH(EP0InBuffer) 02B7 F2 =1 562 CopySD: MOVX @R0, A 02B8 08 =1 563 INC R0 02B9 A3 =1 564 INC DPTR 02BA E0 =1 565 MOVX A, @DPTR 02BB DFFA =1 566 DJNZ R7, CopySD =1 567 ; Fixup complete, get back to the program flow 02BD D0E0 =1 568 POP ACC ; Get rid of the return address 02BF D0E0 =1 569 POP ACC 02C1 E5F0 =1 570 MOV A, B ; Retrieve byte count 02C3 21A9 =1 571 JMP SendEP0InBuffer 572 $INCLUDE(DTables.A51) =1 573 ; This module declares the descriptors =1 574 ; =1 575 ; This example has one Device Descriptor with: =1 576 ; One Configuration - single IN port and single OUT port =1 577 ; One Interface - there is only one method of accessing the ports =1 578 ; One HID Descriptor - to make PC host software simpler =1 579 ; One Endpoint Descriptor - for HID Input Reports =1 580 ; One Report Descriptor - 40 byte IN and 40 byte OUT reports =1 581 ; Multiple Sting Descriptors - to aid the user =1 582 ; A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 10 ---- =1 583 CSEG 02C5 =1 584 DeviceDescriptor: 02C5 1201 =1 585 DB 18, 1 ; Length, Type 02C7 0101 =1 586 DW 101H ; USB Rev 1.1 02C9 000000 =1 587 DB 0, 0, 0 ; Class, Subclass and Protocol 02CC 40 =1 588 DB 64 ; EP0 size 02CD 4242 =1 589 DW 4242H, 1, 1 ; Vendor ID, Product ID and Version 02CF 0001 02D1 0001 02D3 010200 =1 590 DB 1, 2, 0 ; Manufacturer, Product & Serial# Names 02D6 01 =1 591 DB 1 ; #Configs 02D7 =1 592 ConfigurationDescriptor: 02D7 0902 =1 593 DB 9, 2 ; Length, Type 02D9 2200 =1 594 DB LOW(ConfigLength), HIGH(ConfigLength) 02DB 010100 =1 595 DB 1, 1, 0 ; #Interfaces, Configuration#, Config. Name 02DE 80 =1 596 DB 10000000b ; Attributes = Bus Powered 02DF 32 =1 597 DB 50 ; Max. Power is 50x2 = 100mA 02E0 =1 598 InterfaceDescriptor: 02E0 0904 =1 599 DB 9, 4 ; Length, Type 02E2 000001 =1 600 DB 0, 0, 1 ; No alternate setting, HID uses EP1 02E5 03 =1 601 DB 3 ; Class = Human Interface Device 02E6 0000 =1 602 DB 0, 0 ; Subclass and Protocol 02E8 00 =1 603 DB 0 ; Interface Name 02E9 =1 604 HIDDescriptor: 02E9 0921 =1 605 DB 9, 21H ; Length, Type 02EB 0001 =1 606 DB 0, 1 ; HID Class Specification compliance 02ED 00 =1 607 DB 0 ; Country localization (=none) 02EE 01 =1 608 DB 1 ; Number of descriptors to follow 02EF 22 =1 609 DB 22H ; And it's a Report descriptor 02F0 1D00 =1 610 DB LOW(ReportLength), HIGH(ReportLength) 02F2 =1 611 EndpointDescriptor: 02F2 0705 =1 612 DB 7, 5 ; Length, Type 02F4 81 =1 613 DB 10000001b ; Address = IN 1 02F5 03 =1 614 DB 00000011b ; Interrupt 02F6 4000 =1 615 DB 64, 0 ; Maximum packet size (this example only uses 1) 02F8 64 =1 616 DB 100 ; Poll every 0.1 seconds 0022 =1 617 ConfigLength EQU $ - ConfigurationDescriptor =1 618 02F9 =1 619 ReportDescriptor: ; Generated with HID Tool, copied to here 02F9 0600FF =1 620 DB 6, 0, 0FFH ; Usage_Page (Vendor Defined) 02FC 0901 =1 621 DB 9, 1 ; Usage (I/O Device) 02FE A101 =1 622 DB 0A1H, 1 ; Collection (Application) 0300 1901 =1 623 DB 19H, 1 ; Usage_Minimum 0302 2902 =1 624 DB 29H, 2 ; Usage_Maximum 0304 1500 =1 625 DB 15H, 0 ; Logical_Minimum (0) 0306 26FF00 =1 626 DB 26H, 255, 0 ; Logical_Maximum (255) 0309 7508 =1 627 DB 75H, 8 ; Report_Size (8) 030B 9528 =1 628 DB 95H, 40 ; Report_Count (40) 030D 8102 =1 629 DB 81H, 2 ; Input (Data,Var,Abs) = DOTs 030F 1901 =1 630 DB 19H, 1 ; Usage_Minimum 0311 2902 =1 631 DB 29H, 2 ; Usage_Maximum 0313 9102 =1 632 DB 91H, 2 ; Output (Data,Var,Abs) = Text or DOTs 0315 C0 =1 633 DB 0C0H ; End_Collection 001D =1 634 ReportLength EQU $-ReportDescriptor =1 635 0316 =1 636 String0: ; Declare the UNICODE strings 0316 04030904 =1 637 DB 4, 3, 9, 4 ; Only English language strings supported 031A =1 638 String1: ; Manufacturer 031A 2C03 =1 639 DB (String2-String1),3 ; Length, Type 031C 55005300 =1 640 DB "U",0,"S",0,"B",0," ",0,"D",0,"e",0,"s",0,"i",0,"g",0,"n",0," ", 0 0320 42002000 0324 44006500 0328 73006900 032C 67006E00 0330 2000 0332 42007900 =1 641 DB "B",0,"y",0," ",0,"E",0,"x",0,"a",0,"m",0,"p",0,"l",0,"e",0 A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 11 0336 20004500 033A 78006100 033E 6D007000 0342 6C006500 0346 =1 642 String2: ; Product Name 0346 1A03 =1 643 DB (EndOfDescriptors-String2),3 0348 52006500 =1 644 DB "R",0,"e",0,"a",0,"d",0,"e",0,"r",0 034C 61006400 0350 65007200 0354 20004200 =1 645 DB " ",0,"B",0,"o",0,"a",0,"r",0,"d",0 0358 6F006100 035C 72006400 0360 =1 646 EndOfDescriptors: 0360 0000 =1 647 DW 0 ; Backstop for String Descriptors =1 648 =1 649 =1 650 651 $INCLUDE(Main.A51) =1 652 ; This module initializes the microcontroller then executes MAIN forever =1 653 ; =1 654 0362 =1 655 Reset: 0362 7581EB =1 656 MOV SP, #235 ; Initialize the Stack at top of internal memory 0365 75927F =1 657 MOV PageReg, #7FH ; Needed to use MOVX @Ri =1 658 0368 78D6 =1 659 MOV R0, #LOW(USBControl) ; Simulate a disconnect 036A E2 =1 660 MOVX A, @R0 036B 54F3 =1 661 ANL A, #11110011b ; Clear DISCON, DISCOE 036D F2 =1 662 MOVX @R0, A 036E 1203B9 =1 663 CALL Wait100msec ; Give the host time to react 0371 E2 =1 664 MOVX A, @R0 ; Reconnect with this new identity 0372 4406 =1 665 ORL A, #00000110b ; Set DISCOE to enable pullup resistor 0374 F2 =1 666 MOVX @R0, A ; Set RENUM so that 8051 handles USB requests 0375 E4 =1 667 CLR A 0376 F520 =1 668 MOV FLAGS, A ; Start in Default state 0378 F546 =1 669 MOV CurrentConfiguration, A ; This example supports two configurations 037A 7848 =1 670 MOV R0, #DisplayPosition ; Note LEDBuffer follows DisplayPosition 037C 7F2B =1 671 MOV R7, #43 037E 7408 =1 672 MOV A, #8 ; Display a horizontal line 0380 =1 673 ClearDisplay: 0380 F6 =1 674 MOV @R0, A 0381 08 =1 675 INC R0 0382 DFFC =1 676 DJNZ R7, ClearDisplay =1 677 0384 =1 678 InitializeIOSystem: ; This example uses PortA an IN/OUT and =1 679 ; the lower 4 bits of PortC as OUT =1 680 ; Assume a pre-existing configuration (ie Dscope) 0384 7893 =1 681 MOV R0, #LOW(PortA_Config) ; PageReg = 7F = HIGH(PortA_Config) 0386 E4 =1 682 CLR A 0387 F2 =1 683 MOVX @R0, A ; No alternate functions 0388 799C =1 684 MOV R1, #LOW(PortA_OE) 038A F4 =1 685 CPL A ; = 0FFH 038B F3 =1 686 MOVX @R1, A ; Enable PortA for Output 038C 7895 =1 687 MOV R0, #LOW(PortC_Config) ; PageReg = 7F = HIGH(PortC_Config) 038E 799E =1 688 MOV R1, #LOW(PortC_OE) 0390 E2 =1 689 MOVX A, @R0 ; Get current configuration 0391 54F0 =1 690 ANL A, #0F0H 0393 F2 =1 691 MOVX @R0, A ; No alternate functions on lower nibble 0394 E3 =1 692 MOVX A, @R1 ; Get current configuration 0395 440F =1 693 ORL A, #0FH 0397 F3 =1 694 MOVX @R1, A ; Enable PortC_Bits[3:0] for Output 0398 7898 =1 695 MOV R0, #LOW(PortC_Out) 039A E2 =1 696 MOVX A, @R0 039B 54F0 =1 697 ANL A, #0F0H 039D F2 =1 698 MOVX @R0, A ; Set Bits [3:0] low =1 699 A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 12 039E =1 700 InitializeInterruptSystem: ; First initialize the USB level 039E 78AC =1 701 MOV R0, #LOW(IN07IEN) 03A0 F2 =1 702 MOVX @R0, A ; Disable interrupts from IN Endpoints 0-7 03A1 08 =1 703 INC R0 03A2 F2 =1 704 MOVX @R0, A ; Disable interrupts from OUT Endpoints 0-7 03A3 08 =1 705 INC R0 03A4 7403 =1 706 MOV A, #00000011b 03A6 F2 =1 707 MOVX @R0, A ; Enable (Resume, Suspend,) SOF and SUDAV INTs 03A7 08 =1 708 INC R0 03A8 7401 =1 709 MOV A, #00000001b 03AA F2 =1 710 MOVX @R0, A ; Enable Auto Vectoring for USB interrupts 03AB 78AA =1 711 MOV R0, #LOW(OUT07IRQ) 03AD 74FF =1 712 MOV A, #0FFH 03AF F2 =1 713 MOVX @R0, A ; Clear out any pending interrupts =1 714 ; Now enable the main level 03B0 75E801 =1 715 MOV EIE, #00000001b ; Enable INT2 = USB Interrupt (only) 03B3 75A8C0 =1 716 MOV EI, #11000000b ; Enable interrupt subsystem (and Ser1 for Dscope) =1 717 =1 718 ; Initialization Complete. =1 719 ; 03B6 =1 720 MAIN: 03B6 00 =1 721 NOP ; Not much of a main loop for this example 03B7 80FD =1 722 JMP MAIN ; All actions are initiated by interrupts =1 723 ; We are a slave, we wait to be told what to do =1 724 03B9 =1 725 Wait100msec: 03B9 754064 =1 726 MOV Temp, #100 03BC =1 727 Wait1msec: ; A delay loop 03BC 90FB50 =1 728 MOV DPTR, #-1200 03BF A3 =1 729 More: INC DPTR ; 3 cycles 03C0 E582 =1 730 MOV A, DPL ; + 2 03C2 4583 =1 731 ORL A, DPH ; + 2 03C4 70F9 =1 732 JNZ More ; + 3 = 10 cycles x 1200 = 1msec 03C6 D540F3 =1 733 DJNZ Temp, Wait1msec 03C9 22 =1 734 RET =1 735 03CA =1 736 ProcessOutputReport: ; A Report has just been received =1 737 ; The report is 7 characters long and must be translated into a dot pattern 03CA 758601 =1 738 MOV DPS, #1 ; Select the other Data Pointer 03CD 907EC0 =1 739 MOV DPTR, #EP0OutBuffer ; Point to the Report 03D0 7849 =1 740 MOV R0, #LEDBuffer 03D2 7F07 =1 741 MOV R7, #7 ; Have room for 7 characters 03D4 E0 =1 742 ORLoop: MOVX A, @DPTR 03D5 30E702 =1 743 JNB ACC.7, Skip1 ; Valid Characters are 20H to 7FH 03D8 743F =1 744 MOV A, #3FH ; Replace characters > 7FH with ? 03DA C3 =1 745 Skip1: CLR C 03DB 9420 =1 746 SUBB A, #20H 03DD 5002 =1 747 JNC Skip2 03DF 743C =1 748 MOV A, #3CH ; Replace characters < 20H with [] 03E1 75F005 =1 749 Skip2: MOV B, #5 03E4 A4 =1 750 MUL AB ; B = HI((Char-20H)*5), A = LOW 03E5 0586 =1 751 INC DPS ; Swap to DPTR0 03E7 90041A =1 752 MOV DPTR, #LookupTable 03EA 2582 =1 753 ADD A, DPL 03EC F582 =1 754 MOV DPL, A 03EE E5F0 =1 755 MOV A, B 03F0 3583 =1 756 ADDC A, DPH 03F2 F583 =1 757 MOV DPH, A ; DPTR now pointing into Lookup Table 03F4 7E05 =1 758 MOV R6, #5 03F6 E0 =1 759 LTCopy: MOVX A, @DPTR 03F7 F6 =1 760 MOV @R0, A 03F8 A3 =1 761 INC DPTR 03F9 08 =1 762 INC R0 03FA DEFA =1 763 DJNZ R6, LTCopy 03FC 7600 =1 764 MOV @R0, #0 ; Put a space between characters 03FE 08 =1 765 INC R0 A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 13 03FF 0586 =1 766 INC DPS ; Switch to DPTR1 0401 A3 =1 767 INC DPTR ; Point to next character in Output Report 0402 DFD0 =1 768 DJNZ R7, ORLoop 0404 0586 =1 769 INC DPS ; Return DPTR to DPTR0 =1 770 ; Fall into CreateInputReport 0406 =1 771 CreateInputReport: =1 772 ; The report is 40 bytes long in this example =1 773 ; It contains the LED Buffer 0406 907E80 =1 774 MOV DPTR, #EP1InBuffer ; Point to the buffer 0409 7849 =1 775 MOV R0, #LEDBuffer 040B 7F28 =1 776 MOV R7, #40 040D E6 =1 777 IRLoop: MOV A, @R0 040E F0 =1 778 MOVX @DPTR, A 040F A3 =1 779 INC DPTR 0410 08 =1 780 INC R0 0411 DFFA =1 781 DJNZ R7, IRLoop 0413 907FB7 =1 782 MOV DPTR, #IN1ByteCount 0416 7428 =1 783 MOV A, #40 0418 F0 =1 784 MOVX @DPTR, A ; Endpoint 1 now 'armed', next IN will get data 0419 22 =1 785 RET =1 786 041A =1 787 LookupTable: ; Contains the 5 columns of the 7x5 display 041A 00000000 =1 788 DB 00H,00H,00H,00H,00H ; SPACE 041E 00 041F 00007D00 =1 789 DB 00H,00H,7DH,00H,00H ; ! 0423 00 0424 00700070 =1 790 DB 00H,70H,00H,70H,00H ; " 0428 00 0429 147F147F =1 791 DB 14H,7FH,14H,7FH,14H ; # 042D 14 042E 122A7F2A =1 792 DB 12H,2AH,7FH,2AH,24H ; $ 0432 24 0433 62640813 =1 793 DB 62H,64H,08H,13H,23H ; % 0437 23 0438 36495522 =1 794 DB 36H,49H,55H,22H,05H ; & 043C 05 043D 00506000 =1 795 DB 00H,50H,60H,00H,00H ; ' 0441 00 0442 001C2241 =1 796 DB 00H,1CH,22H,41H,00H ; ( 0446 00 0447 0041221C =1 797 DB 00H,41H,22H,1CH,00H ; ) 044B 00 044C 14083E08 =1 798 DB 14H,08H,3EH,08H,14H ; * 0450 14 0451 08083E08 =1 799 DB 08H,08H,3EH,08H,08H ; + 0455 08 0456 00050600 =1 800 DB 00H,05H,06H,00H,00H ; , 045A 00 045B 08080808 =1 801 DB 08H,08H,08H,08H,08H ; - 045F 08 0460 00030300 =1 802 DB 00H,03H,03H,00H,00H ; . 0464 00 0465 02040810 =1 803 DB 02H,04H,08H,10H,20H ; / 0469 20 046A 3E454951 =1 804 DB 3EH,45H,49H,51H,3EH ; 0 046E 3E 046F 00217F01 =1 805 DB 00H,21H,7FH,01H,00H ; 1 0473 00 0474 21434549 =1 806 DB 21H,43H,45H,49H,31H ; 2 0478 31 0479 42415169 =1 807 DB 42H,41H,51H,69H,46H ; 3 047D 46 047E 0C14247F =1 808 DB 0CH,14H,24H,7FH,04H ; 4 0482 04 0483 72515151 =1 809 DB 72H,51H,51H,51H,4EH ; 5 0487 4E A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 14 0488 1E294949 =1 810 DB 1EH,29H,49H,49H,06H ; 6 048C 06 048D 40474850 =1 811 DB 40H,47H,48H,50H,60H ; 7 0491 60 0492 36494949 =1 812 DB 36H,49H,49H,49H,36H ; 8 0496 36 0497 3049494A =1 813 DB 30H,49H,49H,4AH,3CH ; 9 049B 3C 049C 00333300 =1 814 DB 00H,33H,33H,00H,00H ; : 04A0 00 04A1 00656600 =1 815 DB 00H,65H,66H,00H,00H ; ; 04A5 00 04A6 00081422 =1 816 DB 00H,08H,14H,22H,41H ; < 04AA 41 04AB 14141414 =1 817 DB 14H,14H,14H,14H,14H ; = 04AF 14 04B0 41221408 =1 818 DB 41H,22H,14H,08H,00H ; > 04B4 00 04B5 20404548 =1 819 DB 20H,40H,45H,48H,30H ; ? 04B9 30 04BA 26494F41 =1 820 DB 26H,49H,4FH,41H,3EH ; @ 04BE 3E 04BF 3F484848 =1 821 DB 3FH,48H,48H,48H,3FH ; A 04C3 3F 04C4 7F494949 =1 822 DB 7FH,49H,49H,49H,36H ; B 04C8 36 04C9 3E414141 =1 823 DB 3EH,41H,41H,41H,22H ; C 04CD 22 04CE 7F414122 =1 824 DB 7FH,41H,41H,22H,1CH ; D 04D2 1C 04D3 7F494949 =1 825 DB 7FH,49H,49H,49H,41H ; E 04D7 41 04D8 7F484848 =1 826 DB 7FH,48H,48H,48H,40H ; F 04DC 40 04DD 3E414949 =1 827 DB 3EH,41H,49H,49H,2FH ; G 04E1 2F 04E2 7F080808 =1 828 DB 7FH,08H,08H,08H,7FH ; H 04E6 7F 04E7 00417F41 =1 829 DB 00H,41H,7FH,41H,00H ; I 04EB 00 04EC 0201417E =1 830 DB 02H,01H,41H,7EH,40H ; J 04F0 40 04F1 7F081422 =1 831 DB 7FH,08H,14H,22H,41H ; K 04F5 41 04F6 7F010101 =1 832 DB 7FH,01H,01H,01H,01H ; L 04FA 01 04FB 7F201820 =1 833 DB 7FH,20H,18H,20H,7FH ; M 04FF 7F 0500 7F100804 =1 834 DB 7FH,10H,08H,04H,7FH ; N 0504 7F 0505 3E414141 =1 835 DB 3EH,41H,41H,41H,3EH ; O 0509 3E 050A 7F484848 =1 836 DB 7FH,48H,48H,48H,30H ; P 050E 30 050F 3E414542 =1 837 DB 3EH,41H,45H,42H,3DH ; Q 0513 3D 0514 7F484C4A =1 838 DB 7FH,48H,4CH,4AH,31H ; R 0518 31 0519 31494949 =1 839 DB 31H,49H,49H,49H,46H ; S 051D 46 051E 40407F40 =1 840 DB 40H,40H,7FH,40H,40H ; T 0522 40 0523 7E010101 =1 841 DB 7EH,01H,01H,01H,7EH ; U 0527 7E 0528 7C020102 =1 842 DB 7CH,02H,01H,02H,7CH ; V 052C 7C A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 15 052D 7E010E01 =1 843 DB 7EH,01H,0EH,01H,7EH ; W 0531 7E 0532 63140814 =1 844 DB 63H,14H,08H,14H,63H ; X 0536 63 0537 70080708 =1 845 DB 70H,08H,07H,08H,70H ; Y 053B 70 053C 43454951 =1 846 DB 43H,45H,49H,51H,61H ; Z 0540 61 0541 007F4141 =1 847 DB 00H,7FH,41H,41H,00H ; [ 0545 00 0546 7F414141 =1 848 DB 7FH,41H,41H,41H,7FH ; [] 054A 7F 054B 0041417F =1 849 DB 00H,41H,41H,7FH,00H ; ] 054F 00 0550 10204020 =1 850 DB 10H,20H,40H,20H,10H ; ^ 0554 10 0555 01010101 =1 851 DB 01H,01H,01H,01H,01H ; _ 0559 01 055A 00402010 =1 852 DB 00H,40H,20H,10H,00H ; \ 055E 00 055F 02151515 =1 853 DB 02H,15H,15H,15H,0FH ; a 0563 0F 0564 7F091111 =1 854 DB 7FH,09H,11H,11H,0EH ; b 0568 0E 0569 0E111111 =1 855 DB 0EH,11H,11H,11H,02H ; c 056D 02 056E 0E111109 =1 856 DB 0EH,11H,11H,09H,7FH ; d 0572 7F 0573 0E151515 =1 857 DB 0EH,15H,15H,15H,0CH ; e 0577 0C 0578 083F4840 =1 858 DB 08H,3FH,48H,40H,20H ; f 057C 20 057D 18252525 =1 859 DB 18H,25H,25H,25H,3EH ; g 0581 3E 0582 7F081010 =1 860 DB 7FH,08H,10H,10H,0FH ; h 0586 0F 0587 00115F01 =1 861 DB 00H,11H,5FH,01H,00H ; i 058B 00 058C 0201115E =1 862 DB 02H,01H,11H,5EH,00H ; j 0590 00 0591 7F040A11 =1 863 DB 7FH,04H,0AH,11H,00H ; k 0595 00 0596 00417F01 =1 864 DB 00H,41H,7FH,01H,00H ; l 059A 00 059B 1F100C10 =1 865 DB 1FH,10H,0CH,10H,0FH ; m 059F 0F 05A0 1F081010 =1 866 DB 1FH,08H,10H,10H,0FH ; n 05A4 0F 05A5 0E111111 =1 867 DB 0EH,11H,11H,11H,0EH ; o 05A9 0E 05AA 1F141414 =1 868 DB 1FH,14H,14H,14H,08H ; p 05AE 08 05AF 08141414 =1 869 DB 08H,14H,14H,14H,1FH ; q 05B3 1F 05B4 1F081010 =1 870 DB 1FH,08H,10H,10H,08H ; r 05B8 08 05B9 09151515 =1 871 DB 09H,15H,15H,15H,02H ; s 05BD 02 05BE 107E1101 =1 872 DB 10H,7EH,11H,01H,02h ; t 05C2 02 05C3 1E010101 =1 873 DB 1EH,01H,01H,01H,1FH ; u 05C7 1F 05C8 1C020102 =1 874 DB 1CH,02H,01H,02H,1CH ; v 05CC 1C 05CD 1E010601 =1 875 DB 1EH,01H,06H,01H,1EH ; w 05D1 1E A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 16 05D2 110A040A =1 876 DB 11H,0AH,04H,0AH,11H ; x 05D6 11 05D7 18050505 =1 877 DB 18H,05H,05H,05H,1EH ; y 05DB 1E 05DC 11131519 =1 878 DB 11H,13H,15H,19H,11H ; z 05E0 11 05E1 00083641 =1 879 DB 00H,08H,36H,41H,00H ; { 05E5 00 05E6 00007F00 =1 880 DB 00H,00H,7FH,00H,00H ; | 05EA 00 05EB 00413608 =1 881 DB 00H,41H,36H,08H,00H ; } 05EF 00 05F0 08082A1C =1 882 DB 08H,08H,2AH,1CH,08H ; -> 05F4 08 05F5 081C2A08 =1 883 DB 08H,1CH,2AH,08H,08H ; <- 05F9 08 =1 884 885 $INCLUDE(Timer.A51) =1 886 ; This module services the real time interrupt =1 887 ; =1 888 ; Get a Real Time interrupt every One millisecond (using SOF interrupt) =1 889 ; =1 890 ; Strobe the Reader Board columns every 25msec so that no flicker is evident =1 891 ; The circuitry is shown in Figure 6-22 except that Port C is used not Port B =1 892 ; Pin assignment of Port C is: =1 893 ; Bit 0 = Clock =1 894 ; Bit 1 = Data =1 895 ; Bit 2 = Reset =1 896 ; Bit 3 = DIR/OE (0 = Write LEDs, 1 = Read Buttons) 05FA =1 897 ServiceTimerRoutine: 05FA D54A37 =1 898 DJNZ Msec_counter, Done ; Only need to react every 25msec 05FD 754A19 =1 899 MOV Msec_counter, #25 ; Reinitialize =1 900 0600 =1 901 SetupPointers: 0600 7898 =1 902 MOV R0, #Low(PortC_OUT) ; Will strobe the hardware here 0602 7996 =1 903 MOV R1, #Low(PortA_OUT) ; Will output data to here 0604 7A01 =1 904 MOV R2, #0001 ; PortC, Code for Clock Hi =1 905 0606 E548 =1 906 MOV A, DisplayPosition ; Which column are we currently displaying 0608 B4271A =1 907 CJNE A, #39, NextColumn 060B =1 908 ReadButtons: ; Before each full scan 060B 907F9C =1 909 MOV DPTR, #PortA_OE ; Need to flip Port A 060E E4 =1 910 CLR A 060F F0 =1 911 MOVX @DPTR, A ; Setup Port A for INPUT 0610 740C =1 912 MOV A, #01100b ; Set DIR and Reset = 1 0612 F2 =1 913 MOVX @R0, A ; Enable hardware to input 0613 7999 =1 914 MOV R1, #Low(PortA_Pins) 0615 E3 =1 915 MOVX A, @R1 ; Get Port A data and save for a later Report 0616 F547 =1 916 MOV ButtonsValue, A ; 0618 7996 =1 917 MOV R1, #Low(PortA_OUT) 061A 7410 =1 918 MOV A, #0010H ; Set DIR and Reset = 0 and Data = 1 061C F2 =1 919 MOVX @R0, A 061D 74FF =1 920 MOV A, #0FFH 061F F0 =1 921 MOVX @DPTR, A ; Setup Port A for OUTPUT 0620 7A0B =1 922 MOV R2, #0011 ; PortC, Code for Data and Clock = 1 0622 7548FF =1 923 MOV DisplayPosition, #-1 ; Allow for later INC 0625 =1 924 NextColumn: 0625 E4 =1 925 CLR A ; First clear display to prevent ghosting 0626 F3 =1 926 MOVX @R1, A ; Write to Port A 0627 EA =1 927 MOV A, R2 ; = 00x1, x = Data = 1 on Column 0, else 0 0628 F2 =1 928 MOVX @R0, A ; Set clock HI to select next column 0629 E4 =1 929 CLR A ; Set Data and Clock Low 062A F2 =1 930 MOVX @R0, A ; Complete strobe of hardware 062B 0548 =1 931 INC DisplayPosition ; Point to next row of dots 062D E548 =1 932 MOV A, DisplayPosition 062F 2449 =1 933 ADD A, #LEDBuffer ; Index into LED Buffer A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 17 0631 F8 =1 934 MOV R0, A 0632 E6 =1 935 MOV A, @R0 ; Get the next row of dots 0633 F3 =1 936 MOVX @R1, A ; Update the display 0634 22 =1 937 Done: Ret =1 938 939 940 END A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 18 SYMBOL TABLE LISTING ------ ----- ------- N A M E T Y P E V A L U E ATTRIBUTES ACC . . . . . . . . . . . D ADDR 00E0H A B . . . . . . . . . . . . D ADDR 00F0H A BADREQUEST. . . . . . . . C ADDR 01C6H A BUMPDPTR. . . . . . . . . C ADDR 01CCH A BUTTONSVALUE. . . . . . . D ADDR 0047H A CLEARDISPLAY. . . . . . . C ADDR 0380H A CLEARINT2 . . . . . . . . C ADDR 0119H A COMMANDTABLE. . . . . . . C ADDR 01FAH A CONFIGLENGTH. . . . . . . N NUMB 0022H A CONFIGURATIONDESCRIPTOR . C ADDR 02D7H A CONFIGURED. . . . . . . . B ADDR 0020H.0 A COPYRB. . . . . . . . . . C ADDR 01A0H A COPYSD. . . . . . . . . . C ADDR 02B7H A CORRECTSUBROUTINE . . . . C ADDR 01D5H A CREATEINPUTREPORT . . . . C ADDR 0406H A CURRENTCONFIGURATION. . . D ADDR 0046H A CURRENTPOSITION . . . . . D ADDR 0047H A DECONFIGURED. . . . . . . C ADDR 0278H A DEVICEDESCRIPTOR. . . . . C ADDR 02C5H A DEVICE_CLEAR_FEATURE. . . C ADDR 023AH A DEVICE_GET_STATUS . . . . C ADDR 0267H A DEVICE_SET_FEATURE. . . . C ADDR 023AH A DISPLAYPOSITION . . . . . D ADDR 0048H A DONE. . . . . . . . . . . C ADDR 0634H A DPH . . . . . . . . . . . D ADDR 0083H A DPL . . . . . . . . . . . D ADDR 0082H A DPS . . . . . . . . . . . D ADDR 0086H A EI. . . . . . . . . . . . D ADDR 00A8H A EICON . . . . . . . . . . D ADDR 00D8H A EIE . . . . . . . . . . . D ADDR 00E8H A ENDOFDESCRIPTORS. . . . . C ADDR 0360H A ENDPOINTDESCRIPTOR. . . . C ADDR 02F2H A ENDPOINT_CLEAR_FEATURE. . C ADDR 023CH A ENDPOINT_GET_STATUS . . . C ADDR 026BH A ENDPOINT_SET_FEATURE. . . C ADDR 023AH A ENDPOINT_SYNC_FRAME . . . C ADDR 023AH A EP0CONTROL. . . . . . . . N NUMB 7FB4H A EP0INBUFFER . . . . . . . N NUMB 7F00H A EP0IN_ISR . . . . . . . . C ADDR 0118H A EP0OUTBUFFER. . . . . . . N NUMB 7EC0H A EP0OUT_ISR. . . . . . . . C ADDR 0118H A EP1INBUFFER . . . . . . . N NUMB 7E80H A EP1IN_ISR . . . . . . . . C ADDR 0118H A EP1OUT_ISR. . . . . . . . C ADDR 0118H A EP2IN_ISR . . . . . . . . C ADDR 0118H A EP2OUT_ISR. . . . . . . . C ADDR 0118H A EP3IN_ISR . . . . . . . . C ADDR 0118H A EP3OUT_ISR. . . . . . . . C ADDR 0118H A EP4IN_ISR . . . . . . . . C ADDR 0118H A EP4OUT_ISR. . . . . . . . C ADDR 0118H A EP5IN_ISR . . . . . . . . C ADDR 0118H A EP5OUT_ISR. . . . . . . . C ADDR 0118H A EP6IN_ISR . . . . . . . . C ADDR 0118H A EP6OUT_ISR. . . . . . . . C ADDR 0118H A EP7IN_ISR . . . . . . . . C ADDR 0118H A EP7OUT_ISR. . . . . . . . C ADDR 0118H A EXIF. . . . . . . . . . . D ADDR 0091H A EXITISR . . . . . . . . . C ADDR 014BH A EXPIRED_TIME. . . . . . . D ADDR 0042H A FIXUPTHENREPLY. . . . . . C ADDR 02B1H A A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 19 FLAGS . . . . . . . . . . D ADDR 0020H A GET_CLASS_DESCRIPTOR. . . C ADDR 029FH A GET_CONFIGURATION . . . . C ADDR 0264H A GET_DESCRIPTOR. . . . . . C ADDR 027BH A GET_IDLE. . . . . . . . . C ADDR 025DH A GET_INTERFACE . . . . . . C ADDR 023AH A GET_PROTOCOL. . . . . . . C ADDR 023AH A GET_REPORT. . . . . . . . C ADDR 0250H A HANDSHAKE . . . . . . . . C ADDR 01ADH A HIDDESCRIPTOR . . . . . . C ADDR 02E9H A I2CCONTROL. . . . . . . . N NUMB 7FA5H A I2CDATA . . . . . . . . . N NUMB 7FA6H A I2CDATABYTE . . . . . . . D ADDR 0047H A I2C_ISR . . . . . . . . . C ADDR 0118H A IDLE_TIME . . . . . . . . D ADDR 0041H A IN07IEN . . . . . . . . . N NUMB 7FACH A IN07IRQ . . . . . . . . . N NUMB 7FA9H A IN0BYTECOUNT. . . . . . . N NUMB 7FB5H A IN1BYTECOUNT. . . . . . . N NUMB 7FB7H A INITIALIZEINTERRUPTSYSTEM C ADDR 039EH A INITIALIZEIOSYSTEM. . . . C ADDR 0384H A INT0_ISR. . . . . . . . . C ADDR 0118H A INT1_ISR. . . . . . . . . C ADDR 0118H A INT4_ISR. . . . . . . . . C ADDR 0118H A INT5_ISR. . . . . . . . . C ADDR 0118H A INT6_ISR. . . . . . . . . C ADDR 0118H A INTERFACEDESCRIPTOR . . . C ADDR 02E0H A INTERFACE_CLEAR_FEATURE . C ADDR 023AH A INTERFACE_GET_STATUS. . . C ADDR 026BH A INTERFACE_SET_FEATURE . . C ADDR 023AH A INVALID . . . . . . . . . C ADDR 023AH A IRLOOP. . . . . . . . . . C ADDR 040DH A ISDESCRIPTOR. . . . . . . B ADDR 0020H.3 A LEDBUFFER . . . . . . . . D ADDR 0049H A LEDSTROBE . . . . . . . . D ADDR 0048H A LEDVALUE. . . . . . . . . D ADDR 0049H A LIGHTVALUES . . . . . . . D ADDR 0047H A LIMITVALUES . . . . . . . D ADDR 0047H A LOADSUDPTR. . . . . . . . C ADDR 01B8H A LOOKUPTABLE . . . . . . . C ADDR 041AH A LTCOPY. . . . . . . . . . C ADDR 03F6H A MAIN. . . . . . . . . . . C ADDR 03B6H A MONITORSPACE. . . . . . . D ADDR 0021H A MORE. . . . . . . . . . . C ADDR 03BFH A MOTORCONTROL. . . . . . . D ADDR 0048H A MSEC_COUNTER. . . . . . . D ADDR 004AH A NEXTCOLUMN. . . . . . . . C ADDR 0625H A NEXTDPTR. . . . . . . . . C ADDR 01CBH A NEXTSTRING. . . . . . . . C ADDR 0291H A NOTB5 . . . . . . . . . . C ADDR 0181H A NOT_USED. . . . . . . . . C ADDR 0118H A OLD_BUTTONS . . . . . . . D ADDR 0047H A ORLOOP. . . . . . . . . . C ADDR 03D4H A OUT07IEN. . . . . . . . . N NUMB 7FADH A OUT07IRQ. . . . . . . . . N NUMB 7FAAH A OUT0BYTECOUNT . . . . . . N NUMB 7FC5H A OVERLAY . . . . . . . . . D ADDR 0047H A PAGEREG . . . . . . . . . D ADDR 0092H A PCON. . . . . . . . . . . D ADDR 0087H A PORTA_CONFIG. . . . . . . N NUMB 7F93H A PORTA_OE. . . . . . . . . N NUMB 7F9CH A PORTA_OUT . . . . . . . . N NUMB 7F96H A PORTA_PINS. . . . . . . . N NUMB 7F99H A PORTB_CONFIG. . . . . . . N NUMB 7F94H A PORTB_OE. . . . . . . . . N NUMB 7F9DH A PORTB_OUT . . . . . . . . N NUMB 7F97H A A51 MACRO ASSEMBLER RB 23/07/99 16:57:48 PAGE 20 PORTB_PINS. . . . . . . . N NUMB 7F9AH A PORTC_CONFIG. . . . . . . N NUMB 7F95H A PORTC_OE. . . . . . . . . N NUMB 7F9EH A PORTC_OUT . . . . . . . . N NUMB 7F98H A PORTC_PINS. . . . . . . . N NUMB 7F9BH A PROCESSOUTPUTREPORT . . . C ADDR 03CAH A PSW . . . . . . . . . . . D ADDR 00D0H A READBUTTONS . . . . . . . C ADDR 060BH A READERBOARD . . . . . . . N NUMB ----- REPLY . . . . . . . . . . C ADDR 023CH A REPLYBUFFER . . . . . . . D ADDR 0043H A REPORTDESCRIPTOR. . . . . C ADDR 02F9H A REPORTLENGTH. . . . . . . N NUMB 001DH A RESERVED. . . . . . . . . C ADDR 0118H A RESET . . . . . . . . . . C ADDR 0362H A SENDDATA. . . . . . . . . B ADDR 0020H.2 A SENDEP0INBUFFER . . . . . C ADDR 01A9H A SERVICESETUPPACKET. . . . C ADDR 0169H A SERVICETIMERROUTINE . . . C ADDR 05FAH A SETEP0CONTROL . . . . . . C ADDR 01B0H A SETUPDAT. . . . . . . . . N NUMB 7FE8H A SETUPPOINTERS . . . . . . C ADDR 0600H A SET_CLASS_DESCRIPTOR. . . C ADDR 023AH A SET_CONFIGURATION . . . . C ADDR 026EH A SET_DESCRIPTOR. . . . . . C ADDR 023AH A SET_IDLE. . . . . . . . . C ADDR 0257H A SET_INTERFACE . . . . . . C ADDR 023AH A SET_PROTOCOL. . . . . . . C ADDR 023AH A SET_REPORT. . . . . . . . C ADDR 023DH A SKIP. . . . . . . . . . . C ADDR 01D4H A SKIP1 . . . . . . . . . . C ADDR 03DAH A SKIP2 . . . . . . . . . . C ADDR 03E1H A SOF_ISR . . . . . . . . . C ADDR 0158H A SP. . . . . . . . . . . . D ADDR 0081H A STALL . . . . . . . . . . B ADDR 0020H.1 A STARTXFER . . . . . . . . C ADDR 01ACH A STRING0 . . . . . . . . . C ADDR 0316H A STRING1 . . . . . . . . . C ADDR 031AH A STRING2 . . . . . . . . . C ADDR 0346H A SUDAV_ISR . . . . . . . . C ADDR 013CH A SUDPTR. . . . . . . . . . N NUMB 7FD4H A SUSPEND_ISR . . . . . . . C ADDR 0129H A SUTOK_ISR . . . . . . . . C ADDR 0118H A TEMP. . . . . . . . . . . D ADDR 0040H A TIMER0_ISR. . . . . . . . C ADDR 0118H A TIMER1_ISR. . . . . . . . C ADDR 0118H A TIMER2_ISR. . . . . . . . C ADDR 0118H A UART0_ISR . . . . . . . . C ADDR 0118H A UART1_ISR . . . . . . . . C ADDR 0118H A USBCONTROL. . . . . . . . N NUMB 7FD6H A USBIEN. . . . . . . . . . N NUMB 7FAEH A USBIRQ. . . . . . . . . . N NUMB 7FABH A USBRESET_ISR. . . . . . . C ADDR 0120H A USB_ISR . . . . . . . . . C ADDR 0100H A WAIT100MSEC . . . . . . . C ADDR 03B9H A WAIT1MSEC . . . . . . . . C ADDR 03BCH A WAIT4D. . . . . . . . . . C ADDR 0247H A WAKEUP_ISR. . . . . . . . C ADDR 0139H A WITHINSAMEPAGE. . . . . . N NUMB 00B7H A REGISTER BANK(S) USED: 0 ASSEMBLY COMPLETE. 0 WARNING(S), 0 ERROR(S)