Hints on multiplexing multiple timers on a 6522

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
hjalfi
Posts: 107
Joined: 12 Oct 2017

Re: Hints on multiplexing multiple timers on a 6522

Post by hjalfi »

I have it working, with three tone channels plus a PCM drum channel. This is using the shift register to actually emit the bits, with an unrolled loop generating the data eight bits at a time. It works, kinda...

Using a byte value as the note counter simply isn't enough precision, and I only get about two octaves before the notes become unacceptably out of tune. And everything is pitched very low; C1 to C3. This should have not come as a surprise to anyone other than me as I'm trying to squeeze a log value into eight bits.

So I need to somehow increase the sample rate to get more precision, which means reloading the shift register faster, which means extending the counter to 16 bits, which means doing more work to reload the shift register. I don't think that's going to work.

That brings me back to somehow using a tickless approach where I use the timer to wait precisely for the amount of time needed for the next pulse. Somehow.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Hints on multiplexing multiple timers on a 6522

Post by drogon »

hjalfi wrote:
I have it working, with three tone channels plus a PCM drum channel. This is using the shift register to actually emit the bits, with an unrolled loop generating the data eight bits at a time. It works, kinda...
Just to add a note - 3 tone channels + noise: This is essentially the same capabilities as the TI SN76489 which was used in the BBC Micro (and many others including game consoles of the era).

The Beeb made it much more than just the basics by use of a 100Hz interrupt which could dynamically vary the both frequency and amplitude of the audio output enabling the production of many different effects via a somewhat complex but usable 'envelope' command which took some 14 parameters... Latterly, it was used for speech output by modulating the noise generator too.

So I'm wondering if a simple 16 pin DIP IC could save you a whole lot of effort, although it would not interface to the CPU bus directly, but would need to through a port of a VIA. (The Beeb had what it called a "slow bus" for these sorts of things).

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
fachat
Posts: 1124
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Re: Hints on multiplexing multiple timers on a 6522

Post by fachat »

@hjalfi it would help if you could share more details. Like which algorithm you actually use now. What timer values / frequencies you are using. What the note counter actually does. Etc.

André
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
User avatar
hjalfi
Posts: 107
Joined: 12 Oct 2017

Re: Hints on multiplexing multiple timers on a 6522

Post by hjalfi »

Sorry for the lack of response --- I managed to get it working well enough, and got stuck in finishing up the project:

https://www.youtube.com/watch?v=iqWJeM2MKt4

This is doing three-channel polyphony with a PCM drum track (well, PFM or PDM, more like).

It works by using the 6522 shift register running at 12529Hz, meaning I have to service it at 1566Hz. There is only just enough CPU time available, and that's with 8-bit counters which aren't really precise enough. The breakthrough was remembering that I only need to synthesise three channels, not four --- the drum track is much easier to generate.

The algorithm is basically:

Code: Select all

for every SR interrupt
  clear flag
  clear var
  do eight times
    for every voice
      decrement note counter
      if counter < volume for this voice, set flag
      if note counter == 0:
        reload it
    if flag is set:
      rotate a bit into var
  OR in the PCM value (which is a byte)
  SR := var
12529Hz was calculated to give me as much accuracy as possible, so that each note I want to play falls roughly on an integer counter value. In fact it's not great, and I only manage G#0 to C#3 before the inaccuracy goes above 10 cents, which is about the maximum you can get away with. This is a shame, as the demo track really wants to use A3, which is 29 cents flat and sounds terrible. Volume is controlled by changing the mark/space ratio of the output waveforms, but it doesn't work very well. It does produce a nice side-chaining effect, though.

The playback algorithm is using a hair under 100% of the available CPU time, and that's not taking into account the envelope processor (which can apply volume and pitch changes to the playing note) and the time taken to actually calculate what notes to play, and as a result there's an audible glitch between steps in the music, which are mostly covered by effects and drums. Given that I never actually used the envelope processor it's probably not worth having, but maybe someone else will find it useful?

If I had a 2MHz CPU I'd be able to crank the sample rate way up and use 16-bit counters, giving much more accurate music and lower notes.
fachat
Posts: 1124
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Re: Hints on multiplexing multiple timers on a 6522

Post by fachat »

Good you managed to get it working!

Some shared code would be nice, we can always learn - on the other hand there's potential optimization we can help with our expertise.

For example, looking at your algorithm, could it not potentially be optimized by exchanging the two loops, and potentially use some arithmatics and tables instead of the inner loop?

How did you test the output? I'm pretty sure the VICE emulator isn't really up to the task - unless they have replaced my pet audio implementation (which is highly likely given that I wrote it some 20+ years ago or so).
Anyway, my suggestion is to test it on a real machine

André
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
User avatar
hjalfi
Posts: 107
Joined: 12 Oct 2017

Re: Hints on multiplexing multiple timers on a 6522

Post by hjalfi »

Oops, I forgot to link to the website: http://cowlark.com/ptracker All the source is on github.

The loops are, in fact, massively unrolled using macros, as a brute-force way to save as many cycles as possible...

Code: Select all


    .macro synth var, varp, varm
        ldx \var            ; 3
        dex                 ; 2
        zif eq              ; 2/3
            ldx \varp       ; 3
        zendif
        stx \var            ; 3
        cpx \varm           ; 3
        adc #0xff           ; 2
    .endm                   ; = 18

    .rept 8
        lda #0
        synth t1, t1p, t1m
        synth t2, t2p, t2m
        synth t3, t3p, t3m

        cmp #1          ; sets C if >= 1
        rol nextsample
    .endr
(The zif stuff are structured programming macros which turn into simple branch instructions. I find it makes machine code vastly easier to maintain.) (This is from https://github.com/davidgiven/ptracker/ ... ine.S#L140.)

If you can suggest ways to shave cycles off, it desperately needs it.

As for testing... I did actually use VICE. I've been trying to find someone who'll try it on a real PET but nobody's reported back yet!
fachat
Posts: 1124
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Re: Hints on multiplexing multiple timers on a 6522

Post by fachat »

Still haven't had time to take a deeper look or even test it, but still thinking going on in my head.

Did I get it right that for each note, you define the following two values:
- note counter init value = how many bit periods are in one note period. I.e. at a say 10kHz bit period, a value of 4 would give 2500Hz tone?
- volume per note = how many bits in the note period should be set. So, if a note period is 4, and volume is 4 (you check on less than), there would be 3 one-bits and one zero-bit per note period?

So basically you use a simple PWM to create a volume for a note?

I'm not sure this would work well. The same as all zero and all one bits do not give any tone as the output is constant, I would expect a single one-bit (volume 1) or a single zero-bit (volume 4 in above example) would basically give the same output - your ear does not hear the 180 degree phase shift ... volumne in that definition probably only makes sense up to the half note period.

Definitely on my list to test and play around with
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
User avatar
hjalfi
Posts: 107
Joined: 12 Oct 2017

Re: Hints on multiplexing multiple timers on a 6522

Post by hjalfi »

Yup, that's pretty much it. You're right, a high mark/space ratio gives exactly the same effect as a low mark/space ratio. p-tracker only lets you set it from 0 to 15, but on high notes where the period is short odd things happen. In fact the minimum mark time is so high (one 12529Hz sample) that it doesn't have much effect on volume but it does change the timbre significantly. If you listen to the demo track, I'm changing this during long notes to make it sound more interesting.
fachat
Posts: 1124
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Re: Hints on multiplexing multiple timers on a 6522

Post by fachat »

I downloaded the source but as I don't have llvm-mos handy, I wanted to use the binary.
When I started I do have to enter my own sounds?
Is there any demo tune you could share (or if I missed it where I can find it)?
I want to test it on my PET clones...
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
User avatar
hjalfi
Posts: 107
Joined: 12 Oct 2017

Re: Hints on multiplexing multiple timers on a 6522

Post by hjalfi »

The disk image has the file ONWARD which is the piece of music in the demo video. If you're not using the disk image, it's in extras/onward-ride.ptr.
andym00
Posts: 3
Joined: 04 Apr 2012

Re: Hints on multiplexing multiple timers on a 6522

Post by andym00 »

Bit late to see this, but very interesting..
You might find something useful in a system I wrote some 13 years ago for the C64, synthesiisng mutiple PWM voices at high rates.. EOR buffer, just marking the edges of waveform transitions (1 bit per voice), then generating an essentially run length compressed output of 6526 timer cycles and the resultant summed volume of the bit combination.. Each bit had it's own volume, so a volume lut needed to be generated when voice volumes changes..
Seperate left/right frequencies for Pulse width controls..
Timer A controls the base sample rate (63 cycles in this case), Timer B counts underflows of A, which is basically samples, which makes things nice and 8 bit..
https://csdb.dk/forums/?roomid=12&topicid=90296
Post Reply