Skip to content

Instantly share code, notes, and snippets.

@simondotm
Last active April 14, 2022 20:26
Show Gist options
  • Save simondotm/62d3bccc5b57132d837898604a6188e6 to your computer and use it in GitHub Desktop.
Save simondotm/62d3bccc5b57132d837898604a6188e6 to your computer and use it in GitHub Desktop.
Enhanced frequencies on SN76489.md

Supporting Enhanced Frequency Ranges on SN76489

Problem

  • The BBC Micro does not support bass frequencies under 122Hz
  • We want to create music that uses low frequencies

Hypothesis

  • We can simulate low frequency square waves by updating the sound chip using software logic on the CPU side

Details

  • The BBC Micro sound chip (SN76489) is clocked at 4Mhz.
  • Since the squarewave generator is linked to the clock, the frequency range is also linked
  • The SN76489 squarewave generator has 10-bit counters 0-1023
  • Frequency calculation is CLOCK / (2.0 * 16.0 * N)
  • The effective range of frequencies for the BBC Micro is 122.189638319Hz (N=1023) to 125000.0Hz (N=1)
  • To support frequencies between 30.53Hz and 122.07Hz we need to introduce 2 extra bits of precision to the tone register setting, giving us an extra range between 1024 and 4095

Notes

  • When setting a tone register to the SN76489 a ten bit value is sent using two bytes
  • The first byte is the command byte (containing low 4-bits), and the second byte is the data byte containing high 6-bits
  • Bit 6 of the second byte is unused, we can use that as a flag
  • Although adding two bits of extra precision gives us a 12-bit range, there is a lot of precision we arguably dont need (91.55Hz / 3071)
  • To simulate square waves in software we need to set the sound chip to a state where it is playing a continuous tone - 0 or 1

Supporting in YM2SN

  • We could try to simulate the effect in standard VGM
  • Assume that the SN has 12-bit tones instead of 10
  • For values > 1023 we flip to simulated frequencies
  • Output highest frequency (1) and then use intervals to invert the volume from current level to 0
  • VGM is 44100 Hz sample rate, so wait 1 is 1/44100 Hz
  • for a given frequency we find the VGM interval counter that is nearest and run the flip flop logic alongside it

Simulation

  • Change the vgm loop
  • For every 50Hz frame, output the tone + noise registers
  • Then iterate 881 times.
  • Each iteration:
  • Update the low frequency counter for channels with an active low frequency and calc freq volume
  • Update any digi drum channels
  • Modulate that volume with the envelope volume on that channel (at the envelope sampling rate)
  • Emit any changes to volume since last iteration

To support vgm output:

  • Low frequency mode (LFM) or periodic bass mode (PBM)
  • In LFM - either sampled or encoded output, sampled is VGM compatible, encoded is not (requires CPU)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment