Jump to content
IGNORED

Timer IRQs as DLIs Tutorial


Heaven/TQA

Recommended Posts

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

Link to comment
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
Link to comment
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... ;)

Link to comment
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.

Link to comment
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 :)

Link to comment
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...

Link to comment
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 + dist.2@1.79mhz in 64khz mode ;) ).

 

Note: sawtooth needs ch.1 AND 3 (both channels occupied, no chance for IRQ), dist2@1.79mhz 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 dist2@1.79mhz setting can give 2 channels with in-tune high notes.

Link to comment
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
Link to comment
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.

Link to comment
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.

Link to comment
Share on other sites

  • 5 years later...

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.

Link to comment
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.

Link to comment
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...