[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 6502 Delay Loops using Applesoft



On Dec 5, 6:35 am, "Michael J. Mahon" <mjma...@aol.com> wrote:
> Allen Bong wrote:
> > On Dec 3, 1:12 am, sc...@alfter.DIESPAMMERSDIE.us (Scott Alfter)
> > wrote:
>
> >>In article <02b1803a-1471-40cb-a69f-37dbab581...@o23g2000prh.googlegroups.com>,
> >>Allen Bong  <allenbsf6...@gmail.com> wrote:
>
> >>>Has anyone written a gereral delay loop calculating program in
> >>>Applesoft, to calculate the constants required to gererate the
> >>>required time delays in 6502 codes?
>
> >>The handful of times I've needed timing-critical delays (in an audio player
> >>way back in the day, and more recently in some hardware bit-banging code),
> >>it was easy enough to do them manually.  The 6502 datasheet tells you how
> >>many cycles each instruction needs to execute:
>
> >>http://archive.6502.org/datasheets/rockwell_r650x_r651x.pdf
> >>(go to page 10; it's the number in the lower right corner for each
> >>instruction)
>
> >>The Apple II runs at approximately 1 MHz (it's actually a smidge faster than
> >>that), so one cycle takes about one microsecond.  The shortest run time for
> >>any instruction is two cycles, or about two microseconds.  For short delays
> >>(small multiples of 2 us), a block of NOPs will do.  For longer delays, the
> >>math to calculate how long a loop will take is fairly simple.  Consider
> >>this:
>
> >>        LDY #10
> >>]1      DEY
> >>        BNE [1
>
> >>The first two instructions take 2 cycles each.  The branch takes 3 cycles if
> >>the branch is taken to the same page, 4 if the branch is taken to a
> >>different page, or 2 if the branch isn't taken.  Assuming that the code is
> >>all on the same page (which it will be most of the time, but you'd want to
> >>verify where the assembler decides to place your code), LDY executes once,
> >>DEY executes 10 times, and BNE is taken nine times and not taken once.
>
> >>    2 LDY
> >> 10*2 DEY
> >>  9*3 BNE taken
> >>+   2 BNE not taken
> >>=====
> >>   51 cycles total
>
> >>For nested loops, you'd want to calculate the runtime for the inner loop and
> >>plug that into your calculation for the outer loop.
>
> >>I suppose if I had a regular need for calculating delay loops, I might've
> >>knocked together an app to do that.  As shown above, though, they're simple
> >>enough to put together by hand as you need them.
>
> >>  _/_
> >> / v \ Scott Alfter (remove the obvious to send mail)
> >>(IIGS(http://alfter.us/ ;         Top-posting!
> >> \_^_/ rm -rf /bin/laden            >What's the most annoying thing on Usenet?
>
> >>--- news://freenews.netfront.net/ - complaints: n...@netfront.net ---
>
> > Hi Scott,
>
> > Actually, I was thinking something of a more general purpose form of
> > delay-loop calculator.  Not just for use by Apple 2 only.  For example
> > you might design a 6502 SBC running at 1.5MHz or 2MHz using 6502A or
> > 6502B or 65C02 (CMOS).
>
> > Something like this one for the PIC would be most helpful.  Just enter
> > the oscillator frequency used by 6502, how much delay time you wanted
> > in uS, mS or S, then just press "calculate", and a subroutine is
> > produced.  Very cool, isn't?
>
> > Like the ones here:
>
> >http://www.golovchenko.org/cgi-bin/delay
>
> >http://www.biltronix.com/picloops.html
>
> > I don't expect to have the convenient of that but at least one written
> > in Applesoft would be highly appreciated.  If no one had done that, I
> > might try to roll one out myself in Applesoft.
>
> This would be an interesting and instructive exercise, but I predict
> that it will seldom be "useful", even to you.  This is one of those
> cases where real "generality" is only achieved by implementing a
> choice among a host of specialized approaches.
>
> There are two great design pitfalls:  too much generality and too
> much specialization.  ;-)  And the sweet spot is different for every
> different application and context.
>
> I've written several macros to generate <n cycles> or <n milliseconds>
> of delay, but, like Scott, I find that a general purpose delay generator
> is seldom useful.  In NadaNet, I find application for two delay macros
> that are more specialized and useful in the context of NadaNet, but
> particular situations often arise that offer (or require) custom
> timing approaches.
>
> For example, there is often "work" to be done which occupies some part
> of the delay needed, and the cycles required for the work must be
> computed accurately and subtracted from the total delay requirement
> before executing the padding routine.  The process of computing this
> "work delay" and the effort of making it require the same time in spite
> of any conditional branches involved, is typically much more effort than
> writing the padding routine, so very little effort is saved.  (I've
> often wished for an assembler that kept the current cycle count, just
> like it keeps the current program counter, but it should be a *dynamic*
> cycle count, and there's the rub ;-).
>
> Further, it is common that certain registers or flags are important at
> the point that the delay must occur, and a "standard" method will often
> conflict with that requirement.
>
> If you work with several situations requiring sometimes a few, sometimes
> several, and sometimes many cycles of delay, you will find that while a
> few "templates" are useful, no single approach or even a small set of
> approaches is optimal.
>
> -michael
>
> NadaNet 3.1 for Apple II parallel computing!
> Home page:  http://home.comcast.net/~mjmahon/
>
> "The wastebasket is our most important design
> tool--and it's seriously underused."- Hide quoted text -
>
> - Show quoted text -

> For example, there is often "work" to be done which occupies some part
> of the delay needed, and the cycles required for the work must be
> computed accurately and subtracted from the total delay requirement
> before executing the padding routine.  The process of computing this
> "work delay" and the effort of making it require the same time in spite
> of any conditional branches involved, is typically much more effort than
> writing the padding routine, so very little effort is saved.  (I've
> often wished for an assembler that kept the current cycle count, just
> like it keeps the current program counter, but it should be a *dynamic*
> cycle count, and there's the rub ;-).
>

Yes, I have met that situation too.  Recently I was writing my morse
code beeper program and found that I need a 700Hz tone generator for
92.3mS.  So I calculated the delay required to click the speaker at
700 times per second embedded with "LDA $C030".  Then on the outer
loops I calculated the number of loops x 700Hz loops = 92.3mS.

So my outer loop count constant = 92.3mS/(time taken to click speaker
at 700Hz).  Can that be considered as doing the job (clicking speaker)
inside delay loops?

Though it may be a waste of effort writing the delay loops, I guess
I'd still be tempted to write one - OK, just as an exercise.  Projects
make my brain more active and my heart cheering when it works.

Cheers,

Allen