# C64 delay

Yesterday I was looking at some delay methods on the C64. On the 8-bit
PIC microcontrollers I used nested loops. They are easy to calculate
as the vast majority of the assembly instructions takes 1 cycle to
execute.

If you look for delays and timing on the C64 you'll find a lot about
timer IRQs and cycle exact timing. But I am not writing a game or a
demo, I just thought about how to delay 2s for example. I don't even
need an IRQ, busy waiting is just fine.

I found some texts about the jiffy clock or watching out for some
raster lines and so on. Of course I do not like endlessly searching
for information so I gave up after some time. I wanted to find some
easy examples which delay for an approximate (I don't need exact
timing right now) amount of time.

I saw an example where one CIA timer was loaded with 985248, which is
the number of clock cycles per second on a PAL system. So this gives
you a 1s delay. The other timer was then used to count the underflows
of the first one so that the delay can be extended to multiple
seconds. But why? I think there is an easier way.

As a note for myself here is what I came up with:

There are two CIA chips in the C64 each having 2 16-bit timers.
The IOINIT ($FDA3) Kernal routine initializes the CIAs. A part of
this routine initializes CIA #1 timer A beginning at address $FDDD.
The routine first checks the PAL/NTSC flag at $02A6 and sets the timer
A value accordingly. As a result timer A reaches zero and generates an
interrupt at about every 1/60 second on both systems. Timer A runs in
continuous mode and serves as the interrupt source for reading the
keyboard and flashing the cursor.

CIA #1 timer B is not used by the system and is able to count how many
times timer A gets to zero. So why not load timer B with 120 and set
it to count timer A underflows? This way I would get a near 2s delay,
wouldn't I?

It is still busy waiting as I have to check when timer B gets to zero,
but I don't need anything more complicated right now. There are a few
unused bytes between $02A7-$02FF, let's put this handful of
instructions here.

Source is tmpx syntax.


; CIA #1 registers
timblo          = $dc06         ; CIA #1 timer B low byte
timbhi          = $dc07         ; CIA #1 timer B high byte
ciacrb          = $dc0f         ; CIA #1 control register B

               *=$02a8         ; SYS680
               ldx #$00        ; $0078 -> timer B latch
               stx timbhi
               lda #120
               sta timblo

               ; bit 0: start timer B
               ; bit 3: in one-shot mode
               ; bit 4: load the value from the latch
               ; bit 5-6: count timer A zeros
               lda #%01011001
               sta ciacrb

wait            lda timblo
               bne wait        ; not 0 -> goto wait

               rts

It's probably lame, but works.
And even using only the low byte of timer B you can have a delay
between 1/60s and 4.25s.