Prev: F8E2 Up: Map Next: FA60
F92C: read tape bits, IRQ routine
On Commodore computers, the streams consist of four kinds of symbols that denote different kinds of low-to-high-to-low transitions on the read or write signals of the Commodore cassette interface.
  • A break in the communications, or a pulse with very long cycle time.
  • A short pulse, whose cycle time typically ranges from 296 to 424 microseconds, depending on the computer model.
  • A medium-length pulse, whose cycle time typically ranges from 440 to 576 microseconds, depending on the computer model.
  • A long pulse, whose cycle time typically ranges from 600 to 744 microseconds, depending on the computer model.
The actual interpretation of the serial data takes a little more work to explain. The typical ROM tape loader (and the turbo loaders) will initialize a timer with a specified value and start it counting down. If either the tape data changes or the timer runs out, an IRQ will occur. The loader will determine which condition caused the IRQ. If the tape data changed before the timer ran out, we have a short pulse, or a "0" bit. If the timer ran out first, we have a long pulse, or a "1" bit. Doing this continuously and we decode the entire file.
read T2C which has been counting down from $FFFF. subtract this from $FFFF
F92C AE 07 DC LDX $DC07 read VIA 1 timer B high byte
F92F A0 FF LDY #$FF set $FF
F931 98 TYA A = $FF
F932 ED 06 DC SBC $DC06 subtract VIA 1 timer B low byte
F935 EC 07 DC CPX $DC07 compare it with VIA 1 timer B high byte
F938 D0 F2 BNE $F92C if timer low byte rolled over loop
F93A 86 B1 STX $B1 save tape timing constant max byte
F93C AA TAX copy $FF - T2C_l
F93D 8C 06 DC STY $DC06 save VIA 1 timer B low byte
F940 8C 07 DC STY $DC07 save VIA 1 timer B high byte
F943 A9 19 LDA #$19 load timer B, timer B single shot, start timer B
F945 8D 0F DC STA $DC0F save VIA 1 CRB
F948 AD 0D DC LDA $DC0D read VIA 1 ICR
F94B 8D A3 02 STA $02A3 save VIA 1 ICR shadow copy
F94E 98 TYA Y = $FF
F94F E5 B1 SBC $B1 subtract tape timing constant max byte
A = $FF - T2C_h
F951 86 B1 STX $B1 save tape timing constant max byte
$B1 = $FF - T2C_l
F953 4A LSR A A = $FF - T2C_h >> 1
F954 66 B1 ROR $B1 shift tape timing constant max byte
$B1 = $FF - T2C_l >> 1
F956 4A LSR A A = $FF - T2C_h >> 1
F957 66 B1 ROR $B1 shift tape timing constant max byte
$B1 = $FF - T2C_l >> 1
F959 A5 B0 LDA $B0 get tape timing constant min byte
F95B 18 CLC clear carry for add
F95C 69 3C ADC #$3C
F95E C5 B1 CMP $B1 compare with tape timing constant max byte
compare with ($FFFF - T2C) >> 2
F960 B0 4A BCS $F9AC branch if min + $3C >= ($FFFF - T2C) >> 2
min + $3C < ($FFFF - T2C) >> 2
F962 A6 9C LDX $9C get byte received flag
F964 F0 03 BEQ $F969 if not byte received ??
F966 4C 60 FA JMP $FA60 store the tape character
F969 A6 A3 LDX $A3 get EOI flag byte
F96B 30 1B BMI $F988
F96D A2 00 LDX #$00
F96F 69 30 ADC #$30
F971 65 B0 ADC $B0 add tape timing constant min byte
F973 C5 B1 CMP $B1 compare with tape timing constant max byte
F975 B0 1C BCS $F993
F977 E8 INX
F978 69 26 ADC #$26
F97A 65 B0 ADC $B0 add tape timing constant min byte
F97C C5 B1 CMP $B1 compare with tape timing constant max byte
F97E B0 17 BCS $F997
F980 69 2C ADC #$2C
F982 65 B0 ADC $B0 add tape timing constant min byte
F984 C5 B1 CMP $B1 compare with tape timing constant max byte
F986 90 03 BCC $F98B
F988 4C 10 FA JMP $FA10
F98B A5 B4 LDA $B4 get the bit count
F98D F0 1D BEQ $F9AC if all done go ??
F98F 85 A8 STA $A8 save receiver bit count in
F991 D0 19 BNE $F9AC branch always
F993 E6 A9 INC $A9 increment ?? start bit check flag
F995 B0 02 BCS $F999
F997 C6 A9 DEC $A9 decrement ?? start bit check flag
F999 38 SEC
F99A E9 13 SBC #$13
F99C E5 B1 SBC $B1 subtract tape timing constant max byte
F99E 65 92 ADC $92 add timing constant for tape
F9A0 85 92 STA $92 save timing constant for tape
F9A2 A5 A4 LDA $A4 get tape bit cycle phase
F9A4 49 01 EOR #%00000001
F9A6 85 A4 STA $A4 save tape bit cycle phase
F9A8 F0 2B BEQ $F9D5
F9AA 86 D7 STX $D7
F9AC A5 B4 LDA $B4 get the bit count
F9AE F0 22 BEQ $F9D2 if all done go ??
F9B0 AD A3 02 LDA $02A3 read VIA 1 ICR shadow copy
F9B3 29 01 AND #%00000001 mask 0000 000x, timer A interrupt enabled
F9B5 D0 05 BNE $F9BC if timer A is enabled go ??
F9B7 AD A4 02 LDA $02A4 read VIA 1 CRA shadow copy
F9BA D0 16 BNE $F9D2 if ?? just exit
F9BC A9 00 LDA #$00 clear A
F9BE 85 A4 STA $A4 clear the tape bit cycle phase
F9C0 8D A4 02 STA $02A4 save VIA 1 CRA shadow copy
F9C3 A5 A3 LDA $A3 get EOI flag byte
F9C5 10 30 BPL $F9F7
F9C7 30 BF BMI $F988
F9C9 A2 A6 LDX #$A6 set timimg max byte
F9CB 20 E2 F8 JSR $F8E2 set timing
F9CE A5 9B LDA $9B
F9D0 D0 B9 BNE $F98B
F9D2 4C BC FE JMP $FEBC restore registers and exit interrupt
F9D5 A5 92 LDA $92 get timing constant for tape
F9D7 F0 07 BEQ $F9E0
F9D9 30 03 BMI $F9DE
F9DB C6 B0 DEC $B0 decrement tape timing constant min byte
F9DD .BYTE $2C makes next line BIT $B0E6
F9DE E6 B0 INC $B0 increment tape timing constant min byte
F9E0 A9 00 LDA #$00
F9E2 85 92 STA $92 clear timing constant for tape
F9E4 E4 D7 CPX $D7
F9E6 D0 0F BNE $F9F7
F9E8 8A TXA
F9E9 D0 A0 BNE $F98B
F9EB A5 A9 LDA $A9 get start bit check flag
F9ED 30 BD BMI $F9AC
F9EF C9 10 CMP #$10
F9F1 90 B9 BCC $F9AC
F9F3 85 96 STA $96 save cassette block synchronization number
F9F5 B0 B5 BCS $F9AC
F9F7 8A TXA
F9F8 45 9B EOR $9B
F9FA 85 9B STA $9B
F9FC A5 B4 LDA $B4
F9FE F0 D2 BEQ $F9D2
FA00 C6 A3 DEC $A3 decrement EOI flag byte
FA02 30 C5 BMI $F9C9
FA04 46 D7 LSR $D7
FA06 66 BF ROR $BF parity count
FA08 A2 DA LDX #$DA set timimg max byte
FA0A 20 E2 F8 JSR $F8E2 set timing
FA0D 4C BC FE JMP $FEBC restore registers and exit interrupt
FA10 A5 96 LDA $96 get cassette block synchronization number
FA12 F0 04 BEQ $FA18
FA14 A5 B4 LDA $B4
FA16 F0 07 BEQ $FA1F
FA18 A5 A3 LDA $A3 get EOI flag byte
FA1A 30 03 BMI $FA1F
FA1C 4C 97 F9 JMP $F997
FA1F 46 B1 LSR $B1 shift tape timing constant max byte
FA21 A9 93 LDA #$93
FA23 38 SEC
FA24 E5 B1 SBC $B1 subtract tape timing constant max byte
FA26 65 B0 ADC $B0 add tape timing constant min byte
FA28 0A ASL A
FA29 AA TAX copy timimg high byte
FA2A 20 E2 F8 JSR $F8E2 set timing
FA2D E6 9C INC $9C
FA2F A5 B4 LDA $B4
FA31 D0 11 BNE $FA44
FA33 A5 96 LDA $96 get cassette block synchronization number
FA35 F0 26 BEQ $FA5D
FA37 85 A8 STA $A8 save receiver bit count in
FA39 A9 00 LDA #$00 clear A
FA3B 85 96 STA $96 clear cassette block synchronization number
FA3D A9 81 LDA #$81 enable timer A interrupt
FA3F 8D 0D DC STA $DC0D save VIA 1 ICR
FA42 85 B4 STA $B4
FA44 A5 96 LDA $96 get cassette block synchronization number
FA46 85 B5 STA $B5
FA48 F0 09 BEQ $FA53
FA4A A9 00 LDA #$00
FA4C 85 B4 STA $B4
FA4E A9 01 LDA #$01 disable timer A interrupt
FA50 8D 0D DC STA $DC0D save VIA 1 ICR
FA53 A5 BF LDA $BF parity count
FA55 85 BD STA $BD save RS232 parity byte
FA57 A5 A8 LDA $A8 get receiver bit count in
FA59 05 A9 ORA $A9 OR with start bit check flag
FA5B 85 B6 STA $B6
FA5D 4C BC FE JMP $FEBC restore registers and exit interrupt
Prev: F8E2 Up: Map Next: FA60