I’ve commented a few times on this subject but it seems that some people still find it obscure. Also, some of those who read my explanation on this seem to periodically forget it, including SLC 😛
Therefore here’s how it works, in the hope it will stick in the head of those who deal with tape-related activities.
The Cassette read line on the C64 is wired to CIA #1’s FLAG line. This line is edge sensitive; specifically, the CIA chip only reacts to falling edges on the Cassette read line.
What happens when a falling edge is detected on this line then? Bit 4 of $DC0D is set by the hardware, and that’s pretty much about it: programs have no control over this hard wiring and cannot therefore detect rising edges on the Cassette read line, nor, equivalently, the current digital level on the line.
It should be no surprise then that non-IRQ-based loaders use this code (or equivalent variations with the BIT instruction) within their “read bit” sub-routine:
lda $dc0d ; Checks the interrupt register and #$10 ; to see if a pulse (negative beq *-5 ; edge on a C64) came in or not
When bit 4 of DC0D is written to by software it works as a FLAG line interrupt enable bit: if it is set an interrupt request is also generated upon detecting a falling edge on the FLAG line. In fact, an IRQ-based loader on the C64 will do something like this to enable the FLAG line interrupt:
lda #$90 ; CIA #1 Interrupt Control Register setup: sta $dc0d ; enable just FLAG line interrupt (bit 4)
And consequently something like this to attach the IRQ handler:
lda #<IRQ ; Maskable Interrupt Request Vector setup: sta $fffe ; make this vector point to our IRQ handler (ISR) lda #>IRQ ; so that a FLAG line interrupt will cause its sta $ffff ; execution.
The Cassette write line, however, being mapped to a bit at location $1 can be flipped at will: that’s what tape mastering software do, including the Kernal’s “SAVE RAM” routine, in order to produce square waves when recording to tape.
On the C16/+4 both Cassette read and write lines are mapped to bits at location $1, meaning that a program can poll the read line and detect level changes in either direction, i.e. both rising and falling edges. Certain turbo loaders exploit this fact and use the duration of each level of the signal to encode a bit, instead of using the period of a 50% duty-cycle square wave, which is what happens on the C64. This exploitation results in faster load times and makes it necessary to use “halfwaves” to dump the tapes on which such turbo files are encoded.
So there’s nothing special about the 1530 when compared to the 1531: they are essentially the same peripheral with different connectors. The ability to detect both signal edges on the Cassette read line (or lack of it) is entirely related to the wiring of such line within the host computer. That’s the reason a C2N datassette can be used to dump all sorts of 8-bit tapes: it is not limited to detecting only one type of signal edge.
Why is the C64 arrangement of the Cassette read line a beautiful thing compared to C16? Because turbo tape loaders don’t necessarily have to monitor bit 4 of $DC0D in a tight loop in order to not miss an incoming bit from tape. Non-IRQ-based loaders chose to spend a lot of CPU cycles in a tight loop at the cost of not being able to use the CPU for anything else major: they often just shift bits in, flash the border, store bytes, check if all data was loaded, and calculate check bytes. With access to a hardware interrupt, IRQ-based loaders are not concerned about constantly monitoring bit 4 in $DC0D in a desperate attempt not to miss any incoming bit: they spend most of the time doing something else that gets interrupted when a bit is available on the read line, indicated by a falling edge. What do they do then when not processing an incoming bit? You name it: scroll text, play a tune, or even let users play a game such as “Invade-a-Load” 🙂
Obviously there are timing constraints that I have omitted in the above discussion for clarity: you can very well imagine that you can’t shorten bit durations (or their deltas) as much as you want, nor you can have a heavy load in an IRQ-based loader in conjunction with short bit durations.