[comp.sys.amiga.tech] CIA Timers and Interrupt priority problems

jimb@faatcrl.UUCP (Jim Burwell) (01/01/91)

Hi...

I'm writing a CLI based [Med|*tracker] module player.  The thing is pretty
much done, 'cept for one problem.  The music player routine uses Interrupts
from a CIA timer for its timing.  This is better than using vblank since
you don't have to worry about NTSC/PAL timing differences.  But now that CBM 
has stolen both CIA A timers for 2.0, I must use one of the CIA B timers.  
This works fine, except that the CIA B timer hardware Interrupt priorities 
are so high that the music player now interrupts EVERYTHING.  This is no 
problem until you try to call up you favorite BBS while listening to some 
modules.  The timer interrupt constantly interrupts the serial port Receive 
Buffer Full interrupt service routine (or just blocks the interrupt), often
causing a buffer overflow on the serial port.  The result, of course, are 
lots of dropped characters from the serial port, making telcom impossible.
This is unacceptable to me since one of my main reasons for writing this 
player is to give Amiga users the ability listen to modules while modeming. 
(Intuitracker fails mainly because it GURUs all the time.  EVERY time when
 you go into a Zmodem download with JR-Comm.  And secondly, because it doesn't 
 have all the features I wanted in a music player.)

Does anyone have any suggestons ?  

I don't think the timer device would work for me.  It isn't "real time" enough 
for a music player (to much wavering mostly due to task schedualing), plus 
it uses the CIA B timers, which would cause the same problem.

I could recode things to use the vblank Interrupt, but that would require 
compensating for the video mode you're presently in.  Plus I don't want to
give up on the timers yet.

I have been thinking of a scheme to use Software Interrupts called in the
timer interrupt routine.  Something like this:


TimerIntServer:  trap (or whatever)
                 rts

This would get in and out of the high-priority interrupt server quickly,
hopefully giving the time back to other interrupts.  I'm assuming that
there's some sort of software interrupt which doesn't interrupt hardware
interrupt service routines, or is maskable, and which would take effect
upon an rte from the hardware interrupt service routine.  The software
interrupt, would of course be vectored to the music player routine.  
If I remember correctly, the software interrupt service routine can be
interrupted by other hardware interrupts.  Those that arn't "as important"
could be masked, but important interrupts like the RBF, could interrupt
the music player routine at certain points, hopefully solving the serial
overflow problems.  The only problem I see is that the timing could be 
thrown off if the right set of events happens between the rte from the 
hardware interrupt and the calling of the software interrupt (LOTS of
hardware interrupts, leading to/or a Timer interrupt occuring before the
software interrupt was serviced or before it could be masked).  
But I think it could work under most circumstances.

Comments ?

(no flames)

C'ya,
Jim

-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) (01/01/91)

This comes under the category of "show them how little you know about
music on the Amiga, Kent", but could you double or triple buffer your
sound track so you were always working a buffer ahead, and the timing
wasn't so critical? I can't imagine anything in music that the vblank
interval would be accurate enough to time (I'm sure a fiftieth of a
second must be a substantial chunk of a thirty-second note, enough to
hear the difference), so I'm sure I could use a tutorial on just how
music is being done as you see it.

Kent, the man from xanth.
<xanthian@Zorch.SF-Bay.ORG> <xanthian@well.sf.ca.us>

jimb@faatcrl.UUCP (Jim Burwell) (01/02/91)

xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes:

>This comes under the category of "show them how little you know about
>music on the Amiga, Kent", but could you double or triple buffer your
>sound track so you were always working a buffer ahead, and the timing
>wasn't so critical? I can't imagine anything in music that the vblank
>interval would be accurate enough to time (I'm sure a fiftieth of a
>second must be a substantial chunk of a thirty-second note, enough to
>hear the difference), so I'm sure I could use a tutorial on just how
>music is being done as you see it.

Sure.  I could do it the hard way, and double buffer the audio events
and wait for the Audio device to wake me up or something (although the player
doesn't use the Audio device right now), but that would be a pain.  

Most of the other *tracker programs do use vblank.  Just start playing a song
with Intuitracker, then switch the machine from NTSC to PAL mode and you
can hear the difference.  This doesn't effect Med, or my player, since they
use the CIA timers.

C'ya,
Jim
-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

forgeas@swinjm.UUCP (Jean-Michel Forgeas) (01/02/91)

In article <650@faatcrl.UUCP>, Jim Burwell writes:

> [...]This works fine, except that the CIA B timer hardware Interrupt priorities
> are so high that the music player now interrupts EVERYTHING.[...]

Just a suggestion: since Exec is preemptive, your interrupt routine could
just Signal() a task which has a priority of 1 or 2. Then the task really
becomes active each time it is signaled.
--
                                     \___/
Jean-Michel Forgeas                   \-/
cbmvax!cbmehq!cbmfra!swinjm!forgeas    |    The Software Winery
                                      -^-
                           And, where is the universe ?

d88-skl@dront.nada.kth.se (Stellan Klebom) (01/03/91)

In article <650@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:

[deleted text]

>I don't think the timer device would work for me.  It isn't "real time" enough 
>for a music player (to much wavering mostly due to task schedualing), plus 
>it uses the CIA B timers, which would cause the same problem.
>
>I could recode things to use the vblank Interrupt, but that would require 
>compensating for the video mode you're presently in.  Plus I don't want to
>give up on the timers yet.
>
>I have been thinking of a scheme to use Software Interrupts called in the
>timer interrupt routine.  Something like this:
>
>TimerIntServer:  trap (or whatever)
>                 rts
>
>This would get in and out of the high-priority interrupt server quickly,
>hopefully giving the time back to other interrupts.  I'm assuming that
>there's some sort of software interrupt which doesn't interrupt hardware
>interrupt service routines, or is maskable, and which would take effect
>upon an rte from the hardware interrupt service routine.  The software
>interrupt, would of course be vectored to the music player routine.  

So use the timer.device, because that is how the timer.device works...

[text deleted]

>
>C'ya,
>Jim
>
>-- 
>UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
[sig deleted]

Stellan

No sig is a good sig...

jimb@faatcrl.UUCP (Jim Burwell) (01/03/91)

d88-skl@dront.nada.kth.se (Stellan Klebom) writes:

>In article <650@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:

[all kinds of text deleted]

>>I have been thinking of a scheme to use Software Interrupts called in the
>>timer interrupt routine.  Something like this:
>>
>>TimerIntServer:  trap (or whatever)
>>                 rts
>>
>>This would get in and out of the high-priority interrupt server quickly,
>>hopefully giving the time back to other interrupts.  I'm assuming that

>So use the timer.device, because that is how the timer.device works...

Well, no.  There's another level to the timer device which makes it too
unstable for a music program IMHO.  Of course, I havn't really tried it :-).
But, I'm assuming things won't be reliable enough because the timer.device
only returns Exec IOrequests to your task.  Exec must then (eventually) 
wake up your task.  That can take any ammount of time, depending on 
system load, priorities, etc.  

With the scheme I proposed, the player routine would still be on an interrupt,
which is CPU controlled instead of Kernal controlled.

And since you mentioned that the timer.device does exactly what I proposed,
I guess that means what I proposed will work!  Thanx.  You managed to answer
one of my questions.

C'ya,
Jim
-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

ccplumb@spurge.uwaterloo.ca (Colin Plumb) (01/03/91)

In article <650@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:
>Hi...
>
>I'm writing a CLI based [Med|*tracker] module player.  The thing is pretty
>much done, 'cept for one problem.  The music player routine uses Interrupts
>from a CIA timer for its timing.  This is better than using vblank since
>you don't have to worry about NTSC/PAL timing differences.  But now that CBM 
>has stolen both CIA A timers for 2.0, I must use one of the CIA B timers.  

Both CIA A timers are in use in 1.x, it's just that it wasn't properly
documented for a long time.  See Appendix F of the 1.3 Hardware manual, or
other recent sources.

>This works fine, except that the CIA B timer hardware Interrupt priorities 
>are so high that the music player now interrupts EVERYTHING.  This is no 
>problem until you try to call up you favorite BBS while listening to some 
>modules.  The timer interrupt constantly interrupts the serial port Receive 
>Buffer Full interrupt service routine (or just blocks the interrupt), often
>causing a buffer overflow on the serial port.  The result, of course, are 
>lots of dropped characters from the serial port, making telcom impossible.
>This is unacceptable to me since one of my main reasons for writing this 
>player is to give Amiga users the ability listen to modules while modeming. 

Well, you need to, somehow, make your interrupt server faster, putting more
work at lower interrupt levels.  The ultimate is to just have it trigger a
lower-priority event and return.  The ones that are available are:

- Lower-priority hardware interrupts.  Number 2, SOFT, looks particularly
inviting, and it's level 1, the lowest there is.  You can also trigger
(using a write to the INTREQ register) a PORTS (CIA A) interrupt and install
your own server in the chain.  This is completely multitasking-friendly,
and lets you use all of your old code, changing only the checking to see if
it's "really for me".
- Software interrupts.  Probably the thing to use, if you can.  These are
really quite responsive.
- Tasks.  It should be possible to sufficiently preprocess the information the
interrupt server needs that it can be fast enough.  All it's doing, after all,
is stuffing new values into the chip registers and CIA.  I'd be surprised
if you couldn't MOVEM a table into registers and store it out.

>Does anyone have any suggestons ?  

>I have been thinking of a scheme to use Software Interrupts called in the
>timer interrupt routine.  Something like this:
>
>
>TimerIntServer:  trap (or whatever)
>                 rts

Actually, it's the exec.library Cause() function.

>This would get in and out of the high-priority interrupt server quickly,
>hopefully giving the time back to other interrupts.  I'm assuming that
>there's some sort of software interrupt which doesn't interrupt hardware
>interrupt service routines, or is maskable, and which would take effect
>upon an rte from the hardware interrupt service routine.  The software
>interrupt, would of course be vectored to the music player routine.  

Yup.  Make an interrupt structure, and pass a pointer to it to Cause().

>If I remember correctly, the software interrupt service routine can be
>interrupted by other hardware interrupts.  Those that arn't "as important"
>could be masked, but important interrupts like the RBF, could interrupt
>the music player routine at certain points, hopefully solving the serial
>overflow problems.

There's no good multitasking-friendly way to mask off other people's
interrupts except to operate at a certain level interrupt yourself.
I seriously doubt it would be necessary.

>The only problem I see is that the timing could be 
>thrown off if the right set of events happens between the rte from the 
>hardware interrupt and the calling of the software interrupt (LOTS of
>hardware interrupts, leading to/or a Timer interrupt occuring before the
>software interrupt was serviced or before it could be masked).  
>But I think it could work under most circumstances.

If too much is happening, *something* isn't going to get serviced.  I suggest
that a bobble in the music player is preferable to some other things.
-- 
	-Colin

d88-skl@dront.nada.kth.se (Stellan Klebom) (01/04/91)

In article <658@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:

[many kinds of text deleted]

>
>Well, no.  There's another level to the timer device which makes it too
>unstable for a music program IMHO.  Of course, I havn't really tried it :-).
>But, I'm assuming things won't be reliable enough because the timer.device
>only returns Exec IOrequests to your task.  Exec must then (eventually) 
>wake up your task.  That can take any ammount of time, depending on 
>system load, priorities, etc.  
>
>With the scheme I proposed, the player routine would still be on an interrupt,
>which is CPU controlled instead of Kernal controlled.

Well, you can setup your message port so that a software interrupt is generated
when the timer.device replys your IOrequest. Of course your suggested method
have slightly less overhead, but I don't think the difference is so big after
all.
>
>And since you mentioned that the timer.device does exactly what I proposed,
>I guess that means what I proposed will work!  Thanx.  You managed to answer
>one of my questions.
>

Well, I did forget to mention software interrupts in connection to message
ports. I sort of assumed you knew about that possibility...  ;)

>Jim

/Stellan
-----------
This sig is stolen, but that is alright since nobody ever missed it...

jimb@faatcrl.UUCP (Jim Burwell) (01/04/91)

forgeas@swinjm.UUCP (Jean-Michel Forgeas) writes:

>In article <650@faatcrl.UUCP>, Jim Burwell writes:

>> [...]This works fine, except that the CIA B timer hardware Interrupt priorities
>> are so high that the music player now interrupts EVERYTHING.[...]

>Just a suggestion: since Exec is preemptive, your interrupt routine could
>just Signal() a task which has a priority of 1 or 2. Then the task really
>becomes active each time it is signaled.

Hmm.  That MIGHT work.  But I know there would be conditions which could
easily arise which would delay my program from getting it's time slice, and
screw up the music.  And music with screwed up timing is not worth listening
to.  It would probably be so annoying that people would just turn it off :-).

I'd rather avoid the entire issue of Exec task schedualling by keeping things
one step lower-level than Exec.

C'ya,
Jim
-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

jimb@faatcrl.UUCP (Jim Burwell) (01/04/91)

ccplumb@spurge.uwaterloo.ca (Colin Plumb) writes:

>In article <650@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:

>Both CIA A timers are in use in 1.x, it's just that it wasn't properly
>documented for a long time.  See Appendix F of the 1.3 Hardware manual, or
>other recent sources.

Documented or not, under 1.3 OpenResource and AddICRHandler allowed me to
use CIA A Timer A.  Under 2.0, it didn't let me touch it.  This is tested
on some lucky guy's A3000 (hi Jack :-).

[deleted]
>>Buffer Full interrupt service routine (or just blocks the interrupt), often
>>causing a buffer overflow on the serial port.  The result, of course, are 
>>lots of dropped characters from the serial port, making telcom impossible.
>>This is unacceptable to me since one of my main reasons for writing this 
>>player is to give Amiga users the ability listen to modules while modeming. 

>Well, you need to, somehow, make your interrupt server faster, putting more
>work at lower interrupt levels.  The ultimate is to just have it trigger a
>lower-priority event and return.  The ones that are available are:

Well, making the service routine faster is almost impossible.  It's totally
68K assembly, and pretty tense as it is.  I could go though and bum some
cycles probably, but I doubt I could free enough to make a difference.

>- Lower-priority hardware interrupts.  Number 2, SOFT, looks particularly
Hmm.  How does one trigger a low level hardware interrupt.

>inviting, and it's level 1, the lowest there is.  You can also trigger

My original idea was to do a software interrupt in the Timer Int service
routine.  I'll have to look up the Mnemonics in my 68K book.  I'm a MC6809
assembly refugee :-).  I havn't written a whole lot of ASM code on the 68K
family yet.  Mostly C.  On the 6809 I would use a SWI :-).

>(using a write to the INTREQ register) a PORTS (CIA A) interrupt and install
>your own server in the chain.  This is completely multitasking-friendly,
>and lets you use all of your old code, changing only the checking to see if
>it's "really for me".

Hmm.  How does one go about adding your int server into the chain ?  I think
AddICRServer would fail.  I'll have to look into this.  It wouldn't be tough
to figure out if the interrupt is for me.  Wouldn't doing that also fool
any other int handlers which are using that interrupt into thinking 
the interrupt is for them ?  Unless my handler would be put "first in line",
and do an RTE instead of an RTS ?  I don't know what Exec's interrupt 
vectoring code requires (time to look into the RKMs :-).

>- Software interrupts.  Probably the thing to use, if you can.  These are
>really quite responsive.

Yeah.  I agree.  I think that's what I'll do.

>- Tasks.  It should be possible to sufficiently preprocess the information the
>interrupt server needs that it can be fast enough.  All it's doing, after all,
>is stuffing new values into the chip registers and CIA.  I'd be surprised
>if you couldn't MOVEM a table into registers and store it out.

Yeah.  I could re-write the player to set everything up for the next 
"event" and just move the a table of values into the appropriate spot.  But
then I must process the data for the next event.  Of course, as you seem to
indicate, this pre-processing would be done outside of the interrupt service
routine.  But what happens if the next interrupt occurs before my task gets
enough CPU time to prepare the data for the interrupt server ?

>>Does anyone have any suggestons ?  

>>I have been thinking of a scheme to use Software Interrupts called in the
>>timer interrupt routine.  Something like this:
>>
>>
>>TimerIntServer:  trap (or whatever)
>>                 rts

>Actually, it's the exec.library Cause() function.

Hmm.  I'll look into that.  As you may have guessed by now, I'm not REAL 
familiar with the Amiga yet.  I don't have all the system calls memorized
yet.  Thanx for this pointer!  

>>This would get in and out of the high-priority interrupt server quickly,
>>hopefully giving the time back to other interrupts.  I'm assuming that
>>there's some sort of software interrupt which doesn't interrupt hardware
>>interrupt service routines, or is maskable, and which would take effect
>>upon an rte from the hardware interrupt service routine.  The software
>>interrupt, would of course be vectored to the music player routine.  

>Yup.  Make an interrupt structure, and pass a pointer to it to Cause().

Great.  Useful info at last!  There IS a use for c.s.a.t.! :-)

>>If I remember correctly, the software interrupt service routine can be
>>interrupted by other hardware interrupts.  Those that arn't "as important"
>>could be masked, but important interrupts like the RBF, could interrupt
>>the music player routine at certain points, hopefully solving the serial
>>overflow problems.

>There's no good multitasking-friendly way to mask off other people's
>interrupts except to operate at a certain level interrupt yourself.
>I seriously doubt it would be necessary.

I was more thinking more on the lines of masking the interrupts needed to
make this service routine "equivelent" to the original CIA A Timer A interrupt
which worked so well.  Perhaps I won't need to.  But if the software interrupt
gets interrupted by EVERYTHING, then it will probably mess up the music.
Can't have that!  :-)

>>The only problem I see is that the timing could be 
>>thrown off if the right set of events happens between the rte from the 
>>hardware interrupt and the calling of the software interrupt (LOTS of
>>hardware interrupts, leading to/or a Timer interrupt occuring before the
>>software interrupt was serviced or before it could be masked).  
>>But I think it could work under most circumstances.

>If too much is happening, *something* isn't going to get serviced.  I suggest
>that a bobble in the music player is preferable to some other things.

Agreed.  I'm very happy with the way the music player works with the CIA A
timer A interrupt.  I don't notice ANY system slowdown.  Neither does JR-Comm
operating at 19.2Kbaud.  Zmodem doesn't even hiccup once!  And this is on a
lowly A500 with an '010 in it, with 2 floppies and 3 HD partitions.  

As soon as I get this little problem worked out, and add a few more it will 
be ready features, it will be ready for 1.0 distribution!  The program is
totally solid.  It hasn't GURU'ed my system once, and when run on an A3000,
enforcer doesn't make a peep.  (boy, I hope I didn't just jinx myself :-)

Thanx for the info!

C'ya,
Jim
-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

jimb@faatcrl.UUCP (Jim Burwell) (01/05/91)

d88-skl@dront.nada.kth.se (Stellan Klebom) writes:

>In article <658@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:

>>And since you mentioned that the timer.device does exactly what I proposed,
>>I guess that means what I proposed will work!  Thanx.  You managed to answer
>>one of my questions.
>>

>Well, I did forget to mention software interrupts in connection to message
>ports. I sort of assumed you knew about that possibility...  ;)


Nope.  I didn't.  I'm really going to have to sit down and give my RKMs
some study :-).  Everything I need is in there (well, not really :-), the
hard part is finding it!

C'ya,
Jim
-- 
UUCP:  ...!rutgers!faatcrl!jimb              Internet:  jimb@faatcrl.UUCP
		Under brooding skys and watchful eyes
		On convulsive seas of false urgency
		We walk empty corridors in vain - "No Exit", Fate's Warning

glmwc@marlin.jcu.edu.au (Matt Crowd) (01/07/91)

In article <1991Jan3.030604.21890@watdragon.waterloo.edu> ccplumb@spurge.uwaterloo.ca (Colin Plumb) writes:
>In article <650@faatcrl.UUCP> jimb@faatcrl.UUCP (Jim Burwell) writes:
>>Hi...
>>
>>I'm writing a CLI based [Med|*tracker] module player.  The thing is pretty
>>much done, 'cept for one problem.  The music player routine uses Interrupts
>>from a CIA timer for its timing.  This is better than using vblank since
>>you don't have to worry about NTSC/PAL timing differences.  But now that CBM 
>>has stolen both CIA A timers for 2.0, I must use one of the CIA B timers.  
>
>Both CIA A timers are in use in 1.x, it's just that it wasn't properly
>documented for a long time.  See Appendix F of the 1.3 Hardware manual, or
>other recent sources.
>

If they are in use in 1.3 why does MED work in 1.3 but not in 2.0.  It
comes up with an alert in 2.0  "CIA timer A in use".  The code
for the player seems well written.

>	-Colin

Colin (different one!)

jesup@cbmvax.commodore.com (Randell Jesup) (01/10/91)

In article <1991Jan7.104513.9163@marlin.jcu.edu.au> glmwc@marlin.jcu.edu.au (Matt Crowd) writes:
>If they are in use in 1.3 why does MED work in 1.3 but not in 2.0.  It
>comes up with an alert in 2.0  "CIA timer A in use".  The code
>for the player seems well written.

	Because it was mistakenly not marked as being allocated in the 
resource, I think.

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
The compiler runs
Like a swift-flowing river
I wait in silence.  (From "The Zen of Programming")  ;-)