6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Jul 02, 2024 8:50 am

All times are UTC




Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Mon Jun 10, 2024 1:44 pm 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
I have been thinking about simple sound generation techniques for my 65C02 SBC, and using the 65C22's timer T1 in Free-run mode which automatically toggles port b pin 7 seems like an attractive option to get low-cpu usage audio output with low part count. With additional circuitry such as a resistor-DAC controlled by a few output pins, a simple volume control for ADSR could be created. Add a few more 65C22s to get polyphony (and a whole lot of useful GPIO pins).

Now, the simplest form to get a tone of f Hz is to just set the timer to T = CPU clock frequency/2*f which would produce a square wave output with 50% duty cycle.

This is a great start but I would like to be able to produce a bit more Nintendoesque sounds by exploring 12,5% and 25% duty cycles as well.

For any given timer value representing 50% duty cycle, calculation of the active and inactive parts for a 12,5% and 25% duty cycle should be simple enough to do in runtime using LSRs (2 of them for 12,5% i.e. 0.5/4 , 1 of them for 25% i.e. 0.5/2) for the active part Th and then the inactive part would be Tl=T-Th.

I looked in the datasheet and there seems to be latches that you can set without affecting the running counter, but rather affect the _next_ counter. Is this correct? That would mean I could do a glitch free switch back and forth in an IRQ between Th and Tl, for the _next_ trigger of the timer. I.e. just when Th has been started, I would set Tl, and just when Tl has been started, I would set Th.

However, the documention for writing to T1L ($06) worries me:

"8 bits loaded into T1 low order latches. This operation is no different than a write into theT1 Low Order Register"

Does this mean that it restarts the counter once the low value is written to the latch? If so my theory falls apart (I think).

Perhaps I have misunderstood the whole thing?

/Johan


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 10, 2024 4:34 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3366
Location: Ontario, Canada
JohanFr wrote:
However, the documention for writing to T1L ($06) worries me:
Is it WDC documentation you're using? Not a great choice, IMO... for 65C22, 65C02 and others I much prefer the doc from Rockwell... but even their 65C22 doc is occasionally hard to understand. That's because the chip itself has some subtle (but useful) nuances.

JohanFr wrote:
the documention for writing to T1L ($06) worries me:
"8 bits loaded into T1 low order latches. This operation is no different than a write into the T1 Low Order Register"
T1 Low Order Register? So, we're drawing a contrast between Reg $06 and Reg $04, is that right?

According to my notes (based on Rockwell), Register $04 and Register $06 behave almost identically... and the exception pertains to reads (not writes). A read of Reg 6 won't clear the T1 flag in the IFR, whereas a read of Reg 4 will clear the flag. (Both return the same data. But the designers apparently anticipated a need to be able to peek at the timer without scuttling a nascent interrupt.)

I suspect that the snippet you quoted is some author's garbled re-interpretation of the behavior documented by Rockwell.

Edit: oops, that's probably too harsh. The snippet isn't incorrect. But it's entirely unhelpful unless there's an accompanying snippet that pertains to reads, whose behavior does differ between Reg 4 and 6.

Edit: On a broader scale (ie, 65C22 aside), when one finds doc confusing, it can often be helpful to find an alternative version of said doc. :wink:

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Last edited by Dr Jefyll on Mon Jun 10, 2024 4:50 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 10, 2024 4:50 pm 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
Yup I am using the WDC documentation. Thanks for recommending the Rockwell docs, I read the section about timers and it explained it much clearer. Seems like what I want to achieve is very much possible:

"However, by loading the latches only, the processor can access the timer during each down-counting operation without affecting the time-out in process. Instead, the data loaded into the latches will determine the length of the next timeout period. This capability is particularly valuable in the freerunning mode with the output enabled. In this mode the signal on PB7 is inverted and the interrupt flag is set with each timeout. By responding to the interrupts with new data for the latches, the processor can determine the period of the next half cycle during each half cycle of the output signal on PB7 In this manner, very complex waveforms can be generated"


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 10, 2024 10:49 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8462
Location: Southern California
The matter in the data sheet about "very complex waveforms" from PB7 has to do of course with feeding T1 a different value at every time-out interrupt.  If you're going to give it attention at every interrupt, you might as well keep the T1 latch value constant (to set a sampling rate) and then generate an analog voltage at each of those sample times. Without a D/A converter, you can use the VIA's shift register (SR) in mode 100 (shift out free-running at T2 rate) to output a 9-level PWM (0 to 8 bits high), which when followed by an RC filter, is suitable for a 9-level D/A.  This is shown at http://wilsonminesco.com/6502interrupts/index.html#3.3 .  I've used it to generate DTMF.  This is slightly better than 3-bit resolution.  Talking toys used to only use 2-bit resolution.  If you wanted to use it as a volume control instead, you could use it to chop a signal, fast enough that the chopping frequency can be filtered out without any significant effect on the desired audio.  There's a little more about D/A converters in the "circuit potpourri" page of the 6502 primer, at http://wilsonminesco.com/6502primer/potpourri.html#DAC, and there's working sample code there for using the SR as a substitute 9-level DAC.

See also my "Tip of the Day" column which has lots of ideas of things you can do with the VIA and ACIA, and a few tricks that might save you a lot of time, at viewtopic.php?f=7&t=342 .


_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 7:13 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 740
Location: Potsdam, DE
JohanFr wrote:
Now, the simplest form to get a tone of f Hz is to just set the timer to T = CPU clock frequency/2*f which would produce a square wave output with 50% duty cycle.

This is a great start but I would like to be able to produce a bit more Nintendoesque sounds by exploring 12,5% and 25% duty cycles as well.


I wonder if there is some confusion here (probably mine, not knowing what a Nintendoesque sound sounds like) but changing the duty cycle of a 'square' wave won't change its frequency, just its audio spectrum. So it will sound different, but be at the same frequency.

Is that what you intended? Of did you want to output an arbitrary waveform?

If the latter, then generating a PWM controlled square wave may the simplest way to do it, remembering that the square wave has to be above the ear's ability to hear it - so it has to be fast. A low pass filter at somewhat under half the square wave will allow a reasonable approximation to the desired audio output: a constant PWM value gives a constant DC value.

Some numbers: assuming that your phase0 clock is at 1MHz, and your maximum audio frequency is 5kHz (normal speech is between 400-3000Hz) then you have 200 clocks between audio clocks; a signal to noise ratio of around 40dB. Doubling the phase0 clock increases the signal to noise ratio by 6dB _or_ doubles the bandwidth.

However, you need a mechanism to update the counter-end value after each tick; an interrupt at this sort of frequency will occupy a large percentage of your total processor time.

Neil


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 8:03 am 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
Yes I am talking about PWM, i.e. for a given tone frequency, modulate the signal to create different timbre. About 20 seconds in this video is illustrated what I want to achieve:

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

This is a simplified version of the more flexible PWM possibility of the SID-chip which can set a more finegrained PWM. But the 12.5% and 25% numbers are nice because they go well with the 65C02 lsr/ror instructions. You can expand the timbre even further by switching between 12.5, 25, 50 in a playback routine, if desired.

I should have clarified, the intention for this is a music playback routine for games or demos as my plans for my SBC is to have a 70s/early 80s style game console. I have already written a tracker style music software for PC/Linux with synthesized sounds (read: PWMed square waves) and it would be a fun side project to adopt it to automatically generate a music playback routine for the 65C02, just like is done with the SID-fileformat, where you call a "play" routine every frame (i.e every 1/60 s) that parses music data and updates the timer base value etc accordingly.

In theory, the highest I would ever go would be C8 according to https://inspiredacoustics.com/en/MIDI_note_numbers_and_center_frequencies which is roughly 4000 Hz. If my math is correct, a square wave with 25% PWM would require a change after 0.25*1/4000 s for the active part and 0.75*1/4000 s for the passive part. I think the ratio of interrupt vs non-interrupt computing time would only depend on the base frequency (well, twice that), the PWM would only affect the distribution when they happen. (EDIT: In practice I would probably not go over C7 or ~2 KHz).

Arbitrary waveforms is another matter. I might explore that at a later point as well, for low-bitrate sound effects etc.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 8:58 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8462
Location: Southern California
Ah yes, that definitely helps us understand what you're aiming for.  The VIA's shift register can give you the varying duty cycles (one, two, three, or four eighths of the period being a 1, and the rest being a 0), but the frequencies would be too high for audio, and the frequency resolution wouldn't be fine enough at one end of the scale.  I'll try to think of a way to do it with minimal parts and minimal software overhead.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 9:07 am 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
GARTHWILSON wrote:
The matter in the data sheet about "very complex waveforms" from PB7 has to do of course with feeding T1 a different value at every time-out interrupt.  If you're going to give it attention at every interrupt, you might as well keep the T1 latch value constant (to set a sampling rate) and then generate an analog voltage at each of those sample times. Without a D/A converter, you can use the VIA's shift register (SR) in mode 100 (shift out free-running at T2 rate) to output a 9-level PWM (0 to 8 bits high), which when followed by an RC filter, is suitable for a 9-level D/A.  This is shown at http://wilsonminesco.com/6502interrupts/index.html#3.3 .  I've used it to generate DTMF.  This is slightly better than 3-bit resolution.  Talking toys used to only use 2-bit resolution.  If you wanted to use it as a volume control instead, you could use it to chop a signal, fast enough that the chopping frequency can be filtered out without any significant effect on the desired audio.  There's a little more about D/A converters in the "circuit potpourri" page of the 6502 primer, at http://wilsonminesco.com/6502primer/potpourri.html#DAC, and there's working sample code there for using the SR as a substitute 9-level DAC.

See also my "Tip of the Day" column which has lots of ideas of things you can do with the VIA and ACIA, and a few tricks that might save you a lot of time, at viewtopic.php?f=7&t=342 .



Thank you for the tips, most appreciated! But I am bit worried that generating a PWMed square wave using sample playback would require a much higher frequency to avoid aliasing etc and I think it would consume too much CPU and also memory that is needed for visuals and other stuff I have in mind. Right now, interfacing the address bus and data bus of my VGA-circuit is done by using the 65C22 shift register so it's eating a lot of cycles as it is :( .

My thoughts yesterday was to have the PB7-timer driven output as the primary source of audio, and then feed that signal into an 4-input AND-gate on one side, and four bits of volume control into the other, then connect the output to a resistor-dac, DC-blocking capacitor and other circuitry needed to convert to line level audio output. Then the primary application would be to set the volume of the square wave, but I think it could also be used as a 4-bit DAC for sample playback if PB7 is set to 1. I haven't explored this part at all so there are probably many problems on the way.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 9:11 am 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
GARTHWILSON wrote:
Ah yes, that definitely helps us understand what you're aiming for.  The VIA's shift register can give you the varying duty cycles (one, two, three, or four eighths of the period being a 1, and the rest being a 0), but the frequencies would be too high for audio, and the frequency resolution wouldn't be fine enough at one end of the scale.  I'll try to think of a way to do it with minimal parts and minimal software overhead.


Looks like our replies are out of phase, apologies for any redundancy :oops:

I think the resulting tone frequency range I am interested in is around 40-4000 Hz, if that helps. These are not hard numbers, but I would want something to be able to play some lows and some highs for game melodies and melody based sound effects.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 3:35 pm 
Offline

Joined: Thu Dec 26, 2002 12:29 pm
Posts: 61
Location: Occitanie, France
I'm old and rusty on these things now, but can't you use frequency interference techniques to get the required "low" frequencies from higher ones ?
Isn't that what beat frequencies are?
Just my 2cents (Euros, of course).

_________________
Glenn-in-France


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 11, 2024 5:06 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 740
Location: Potsdam, DE
It is, but they're not straight-forward when you do it with square waves (the sum and difference results come from sines, but square waves are an infinite series of sines... the result may not be what you want. (though it may!))

(In general here, without any specific knowledge of the 6522...)

If you want a single voice, generating it is as simple as loading a CTC counter when a note starts, and loading another note as required.
Changing the timbre by changing the mark-space ratio isn't much more complex, but rather than simple divider, you need something to set an output at a base frequency, and reset it some convenient time during the cycle, and keep doing it. A simple low frequency PWM.
If you need an arbitrary waveform, then you need a high-frequency constant square wave being PWMed with the desired signal... needs a processor intervention _each and every_ cycle.

Fast, cheap, on time. Pick one...

Neil


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 12, 2024 8:23 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8237
Location: Midwestern USA
barnacle wrote:
It is, but they're not straight-forward when you do it with square waves (the sum and difference results come from sines, but square waves are an infinite series of sines... the result may not be what you want. (though it may!))

Interesting you mention that.

Way back when I was in high school and learning about acoustic phenomenon as part of my music education, a science class project I did was to demonstrate beat-frequency effects, using two Wien bridge oscillators—vacuum-tube powered—and two square-wave generators, the circuit of which was a pair of cross-connected triodes, flip-flop style.

As expected, combining the sine wave signals produced audible sum and difference frequencies that, for the most part, were tolerable.  Combining the square waves, on the other hand, produced something that sounded mostly like a wounded bird squawking, not the least bit pleasant!  The unpleasantness, I later learned, was due to the theoretically-infinite number of odd-order harmonics in the two square waves clashing with each other and producing a whole lot of dissonances.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 13, 2024 11:18 am 
Offline

Joined: Wed Nov 16, 2011 9:39 am
Posts: 48
barnacle wrote:
It is, but they're not straight-forward when you do it with square waves (the sum and difference results come from sines, but square waves are an infinite series of sines... the result may not be what you want. (though it may!))

(In general here, without any specific knowledge of the 6522...)

If you want a single voice, generating it is as simple as loading a CTC counter when a note starts, and loading another note as required.
Changing the timbre by changing the mark-space ratio isn't much more complex, but rather than simple divider, you need something to set an output at a base frequency, and reset it some convenient time during the cycle, and keep doing it. A simple low frequency PWM.
If you need an arbitrary waveform, then you need a high-frequency constant square wave being PWMed with the desired signal... needs a processor intervention _each and every_ cycle.

Fast, cheap, on time. Pick one...

Neil


Building an external version was my first thought, before I considered using PB7 output. Theoretically it should be simple to calculate T2 and T1 based off T and a duty cycle, then switch back and forth between them (I am not sure if that is what you suggested or just another way of doing it). Chip count wise, much more complex than just using PB7. But it would eliminate the need for interrupts entirely.

Maybe I will do a combination, one voice with PWM possibilities using external circuitry, and one or two voices the PB7 on one (or two) 65C22. Many possibilities :)

I think playing samples or otherwise generate waveforms digitally at a fixed sample rate just takes too much memory and execution time if it is to be controlled by the CPU, and this isn't ideal if the CPU is meant to mainly do other tasks, so I will probably skip that for now. Might revisit it in the future sometime, using some kind of CPU-independent circuitry.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 14, 2024 5:40 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 740
Location: Potsdam, DE
Yes, for both video and audio, DMA of some kind is the way to go. The ear is very sensitive to tiny changes in sample timing and to alias frequencies generated (though my background is broadcast quality digital audio!).

A memory that you can fill up off-stage, as it were, and just let the audio hardware grab samples as it needs to output them... it's getting into serious hardware, though, and perhaps beyond your current design scope.

Neil


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: