[net.micro.cbm] 6502 Timing delay routine problem

pugsly@isrnix.UUCP (David Roth) (11/09/85)

The following is an example from a book called:Assembly Language Programming
with the Commodore 64 by Marvin L. De Jong. .
My interest in this type of routine is that I am trying to develop a routine
that will do millisecond delays greater than $00ff, which will require two
bytes. This example will produce a delay of 10 million clock cycles, which is
approxmiately 10 seconds.
The PROBLEM I am having with this routine is that it hangs after it is called
several times and doesn't RTS.
BUT it does appear to work fine if you change the BASIC example to run it.
Enough talk...Here is the source code.
Assemble it in the assembler of your
choice (I use MAE) and save the binary to disk.
           .rc
           .ba $c000
           .os
;-----------------------------------
icr        .de $dd0d ;CIA Interrupt Control Register
talo       .de $dd04 ;Timer A:Low-Byte
tahi       .de $dd05 ;Timer A:High-Byte
tblo       .de $dd06 ;Timer B:Low-Byte
tbhi       .de $dd07 ;Timer B:High-Byte
cra        .de $dd0e ;CIA Control Register A
crb        .de $dd0f ;CIA Control Register B
;-----------------------------------
;
start
;
      sei      ;disable systems interrupts.
      lda #$7f ;disable interrupts from CIA #2.
      sta icr
      lda #$4f ;delay for 50000 clock cycles.
      sta talo ;$c34f + 1 = 50000.
      lda #$c3 ;load the msb of the timer.
      sta tahi
      lda #199 ;tb counts 200 ta underflows.
      sta tblo
      lda #00
      sta tbhi
      lda #$49 ;set up tb and start it.
      sta crb
      lda #$01 ;timer a in free running mode.
      sta cra  ;start timer a.
      lda #$02 ;mask all but timer b flag.
wait  bit icr  ;logical and with icr.
      beq wait ;wait for timer flag to be set.
      cli      ;enable interrupts.
      rts
      .en


Now that you have assembled it and saved it to disk power the C64 down and turn it back on.
Do the following:
LOAD"BINARYEXAMPLE",8,1
NEW

And enter the the following BASIC program.


100 for i=1 to 100
110 :   print "now"
120 :   sys12*4096
200 next i
ready.

Now run it:

RUN

What happens on my system is that it prints "now" no more than 4 or 5 times before it just hangs. I clocked it and waiting several mins. for a 10 second routine to finish is enough for me to know something is wrong.

This is the interesting part...if you add to the above program:
130 PRINT "a"

It will work fine by printing "NOW" and then printing "A" then works as hoped.
It doesn't hang!

Can anyone explain this? Can anyone come up with a working example?

The need for all this is for my music software development. Please don't flame to me about using the "jiffies". 1/60 of a second just doesn't cut it for what I want to do.

As you might guess. My music softwafe is all in 6502 and it hangs playing that note forever. I tried saving all the registers and status before calling the routine and restoring after and no luck.

Thanks in advance.

David A. Roth
...decvax!pur-ee!isrnix!pugsly
...ihnp4!isrnix!pugsly
Indianapolis,IN

chemuncg@ecsvax.UUCP (Harvey B. Herman) (11/18/85)

The following change seems to fix the problem:
   old        new
lda #$01   lda #$11  at $c01f
Timer a was never stopped and this change will latch the data even if
it is still running.  Stopping timer a might also work but this change
was easier.
Harvey B. Herman
Chem. Dept.
UNC-Greensboro
Greensboro, NC 27412
No warrantees.