VIA Timer 1 or Timer 2?

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
Victragic
Frogger '07
Posts: 605
Joined: Tue Nov 14, 2006 5:56 pm
Location: South Australia

VIA Timer 1 or Timer 2?

Post by Victragic »

Hi folks,

inspired by Mike's 'TI$ in the border' project, I sought after and found a program based for a generic 6502 chip that uses timer 1 on a 6522 chip to generate an NMI interrupt for an accurate timer.. amazing thing the internet, it seems whatever you want is out there, somewhere..

The program is here, I haven't sought permission to republish it so just a link - it's really easy to convert to the VIC, though as I don't have a real VIC I can't verify what the correct timing should be for the (approx) 1 mhz 6522 on the VIC..

http://www.6502.org/tutorials/interrupts.html

Look under 2.1 for the program.

My question is, on the VIC 20, which timer is better to use? Ie I'm assuming the cassette deck uses one of the timers, as would a serial disk drive, so can someone tell me which timers these particular devices use?

Also, would it even be possible for this wedge to be run while a disk or cassette operation was taking place? Or would the NMI call disrupt data transfer?

I know this is somewhere between a hardware and a software question, but it's really to solve a programming problem I have in trying to generate an alarm clock on the VIC that is accurate and 'uninterruptable' if that makes sense..

Cheers
-G
3^4 is 81.0000001
User avatar
Mike
Herr VC
Posts: 4839
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

If you're going to use an NMI to update the clock, the only option is VIA 1, which controls the RS 232 interface. Here, timer 1 is shared with tape operation, so you'd stick with timer 2. VIA 2 is connected to the IRQ line, and controls keyboard, cassette, and disc drive.

The most sensible solution would be, to put only the jiffy clock update into the NMI routine. This needs to be called every 1/60's of a second. The corresponding values to put in the timer *are* different for PAL and NTSC machines. As long as you keep the NMI routine short, I don't expect big troubles with tape and/or disc access.

You could then still use my display routine in the IRQ. But you'd: a) skip the original jiffy clock update, and b) instead include the 'check for RUN STOP' code, that I've pointed to in an earlier post.

Greetings,

Michael
User avatar
Victragic
Frogger '07
Posts: 605
Joined: Tue Nov 14, 2006 5:56 pm
Location: South Australia

Post by Victragic »

Thanks Michael,

VIA 1 Timer 2 - got it.

So, I assume my wedge just needs to

1) Check the Interrupt Flag Register for the Timer 2 time-out flag
2) If not set, continue to $FEAD
3) If set, increment the clock and then continue to $FEAD

Seems simple enough, now to get the right timing..

I may actually make my own timer independent of the jiffy clock so that it isn't affected by changes to TI$.. good thing about that would be I could put it in a more friendly format, ie 1/60th of a second (or 1/20th of a second I guess in order to reduce NMI calls), and just store those variables on the screen directly to fall within the character codes 48-57.. TOD, effectively, rather than TI$..

Cheers, all good fun..

-Glen
3^4 is 81.0000001
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Post by Kweepa »

Hi,

I'm trying to do something similar, with cc65.

Code: Select all

.proc playSoundIrq

; check it's from timer 2
lda $911d
and #$20
beq end

; do some stuff here

restartTimer2:
lda #$e6
sta $9118
lda #$1b
sta $9119

end:
jmp $eabf

.endproc

.proc _playSoundInitialize

sei

lda $911b
and #$df	; set timer 2 to one-shot mode
sta $911b

lda #$a0    ; set timer 2 enable
sta $911e

; trigger every 7143=$1BE6 cycles (1000000/140)
lda #$e6
sta $9118
lda #$1b
sta $9119

; insert irq into chain
lda #<playSoundIrq
sta $314
lda #>playSoundIrq
sta $315

cli

rts

.endproc
As you might guess from the name, I'm attempting to play sounds at 140Hz. Everything seems to work except that the sounds play much slower than I'd expect - it seems more like 50Hz. I tried changing the hi byte to #$b instead of #$1b but it didn't seem to affect the timing.

My first thought is that perhaps cc65's runtime also uses timer 2 for something, but if I don't start the timer in the initialize, I don't get any interrupts from timer 2 at all. I also did a quick search of the cc65 sources and didn't find any references to $9119, VIA1 + 9, or the t2_hi member of __6522.

Please help a confused Kweepa.
User avatar
Mike
Herr VC
Posts: 4839
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

VIA #1 makes NMIs.
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Post by Kweepa »

So if I just switch everything over to VIA #2 it should work?
I'm not sure what the significance of your comment is, unless you just mean there's no point in using SEI and CLI around the initialization code.
User avatar
Mike
Herr VC
Posts: 4839
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

O.K., more elaborated answer:

The topic of the thread was to do an interrupt, preferably an NMI, that should be independent of the keyscan/jiffy IRQ.

Inthusfar your request of doing a 140 Hz interrupt for your soundplayer fits the topic.

But while your routine sets up timer 2 in VIA #1 correctly, causing an NMI, you're putting your ISR into the standard ($0314) IRQ vector, which of course is still executed at 60 Hz. If you're going to correct that error, don't forget, that the end of your ISR:

Code: Select all

end: 
jmp $eabf 
... also should jump elsewhere.
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Post by Kweepa »

Ok, thanks very much!
So I should use $318-9 and jmp $fead.
I'll post the working code later for future reference.
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Combining two via timers

Post by Noizer »

Hello everyone enjoing retro coding on vic20,
years ago I started coding for fun on speccy48K and C64 and created a sample trackers using 4bit samples at around 20Khz hear frequency. I could collect some experience in ml coding on this different systems, which are from some points of view similar but also very different.
These trackers produces some nice techno beats or similar style direction. Samplesets can be changed, as the bpm too. The looping patterns can be updated in real time, what makes the most of the fun.
Anyway, I thought this time, keeping in mind the limited ressouces of a vic20, accepting the challenge about a new approach. Instead of using real samples one could create maybee similar sounds in realtime, on a stock machine?
So I experimented coding an consulting me online, on denial of course, how it could possible to create soundwaves on the fly, apart from using the vic voices. I must confess that the viznut waveforms sounds pretty nice, but are hard to handle, and are to loud in comparison to $900E waves.
BTW, I found some interessant topics, of course on denial too, which combining with my own ideas an experience, I should be able to realize something to that idea.
So I coded a sort of (beta) tracker, able to create pwm waves through $900E, with dynamic modifications as pulse wide, pulse fx, different volumes per sample, pitch modify, changable note duration....on a stock vic 20 :D . Sounds like a c64 ;) but not near so bad as sid vicious = good idea but ear piercing :\ .
By playing with the parameters a variety of sounds can be created: pwm tones, analog sounding bass drums or core distorted bass drums, snares, toms, and strange sfx similar sounding like ring modulated, sometimes remembering voices, as again, knowed from the big brother c64.
Back to this topic, of course one is able to change the beat in real time by typing in proper value to patterns, for each sound 10 bytes wide.
Unfortunatelly here is also the limit of this approach, changing parameters involves a change in the duration of a loop from the beat.
So the tempo variates from for example 4/4 to 3/4 or around. It's of course possible to fix the tempo but this takes a while, playing with the parameters. It would be nice not to worry about that.
Currently the routine runs in irq 0314-15, the beat driven by $9124-25. The irq will only be exit, as the by the parameters generates sample, play is done.
This behavoir causes the changes in beat duration.
So my reflections suggested me to think inverse. Instead of driving the output of a sample through an irq, the irq should drive how long cycles the sample have to play, and then "interrupt" acts, as the function suggestes, breaking playback and fetching an new (virtual) sample.
A constant timer interrupt should guarantee this, so no matter which pitch the tone is played, the beat stays even.
My tests to this, using and endless loop of "INC$900F JMP BACK", showed to me that a timer interrupt, even feeded with 9124-25=FFFF, too fast is to play a sample. I was not able to figure out how this could be done slower, because I never thought before about this "inverse" idea of handling irqs.
Here is the question: is it possible to combine two via timers to count, for example to 1 second intervall and then trigger an interrupt to stop the endless loop (sample play) at a regular interval, even again?
Thanx in advance for all you out there and your support
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
User avatar
Mike
Herr VC
Posts: 4839
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Combining two via timers

Post by Mike »

Hi, Noizer!

Unlike the CIAs in the C64, the VIA timers don't provide to concatenate, i.e. for example count underflows of timer #1 with timer #2 (and then, as I suppose you want) let timer #2 make an interrupt on that one's underflow.

One thing you should be wary of: in continuous mode, the timers underflow to $FFFF before they are reloaded from the latches. If you need the longest possible period, you need to load the latches with $FFFE.

That being said, the normal modus operandi for trackers still is to use IRQ with a "slow" timer to advance along the patterns; for samples an NMI is used with enable flags, possibly two buffers with an init, (re-)start and end pointer. That idea is of course taken to the extreme with SID Vicious, which *only* plays a totally synthezised sample from the three emulated SID voices in the NMI, at ~6 kHz, and the IRQ routine executes the patched tracker routine. Whatever time is left for the CPU to run in the foreground - non-IRQ/non-NMI - executes the RNG for the noise waveform.

IMO, SID Vicious does a pretty good job at the whole thing. Filters, etc., are of course beyond reach, but many SID tunes can be played back quite faithfully. So I'd be interested where you'd pinpoint the ear-screeching sounds. ;)

...

Oh, and welcome to Denial! Here's the real deal! :mrgreen:

Michael


P.S. feel free to post any relevant executable program from your experiments. Makes it easier for the Programming section to discuss details. :)
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Re: VIA Timer 1 or Timer 2?

Post by Noizer »

Hello everybody,

I'm not sure if it is allowed to continue so an old entry like this, but the topic in this blog is similar to my last topic "combining two timers".
Due I'm not that crack, especially with nmi coding, still searching for working examples, I tried to figure out how the code posted here works... but it doesn't work at all.
Shift+comm. seems to toggle case mode, but i don't got a Cursor...
Got Someone an idea why not?
Probably i should post the modified code here in future...
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
User avatar
Mike
Herr VC
Posts: 4839
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: VIA Timer 1 or Timer 2?

Post by Mike »

Noizer wrote:I'm not sure if it is allowed to continue so an old entry like this, but the topic in this blog is similar to my last topic "combining two timers".
Since you chose to reply in the thread here, I merged the other thread, "combining two timers" into this one here.
especially with nmi coding, still searching for working examples, I tried to figure out how the code posted here works...
Two things to note here: Kweepa's code most probably went its way in experimental state - as you see the thread wasn't followed-up as such there was no real conclusion. No wonders the code doesn't work as is. :wink:

Second: timer #2 in the VIAs is one-shot only. I was in error suggesting its use here. Simple as that.

...

Nonetheless, you find a working example of an NMI interrupt handler for example with my Paddlescope. The thread over there also features source.
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Re: VIA Timer 1 or Timer 2?

Post by Noizer »

OK Mike, thank for your supporting. I'll check for sure your code in the spare time.
So I understood that it's not possible to generate a wide interval irq with vic20.
But what's about some additional hardware which could externally interrupt the sample playing at a constant rate, for example connected to userport?
Probably I'm getting a little out of this topic...
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
Post Reply