iec.a65

     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:  
Valid XHTML 1.0 Strict
iec.a65.html; generated on Fri Sep 18 21:44:54 2015 by ca65html
uz@cc65.org