A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 1 DOS MACRO ASSEMBLER A51 V5.28m OBJECT MODULE PLACED IN TEMPS.OBJ ASSEMBLER INVOKED BY: C:\ANCHOR\KEIL2K\BIN\A51.EXE TEMPS.A51 RB(0) DB EP LOC OBJ LINE SOURCE 1 NAME Temperatures 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 7F99 =1 35 PortA_PINS EQU 07F99H 7F9A =1 36 PortB_PINS EQU 07F9AH 7F93 =1 37 PortA_Config EQU 07F93H 7F94 =1 38 PortB_Config EQU 07F94H 7F96 =1 39 PortA_OUT EQU 07F96H 7F9C =1 40 PortA_OE EQU 07F9CH 7F9D =1 41 PortB_OE EQU 07F9DH =1 42 ; =1 43 ; Byte Variables =1 44 ---- =1 45 DSEG AT 20H 0020 =1 46 FLAGS: DS 1 ; This register is bit-addressable =1 47 ; Bit Variables 0000 =1 48 Configured EQU FLAGS.0 ; Is this device configured 0001 =1 49 STALL EQU FLAGS.1 ; Need to STALL endpoint 0 0002 =1 50 SendData EQU FLAGS.2 ; Need to send data to PC Host 0003 =1 51 IsDescriptor EQU FLAGS.3 ; Enable a shortcut reply =1 52 ; 0021 =1 53 MonitorSpace: DS 1FH ; Used by Dscope 0040 =1 54 Temp: DS 1 ; A temporary working register 0041 =1 55 Idle_Time: DS 1 ; The time the PC host wants us to wait 0042 =1 56 Expired_Time: DS 1 ; A downcounter for timed Reports 0043 =1 57 ReplyBuffer: DS 3 ; First byte is Count =1 58 ; A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 2 =1 59 ; Declare the specific variables used by each of the examples 0046 =1 60 Overlay EQU $ 0046 =1 61 Old_Buttons: DS 1 ; Used by BAL: stores current button position 0047 =1 62 LEDstrobe: DS 1 ; Used by BAL: strobe one LED on at a time 0048 =1 63 LEDvalue: DS 1 ; Used by BAL: stores current LED value 0049 =1 64 Msec_Counter: DS 1 ; Used by BAL: counts up to 4 msec =1 65 0046 =1 66 ORG Overlay ; Overlay the variables (only one set in use at any one tim e) 0046 =1 67 I2CDataByte: DS 1 ; Used by I2C: keep a local copy of data read from I2C bus =1 68 0046 =1 69 ORG Overlay 0046 =1 70 LightValues: DS 6 ; Used by LP: local buffer for light brightness =1 71 0046 =1 72 ORG Overlay 0046 =1 73 LimitValues: DS 12 ; Used by Temps: local buffer for limits =1 74 0046 =1 75 ORG Overlay 0046 =1 76 LEDBuffer: DS 42 ; Used by RB: local buffer for reader board =1 77 ; 78 $INCLUDE(..\Vectors.A51) =1 79 ; This module is common to all of the examples. =1 80 ; It contains all of the interrupt vector declarations and =1 81 ; the first level interrupt servicing (register save, call subroutine, =1 82 ; clear interrupt source, restore registers, return) =1 83 ; Suspend and Resume are handled totally in this module =1 84 ; =1 85 ; A Reset sends us to Program space location 0 ---- =1 86 CSEG AT 0 ; Code space =1 87 USING 0 ; Reset forces Register Bank 0 0000 020364 =1 88 LJMP Reset =1 89 ; =1 90 ; The interrupt vector table is also located here =1 91 ; EZ-USB has two levels of USB interrupts: =1 92 ; 1-the main level is described in this table (at ORG 43H) =1 93 ; 2-there are 21 sources of USB interrupts and these are described in USB_ISR =1 94 ; This means that two levels of acknowledgement and clearing will be required =1 95 ; LJMP INT0_ISR ; Features not used are commented out =1 96 ; ORG 0BH =1 97 ; LJMP Timer0_ISR =1 98 ; ORG 13H =1 99 ; LJMP INT1_ISR =1 100 ; ORG 1BH =1 101 ; LJMP Timer1_ISR =1 102 ; ORG 23H =1 103 ; LJMP UART0_ISR =1 104 ; ORG 2BH =1 105 ; LJMP Timer2_ISR =1 106 ; ORG 33H =1 107 ; LJMP WakeUp_ISR =1 108 ; ORG 3BH =1 109 ; LJMP UART1_ISR 0043 =1 110 ORG 43H 0043 020100 =1 111 LJMP USB_ISR ; Auto Vector will replace byte 45H =1 112 ; ORG 4BH =1 113 ; LJMP I2C_ISR =1 114 ; ORG 53H =1 115 ; LJMP INT4_ISR =1 116 ; ORG 5BH =1 117 ; LJMP INT5_ISR =1 118 ; ORG 63H =1 119 ; LJMP INT6_ISR =1 120 00E0 =1 121 ORG 0E0H ; Keep out of the way of dScope monitor =1 122 ; If you are not using dScope then this memory hole =1 123 ; may be used for useful routines. A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 3 0100 =1 124 ORG 100H 0100 02013C =1 125 USB_ISR:LJMP SUDAV_ISR 0103 00 =1 126 DB 0 ; Pad entries to 4 bytes 0104 020158 =1 127 LJMP SOF_ISR 0107 00 =1 128 DB 0 0108 020118 =1 129 LJMP SUTOK_ISR 010B 00 =1 130 DB 0 010C 020129 =1 131 LJMP Suspend_ISR 010F 00 =1 132 DB 0 0110 020120 =1 133 LJMP USBReset_ISR 0113 00 =1 134 DB 0 0114 020118 =1 135 LJMP Reserved 0117 00 =1 136 DB 0 =1 137 ; LJMP EP0In_ISR ; Endpoint Interrupts are not used in these examples =1 138 ; DB 0 ; Comment out features not used =1 139 ; LJMP EP0Out_ISR =1 140 ; DB 0 =1 141 ; LJMP EP1In_ISR =1 142 ; DB 0 =1 143 ; LJMP EP1Out_ISR =1 144 ; DB 0 =1 145 ; LJMP EP2In_ISR =1 146 ; DB 0 =1 147 ; LJMP EP2Out_ISR =1 148 ; DB 0 =1 149 ; LJMP EP3In_ISR =1 150 ; DB 0 =1 151 ; LJMP EP3Out_ISR =1 152 ; DB 0 =1 153 ; LJMP EP4In_ISR =1 154 ; DB 0 =1 155 ; LJMP EP4Out_ISR =1 156 ; DB 0 =1 157 ; LJMP EP5In_ISR =1 158 ; DB 0 =1 159 ; LJMP EP5Out_ISR =1 160 ; DB 0 =1 161 ; LJMP EP6In_ISR =1 162 ; DB 0 =1 163 ; LJMP EP6Out_ISR =1 164 ; DB 0 =1 165 ; LJMP EP7In_ISR =1 166 ; DB 0 =1 167 ; LJMP EP7Out_ISR =1 168 ; End of Interrupt Vector tables =1 169 =1 170 ; When a feature is used insert the required interrupt processing here =1 171 ; The example use only used Endpoints 0 and 1 and also SOF for timing 0118 =1 172 Reserved: 0118 =1 173 INT0_ISR: 0118 =1 174 Timer0_ISR: 0118 =1 175 INT1_ISR: 0118 =1 176 Timer1_ISR: 0118 =1 177 UART0_ISR: 0118 =1 178 Timer2_ISR: 0118 =1 179 UART1_ISR: 0118 =1 180 I2C_ISR: 0118 =1 181 INT4_ISR: 0118 =1 182 INT5_ISR: 0118 =1 183 INT6_ISR: 0118 =1 184 SUTOK_ISR: 0118 =1 185 EP0In_ISR: 0118 =1 186 EP0Out_ISR: 0118 =1 187 EP1In_ISR: 0118 =1 188 EP1Out_ISR: 0118 =1 189 EP2In_ISR: A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 4 0118 =1 190 EP2Out_ISR: 0118 =1 191 EP3In_ISR: 0118 =1 192 EP3Out_ISR: 0118 =1 193 EP4In_ISR: 0118 =1 194 EP4Out_ISR: 0118 =1 195 EP5In_ISR: 0118 =1 196 EP5Out_ISR: 0118 =1 197 EP6In_ISR: 0118 =1 198 EP6Out_ISR: 0118 =1 199 EP7In_ISR : 0118 =1 200 EP7Out_ISR: 0118 =1 201 Not_Used: ; Should not get any of these 0118 32 =1 202 RETI =1 203 0119 =1 204 ClearINT2: ; Tell the hardware that we're done 0119 E591 =1 205 MOV A, EXIF 011B C2E4 =1 206 CLR ACC.4 ; Clear the Interrupt 2 bit 011D F591 =1 207 MOV EXIF, A 011F 22 =1 208 RET =1 209 0120 =1 210 USBReset_ISR: ; Bus has been Reset, move to DEFAULT state 0120 C0E0 =1 211 PUSH ACC 0122 C200 =1 212 CLR Configured 0124 3119 =1 213 CALL ClearINT2 =1 214 ; No need to clear source of interrupt 0126 D0E0 =1 215 POP ACC 0128 32 =1 216 RETI =1 217 0129 =1 218 Suspend_ISR: ; SIE detected an Idle bus 0129 C0E0 =1 219 PUSH ACC 012B E587 =1 220 MOV A, PCON 012D 4401 =1 221 ORL A, #1 012F F587 =1 222 MOV PCON, A ; Go to sleep! 0131 00 =1 223 NOP 0132 00 =1 224 NOP ; Wake up here due to a USBResume 0133 00 =1 225 NOP 0134 3119 =1 226 CALL ClearINT2 0136 D0E0 =1 227 POP ACC 0138 32 =1 228 RETI =1 229 0139 =1 230 WakeUp_ISR: ; Not using external WAKEUP in these examples =1 231 ; So this must be due to a USBResume 0139 C2DC =1 232 CLR EICON.4 ; Clear the wakeup interrupt source 013B 32 =1 233 RETI =1 234 013C =1 235 SUDAV_ISR: ; A Setup packet has been received 013C C0D0 =1 236 PUSH PSW ; Save Registers before the service routine 013E C0E0 =1 237 PUSH ACC 0140 C082 =1 238 PUSH DPL 0142 C083 =1 239 PUSH DPH 0144 120169 =1 240 CALL ServiceSetupPacket 0147 3119 =1 241 CALL ClearINT2 =1 242 ; Clear the source of the interrupt 0149 7401 =1 243 MOV A, #00000001b 014B 907FAB =1 244 ExitISR:MOV DPTR, #USBIRQ 014E F0 =1 245 MOVX @DPTR, A 014F D083 =1 246 POP DPH ; Restore Registers 0151 D082 =1 247 POP DPL 0153 D0E0 =1 248 POP ACC 0155 D0D0 =1 249 POP PSW 0157 32 =1 250 RETI =1 251 0158 =1 252 SOF_ISR: ; A Start-Of-Frame packet has been received 0158 C0D0 =1 253 PUSH PSW ; Save Registers before the service routine 015A C0E0 =1 254 PUSH ACC 015C C082 =1 255 PUSH DPL A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 5 015E C083 =1 256 PUSH DPH 0160 120403 =1 257 CALL ServiceTimerRoutine 0163 3119 =1 258 CALL ClearINT2 =1 259 ; Clear the source of the interrupt 0165 7402 =1 260 MOV A, #00000010b 0167 80E2 =1 261 JMP ExitISR =1 262 =1 263 264 $INCLUDE(..\USB_INT.A51) =1 265 ; This module is common to all of the examples. =1 266 ; It services USB Requests from the SIE. =1 267 ; Interpretation of the Output Reports is handled by MAIN =1 268 ; ---- =1 269 CSEG 0169 =1 270 ServiceSetupPacket: 0169 907FE8 =1 271 MOV DPTR, #SETUPDAT ; Point to Setup Packet data 016C E0 =1 272 MOVX A, @DPTR ; Get the RequestType 016D A2E7 =1 273 MOV C, ACC.7 ; Bit 7 = 1 means IO device needs to send data to P C Host 016F 9202 =1 274 MOV SendData, C 0171 545C =1 275 ANL A, #01011100b ; IF RequestType[6.4.3.2] = 1 THEN goto BadRequest 0173 7051 =1 276 JNZ BadRequest 0175 E0 =1 277 MOVX A, @DPTR ; IF RequestType[1&0] = 1 THEN goto BadRequest 0176 A2E0 =1 278 MOV C, ACC.0 0178 82E1 =1 279 ANL C, ACC.1 017A 404A =1 280 JC BadRequest 017C 30E502 =1 281 JNB ACC.5, NotB5 ; IF RequestType[5] = 1 THEN RequestType[1,0] = [1, 1] 017F 7403 =1 282 MOV A, #00000011b 0181 5403 =1 283 NotB5: ANL A, #00000011b ; Set CommandIndex[5,4] = RequestType[1,0] 0183 C4 =1 284 SWAP A 0184 F540 =1 285 MOV Temp, A ; Save HI nibble of CommandIndex =1 286 ; Set CommandIndex[3,0] = Request[3,0] 0186 A3 =1 287 INC DPTR ; Point to Request 0187 E0 =1 288 MOVX A, @DPTR 0188 540F =1 289 ANL A, #00001111b ; Only 13 are defined today, handle in table 018A 4540 =1 290 ORL A, Temp 018C 1201D5 =1 291 CALL CorrectSubroutine ; goto CommandTable(CommandIndex) =1 292 ; Returns STALL=1 if a stall is required 018F 200134 =1 293 JB STALL, BadRequest 0192 300218 =1 294 JNB SendData, HandShake 0195 200320 =1 295 JB IsDescriptor, LoadSUDPTR; EZ-USB has a short cut for descriptors =1 296 ; Send data in ReplyBuffer 0198 907F02 =1 297 MOV DPTR, #EP0InBuffer+2 019B 7846 =1 298 MOV R0, #ReplyBuffer+3 019D 754003 =1 299 MOV Temp, #3 ; Copy maximum byte count 01A0 E6 =1 300 CopyRB: MOV A, @R0 01A1 F0 =1 301 MOVX @DPTR, A 01A2 1582 =1 302 DEC DPL 01A4 18 =1 303 DEC R0 01A5 D540F8 =1 304 DJNZ Temp, CopyRB 01A8 E6 =1 305 MOV A, @R0 ; Get real byte count 01A9 =1 306 SendEP0InBuffer: 01A9 907FB5 =1 307 MOV DPTR, #In0ByteCount 01AC =1 308 StartXfer: 01AC F0 =1 309 MOVX @DPTR, A ; This write initiates the transfer 01AD =1 310 HandShake: ; Handshake with host 01AD 754002 =1 311 MOV Temp, #00000010b ; Set HSNAK to tell the SIE that we're done 01B0 =1 312 SetEP0Control: 01B0 907FB4 =1 313 MOV DPTR, #EP0Control 01B3 E0 =1 314 MOVX A, @DPTR 01B4 4540 =1 315 ORL A, Temp 01B6 F0 =1 316 MOVX @DPTR, A 01B7 22 =1 317 RET 01B8 =1 318 LoadSUDPTR: ; Send the data pointed to by DPTR 01B8 858240 =1 319 MOV Temp, DPL A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 6 01BB E583 =1 320 MOV A, DPH 01BD 907FD4 =1 321 MOV DPTR, #SUDPTR 01C0 F0 =1 322 MOVX @DPTR, A 01C1 E540 =1 323 MOV A, Temp 01C3 A3 =1 324 INC DPTR 01C4 80E6 =1 325 JMP StartXfer 01C6 =1 326 BadRequest: ; Invalid Request was received 01C6 754003 =1 327 MOV Temp, #00000011b ; Set EP0STALL and HSNAK 01C9 80E5 =1 328 JMP SetEP0Control =1 329 01CB =1 330 NextDPTR: ; Returns (DPTR + byte DPTR is pointing to) 01CB E0 =1 331 MOVX A, @DPTR 01CC =1 332 BumpDPTR: ; Returns (DPTR + ACC) 01CC 2582 =1 333 ADD A, DPL 01CE F582 =1 334 MOV DPL, A 01D0 5002 =1 335 JNC Skip 01D2 0583 =1 336 INC DPH ; Need 16 bit arithmetic here 01D4 22 =1 337 Skip: RET =1 338 01D5 =1 339 CorrectSubroutine: ; Jump to the subroutine that DPTR is pointing to 01D5 9001FA =1 340 MOV DPTR, #CommandTable 01D8 31CC =1 341 CALL BumpDPTR ; Point to entry 01DA E0 =1 342 MOVX A, @DPTR ; Get the offset 01DB 9001FA =1 343 MOV DPTR, #CommandTable 01DE 31CC =1 344 CALL BumpDPTR ; Get the routine address 01E0 C082 =1 345 PUSH DPL ; Create a RETURN address on stack 01E2 C083 =1 346 PUSH DPH ; Note: JMP @A+DPTR not used since A, DPTR needed 01E4 7845 =1 347 MOV R0, #ReplyBuffer+2 01E6 E4 =1 348 CLR A 01E7 F6 =1 349 MOV @R0, A ; Clear ReplyBuffer 01E8 18 =1 350 DEC R0 01E9 F6 =1 351 MOV @R0, A 01EA 18 =1 352 DEC R0 01EB 7601 =1 353 MOV @R0, #1 ; Default non-descriptor reply 01ED 907FEA =1 354 MOV DPTR, #SETUPDAT+2 ; Point to LOW(wValue) 01F0 E0 =1 355 MOVX A, @DPTR ; Many of the routines need these 01F1 F5F0 =1 356 MOV B, A ; LOW(wValue) in B 01F3 A3 =1 357 INC DPTR 01F4 E0 =1 358 MOVX A, @DPTR ; HIGH(wValue) in A 01F5 C201 =1 359 CLR STALL 01F7 C203 =1 360 CLR IsDescriptor 01F9 22 =1 361 RET ; Go to service routine =1 362 =1 363 ; Since the table only contains byte offsets, it is important that all these routines are =1 364 ; within one page (100H) of CommandTable =1 365 ; 01FA =1 366 CommandTable: =1 367 ; First 16 commands are for the Device 01FA 6D =1 368 DB Device_Get_Status - CommandTable 01FB 40 =1 369 DB Device_Clear_Feature - CommandTable 01FC 40 =1 370 DB Invalid - CommandTable 01FD 40 =1 371 DB Device_Set_Feature - CommandTable 01FE 40 =1 372 DB Invalid - CommandTable 01FF 40 =1 373 DB Invalid - CommandTable ; SIE implements Device_Set_Address 0200 81 =1 374 DB Get_Descriptor - CommandTable 0201 40 =1 375 DB Set_Descriptor - CommandTable 0202 6A =1 376 DB Get_Configuration - CommandTable 0203 74 =1 377 DB Set_Configuration - CommandTable 0204 40 =1 378 DB Invalid - CommandTable 0205 40 =1 379 DB Invalid - CommandTable 0206 40 =1 380 DB Invalid - CommandTable 0207 40 =1 381 DB Invalid - CommandTable 0208 40 =1 382 DB Invalid - CommandTable 0209 40 =1 383 DB Invalid - CommandTable =1 384 ; Next 16 commands are for the Interface 020A 71 =1 385 DB Interface_Get_Status - CommandTable A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 7 020B 40 =1 386 DB Interface_Clear_Feature - CommandTable 020C 40 =1 387 DB Invalid - CommandTable 020D 40 =1 388 DB Interface_Set_Feature - CommandTable 020E 40 =1 389 DB Invalid - CommandTable 020F 40 =1 390 DB Invalid - CommandTable 0210 A5 =1 391 DB Get_Class_Descriptor - CommandTable 0211 40 =1 392 DB Set_Class_Descriptor - CommandTable 0212 40 =1 393 DB Invalid - CommandTable 0213 40 =1 394 DB Invalid - CommandTable 0214 40 =1 395 DB Get_Interface - CommandTable 0215 40 =1 396 DB Set_Interface - CommandTable 0216 40 =1 397 DB Invalid - CommandTable 0217 40 =1 398 DB Invalid - CommandTable 0218 40 =1 399 DB Invalid - CommandTable 0219 40 =1 400 DB Invalid - CommandTable =1 401 ; Next 16 commands are for the Endpoint 021A 71 =1 402 DB Endpoint_Get_Status - CommandTable 021B 42 =1 403 DB Endpoint_Clear_Feature - CommandTable 021C 40 =1 404 DB Invalid - CommandTable 021D 40 =1 405 DB Endpoint_Set_Feature - CommandTable 021E 40 =1 406 DB Invalid - CommandTable 021F 40 =1 407 DB Invalid - CommandTable 0220 40 =1 408 DB Invalid - CommandTable 0221 40 =1 409 DB Invalid - CommandTable 0222 40 =1 410 DB Invalid - CommandTable 0223 40 =1 411 DB Invalid - CommandTable 0224 40 =1 412 DB Invalid - CommandTable 0225 40 =1 413 DB Invalid - CommandTable 0226 40 =1 414 DB Endpoint_Sync_Frame - CommandTable 0227 40 =1 415 DB Invalid - CommandTable 0228 40 =1 416 DB Invalid - CommandTable 0229 40 =1 417 DB Invalid - CommandTable =1 418 ; Next 16 commands are Class Requests 022A 40 =1 419 DB Invalid - CommandTable 022B 56 =1 420 DB Get_Report - CommandTable 022C 63 =1 421 DB Get_Idle - CommandTable 022D 40 =1 422 DB Get_Protocol - CommandTable 022E 40 =1 423 DB Invalid - CommandTable 022F 40 =1 424 DB Invalid - CommandTable 0230 40 =1 425 DB Invalid - CommandTable 0231 40 =1 426 DB Invalid - CommandTable 0232 40 =1 427 DB Invalid - CommandTable 0233 43 =1 428 DB Set_Report - CommandTable 0234 5D =1 429 DB Set_Idle - CommandTable 0235 40 =1 430 DB Set_Protocol - CommandTable 0236 40 =1 431 DB Invalid - CommandTable 0237 40 =1 432 DB Invalid - CommandTable 0238 40 =1 433 DB Invalid - CommandTable 0239 40 =1 434 DB Invalid - CommandTable =1 435 ; =1 436 ; Many requests are INVALID for this example 023A =1 437 Get_Protocol: ; We are not a Boot device 023A =1 438 Set_Protocol: ; We are not a Boot device 023A =1 439 Set_Descriptor: ; Our Descriptors are static 023A =1 440 Set_Class_Descriptor: ; Our Descriptors are static 023A =1 441 Set_Interface: ; We only have one Interface 023A =1 442 Get_Interface: ; We do not have an Alternate setting 023A =1 443 Device_Set_Feature: ; We have no features that can be set or cleared 023A =1 444 Interface_Set_Feature: ; We have no features that can be set or cleared 023A =1 445 Endpoint_Set_Feature: ; We have no features that can be set or cleared 023A =1 446 Device_Clear_Feature: ; We have no features that can be set or cleared 023A =1 447 Interface_Clear_Feature: ; We have no features that can be set or cleared 023A =1 448 Endpoint_Sync_Frame: ; We are not an Isonchronous device =1 449 023A =1 450 Invalid: ; Invalid Request made, STALL the Endpoint 023A D201 =1 451 SETB STALL A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 8 =1 452 ; 023C =1 453 Endpoint_Clear_Feature: ; We have no features that can be set or cleared =1 454 ; 023C 22 =1 455 Reply: RET =1 456 023D =1 457 Set_Report: ; Host wants to sent us a Report. =1 458 ; The ONLY case in this example where host sends data to us 023D 3000FA =1 459 JNB Configured, Invalid ; Need to be Configured to do this command 0240 907FC5 =1 460 MOV DPTR, #Out0ByteCount ; Enable EP0OutBuffer to receive data 0243 F0 =1 461 MOVX @DPTR, A ; Any value will do 0244 907FAA =1 462 MOV DPTR, #OUT07IRQ ; Wait for valid data in EP0OutBuffer 0247 E0 =1 463 Wait4D: MOVX A, @DPTR 0248 5401 =1 464 ANL A, #00000001b 024A 60FB =1 465 JZ Wait4D 024C F0 =1 466 MOVX @DPTR, A ; Clear the interrupt 024D 0203EE =1 467 JMP ProcessOutputReport ; RETurn via this subroutine 0250 =1 468 Get_Report: ; Host wants a Report 0250 3000E7 =1 469 JNB Configured, Invalid ; Need to be Configured to do this command 0253 08 =1 470 INC R0 ; Point to ReplyBuffer(1) 0254 7618 =1 471 MOV @R0, #18H ; Reply with a recognizable (arbitary) value 0256 22 =1 472 RET 0257 =1 473 Set_Idle: ; Host wants to tell us how often we should talk 0257 3000E0 =1 474 JNB Configured, Invalid ; Need to be Configured to do this command 025A F541 =1 475 MOV Idle_Time, A 025C 22 =1 476 RET ; Handshake with host 025D =1 477 Get_Idle: ; Host must have forgotten what he told us to do 025D 3000DA =1 478 JNB Configured, Invalid ; Need to be Configured to do this command 0260 08 =1 479 INC R0 ; Point to ReplyBuffer(1) 0261 A641 =1 480 MOV @R0, Idle_Time 0263 22 =1 481 RET 0264 =1 482 Get_Configuration: 0264 3000D5 =1 483 JNB Configured, Reply =1 484 ; If configured return a 1 (via Device_Get_Status) 0267 =1 485 Device_Get_Status: ; Only two bits of Device Status are defined 0267 08 =1 486 INC R0 ; Point to ReplyBuffer(1) 0268 7601 =1 487 MOV @R0, #1 ; Bit 1=Remote Wakeup(=0), Bit 0=Self Powered(=1) 026A 22 =1 488 RET =1 489 026B =1 490 Interface_Get_Status: ; Interface Status is currently defined as 0 026B =1 491 Endpoint_Get_Status: 026B 7602 =1 492 MOV @R0, #2 026D 22 =1 493 RET 026E =1 494 Set_Configuration: ; Valid values are 0 and 1 026E E5F0 =1 495 MOV A, B ; Get LOW(wValue) 0270 6006 =1 496 JZ Deconfigured 0272 14 =1 497 DEC A 0273 70C5 =1 498 JNZ Invalid 0275 D200 =1 499 SETB Configured 0277 22 =1 500 RET 0278 =1 501 Deconfigured: 0278 C200 =1 502 CLR Configured 027A 22 =1 503 RET 027B =1 504 Get_Descriptor: ; Host wants to know who/what we are 027B D203 =1 505 SETB IsDescriptor 027D 14 =1 506 DEC A ; Valid Values are 1, 2 and 3 027E 9002C5 =1 507 MOV DPTR, #DeviceDescriptor 0281 60B9 =1 508 JZ Reply 0283 14 =1 509 DEC A 0284 9002D7 =1 510 MOV DPTR, #ConfigurationDescriptor 0287 60B3 =1 511 JZ Reply 0289 14 =1 512 DEC A 028A 70AE =1 513 JNZ Invalid =1 514 ; Request is for a String Descriptor 028C 900318 =1 515 MOV DPTR, #String0 ; Point to String 0 028F E5F0 =1 516 MOV A, B ; Get String Index 0291 =1 517 NextString: A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 9 0291 601E =1 518 JZ FixUpthenReply 0293 F540 =1 519 MOV Temp, A ; Save String Index 0295 31CB =1 520 CALL NextDPTR 0297 E0 =1 521 MOVX A, @DPTR ; Get the String Length (= 0 means we're at Backsto p) 0298 60A0 =1 522 JZ Invalid ; Asked for a string I don't have 029A E540 =1 523 MOV A, Temp 029C 14 =1 524 DEC A 029D 80F2 =1 525 JMP NextString ; Check if we are there yet 029F =1 526 Get_Class_Descriptor: ; Valid values are 21H, 22H, 23H for Class Request 029F D203 =1 527 SETB IsDescriptor 02A1 C3 =1 528 CLR C 02A2 9421 =1 529 SUBB A, #21H 02A4 9002E9 =1 530 MOV DPTR, #HIDDescriptor 02A7 6093 =1 531 JZ Reply 02A9 14 =1 532 DEC A 02AA 9002F9 =1 533 MOV DPTR, #ReportDescriptor 02AD 608D =1 534 JZ Reply =1 535 ; DEC A ; This example does not use Physical Descriptors =1 536 ; JZ Send_Physical_Descriptor 02AF 8089 =1 537 JMP Invalid =1 538 ; =1 539 ; Error check: this MUST be on within a page of CommandTable 00B7 =1 540 WithinSamePage EQU $ - CommandTable =1 541 ; 02B1 =1 542 FixUpthenReply: ; EZ-USB Rev D has a String Descriptor bug =1 543 ; Need to fill the IN0BUF (@ 7F00H) myself 02B1 E0 =1 544 MOVX A, @DPTR ; Get the string length 02B2 FF =1 545 MOV R7, A ; Save counter 02B3 F5F0 =1 546 MOV B, A 02B5 7800 =1 547 MOV R0, #LOW(EP0InBuffer) ; PageReg = 7FH = HIGH(EP0InBuffer) 02B7 F2 =1 548 CopySD: MOVX @R0, A 02B8 08 =1 549 INC R0 02B9 A3 =1 550 INC DPTR 02BA E0 =1 551 MOVX A, @DPTR 02BB DFFA =1 552 DJNZ R7, CopySD =1 553 ; Fixup complete, get back to the program flow 02BD D0E0 =1 554 POP ACC ; Get rid of the return address 02BF D0E0 =1 555 POP ACC 02C1 E5F0 =1 556 MOV A, B ; Retrieve byte count 02C3 21A9 =1 557 JMP SendEP0InBuffer 558 $INCLUDE(DTables.A51) =1 559 ; This module declares the descriptors =1 560 ; =1 561 ; This example has one Device Descriptor with: =1 562 ; One Configuration - single IN port and single OUT port =1 563 ; One Interface - there is only one method of accessing the ports =1 564 ; One HID Descriptor - to make PC host software simpler =1 565 ; One Endpoint Descriptor - for HID Input Reports =1 566 ; One Report Descriptor - one 7 byte IN and one 12 byte OUT report =1 567 ; Multiple Sting Descriptors - to aid the user =1 568 ; ---- =1 569 CSEG 02C5 =1 570 DeviceDescriptor: 02C5 1201 =1 571 DB 18, 1 ; Length, Type 02C7 0101 =1 572 DW 101H ; USB Rev 1.1 02C9 000000 =1 573 DB 0, 0, 0 ; Class, Subclass and Protocol 02CC 40 =1 574 DB 64 ; EP0 size 02CD 4242 =1 575 DW 4242H, 1, 1 ; Vendor ID, Product ID and Version 02CF 0001 02D1 0001 02D3 010200 =1 576 DB 1, 2, 0 ; Manufacturer, Product & Serial# Names 02D6 01 =1 577 DB 1 ; #Configs 02D7 =1 578 ConfigurationDescriptor: 02D7 0902 =1 579 DB 9, 2 ; Length, Type 02D9 2200 =1 580 DB LOW(ConfigLength), HIGH(ConfigLength) A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 10 02DB 010100 =1 581 DB 1, 1, 0 ; #Interfaces, Configuration#, Config. Name 02DE 80 =1 582 DB 10000000b ; Attributes = Bus Powered 02DF 32 =1 583 DB 50 ; Max. Power is 50x2 = 100mA 02E0 =1 584 InterfaceDescriptor: 02E0 0904 =1 585 DB 9, 4 ; Length, Type 02E2 000001 =1 586 DB 0, 0, 1 ; No alternate setting, HID uses EP1 02E5 03 =1 587 DB 3 ; Class = Human Interface Device 02E6 0000 =1 588 DB 0, 0 ; Subclass and Protocol 02E8 00 =1 589 DB 0 ; Interface Name 02E9 =1 590 HIDDescriptor: 02E9 0921 =1 591 DB 9, 21H ; Length, Type 02EB 0001 =1 592 DB 0, 1 ; HID Class Specification compliance 02ED 00 =1 593 DB 0 ; Country localization (=none) 02EE 01 =1 594 DB 1 ; Number of descriptors to follow 02EF 22 =1 595 DB 22H ; And it's a Report descriptor 02F0 1F00 =1 596 DB LOW(ReportLength), HIGH(ReportLength) 02F2 =1 597 EndpointDescriptor: 02F2 0705 =1 598 DB 7, 5 ; Length, Type 02F4 81 =1 599 DB 10000001b ; Address = IN 1 02F5 03 =1 600 DB 00000011b ; Interrupt 02F6 4000 =1 601 DB 64, 0 ; Maximum packet size (this example only uses 1) 02F8 64 =1 602 DB 100 ; Poll every 0.25 seconds 0022 =1 603 ConfigLength EQU $ - ConfigurationDescriptor =1 604 02F9 =1 605 ReportDescriptor: ; Generated with HID Tool, copied to here 02F9 0600FF =1 606 DB 6, 0, 0FFH ; Usage_Page (Vendor Defined) 02FC 0901 =1 607 DB 9, 1 ; Usage (I/O Device) 02FE A101 =1 608 DB 0A1H, 1 ; Collection (Application) 0300 1901 =1 609 DB 19H, 1 ; Usage_Minimum 0302 2902 =1 610 DB 29H, 2 ; Usage_Maximum 0304 1500 =1 611 DB 15H, 0 ; Logical_Minimum (0) 0306 25FF00 =1 612 DB 25H, 255, 0 ; Logical_Maximum (255) 0309 7508 =1 613 DB 75H, 8 ; Report_Size (8) 030B 9507 =1 614 DB 95H, 7 ; Report_Count (7) 030D 8102 =1 615 DB 81H, 2 ; Input (Data,Var,Abs) 030F 1901 =1 616 DB 19H, 1 ; Usage_Minimum 0311 2902 =1 617 DB 29H, 2 ; Usage_Maximum 0313 950C =1 618 DB 95H, 12 ; Report_Count (12) 0315 9102 =1 619 DB 91H, 2 ; Output (Data,Var,Abs) 0317 C0 =1 620 DB 0C0H ; End_Collection 001F =1 621 ReportLength EQU $-ReportDescriptor =1 622 0318 =1 623 String0: ; Declare the UNICODE strings 0318 04030904 =1 624 DB 4, 3, 9, 4 ; Only English language strings supported 031C =1 625 String1: ; Manufacturer 031C 2C03 =1 626 DB (String2-String1),3 ; Length, Type 031E 55005300 =1 627 DB "U",0,"S",0,"B",0," ",0,"D",0,"e",0,"s",0,"i",0,"g",0,"n",0," ", 0 0322 42002000 0326 44006500 032A 73006900 032E 67006E00 0332 2000 0334 42007900 =1 628 DB "B",0,"y",0," ",0,"E",0,"x",0,"a",0,"m",0,"p",0,"l",0,"e",0 0338 20004500 033C 78006100 0340 6D007000 0344 6C006500 0348 =1 629 String2: ; Product Name 0348 1A03 =1 630 DB (EndOfDescriptors-String2),3 034A 54006500 =1 631 DB "T",0,"e",0,"m",0,"p",0,"e",0,"r",0 034E 6D007000 0352 65007200 0356 61007400 =1 632 DB "a",0,"t",0,"u",0,"r",0,"e",0,"s",0 035A 75007200 035E 65007300 0362 =1 633 EndOfDescriptors: A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 11 0362 0000 =1 634 DW 0 ; Backstop for String Descriptors =1 635 =1 636 =1 637 638 $INCLUDE(Main.A51) =1 639 ; This module initializes the microcontroller then executes MAIN forever =1 640 ; =1 641 0364 =1 642 Reset: 0364 7581EB =1 643 MOV SP, #235 ; Initialize the Stack 0367 75927F =1 644 MOV PageReg, #7FH ; Allows MOVX Ri to access EZ-USB memory =1 645 036A 78D6 =1 646 MOV R0, #Low(USBControl) ; Simulate a disconnect 036C E2 =1 647 MOVX A, @R0 036D 54F3 =1 648 ANL A, #11110011b ; Clear DISCON, DISCOE 036F F2 =1 649 MOVX @R0, A 0370 1203DD =1 650 CALL Wait100msec ; Give the host time to react 0373 E2 =1 651 MOVX A, @R0 ; Reconnect with this new identity 0374 4406 =1 652 ORL A, #00000110b ; Set DISCOE to enable pullup resistor 0376 F2 =1 653 MOVX @R0, A ; Set RENUM so that 8051 handles USB requests 0377 E4 =1 654 CLR A 0378 F520 =1 655 MOV FLAGS, A ; Start in Default state 037A =1 656 Initialize4msecCounter: 037A 04 =1 657 INC A ; = 1 037B F542 =1 658 MOV Expired_Time, A 037D F549 =1 659 MOV Msec_counter, A 037F =1 660 InitializeIOSystem: ; Work around the Dscope monitor I/O needs =1 661 ; Setup Port A as 8-bit OUTPUT port (no alternate functions) =1 662 ; Setup an 8-bit INPUT port using PortB_Bits [7:4] and PortC_Bits[3:0] =1 663 ; Assume a pre-existing configuration (ie Dscope) 037F 7893 =1 664 MOV R0, #LOW(PortA_Config) ; PageReg = 7F = HIGH(PortA_Config) 0381 E4 =1 665 CLR A 0382 F2 =1 666 MOVX @R0, A ; No alternate functions 0383 799C =1 667 MOV R1, #LOW(PortA_OE) 0385 F4 =1 668 CPL A ; = 0FFH 0386 F3 =1 669 MOVX @R1, A ; Enable PortA for Output 0387 08 =1 670 INC R0 ; Point to PortB_Config 0388 09 =1 671 INC R1 ; Point to PortB_OE 0389 E2 =1 672 MOVX A, @R0 ; Get current configuration 038A 540F =1 673 ANL A, #0FH 038C F2 =1 674 MOVX @R0, A ; No alternate functions on upper nibble 038D E3 =1 675 MOVX A, @R1 ; Get current configuration 038E 44F0 =1 676 ORL A, #0F0H 0390 F3 =1 677 MOVX @R1, A ; Enable PortB_Bits[7:4] for Output 0391 08 =1 678 INC R0 ; Point to PortC_Config 0392 09 =1 679 INC R1 ; Point to PortC_OE 0393 E2 =1 680 MOVX A, @R0 ; Get current configuration 0394 54F0 =1 681 ANL A, #0F0H 0396 F2 =1 682 MOVX @R0, A ; No alternate functions on lower nibble 0397 E3 =1 683 MOVX A, @R1 ; Get current configuration 0398 440F =1 684 ORL A, #0FH 039A F3 =1 685 MOVX @R1, A ; Enable PortC_Bits[3:0] for Output 039B =1 686 InitializeThermometers: 039B 0203C6 =1 687 JMP InitializeInterruptSystem 039E 7896 =1 688 MOV R0, #Low(PortA_Out) ; Do all six at the same time 03A0 7404 =1 689 MOV A, #00000100b ; Select pattern 03A2 FE =1 690 ILoop: MOV R6, A 03A3 7401 =1 691 MOV A, #00000001b ; Port A idle state 03A5 4E =1 692 ORL A, R6 03A6 F2 =1 693 MOVX @R0, A ; Select one of the thermometers 03A7 7D0C =1 694 MOV R5, #0CH ; Configure command 03A9 120423 =1 695 CALL SendByte 03AC 7D0A =1 696 MOV R5, #00001010b ; Set CPU mode and continuous conversion 03AE 120423 =1 697 CALL SendByte 03B1 FA =1 698 MOV R2, A ; Save A 03B2 7401 =1 699 MOV A, #00000001b ; Port A idle state A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 12 03B4 F2 =1 700 MOVX @R0, A 03B5 754014 =1 701 MOV Temp, #20 03B8 1203E0 =1 702 CALL Wait1msec ; Wait for write to complete 03BB EA =1 703 MOV A, R2 ; Restore A 03BC 7DEE =1 704 MOV R5, #0EEH ; Start temperature conversion command 03BE 120423 =1 705 CALL SendByte 03C1 CE =1 706 XCH A, R6 03C2 C3 =1 707 CLR C ; Need to zero fill 03C3 33 =1 708 RLC A 03C4 70DC =1 709 JNZ ILoop =1 710 03C6 =1 711 InitializeInterruptSystem: ; First initialize the USB level 03C6 E4 =1 712 CLR A 03C7 78AC =1 713 MOV R0, #LOW(IN07IEN) 03C9 F2 =1 714 MOVX @R0, A ; Disable interrupts from IN Endpoints 0-7 03CA 08 =1 715 INC R0 03CB F2 =1 716 MOVX @R0, A ; Disable interrupts from OUT Endpoints 0-7 03CC 08 =1 717 INC R0 03CD 7403 =1 718 MOV A, #00000011b 03CF F2 =1 719 MOVX @R0, A ; Enable (Resume, Suspend,) SOF and SUDAV INTs 03D0 08 =1 720 INC R0 03D1 7401 =1 721 MOV A, #00000001b 03D3 F2 =1 722 MOVX @R0, A ; Enable Auto Vectoring for USB interrupts =1 723 ; Now enable the main level 03D4 75E801 =1 724 MOV EIE, #00000001b ; Enable INT2 = USB Interrupt (only) 03D7 75A8C0 =1 725 MOV EI, #11000000b ; Enable interrupt subsystem (and Ser1 for dScope) =1 726 =1 727 ; Initialization Complete. =1 728 ; 03DA =1 729 MAIN: 03DA 00 =1 730 NOP ; Not much of a main loop for this example 03DB 80FD =1 731 JMP MAIN ; All actions are initiated by interrupts =1 732 ; We are a slave, we wait to be told what to do =1 733 03DD =1 734 Wait100msec: 03DD 754064 =1 735 MOV Temp, #100 03E0 =1 736 Wait1msec: ; A delay loop 03E0 90FB50 =1 737 MOV DPTR, #-1200 03E3 A3 =1 738 More: INC DPTR ; 3 cycles 03E4 E582 =1 739 MOV A, DPL ; + 2 03E6 4583 =1 740 ORL A, DPH ; + 2 03E8 70F9 =1 741 JNZ More ; + 3 = 10 cycles x 1200 = 1msec 03EA D540F3 =1 742 DJNZ Temp, Wait1msec 03ED 22 =1 743 RET =1 744 03EE =1 745 ProcessOutputReport: ; A Report has just been received =1 746 ; The report is 12 bytes long in this example =1 747 ; It contains a new limits values 03EE 907EC0 =1 748 MOV DPTR, #EP0OutBuffer ; Point to the Report 03F1 7846 =1 749 MOV R0, #LimitValues 03F3 7F0C =1 750 MOV R7, #12 03F5 E0 =1 751 CopyOR: MOVX A, @DPTR ; Get the Data 03F6 F6 =1 752 MOV @R0, A ; Update the local variable 03F7 A3 =1 753 INC DPTR 03F8 08 =1 754 INC R0 03F9 DFFA =1 755 DJNZ R7, CopyOR 03FB 22 =1 756 RET =1 757 03FC =1 758 CreateInputReport: ; Called from TIMER which detected the need =1 759 ; The report is seven bytes long in this example =1 760 ; It contains the temperature readings 03FC 907FB7 =1 761 MOV DPTR, #IN1ByteCount 03FF 7407 =1 762 MOV A, #7 0401 F0 =1 763 MOVX @DPTR, A ; Endpoint 1 now 'armed', next IN will get data 0402 22 =1 764 RET =1 765 A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 13 766 $INCLUDE(Timer.A51) =1 767 ; This module services the real time interrupt =1 768 ; It is also responsible for the "real world" thermometers =1 769 ; =1 770 ; CHANGE SINCE THE BOOK TEXT WAS FINALIZED: Idle_Time is used by the Operating System =1 771 ; to override the report times defined in the Endpoint Descriptor. A device driver =1 772 ; will modify Idle_Time to change the reporting characteristics of a HID device. =1 773 ; During initialization the OS sets Idle_Time = 0 which turns reporting OFF unless =1 774 ; a change is detected; an application that starts to poll a HID device will appear =1 775 ; to hang. While it is possible to write extra PCHost application code to re-enable =1 776 ; Idle_Time is it simpler to defeat this mechanism by IGNORRING the Idle_Time value. =1 777 ; =1 778 ; Get a Real Time interrupt every One millisecond (using SOF interrupt) =1 779 ; =1 780 ; We have one task = Read the thermometers =1 781 ; We will poll the thermometers at 100msec intervals and store the temperatures =1 782 ; directly in the EP0InBuffer. This way the PCHost will always get the latest =1 783 ; temperature readings. =1 784 ; =1 785 ; The hardware for this example is shown in Figure 9-7. =1 786 ; We are using Port A for Output =1 787 ; CLK is on Bit0, DQ is on Bit1 and the thermometers are selected by Bits[7:2] =1 788 ; =1 789 ; The registers used in this routine are: =1 790 ; A = Value written to Port A =1 791 ; DPTR = Pointer to EP0InBuffer =1 792 ; R0 = Pointer to PortA_Out =1 793 ; R1 = Pointer to PortA_Config then PortA_Pins =1 794 ; R2 = a save register =1 795 ; R5 = Data to be sent, or received =1 796 ; R6 = Thermometer selector =1 797 ; R7 = Bit counter =1 798 ; 0403 =1 799 ServiceTimerRoutine: 0403 D54946 =1 800 DJNZ Msec_counter, Done ; Only need to check every 4msec 0406 754964 =1 801 MOV Msec_counter, #100 ; Reinitialize =1 802 ; 0409 907F00 =1 803 MOV DPTR, #EP0InBuffer 040C 7896 =1 804 MOV R0, #Low(PortA_Out) 040E 7404 =1 805 MOV A, #00000100b ; Select pattern 0410 FE =1 806 Loop: MOV R6, A 0411 7401 =1 807 MOV A, #00000001b ; Port A idle state 0413 4E =1 808 ORL A, R6 0414 F2 =1 809 MOVX @R0, A ; Select one of the thermometers 0415 7DAA =1 810 MOV R5, #0AAH ; Get temperature command 0417 120423 =1 811 CALL SendByte 041A 120432 =1 812 CALL ReceiveByte 041D EE =1 813 MOV A, R6 ; Get select pattern 041E C3 =1 814 CLR C ; Need to zero fill 041F 33 =1 815 RLC A ; Rotate pattern 0420 70EE =1 816 JNZ Loop 0422 22 =1 817 RET 0423 =1 818 SendByte: ; Transmit a byte to a thermometer 0423 7F08 =1 819 MOV R7, #8 0425 14 =1 820 SLoop: DEC A 0426 F2 =1 821 MOVX @R0, A ; Set CLK low 0427 CD =1 822 XCH A, R5 ; Get the data to be sent 0428 13 =1 823 RRC A ; Put LS bit in Carry 0429 CD =1 824 XCH A, R5 042A 92E1 =1 825 MOV ACC.1, C ; Put data bit in DQ 042C F2 =1 826 MOVX @R0, A 042D 04 =1 827 INC A 042E F2 =1 828 MOVX @R0, A ; Set CLK high 042F DFF4 =1 829 DJNZ R7, SLoop 0431 22 =1 830 RET 0432 =1 831 ReceiveByte: ; Receive a byte from a thermometer A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 14 0432 7F09 =1 832 MOV R7, #9 ; Actually we get 9 bits and discard bit0 0434 FA =1 833 MOV R2, A ; Save A while we reconfigure 0435 7993 =1 834 MOV R1, #Low(PortA_Config) 0437 74FD =1 835 MOV A, #11111101b 0439 F3 =1 836 MOVX @R1, A ; Set bit 1 as input 043A 7999 =1 837 MOV R1, #Low(PortA_Pins) 043C EA =1 838 MOV A, R2 ; Retreive A 043D 14 =1 839 GLoop: DEC A 043E F2 =1 840 MOVX @R0, A ; Set CLK low 043F E3 =1 841 MOVX A, @R1 0440 A2E1 =1 842 MOV C, ACC.1 ; Get DQ 0442 CD =1 843 XCH A, R5 0443 13 =1 844 RRC A ; Copy DQ into MSB 0444 CD =1 845 XCH A, R5 0445 04 =1 846 INC A 0446 F2 =1 847 MOVX @R0, A ; Set CLK high 0447 DFF4 =1 848 DJNZ R7, GLoop 0449 ED =1 849 MOV A, R5 ; Get the received temperature 044A F0 =1 850 MOVX @DPTR, A 044B A3 =1 851 INC DPTR 044C 22 =1 852 Done: RET =1 853 =1 854 855 856 END A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 15 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 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 COPYOR. . . . . . . . . . C ADDR 03F5H A COPYRB. . . . . . . . . . C ADDR 01A0H A COPYSD. . . . . . . . . . C ADDR 02B7H A CORRECTSUBROUTINE . . . . C ADDR 01D5H A CREATEINPUTREPORT . . . . C ADDR 03FCH 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 DONE. . . . . . . . . . . C ADDR 044CH 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 0362H 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 FLAGS . . . . . . . . . . D ADDR 0020H A GET_CLASS_DESCRIPTOR. . . C ADDR 029FH A GET_CONFIGURATION . . . . C ADDR 0264H A GET_DESCRIPTOR. . . . . . C ADDR 027BH A A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 16 GET_IDLE. . . . . . . . . C ADDR 025DH A GET_INTERFACE . . . . . . C ADDR 023AH A GET_PROTOCOL. . . . . . . C ADDR 023AH A GET_REPORT. . . . . . . . C ADDR 0250H A GLOOP . . . . . . . . . . C ADDR 043DH A HANDSHAKE . . . . . . . . C ADDR 01ADH A HIDDESCRIPTOR . . . . . . C ADDR 02E9H A I2CCONTROL. . . . . . . . N NUMB 7FA5H A I2CDATA . . . . . . . . . N NUMB 7FA6H A I2CDATABYTE . . . . . . . D ADDR 0046H A I2C_ISR . . . . . . . . . C ADDR 0118H A IDLE_TIME . . . . . . . . D ADDR 0041H A ILOOP . . . . . . . . . . C ADDR 03A2H A IN07IEN . . . . . . . . . N NUMB 7FACH A IN07IRQ . . . . . . . . . N NUMB 7FA9H A IN0BYTECOUNT. . . . . . . N NUMB 7FB5H A IN1BYTECOUNT. . . . . . . N NUMB 7FB7H A INITIALIZE4MSECCOUNTER. . C ADDR 037AH A INITIALIZEINTERRUPTSYSTEM C ADDR 03C6H A INITIALIZEIOSYSTEM. . . . C ADDR 037FH A INITIALIZETHERMOMETERS. . C ADDR 039BH 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 ISDESCRIPTOR. . . . . . . B ADDR 0020H.3 A LEDBUFFER . . . . . . . . D ADDR 0046H A LEDSTROBE . . . . . . . . D ADDR 0047H A LEDVALUE. . . . . . . . . D ADDR 0048H A LIGHTVALUES . . . . . . . D ADDR 0046H A LIMITVALUES . . . . . . . D ADDR 0046H A LOADSUDPTR. . . . . . . . C ADDR 01B8H A LOOP. . . . . . . . . . . C ADDR 0410H A MAIN. . . . . . . . . . . C ADDR 03DAH A MONITORSPACE. . . . . . . D ADDR 0021H A MORE. . . . . . . . . . . C ADDR 03E3H A MSEC_COUNTER. . . . . . . D ADDR 0049H 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 0046H A OUT07IEN. . . . . . . . . N NUMB 7FADH A OUT07IRQ. . . . . . . . . N NUMB 7FAAH A OUT0BYTECOUNT . . . . . . N NUMB 7FC5H A OVERLAY . . . . . . . . . D ADDR 0046H 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_PINS. . . . . . . . N NUMB 7F9AH A PROCESSOUTPUTREPORT . . . C ADDR 03EEH A PSW . . . . . . . . . . . D ADDR 00D0H A RECEIVEBYTE . . . . . . . C ADDR 0432H A REPLY . . . . . . . . . . C ADDR 023CH A REPLYBUFFER . . . . . . . D ADDR 0043H A A51 MACRO ASSEMBLER TEMPS 21/07/99 23:06:35 PAGE 17 REPORTDESCRIPTOR. . . . . C ADDR 02F9H A REPORTLENGTH. . . . . . . N NUMB 001FH A RESERVED. . . . . . . . . C ADDR 0118H A RESET . . . . . . . . . . C ADDR 0364H A SENDBYTE. . . . . . . . . C ADDR 0423H A SENDDATA. . . . . . . . . B ADDR 0020H.2 A SENDEP0INBUFFER . . . . . C ADDR 01A9H A SERVICESETUPPACKET. . . . C ADDR 0169H A SERVICETIMERROUTINE . . . C ADDR 0403H A SETEP0CONTROL . . . . . . C ADDR 01B0H A SETUPDAT. . . . . . . . . N NUMB 7FE8H 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 SLOOP . . . . . . . . . . C ADDR 0425H 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 0318H A STRING1 . . . . . . . . . C ADDR 031CH A STRING2 . . . . . . . . . C ADDR 0348H 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 TEMPERATURES. . . . . . . N NUMB ----- 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 03DDH A WAIT1MSEC . . . . . . . . C ADDR 03E0H 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)