PSG frequency register meaning at zero

페이지 1/2
| 2

By Wild_Penguin

Hero (616)

Wild_Penguin의 아바타

03-05-2020, 23:13

Hi,

Not sure if I should write here or in Hardware forum, however as I've done my tests in Basic on OpenMSX ... this could also be a SW "feature".

I wrote a PSG tester (in Basic) - originally because my NMS8255 still seems to have some mixing issues with it's internal PSG, and I need to troubleshoot it a bit - but I got a bit (a lot) carried away.

Now in many places it is told that the PSG produces sound according to formula:

value = Fi / (16 * Freq)

where Fi is the internal frequency (1789772.5 Hz according to the Wiki on the MSX), Freq is the frequency produced and value is the value in the register. This is mentioned in the Wiki on this page where the Basic sound command is mentioned and elsewhere.

Now what happens when the register value is near zero? I can not find this information anywhere! Not even the application manuals I can find are clear on this. With the sound channels the frequency will be outside hearing range of human beings (maybe the analog circuits still can produce the sound, maybe not, an oscilloscope could tell) but with the noise generator I can hear the sound produced if I type:

sound6,0
sound6,1

(with mixing mask etc. set so that one can hear the noise from some/one of the channels)

I can definitely hear a definite difference with these settings. So 0 and 1 are handled differently by the PSG! Although, according to the documentation I've found, 0 should result in "division by zero" in the PSG - so it must handle it somehow. It is not replacing it by 1 (since I can hear a difference), or Basic is doing something behind my back?

I should mention I made these test with OpenMSX (I'm assuming it's emulation is accurate enough, though must admit haven't tried on real hardware).

Anyone have any idea, what is happening at frequence register = 0 value?

p.s. As a sidenote, I've noticed I can not read or write PSG registers (with OpenMSX) with OUT&hFA0,7:OUT&HF1,&b000000:INP(&HF2) - only sometimes the values are actually written, sometimes they aren't, and reading also works only sometimes. Any idea, why?

Login or 등록 to post comments

By Wild_Penguin

Hero (616)

Wild_Penguin의 아바타

04-05-2020, 07:46

Whoops! Eek! In the sidenote:

Wild_Penguin wrote:

OUT&hFA0,7:OUT&HF1,&b000000:INP(&HF2)

Should be registers &hA0 (set register address), &hA1 (write) and &hA2 (read)! I was tired when I wrote the above Tongue .

Also, nitpickers might notice I'm writing about "near zero" ... well, that is not my question but the actual question is what happens at zero (to remove any ambiguity).

By wouter_

Champion (437)

wouter_의 아바타

04-05-2020, 10:51

Hi Wild_penguin,

The PSG noise is a binary signal, it randomly flips between 0 and 1, this signal is later _multiplied_ by the tone signal (a square wave) of channel A, B or C. That product is scaled by the volume setting and finally the 3 channels are summed together.

Let's first define what the 'frequency' of a random signal is. In the context of the PSG it's the maximum rate at which the signal flips. In other words: it's the rate at which we generate a new random value and either flip or not flip the output. Note that this differs by a factor 2x of how you typically define the frequency of a signal: e.g. to generate a square wave of 440Hz you need 880 flips per second.

The formula for the noise 'frequency' that is used in openMSX is the following (I'm reasonably sure it is the same in a real PSG):

freq = 223722Hz / (value ? 2 * value : 1)
so for value=0 you divide by 1, for values>0 you divide by 2*value
note: 223722Hz = 3.57MHz / 16

Note that it's a 'random' signal, so even if you select a high frequency outside the human hearing range, it's possible that the signal randomly doesn't flip for many consecutive samples. So some component of the signal remains audible. And this only describes the digital output of the PSG, as you said, the analog circuit in the MSX also plays a role.

When emulating high sound frequencies (approaching or succeeding the typical host sample rate of 44100Hz) it's important to use a proper resample algorithm. For best results select the 'high quality' resample algorithm in openMSX (with the command 'set resampler hq'). Though this is computationally more expensive than the default openMSX resample algorithm (and in many cases the default is good enough).

Wouter

By Grauw

Ascended (9379)

Grauw의 아바타

04-05-2020, 14:47

Wild_Penguin wrote:

Now what happens when the register value is near zero? [...] I can definitely hear a definite difference with these settings. So 0 and 1 are handled differently by the PSG! Although, according to the documentation I've found, 0 should result in "division by zero" in the PSG - so it must handle it somehow. [...] Anyone have any idea, what is happening at frequence register = 0 value?

There is no division going on, so there is no division by zero. The PSG has an internal period counter, each internal tick it increments and then checks if it’s greater or equal to the period you specified in the register. If that’s the case, it flips the output signal and sets the counter back to zero.

This means that no matter if you specify a period of 0 or 1, since the internal counter is incremented before the comparison, both >= 0 and >= 1 comparisons are instantly true, and both result in a tone of the highest frequency the PSG can produce.

I’ll quote an openmsx source code comment:

// Careful studies of the chip output prove that it instead counts up from
// 0 until the counter becomes greater or equal to the period. This is an
// important difference when the program is rapidly changing the period to
// modulate the sound.
// Also, note that period = 0 is the same as period = 1. This is mentioned
// in the YM2203 data sheets. However, this does NOT apply to the Envelope
// period. In that case, period = 0 is half as period = 1.
Wild_Penguin wrote:

It is not replacing it by 1 (since I can hear a difference), or Basic is doing something behind my back? I should mention I made these test with OpenMSX (I'm assuming it's emulation is accurate enough, though must admit haven't tried on real hardware).

I tested on a real MSX turbo R, and both a period of 0 and 1 produce the same noise.

SOUND 7,&HB7
SOUND 8,15
SOUND 6,0
Wild_Penguin wrote:

p.s. As a sidenote, I've noticed I can not read or write PSG registers (with OpenMSX) with OUT&hFA0,7:OUT&HF1,&b000000:INP(&HF2) - only sometimes the values are actually written, sometimes they aren't, and reading also works only sometimes. Any idea, why?

The PSG is accessed on the BIOS ISR, so you must disable interrupts between setting the register number and value. In BASIC you want to use the SOUND command.

By Parn

Hero (608)

Parn의 아바타

04-05-2020, 17:05

This is interesting to know because most other PSGs seem to use a different formula, where the specified 12-bit period is actually TP+1, so it varies from 1 to 4096 instead of 0 to 4095. I saw this in SCC, 2A03, MMC5 and VRC6. Of course none of this is from actual official documentation, so I wonder what's really correct.

By Grauw

Ascended (9379)

Grauw의 아바타

04-05-2020, 18:13

Yes the AY-3-8910 and YM2419 count differently from e.g. the SCC. It’s because they count up towards the period and do a greater-or-equals comparison.

Iirc the SCC counts down from the set period and does an equals-zero comparison, which means the period 0 is treated as a period of 4096. Also the period you specify is 1 lower than the PSG (TP+1). Lastly when the frequency is changed the internal counter is reset immediately, which results in distortions when the frequency is changed while a tone is audible (like for pitch bends). The PSG does not have this issue because it counts up and does a greater-or-equals comparison.

I think the DCSG is also different although I forgot the details about the counting and comparison. Actually there’s even a difference between the Texas Instruments SN76489 DCSG and the Sega one. The SN76489 treats 0 as a period of 1024, while the Sega PSG works like the AY3 / YM2419 does. Now I wonder if this also means that between them the period is also off by 1.

By Wild_Penguin

Hero (616)

Wild_Penguin의 아바타

04-05-2020, 20:54

Thanks for the replies, this is very interesting information!

I wouldn't have noticed anything unless I had been playing around in OpenMSX.

FWIW, here is a screenshot from audacity showing what was recorded in OpenMSX; register7 bitmask set to 000111b, 8 to 15, and 6 to 1, then 0, then again to 1:

(I know my sound command is a bit dirty, but it is an emulated machine and supposedly basic protects the dangerous registers with SOUND command).

I've also uploaded a video to hear the difference (and showing what I'm doing) here.

I need to test on real HW, too :o (though, I didn't mean to test the noise, I wanted to test volume levels - but that's another issue).

In the meantime, maybe the OpenMSX folks want to comment on this? Have I found some obscure bug, as the behavior seems different to what Grauw is describing?

By Manuel

Ascended (17064)

Manuel의 아바타

04-05-2020, 21:55

Maybe I don't understand, but what is wrong, you think?

By Wild_Penguin

Hero (616)

Wild_Penguin의 아바타

04-05-2020, 22:06

Hi Manuel!

Grauw wrote:

I tested on a real MSX turbo R, and both a period of 0 and 1 produce the same noise.

This is not the case on the emulated Turbo-R - there is a clear difference with 0 and 1. However, there are many factors here - maybe the sound is indeed different on a real machine, too, and the analog circuit is masking it on Grauw's machine?

EDIT: But reading Parn's reply... I think we got conflicting accounts now here. I believe more testing is needed before this is deemed some bug on OpenMSX! Sorry for suspecting one "too soon" oO

By Parn

Hero (608)

Parn의 아바타

04-05-2020, 22:11

Wild_Penguin wrote:

I need to test on real HW, too Shocked! (though, I didn't mean to test the noise, I wanted to test volume levels - but that's another issue).

Hey, I can assure you SOUND 6,0 and SOUND 6,1 really do sound different from each other in real hardware. I don't fully understand it but I'd bet this register probably works a bit differently from the period registers for each sound channel.

EDIT: Now I see I'm contradicting what Grauw previously reported. I'm probably misremembering. I'll leave the comment above for all to see I'm not trying to hide my stupidity. Tongue Tongue

Grauw wrote:

Yes the AY-3-8910 and YM2419 count differently from e.g. the SCC. It’s because they count up towards the period and do a greater-or-equals comparison.

So this is why TP=0 is equivalent to TP=1 in PSG's case. Gotcha.

Grauw wrote:

I think the DCSG is also different although I forgot the details about the counting and comparison. Actually there’s even a difference between the Texas Instruments SN76489 DCSG and the Sega one. The SN76489 treats 0 as a period of 1024, while the Sega PSG works like the AY3 / YM2419 does. Now I wonder if this also means that between them the period is also off by 1.

Yes, the DCSG treats 0 as 1024 because it decrements before comparison, according to the docs.

By Manuel

Ascended (17064)

Manuel의 아바타

04-05-2020, 22:10

Which hardware did you try, Parn?

페이지 1/2
| 2