Jump to content
Heaven/TQA

Timer IRQs as DLIs Tutorial

Recommended Posts

it always was a miracle for me how I can setup pokey timers or so to say IRQs as rasters instead of DLIs? can f.e. Analmux write a small tutorial how I can setup the freq values to use them as DLIs?

 

I am too stupid to understand the clock settings plus cycle things... ;)

 

thanks!

Share this post


Link to post
Share on other sites

Yeah, a good tutorial on this with some of the info from the NMI/Timers thread would be useful. This is the type of stuff that needs to go in a wiki somewhere. afaik it's like this 15khz timer 1 "count" = 1 line, 64khz around 4 counts = 1 line and the 1.79 timer you should in theory be able to time to any colour clock on the screen. If you just want an equivalent of C64s rasters then the 15khz one is fine.

 

 

Pete

Share this post


Link to post
Share on other sites

I'm not 100% sure, and I'd need to do some little tests then.

 

But setting up the timer IRQs involves the following:

(suppose we use timer 4)

 

-initialize timer (f.e. start at scanline n)

-activate a timer pattern, f.e. at scanline n, n+50, n+100

 

Initialization is done, not by the timer itself, but by syncing to a display event. Therefore, at start of 'game' (or other action), we'd need to do init code ONE TIME....f.e. antic 4 screen, n=42, then do DLI at top-line, and do 2 (or 3) wsyncs. Then we are on the desired scanline. Now we do initialize IRQ timer.

 

The next timer IRQ is on line n+50, thus (n+50)-n = 50, subtract 1 = 49, store into $D206 (AUDF4)

Then do pokey init (LDA 0 STA $D20F LDA 3 STA $D20F), and then a countdown timer reset (STA $D209 (="STIMER")).

Redefine timer4 IRQ vector

...wait for next interrupt...

again 49 into $D206, pokey init, countdown timer init, redefine timer4 vector

...wait for next interrupt...

now we need to 'close the circle'. scanline n+100+212 (=n+312) is the same as scanline n, but then 1 frame later.

store 211 into $D206, etc.

 

(And we must not forget to activate timer IRQ somewhere, which means bit 2 of IRQEN ($D20E) must be put to 1)

Edited by analmux

Share this post


Link to post
Share on other sites

I'm not 100% sure, and I'd need to do some little tests then.

 

But setting up the timer IRQs involves the following:

(suppose we use timer 4)

 

-initialize timer (f.e. start at scanline n)

-activate a timer pattern, f.e. at scanline n, n+50, n+100

 

Initialization is done, not by the timer itself, but by syncing to a display event. Therefore, at start of 'game' (or other action), we'd need to do init code ONE TIME....f.e. antic 4 screen, n=42, then do DLI at top-line, and do 2 (or 3) wsyncs. Then we are on the desired scanline. Now we do initialize IRQ timer.

 

The next timer IRQ is on line n+50, thus (n+50)-n = 50, subtract 1 = 49, store into $D206 (AUDF4)

Then do pokey init (LDA 0 STA $D20F LDA 3 STA $D20F), and then a countdown timer reset (STA $D209 (="STIMER")).

Redefine timer4 IRQ vector

...wait for next interrupt...

again 49 into $D206, pokey init, countdown timer init, redefine timer4 vector

...wait for next interrupt...

now we need to 'close the circle'. scanline n+100+212 (=n+312) is the same as scanline n, but then 1 frame later.

store 211 into $D206, etc.

 

(And we must not forget to activate timer IRQ somewhere, which means bit 2 of IRQEN ($D20E) must be put to 1)

 

 

ok. understood... but a real life example would be usefull... I am completly new to all the setting IRQs up with pokey.... that's why I am stucked with the speech samples in Gridrunner... oops... that should be kept as a suprise... ;)

Share this post


Link to post
Share on other sites

Yeah, a good tutorial on this with some of the info from the NMI/Timers thread would be useful. This is the type of stuff that needs to go in a wiki somewhere. afaik it's like this 15khz timer 1 "count" = 1 line, 64khz around 4 counts = 1 line and the 1.79 timer you should in theory be able to time to any colour clock on the screen. If you just want an equivalent of C64s rasters then the 15khz one is fine.

 

 

Pete

 

Mostly right. However, 4 counts at 64Khz doesn't give one scanline. It's 1789790Hz, 1789790/114 (15Khz), and 1789790/28 (64Khz). So 28*4 = 112 not 114 which is number of CPU cycles per scanline.

Share this post


Link to post
Share on other sites

To analmux.. one question

 

In the "other" thread you said that "Maybe the most flexible way to do this is to use timer4 (the other timers: timer1 & timer 2 might be needed for more flexible pokey features for the music). Then clocking pokey at 15khz, channel 1&3 can be individually clocked. Then we'd have sawtooth wave if needed, or distortion 2 @ 1.79mhz to have high notes in tune."..

 

I prefer to use a timer in channel one, clocked at 1.79mhz, then you can have almost the same options, but with access to the 64khz clock (for voices 2, 3 and 4). With your option you can have 2 channels clocked at 1.79mhz, but I don't know what is better from a "music" standpoint.. what do you think?

 

To PeteD.. yeah, you cannot use the timer channel for music because you need the AUDF register to set the timer value.. but if that frequency value is useful to your music composition maybe you can use it :). You can change the volume and the distortion of the channel.. and you can play samples with that channel (because that uses only the volume part).

 

 

One example, that I know works in real hardware and in the last Altirra emulator (1.3pre10, posted somewhere in this forum), from project-M:

 

using the 15khz, timer 4..

 

// start disabling IRQs
sei
lda #0
sta IRQEN


// I dont use the OS code, so I hijack the IRQ vector
lda #<IRQ1_address
sta IRQH_VECTOR
lda #>IRQ1_address
sta IRQH_VECTOR+1


// init irq timer 4 and general clock
lda #0		// volume = 0
sta AUDC4
lda #1		// 0 ==> count one scan line (minimum resolution!), 1 ==> count two ..
sta AUDF4
lda #1		// 15khz mode
sta AUDCTL

 

After that, you need some code to sync the start of the IRQ to a specific horizontal position (you need to do this only once in your game).

In my case I wanted to sync to a point near the start of the line. There is jitter here! your entry point is not the same every time. You can only be sure that you are starting BEFORE a given position.

This code isn't necessarily the optimal one and maybe is doing some unnecessary things..

Also this thing is syncing to an odd or even scan line (I don't remember which), because I'm doing one IRQ every 2 scan lines. If you want one IRQ every scan line, or every 3 or 4, or another value, you may need to change this code.

 

// sync IRQs start (to an odd or even scan line)
sta WSYNC
sta WSYNC

lda VCOUNT
Sync_irq_15KHz sta WSYNC
cmp VCOUNT
beq Sync_irq_15KHz

sta WSYNC
sta WSYNC

lda #0
sta SKCTL

:10 nop		// dummy cycles.. add more or less to start at a different x position in the line
lda 0

lda #3
sta SKCTL

lda #1		// just need to be different than 0
sta STIMER

cli		// enable IRQ's

 

But we still need to enable IRQEN with the number of the timer that we are going to use (1, 2 or 4).

I do that on a DLI at the start of the screen with just:

 

lda #4

sta IRQEN

 

and the last IRQ in the chain in that frame does:

 

lda #0

sta IRQEN

 

to disable the IRQ's..

 

The general IRQ code does something like this:

 

IRQ1_address

sta m_irqSaveA

// reset the timer
lda #0
sta IRQEN

lda #4
sta IRQEN


// IRQ code..


// exit
lda m_irqSaveA

rti

 

Anyway I think that the way to go is the 1.79mhz timer (only in channel 1), specially if you need to sync to different horizontal positions, in different scan lines..

 

Hope that helps :)

Share this post


Link to post
Share on other sites

To analmux.. one question

 

In the "other" thread you said that "Maybe the most flexible way to do this is to use timer4 (the other timers: timer1 & timer 2 might be needed for more flexible pokey features for the music). Then clocking pokey at 15khz, channel 1&3 can be individually clocked. Then we'd have sawtooth wave if needed, or distortion 2 @ 1.79mhz to have high notes in tune."..

 

I prefer to use a timer in channel one, clocked at 1.79mhz, then you can have almost the same options, but with access to the 64khz clock (for voices 2, 3 and 4). With your option you can have 2 channels clocked at 1.79mhz, but I don't know what is better from a "music" standpoint.. what do you think?

 

To PeteD.. yeah, you cannot use the timer channel for music because you need the AUDF register to set the timer value.. but if that frequency value is useful to your music composition maybe you can use it :). You can change the volume and the distortion of the channel.. and you can play samples with that channel (because that uses only the volume part).

 

 

One example, that I know works in real hardware and in the last Altirra emulator (1.3pre10, posted somewhere in this forum), from project-M:

 

using the 15khz, timer 4..

 

// start disabling IRQs
sei
lda #0
sta IRQEN


// I dont use the OS code, so I hijack the IRQ vector
lda #<IRQ1_address
sta IRQH_VECTOR
lda #>IRQ1_address
sta IRQH_VECTOR+1


// init irq timer 4 and general clock
lda #0		// volume = 0
sta AUDC4
lda #1		// 0 ==> count one scan line (minimum resolution!), 1 ==> count two ..
sta AUDF4
lda #1		// 15khz mode
sta AUDCTL

 

After that, you need some code to sync the start of the IRQ to a specific horizontal position (you need to do this only once in your game).

In my case I wanted to sync to a point near the start of the line. There is jitter here! your entry point is not the same every time. You can only be sure that you are starting BEFORE a given position.

This code isn't necessarily the optimal one and maybe is doing some unnecessary things..

Also this thing is syncing to an odd or even scan line (I don't remember which), because I'm doing one IRQ every 2 scan lines. If you want one IRQ every scan line, or every 3 or 4, or another value, you may need to change this code.

 

// sync IRQs start (to an odd or even scan line)
sta WSYNC
sta WSYNC

lda VCOUNT
Sync_irq_15KHz sta WSYNC
cmp VCOUNT
beq Sync_irq_15KHz

sta WSYNC
sta WSYNC

lda #0
sta SKCTL

:10 nop		// dummy cycles.. add more or less to start at a different x position in the line
lda 0

lda #3
sta SKCTL

lda #1		// just need to be different than 0
sta STIMER

cli		// enable IRQ's

 

But we still need to enable IRQEN with the number of the timer that we are going to use (1, 2 or 4).

I do that on a DLI at the start of the screen with just:

 

lda #4

sta IRQEN

 

and the last IRQ in the chain in that frame does:

 

lda #0

sta IRQEN

 

to disable the IRQ's..

 

The general IRQ code does something like this:

 

IRQ1_address

sta m_irqSaveA

// reset the timer
lda #0
sta IRQEN

lda #4
sta IRQEN


// IRQ code..


// exit
lda m_irqSaveA

rti

 

Anyway I think that the way to go is the 1.79mhz timer (only in channel 1), specially if you need to sync to different horizontal positions, in different scan lines..

 

Hope that helps :)

 

I think you made it more complex than it is. You don't need to keep enabling IRQ. You only have to enable it once. STA STIMER will reset the counter not enabling/disabling IRQEN. You are actually acknowledging IRQ in the interrupt service routine so that another IRQ occurs, but the counting has already reset and begun counting as it's a periodic interrupt. You can prove that by moving around the acknowledgement code within the IRQ and use 1.79Mhz timer and you will see that number of cycles to IRQ remains constant...

Share this post


Link to post
Share on other sites

thx NRV helps... will go through the code and maybe one of missing knowledge is gone then... ;)

 

btw. in some of the famous c= hacking issues theer is enough code snippets how to avoid the the jitter with 6502 code... esp. on vic-20 or c64 where you don't have a wsync register.

Share this post


Link to post
Share on other sites

For Project M, I wouldn't worry about jitter... it only means you have an indeterminate delay from 0 to 6 cycles, that equates to all of 3 character positions. In most cases, especially Narrow-screen mode, you can easily cope with that.

Share this post


Link to post
Share on other sites

To analmux.. one question

 

In the "other" thread you said that "Maybe the most flexible way to do this is to use timer4 (the other timers: timer1 & timer 2 might be needed for more flexible pokey features for the music). Then clocking pokey at 15khz, channel 1&3 can be individually clocked. Then we'd have sawtooth wave if needed, or distortion 2 @ 1.79mhz to have high notes in tune."..

 

I prefer to use a timer in channel one, clocked at 1.79mhz, then you can have almost the same options, but with access to the 64khz clock (for voices 2, 3 and 4). With your option you can have 2 channels clocked at 1.79mhz, but I don't know what is better from a "music" standpoint.. what do you think?

 

If you want to include a tune written in 64khz mode, then the 1.79mhz clock is the best solution. Then you must use timer 1. Only thing is: timer 1(&3) is needed for sawtooth waveform, so no sawtooth instruments then. (By accident I'm writing a new RMT hack (#4) which supports sawtooth + [email protected] in 64khz mode ;) ).

 

Note: sawtooth needs ch.1 AND 3 (both channels occupied, no chance for IRQ), [email protected] needs 1 OR 3. When 1 is occupied by IRQ, then 3 is still free.

 

On the other hand, if you change your mind, and go using 15khz mode tunes, then you can choose any timer (1,2 or 4) you like. Then I'd do timer 4.

 

But, from a music standpoint:

64khz mode is best for 'highpitched' tunes. The tuning of the higher notes are just acceptible. If real basses are needed (instead of the genC/E basses), then we'd need 15khz mode. Then [email protected] setting can give 2 channels with in-tune high notes.

Share this post


Link to post
Share on other sites

Something I have been wondering lately (but were too lazy to check the schematics yet :)) is whether a dual-pokey upgrade also doubles the timers? i.e. is the /IRQ line connected?

Share this post


Link to post
Share on other sites

Something I have been wondering lately (but were too lazy to check the schematics yet :)) is whether a dual-pokey upgrade also doubles the timers? i.e. is the /IRQ line connected?

So far, the practice has been NOT to connect the IRQ lines together. In fact, some stereo software won't work properly if you do. Perhaps the lack of IRQ response is used to detect the 2nd Pokey in some cases. This seems like a shame to me, since it's easy to disable all IRQ's from the 2nd Pokey but still leave them available to use.

Edited by Bryan

Share this post


Link to post
Share on other sites

So far, the practice has been NOT to connect the IRQ lines together. In fact, some stereo software won't work properly if you do. Perhaps the lack of IRQ response is used to detect the 2nd Pokey in some cases. This seems like a shame to me, since it's easy to disable all IRQ's from the 2nd Pokey but still leave them available to use.

 

That's a pity. It would be great to have three extra timers for something I have in mind. Perhaps future upgrades could have a hardware switch for old (not connected) and new (connected) mode operation.

Share this post


Link to post
Share on other sites

So far, the practice has been NOT to connect the IRQ lines together. In fact, some stereo software won't work properly if you do. Perhaps the lack of IRQ response is used to detect the 2nd Pokey in some cases. This seems like a shame to me, since it's easy to disable all IRQ's from the 2nd Pokey but still leave them available to use.

 

That's a pity. It would be great to have three extra timers for something I have in mind. Perhaps future upgrades could have a hardware switch for old (not connected) and new (connected) mode operation.

 

One of the reasons I never upgraded to dual/quad POKEY although you can use the timer IRQs in the first POKEY and use the other POKEYs for the sound channels. However, I am more into timing stuff so I had to employ more of a software solution and have my PC interface cable to trigger off Proceed/Interrupt lines on the SIO to generate the extra timer interrupts.

Share this post


Link to post
Share on other sites

I just gave it a shot.

 

irqsplits.xex (Source on github).

 

I left sound enabled so you can see how the sound channel signal toggles correspond to IRQ frame locations when you pull up the Altirra audio monitor.

 

post-21021-0-00708800-1412014908_thumb.png

  • Like 1

Share this post


Link to post
Share on other sites

The downside to Timer IRQs is the "scanline-friendly" method requires using 16 KHz mode, which affects all voices if not otherwise forced to 1.79 MHz mode.

 

16 KHz gives the handy 114 divisor rather than 28 in normal 64 KHz mode.

 

Example - I had those ones I posted years ago, probably before anyone was using them commonly. No idea where it is now.

 

The other downside to Timers is the duration available. If you do the maths, in 16 or 64 KHz mode you can't cover the entire screen, you need multiple instances to keep in sync.

 

Possibly the best usage might be to have a DLI first. Use voice 3, put it in 1.79 MHz mode with AUDF3=00. Wait a short time to ensure the divisor has counted down then set back to 64 KHz mode and do the maths to work out what AUDF value is needed.

 

The other thing is that under emulation your results will vary - modern Altirra and probably Atari800 versions should be pretty spot on, Atari800Win+ is only scanline accurate.

Share this post


Link to post
Share on other sites

C64, hardware timers are by the CIAs, raster IRQ by VIC. SID has no part in such stuff, in fact the machine will operate otherwise normally without one even present.

 

Most other computers, the sound hardware plays little part in the remainder - although sound chip in use by ST, BBC, Spectrum etc does have general purpose IO bits.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...