1: ; B-34. Function Name: TALK 2: ; 3: ; Purpose: Command a device on the serial bus to TALK 4: ; Call address: $FFB4 (hex) 65460 (decimal) 5: ; Communication registers: A 6: ; Preparatory routines: None 7: ; Error returns: See READST 8: ; Stack requirements: 8 9: ; Registers affected: A 10: ; 11: ; Description: To use this routine the accumulator must first be loaded 12: ; with a device number between 0 and 31. When called, this routine then 13: ; ORs bit by bit to convert this device number to a talk address. Then this 14: ; data is transmitted as a command on the serial bus. 15: ; 16: ; How to Use: 17: ; 18: ; 1) Load the accumulator with the device number. 19: ; 2) Call this routine. 20: ; 21: ; EXAMPLE: 22: ; 23: ; ;COMMAND DEVICE #4 TO TALK 24: ; LDA #4 25: ; JSR TALK 26: ; 27: iTALK: 28: ora #IEEE_TALK ; create primary address for TALK 29: 30: .byte ASM_BIT3 ; hide next instruction 31: 32: ; B-14. Function Name: LISTEN 33: ; 34: ; Purpose: Command a device on the serial bus to listen 35: ; Call Address: $FFB1 (hex) 65457 (decimal) 36: ; Communication registers: A 37: ; Preparatory routines: None 38: ; Error returns: See READST 39: ; Stack requirements: None 40: ; Registers affected: A 41: ; 42: ; Description: This routine will command a device on the serial bus to 43: ; receive data. The accumulator must be loaded with a device number between 44: ; 0 and 31 before calling the routine. LISTEN will OR the number bit by bit 45: ; to convert to a listen address, then transmits this data as a command on 46: ; the serial bus. The specified device will then go into listen mode, and 47: ; be ready to accept information. 48: ; 49: ; How to Use: 50: ; 1) Load the accumulator with the number of the device to command 51: ; to LISTEN. 52: ; 2) Call this routine using the JSR instruction. 53: ; 54: ; EXAMPLE: 55: ; ;COMMAND DEVICE #8 TO LISTEN 56: ; LDA #8 57: ; JSR LISTEN 58: ; 59: ; 60: iLISTEN: 61: ora #IEEE_LISTEN ; create primary address for TALK 62: jsr LF0A4 ; TODO (assumed: Wait for RS232 transmission to stop) 63: 64: IecOutputCommand: 65: pha ; remember byte to be output 66: 67: bit zC3PO ; test: Is there already some character in the output buffer? 68: bpl @BufferByte ; no -> branch, do not output but put the byte into the buffer instead 69: 70: ; there is some byte in the output buffer. 71: ; output it on the IEC bus. 72: 73: sec 74: ror zTSFCNT ; set zTSFCNT.7, thus: Signal an EOI on output 75: 76: .ifdef JIFFY 77: jsr JDLFBFE 78: .else 79: jsr IecOutputByte ; output a byte on IEC bus 80: .endif 81: 82: ; IecOutputByte returns with C == 0 83: lsr zC3PO ; unset zC3PO.7, thus: 84: ; mark: There is no byte in the buffer 85: lsr zTSFCNT ; unset zTSFCNT.7. Subsequent bytes will not be signalled with EOI 86: 87: @BufferByte: 88: ; here, zC3PO.7 is unset. 89: ; Either we jumped here because of the bpl, or it was specifically unset two lines above 90: 91: ; Thus, the buffer is already marked as empty 92: 93: pla ; get back the byte to be output 94: sta zBSOUR ; and store it into the output buffer 95: 96: .if CompileComputer >= C64_GENERAL 97: sei ; make sure the interrupt does not disturb our timing 98: 99: ; it is not completely clear if this command is missing 100: ; on the VIC20, or if it is not critical there, as the VIC20 101: ; does not have badlines, which might help the timing here. 102: .endif 103: 104: ; TODO: document 105: .ifdef JIFFY 106: jsr JDLF0ED 107: .else 108: jsr IecDataClear 109: .endif 110: 111: cmp #IEEE_UNLISTEN 112: bne @NotUNLISTEN 113: 114: jsr IecClkClear 115: 116: @NotUNLISTEN: 117: 118: ; set ATN state 119: 120: lda IEC_REG_ATN_OUT 121: ora #IEC_B_ATN_OUT 122: sta IEC_REG_ATN_OUT 123: 124: IecOutputByte2: 125: .if CompileComputer >= C64_GENERAL 126: sei ; make sure the interrupt does not disturb our timing 127: 128: ; it is not completely clear if this command is missing 129: ; on the VIC20, or if it is not critical there, as the VIC20 130: ; does not have badlines, which might help the timing here. 131: .endif 132: jsr IecClkSet 133: jsr IecDataClear 134: jsr IecDelay1ms 135: 136: 137: 138: IecOutputByte: 139: sei ; make sure the interrupt does not disturb our timing 140: 141: .if CompileComputer >= VIC20_06 142: jsr IecDataClear 143: .endif 144: 145: jsr IecGetDataClockIn 146: IEC_GET_DATA_INTO_CARRY 147: bcs @DeviceNotPresent 148: jsr IecClkClear 149: bit zTSFCNT 150: bpl @LED5A 151: 152: @WaitDataInactive: 153: jsr IecGetDataClockIn 154: IEC_GET_DATA_INTO_CARRY 155: bcc @WaitDataInactive 156: 157: @WaitDataActive: 158: jsr IecGetDataClockIn 159: IEC_GET_DATA_INTO_CARRY 160: bcs @WaitDataActive 161: 162: @LED5A: 163: jsr IecGetDataClockIn 164: IEC_GET_DATA_INTO_CARRY 165: bcc @LED5A 166: 167: jsr IecClkSet 168: 169: .ifdef JIFFY 170: txa 171: pha 172: ldx #8 173: .else 174: lda #8 ; number of bits to be output 175: sta zCNTDN 176: .endif 177: 178: @NextBit: 179: 180: .ifdef JIFFY 181: pha 182: pla 183: bit IEC_REG 184: bmi @JDLED72 185: pla 186: tax 187: jmp SendTimeout 188: 189: @JDLED72: 190: jsr IecDataClear 191: ror zBSOUR 192: bcs @JDLED7C 193: jsr IecDataSet 194: 195: @JDLED7C: 196: jsr IecClkClear 197: lda IEC_REG 198: and # ~ IEC_B_DATA_OUT 199: ora #IEC_B_CLK_OUT 200: php 201: pha 202: jsr JDLF8EA 203: pla 204: plp 205: dex 206: bne @NextBit 207: pla 208: tax 209: 210: .else 211: lda IEC_REG_DATA_CLK_IN 212: cmp IEC_REG_DATA_CLK_IN 213: bne @NextBit ; wait for IEC register to settle (TODO entprellen) 214: IEC_REG__DATA_IN_INTO_CARRY 215: bcc SendTimeout ; data set (inactive) -> something/someone else is messing with us, there is a transmission problem -> branch 216: 217: ror zBSOUR ; next bit to output (LSB) into C 218: bcs @OutputData1 ; is it set -> output a "1" (inactive) on the IEC bus data line 219: jsr IecDataSet ; it was not set -> output a "0" (active) on the IEC bus data line 220: bne @ContinueAfterOutputData ; skip next command 221: 222: @OutputData1: 223: jsr IecDataClear ; output a "1" (inactive) on the IEC bus data line 224: 225: @ContinueAfterOutputData: 226: jsr IecClkClear ; clear clock to indicate: Data has been set accordingly 227: 228: ; delay 8 (4*2) clock cycles, giving the other side time to read the value in 229: nop 230: nop 231: nop 232: nop 233: 234: ; clear DATA and set Clock again, indicating the bit is not available anymore 235: lda IEC_REG_DATA_CLK_OUT 236: and #~IEC_B_DATA_OUT 237: ora #IEC_B_CLK_OUT 238: sta IEC_REG_DATA_CLK_OUT 239: 240: dec zCNTDN ; still bits to be output? 241: bne @NextBit ; yes -> branch -> process the next bit 242: .endif 243: 244: ; TODO document 245: 246: ; wait for acknowledgement from other side 247: 248: lda #>$0400 ; set timer to approx. 1000 µs ( = 1 ms) 249: sta IEC_TIMER_HI 250: 251: .if CompileComputer >= C64_GENERAL 252: 253: ; start timer B with one-shot mode, no PB7, counting PHI2 254: lda #CIA_CRB_B_START | CIA_CRB_B_ONESHOT | CIA_CRB_B_FORCE_LOAD 255: sta CIA1 + CIA_O_CRB 256: 257: lda IEC_TIMER_FLAG_REG ; make sure the ICR is cleared, so we do not 258: ; immediately stop the following loop because 259: ; some other TB underflow condition has occurred before 260: .endif 261: 262: 263: @WaitForAck: 264: lda IEC_TIMER_FLAG_REG 265: and #IEC_TIMER_FLAG_B 266: bne SendTimeout 267: jsr IecGetDataClockIn 268: IEC_GET_DATA_INTO_CARRY 269: bcs @WaitForAck 270: cli 271: rts 272: 273: 274: @DeviceNotPresent: 275: lda #$80 ; set bit: device not present error 276: 277: .byte ASM_BIT3 ; hide the next instruction 278: 279: SendTimeout: 280: lda #$03 ; set bits: read timeout and write timeout 281: 282: IecSetStatusAndFreeBus: 283: jsr SetStatus ; set the status bits 284: 285: .if CompileComputer = VIC20_02 286: jsr IEC_CLR_ATN 287: jsr IecClkSet 288: .endif 289: 290: cli 291: .if CompileComputer >= VIC20_06 292: clc 293: bcc IecClearAtnAndClockAndDataAfterDelay 294: ; ------------------ 295: .else 296: jmp IecDataClear 297: ; ------------------ 298: .endif 299: 300: ; B-27. Function Name: SECOND 301: ; 302: ; Purpose: Send secondary address for LISTEN 303: ; Call address: $FF93 (hex) 65427 (decimal) 304: ; Communication registers: A 305: ; Preparatory routines: LISTEN 306: ; Error returns: See READST 307: ; Stack requirements: 8 308: ; Registers affected: A 309: ; 310: ; Description: This routine is used to send a secondary address to an 311: ; I/O device after a call to the LISTEN routine is made, and the device is 312: ; commanded to LISTEN. The routine canNOT be used to send a secondary 313: ; address after a call to the TALK routine. 314: ; A secondary address is usually used to give setup information to a 315: ; device before I/O operations begin. 316: ; When a secondary address is to be sent to a device on the serial bus, 317: ; the address must first be ORed with $60. 318: ; 319: ; How to Use: 320: ; 321: ; 1) load the accumulator with the secondary address to be sent. 322: ; 2) Call this routine. 323: ; 324: ; EXAMPLE: 325: ; 326: ; ;ADDRESS DEVICE #8 WITH COMMAND (SECONDARY ADDRESS) #15 327: ; LDA #8 328: ; JSR LISTEN 329: ; LDA #15 330: ; JSR SECOND 331: ; 332: ; 333: iSECOND: 334: sta zBSOUR ; byte (secondary address after LISTEN) to be output 335: jsr IecOutputByte2 336: 337: IEC_CLR_ATN: 338: 339: ; clear ATN state 340: lda IEC_REG_ATN_OUT 341: and #~IEC_B_ATN_OUT 342: sta IEC_REG_ATN_OUT 343: 344: rts 345: 346: ; B-35. Function Name: TKSA 347: ; 348: ; Purpose: Send a secondary address to a device commanded to TALK 349: ; Call address: $FF96 (hex) 65430 (decimal) 350: ; Communication registers: A 351: ; Preparatory routines: TALK 352: ; Error returns: See READST 353: ; Stack requirements: 8 354: ; Registers affected: A 355: ; 356: ; 357: ; 358: ; Description: This routine transmits a secondary address on the serial 359: ; bus for a TALK device. This routine must be called with a number between 360: ; 0 and 31 in the accumulator. The routine sends this number as a secondary 361: ; address command over the serial bus. This routine can only be called 362: ; after a call to the TALK routine. It will not work after a LISTEN. 363: ; 364: ; How to Use: 365: ; 366: ; 0) Use the TALK routine. 367: ; 1) Load the accumulator with the secondary address. 368: ; 2) Call this routine. 369: ; 370: ; EXAMPLE: 371: ; 372: ; ;TELL DEVICE #4 TO TALK WITH COMMAND #7 373: ; LDA #4 374: ; JSR TALK 375: ; LDA #7 376: ; JSR TALKSA 377: ; 378: iTKSA: 379: sta zBSOUR ; byte (secondary address after TALK) to be output 380: jsr IecOutputByte2 381: 382: ; perform talk - listener - change (TODO) 383: 384: iTKSA2: 385: sei 386: jsr IecDataSet 387: jsr IEC_CLR_ATN 388: jsr IecClkClear 389: 390: @LEDD6: 391: .ifdef JIFFY 392: bit IEC_REG 393: .else 394: jsr IecGetDataClockIn 395: .endif 396: 397: .ifdef JIFFY 398: bvs @LEDD6 399: .elseif CompileComputer >= C64_GENERAL 400: bmi @LEDD6 401: .else 402: bcs @LEDD6 403: .endif 404: cli 405: rts 406: 407: ; B-6. Function Name: CIOUT 408: ; 409: ; Purpose: Transmit a byte over the serial bus 410: ; Call address: $FFA8 (hex) 65448 (decimal) 411: ; Communication registers: A 412: ; Preparatory routines: LISTEN, [SECOND] 413: ; Error returns: See READST 414: ; Stack requirements: 5 415: ; Registers affected: None 416: ; 417: ; Description: This routine is used to send information to devices on the 418: ; serial bus. A call to this routine will put a data byte onto the serial 419: ; bus using full serial handshaking. Before this routine is called, the 420: ; LISTEN KERNAL routine must be used to command a device on the serial bus 421: ; to get ready to receive data. (If a device needs a secondary address, it 422: ; must also be sent by using the SECOND KERNAL routine.) The accumulator is 423: ; loaded with a byte to handshake as data on the serial bus. A device must 424: ; be listening or the status word will return a timeout. This routine 425: ; always buffers one character. (The routine holds the previous character 426: ; to be sent back.) So when a call to the KERNAL UNLSN routine is made to 427: ; end the data transmission, the buffered character is sent with an End Or 428: ; Identify (EOI) set. Then the UNLSN command is sent to the device. 429: ; 430: ; How to Use: 431: ; 432: ; 0) Use the LISTEN KERNAL routine (and the SECOND routine if needed). 433: ; 1) Load the accumulator with a byte of data. 434: ; 2) Call this routine to send the data byte. 435: ; 436: ; EXAMPLE: 437: ; 438: ; 439: ; LDA #'X ;SEND AN X TO THE SERIAL BUS 440: ; JSR CIOUT 441: ; 442: ; 443: iCIOUT: 444: bit zC3PO ; check if there is already a byte buffered to be output 445: bmi @SendBufferedChar ; there is one -> branch, send it 446: 447: sec ; there was none -> set bit 7 to mark that we now have a byte to be output 448: ror zC3PO 449: 450: bne @NoCached ; uncond. branch: store the next byte to be output 451: ; ------------------ 452: 453: @SendBufferedChar: 454: pha ; remember the new byte to be output 455: .ifdef JIFFY 456: jsr $FBFE 457: .else 458: jsr IecOutputByte ; output the old buffered byte 459: .endif 460: pla ; get back the new byte to be output 461: 462: @NoCached: 463: sta zBSOUR ; store the new byte to be output on the next call 464: 465: clc ; mark: no error 466: rts 467: ; ------------------ 468: 469: 470: ; B-38. Function Name: UNTLK 471: ; 472: ; Purpose: Send an UNTALK command 473: ; Call address: $FFAB (hex) 65451 (decimal) 474: ; Communication registers: None 475: ; Preparatory routines: None 476: ; Error returns: See READST 477: ; Stack requirements: 8 478: ; Registers affected: A 479: ; 480: ; Description: This routine transmits an UNTALK command on the serial 481: ; bus. All devices previously set to TALK will stop sending data when this 482: ; command is received. 483: ; 484: ; How to Use: 485: ; 1) Call this routine. 486: ; 487: ; 488: ; EXAMPLE: 489: ; JSR UNTALK 490: ; 491: iUNTLK: 492: .if CompileComputer >= C64_GENERAL 493: sei 494: .endif 495: 496: ; make sure to signal the talker that we will take over the bus now! 497: 498: .ifdef JIFFY 499: .else 500: jsr IecClkSet 501: .endif 502: 503: ; set ATN state 504: 505: lda IEC_REG_ATN_OUT 506: ora #IEC_B_ATN_OUT 507: sta IEC_REG_ATN_OUT 508: 509: .ifdef JIFFY 510: jsr IecClkSet 511: .endif 512: 513: lda #IEEE_UNTALK ; set command byte: UNTALK 514: 515: .byte ASM_BIT3 ; hide the next instruction 516: 517: ; B-37. Function Name: UNLSN 518: ; 519: ; Purpose: Send an UNLISTEN command 520: ; Call address: $FFAE (hex) 65454 (decimal) 521: ; Communication registers: None 522: ; Preparatory routines: None 523: ; Error returns: See READST 524: ; Stack requirements: 8 525: ; Registers affected: A 526: ; 527: ; Description: This routine commands all devices on the serial bus to 528: ; stop receiving data from the Commodore 64 (i.e., UNLISTEN). Calling this 529: ; routine results in an UNLISTEN command being transmitted on the serial 530: ; bus. Only devices previously commanded to listen are affected. This 531: ; routine is normally used after the Commodore 64 is finished sending data 532: ; to external devices. Sending the UNLISTEN commands the listening devices 533: ; to get off the serial bus so it can be used for other purposes. 534: ; 535: ; How to Use: 536: ; 1) Call this routine. 537: ; 538: ; EXAMPLE: 539: ; JSR UNLSN 540: ; 541: iUNLSN: 542: lda #IEEE_UNLISTEN ; set command byte: UNLISTEN 543: 544: jsr IecOutputCommand ; output the command byte on the IEC bus 545: 546: .if CompileComputer = VIC20_02 547: bne IEC_CLR_ATN ; done (bug) 548: ; --------------------- 549: .else 550: 551: IecClearAtnAndClockAndDataAfterDelay: 552: jsr IEC_CLR_ATN ; clear ATN 553: 554: ; TODO document 555: 556: IecClearClockAndDataAfterDelay: 557: txa 558: .if CompileComputer >= C64_GENERAL 559: ; TODO define 560: ldx #10 561: .else 562: ldx #11 563: .endif 564: @Delay: dex 565: bne @Delay 566: tax 567: jsr IecClkClear 568: jmp IecDataClear 569: .endif 570: 571: ; B-1. Function Name: ACPTR 572: ; 573: ; Purpose: Get data from the serial bus 574: ; Call address: $FFA5 (hex) 65445 (decimal) 575: ; Communication registers: A 576: ; Preparatory routines: TALK, TKSA 577: ; Error returns: See READST 578: ; Stack requirements: 13 579: ; Registers affected: A, X 580: ; 581: ; 582: ; 583: ; Description: This is the routine to use when you want to get informa- 584: ; tion from a device on the serial bus, like a disk. This routine gets a 585: ; byte of data off the serial bus using full handshaking. The data is 586: ; returned in the accumulator. To prepare for this routine the TALK routine 587: ; must be called first to command the device on the serial bus to send data 588: ; through the bus. If the input device needs a secondary command, it must 589: ; be sent by using the TKSA KERNAL routine before calling this routine. 590: ; Errors are returned in the status word. The READST routine is used to 591: ; read the status word. 592: ; 593: ; 594: ; How to Use: 595: ; 596: ; 0) Command a device on the serial bus to prepare to send data to 597: ; the Commodore 64. (Use the TALK and TKSA KERNAL routines.) 598: ; 1) Call this routine (using JSR). 599: ; 2) Store or otherwise use the data. 600: ; 601: ; 602: ; EXAMPLE: 603: ; 604: ; ;GET A BYTE FROM THE BUS 605: ; JSR ACPTR 606: ; STA DATA 607: ; 608: ; 609: ; 610: iACPTR: 611: .ifdef JIFFY 612: jmp $FBAA 613: 614: .else 615: 616: sei ; make sure to be able to hold the timing 617: 618: .if CompileComputer < VIC20_06 619: lda #8 ; 8 bits to be input 620: .else 621: lda #0 ; TODO: ??? 622: .endif 623: .endif 624: 625: JDiACPTR: 626: sta zCNTDN ; and store it as counter 627: 628: 629: 630: .if CompileComputer >= VIC20_06 631: jsr IecClkClear ; clear CLOCK to signal: We are ready to handle the byte 632: .endif 633: 634: 635: @WaitDataInactive: 636: 637: ; wait for DATA to become inactive: 638: ; That is, wait for the other side to be ready to send a byte 639: 640: jsr IecGetDataClockIn 641: .if CompileComputer >= C64_GENERAL 642: bpl @WaitDataInactive 643: .else 644: bcc @WaitDataInactive 645: jsr IecDataClear ; clear DATA (unnecessary, as the loop would not terminate if we would not have data cleared!) 646: .endif 647: 648: @LEE20: 649: 650: lda #>$0100 ; set timer to approx. 250 µs 651: sta IEC_TIMER_HI 652: 653: .if CompileComputer >= C64_GENERAL 654: ; start timer B with one-shot mode, no PB7, counting PHI2 655: lda #CIA_CRB_B_START | CIA_CRB_B_ONESHOT | CIA_CRB_B_FORCE_LOAD 656: sta CIA1 + CIA_O_CRB 657: 658: jsr IecDataClear ; clear DATA 659: 660: lda IEC_TIMER_FLAG_REG ; make sure the ICR is cleared, so we do not 661: ; immediately stop the following loop because 662: ; some other TB underflow condition has occurred before 663: 664: .endif 665: 666: @LEE30: lda IEC_TIMER_FLAG_REG 667: and #IEC_TIMER_FLAG_B 668: bne @LEE3E 669: 670: jsr IecGetDataClockIn 671: 672: .if CompileComputer >= C64_GENERAL 673: bmi @LEE30 674: bpl @LEE56 675: .else 676: bcs @LEE30 677: bcc @LEE56 678: .endif 679: 680: 681: @LEE3E: 682: 683: .if CompileComputer = VIC20_02 684: 685: jsr IecDataSet 686: txa 687: ldx #$10 688: @Delay: dex 689: bne @Delay 690: tax 691: jsr IecDataClear 692: jsr IecGetDataClockIn 693: 694: lda #$40 ; status bit: EOI 695: jsr SetStatus ; set the status to EOI 696: 697: @LEE56: lda IEC_REG_DATA_CLK_IN 698: cmp IEC_REG_DATA_CLK_IN 699: bne @LEE56 700: IEC_REG__CLOCK_IN_INTO_CARRY 701: bcc @LEE56 702: lsr a 703: ror zTBTCNT 704: 705: @WaitClkInactive: 706: lda IEC_REG_DATA_CLK_IN 707: cmp IEC_REG_DATA_CLK_IN 708: bne @WaitClkInactive 709: 710: IEC_REG__CLOCK_IN_INTO_CARRY 711: bcs @WaitClkInactive 712: dec zCNTDN 713: bne @LEE56 714: jsr IecDataSet 715: lda zTBTCNT 716: cli 717: clc 718: rts 719: 720: .else 721: 722: lda zCNTDN 723: beq @Proceed 724: 725: lda #$02 ; set status: read timeout 726: jmp IecSetStatusAndFreeBus ; ... and free the bus and exit 727: ; ------------------ 728: 729: @Proceed: 730: jsr IecDataSet 731: .if CompileComputer >= C64_GENERAL 732: jsr IecClkClear 733: .else 734: jsr IecClearClockAndDataAfterDelay 735: .endif 736: lda #$40 737: jsr SetStatus 738: inc zCNTDN 739: bne @LEE20 740: 741: @LEE56: lda #8 ; number of bits to be input 742: sta zCNTDN 743: @LEE5A: 744: lda IEC_REG_DATA_CLK_IN 745: cmp IEC_REG_DATA_CLK_IN 746: bne @LEE5A 747: 748: .if CompileComputer >= C64_GENERAL 749: asl a 750: bpl @LEE5A 751: .else 752: lsr a 753: bcc @LEE5A 754: lsr a 755: .endif 756: ror zTBTCNT 757: @LEE67: 758: lda IEC_REG_DATA_CLK_IN 759: cmp IEC_REG_DATA_CLK_IN 760: bne @LEE67 761: .if CompileComputer >= C64_GENERAL 762: asl a 763: bmi @LEE67 764: .else 765: lsr a 766: bcs @LEE67 767: .endif 768: 769: dec zCNTDN 770: bne @LEE5A 771: jsr IecDataSet 772: .if CompileComputer >= C64_GENERAL 773: bit zSTATUS 774: bvc @LEE80 775: .else 776: lda zSTATUS 777: beq @LEE80 778: .endif 779: jsr IecClearClockAndDataAfterDelay 780: @LEE80: lda zTBTCNT 781: cli 782: clc 783: rts 784: .endif 785: 786: IecClkClear: 787: ; clear (set inactive) the clock line 788: lda IEC_REG_DATA_CLK_OUT 789: and #~IEC_B_CLK_OUT 790: sta IEC_REG_DATA_CLK_OUT 791: rts 792: 793: IecClkSet: 794: ; set (set active) the clock line 795: lda IEC_REG_DATA_CLK_OUT 796: ora #IEC_B_CLK_OUT 797: sta IEC_REG_DATA_CLK_OUT 798: rts 799: 800: .segment "KERNAL_IEC_DATA" 801: 802: IecDataClear: 803: lda IEC_REG_DATA_CLK_OUT 804: and #~IEC_B_DATA_OUT 805: sta IEC_REG_DATA_CLK_OUT 806: rts 807: IecDataSet: 808: lda IEC_REG_DATA_CLK_OUT 809: ora #IEC_B_DATA_OUT 810: sta IEC_REG_DATA_CLK_OUT 811: rts 812: 813: ; reads in IEC register and returns 814: ; * C64: 815: ; - DATA IN in Carry 816: ; - CLOCK IN in A & 0x80 817: ; * VIC20: 818: ; - CLOCK IN in Carry 819: ; - DATA IN in A & 0x01 820: ; 821: IecGetDataClockIn: 822: lda IEC_REG_DATA_CLK_IN 823: cmp IEC_REG_DATA_CLK_IN 824: bne IecGetDataClockIn 825: .if CompileComputer >= C64_GENERAL 826: asl a 827: .else 828: lsr a 829: .endif 830: rts 831: 832: 833: .segment "KERNAL_IEC_DELAY" 834: 835: IecDelay1ms: 836: 837: .if CompileComputer >= C64_GENERAL 838: txa 839: ldx #184 840: @Delay: dex 841: bne @Delay 842: tax 843: .else 844: lda #>$0400 ; program T2 for $0400 = 1024 cycles (approx. 1 ms) 845: sta VIA2_T2CH ; (low byte is not written, thus, should be 0) 846: 847: ; wait for T2 flag being set in the IFR, 848: ; telling us that the timer expired 849: @Wait: 850: lda VIA2_IFR 851: and #VIA_IFR_B_T2 852: beq @Wait 853: .endif 854: rts 855: