Prev: FBC8 Up: Map Next: FC6A
FBCD: tape write IRQ routine
this is the routine that writes the bits to the tape. it is called each time VIA 2 T2 times out and checks if the start bit is done, if so checks if the data bits are done, if so it checks if the byte is done, if so it checks if the synchronisation bytes are done, if so it checks if the data bytes are done, if so it checks if the checksum byte is done, if so it checks if both the load and verify copies have been done, if so it stops the tape
FBCD A5 A8 LDA $A8 get start bit first cycle done flag
FBCF D0 12 BNE $FBE3 if first cycle done go do rest of byte
each byte sent starts with two half cycles of $0110 system clocks and the whole block ends with two more such half cycles
FBD1 A9 10 LDA #$10 set first start cycle time constant low byte
FBD3 A2 01 LDX #$01 set first start cycle time constant high byte
FBD5 20 B1 FB JSR $FBB1 write time constant and toggle tape
FBD8 D0 2F BNE $FC09 if first half cycle go restore registers and exit interrupt
FBDA E6 A8 INC $A8 set start bit first start cycle done flag
FBDC A5 B6 LDA $B6 get buffer address high byte
FBDE 10 29 BPL $FC09 if block not complete go restore registers and exit interrupt. the end of a block is indicated by the tape buffer high byte b7 being set to 1
FBE0 4C 57 FC JMP $FC57 else do tape routine, block complete exit
continue tape byte write. the first start cycle, both half cycles of it, is complete so the routine drops straight through to here
FBE3 A5 A9 LDA $A9 get start bit check flag
FBE5 D0 09 BNE $FBF0 if the start bit is complete go send the byte bits
after the two half cycles of $0110 ststem clocks the start bit is completed with two half cycles of $00B0 system clocks. this is the same as the first part of a 1 bit
FBE7 20 AD FB JSR $FBAD set time constant for bit = 1 and toggle tape
FBEA D0 1D BNE $FC09 if first half cycle go restore registers and exit interrupt
FBEC E6 A9 INC $A9 set start bit check flag
FBEE D0 19 BNE $FC09 restore registers and exit interrupt, branch always
continue tape byte write. the start bit, both cycles of it, is complete so the routine drops straight through to here. now the cycle pairs for each bit, and the parity bit, are sent
FBF0 20 A6 FB JSR $FBA6 send lsb from tape write byte to tape
FBF3 D0 14 BNE $FC09 if first half cycle go restore registers and exit interrupt
else two half cycles have been done
FBF5 A5 A4 LDA $A4 get tape bit cycle phase
FBF7 49 01 EOR #%00000001 toggle b0
FBF9 85 A4 STA $A4 save tape bit cycle phase
FBFB F0 0F BEQ $FC0C if bit cycle phase complete go setup for next bit
each bit is written as two full cycles. a 1 is sent as a full cycle of $0160 system clocks then a full cycle of $00C0 system clocks. a 0 is sent as a full cycle of $00C0 system clocks then a full cycle of $0160 system clocks. to do this each bit from the write byte is inverted during the second bit cycle phase. as the bit is inverted it is also added to the, one bit, parity count for this byte
FBFD A5 BD LDA $BD get tape write byte
FBFF 49 01 EOR #%00000001 invert bit being sent
FC01 85 BD STA $BD save tape write byte
FC03 29 01 AND #%00000001 mask b0
FC05 45 9B EOR $9B EOR with tape write byte parity bit
FC07 85 9B STA $9B save tape write byte parity bit
This entry point is used by the routine at FBC8.
FC09 4C BC FE JMP $FEBC restore registers and exit interrupt
the bit cycle phase is complete so shift out the just written bit and test for byte end
FC0C 46 BD LSR $BD shift bit out of tape write byte
FC0E C6 A3 DEC $A3 decrement tape write bit count
FC10 A5 A3 LDA $A3 get tape write bit count
FC12 F0 3A BEQ $FC4E if all the data bits have been written go setup for sending the parity bit next and exit the interrupt
FC14 10 F3 BPL $FC09 if all the data bits are not yet sent just restore the registers and exit the interrupt
This entry point is used by the routine at FC6A.
do next tape byte
the byte is complete. the start bit, data bits and parity bit have been written to the tape so setup for the next byte
FC16 20 97 FB JSR $FB97 new tape byte setup
FC19 58 CLI enable the interrupts
FC1A A5 A5 LDA $A5 get cassette synchronization character count
FC1C F0 12 BEQ $FC30 if synchronisation characters done go do block data
at the start of each block sent to tape there are a number of synchronisation bytes that count down to the actual data. the commodore tape system saves two copies of all the tape data, the first is loaded and is indicated by the synchronisation bytes having b7 set, and the second copy is indicated by the synchronisation bytes having b7 clear. the sequence goes $09, $08, ..... $02, $01, data bytes
FC1E A2 00 LDX #$00 clear X
FC20 86 D7 STX $D7 clear checksum byte
FC22 C6 A5 DEC $A5 decrement cassette synchronization byte count
FC24 A6 BE LDX $BE get cassette copies count
FC26 E0 02 CPX #$02 compare with load block indicator
FC28 D0 02 BNE $FC2C branch if not the load block
FC2A 09 80 ORA #$80 this is the load block so make the synchronisation count go $89, $88, ..... $82, $81
FC2C 85 BD STA $BD save the synchronisation byte as the tape write byte
FC2E D0 D9 BNE $FC09 restore registers and exit interrupt, branch always
the synchronization bytes have been done so now check and do the actual block data
FC30 20 D1 FC JSR $FCD1 check read/write pointer, return Cb = 1 if pointer >= end
FC33 90 0A BCC $FC3F if not all done yet go get the byte to send
FC35 D0 91 BNE $FBC8 if pointer > end go flag block done and exit interrupt
else the block is complete, it only remains to write the checksum byte to the tape so setup for that
FC37 E6 AD INC $AD increment buffer pointer high byte, this means the block done branch will always be taken next time without having to worry about the low byte wrapping to zero
FC39 A5 D7 LDA $D7 get checksum byte
FC3B 85 BD STA $BD save checksum as tape write byte
FC3D B0 CA BCS $FC09 restore registers and exit interrupt, branch always
the block isn't finished so get the next byte to write to tape
FC3F A0 00 LDY #$00 clear index
FC41 B1 AC LDA ($AC),Y get byte from buffer
FC43 85 BD STA $BD save as tape write byte
FC45 45 D7 EOR $D7 XOR with checksum byte
FC47 85 D7 STA $D7 save new checksum byte
FC49 20 DB FC JSR $FCDB increment read/write pointer
FC4C D0 BB BNE $FC09 restore registers and exit interrupt, branch always
set parity as next bit and exit interrupt
FC4E A5 9B LDA $9B get parity bit
FC50 49 01 EOR #%00000001 toggle it
FC52 85 BD STA $BD save as tape write byte
This entry point is used by the routines at FC6A and FCB8.
FC54 4C BC FE JMP $FEBC restore registers and exit interrupt
tape routine, block complete exit
FC57 C6 BE DEC $BE decrement copies remaining to read/write
FC59 D0 03 BNE $FC5E branch if more to do
FC5B 20 CA FC JSR $FCCA stop the cassette motor
FC5E A9 50 LDA #$50 set tape write leader count
FC60 85 A7 STA $A7 save tape write leader count
FC62 A2 08 LDX #$08 set index for write tape leader vector
FC64 78 SEI disable the interrupts
FC65 20 BD FC JSR $FCBD set the tape vector
FC68 D0 EA BNE $FC54 restore registers and exit interrupt, branch always
Prev: FBC8 Up: Map Next: FC6A