12.5MHz One Bit DAC Using Rational Numbers
Posted: Sun May 09, 2021 12:25 pm
This message is not specific to 6502 but uses a variation of a circuit commonly used in contemporary 6502 systems and unconventional numeric representation suitable for 6502.
While prototyping a seven bit, dual core, clock stretching circuit (which definitely works with 25MHz input), it occurred to me that a minor variation of the circuit may be used to produce high quality audio. The minimal implementation requires two 8 bit latches and four 4 bit counters. The preferred embodiment requires an additional two counter chips to obtain a superset of 8 bit linear PCM.
The clock stretching circuit produces square waves with a minimum of two ticks high and two ticks low. Either phase may be extended by 2^N ticks. In the case where A+B=260 ticks, the result is 8 bit linear PCM from a one bit DAC. However, where A+B<>260, other ratios are possible. In the case where PWM incurs strictly one less tick, it is impossible for the average to equal zero. In this specific case, the average is very close to -1/2 or +1/2. Near the middle of the range, this is a good approximation of 9 bit quality. Similar reductions most heavily strake the middle of the range such that a rational approximation routine or look-up table may approximate 11 bit quality or better. With 16 latch bits, it is not possible to attain 16 bit audio quality. By counting, all representations where A=B are functionally equivalent. Likewise for integer multiples. Regardless, the scheme is equally bad at approximating linear and logarithmic PCM.
One of the problems with the use of PWM to obtain 16 bit sound is the obscene clock frequency. To obtain 65536 linear intervals within a 48kHz sample, a 3.15GHz clock is required. However, if the length of the interval is variable but restricted such that A+B<=260, we only require a 12.48MHz clock. Indeed, this frequency is only a recommendation. If you only have a 16MHz ceramic resonator, a 24MHz crystal or 28MHz NTSC/PAL crystal, that'll do.
You may assume that free running counters, loaded asynchronously, would have terrible quality. However, I assure you that the aggregate non-linearity is the opposite of a tinny one bit DAC. An ex-classmate wrote a utility to downsample PCM audio by reading two values and writing the value with the greatest magnitude. This process may be repeated, as required. The intention is to create thumping bass. Where a DAC with rational ratio over-runs its time-slot, it is most likely to occur in the phase with the largest magnitude. The result is a more moderate version of a PCM bass thumper. Furthermore, error is proportionately reduced with the repetition of full cycles. This occurs when sample frequency is reduced or the DAC is clocked faster. This leads to the counter-intuitive effect that a rational DAC becomes bassy when it is driven too fast.
There are many other sources of error. Some errors may be reduced by synchronously loading latches, alternating latch writes or sensing DAC phase prior to write. However, gains are minor because jitter (and race conditions) may remain. An effective technique to reduce error is to synchronously write upper nybbles first and wire latches appropriately. This requires zero additional hardware while incurring zero additional jitter. In particular, it keeps one source of transient error outside of the four most significant bits.
While prototyping a seven bit, dual core, clock stretching circuit (which definitely works with 25MHz input), it occurred to me that a minor variation of the circuit may be used to produce high quality audio. The minimal implementation requires two 8 bit latches and four 4 bit counters. The preferred embodiment requires an additional two counter chips to obtain a superset of 8 bit linear PCM.
The clock stretching circuit produces square waves with a minimum of two ticks high and two ticks low. Either phase may be extended by 2^N ticks. In the case where A+B=260 ticks, the result is 8 bit linear PCM from a one bit DAC. However, where A+B<>260, other ratios are possible. In the case where PWM incurs strictly one less tick, it is impossible for the average to equal zero. In this specific case, the average is very close to -1/2 or +1/2. Near the middle of the range, this is a good approximation of 9 bit quality. Similar reductions most heavily strake the middle of the range such that a rational approximation routine or look-up table may approximate 11 bit quality or better. With 16 latch bits, it is not possible to attain 16 bit audio quality. By counting, all representations where A=B are functionally equivalent. Likewise for integer multiples. Regardless, the scheme is equally bad at approximating linear and logarithmic PCM.
One of the problems with the use of PWM to obtain 16 bit sound is the obscene clock frequency. To obtain 65536 linear intervals within a 48kHz sample, a 3.15GHz clock is required. However, if the length of the interval is variable but restricted such that A+B<=260, we only require a 12.48MHz clock. Indeed, this frequency is only a recommendation. If you only have a 16MHz ceramic resonator, a 24MHz crystal or 28MHz NTSC/PAL crystal, that'll do.
You may assume that free running counters, loaded asynchronously, would have terrible quality. However, I assure you that the aggregate non-linearity is the opposite of a tinny one bit DAC. An ex-classmate wrote a utility to downsample PCM audio by reading two values and writing the value with the greatest magnitude. This process may be repeated, as required. The intention is to create thumping bass. Where a DAC with rational ratio over-runs its time-slot, it is most likely to occur in the phase with the largest magnitude. The result is a more moderate version of a PCM bass thumper. Furthermore, error is proportionately reduced with the repetition of full cycles. This occurs when sample frequency is reduced or the DAC is clocked faster. This leads to the counter-intuitive effect that a rational DAC becomes bassy when it is driven too fast.
There are many other sources of error. Some errors may be reduced by synchronously loading latches, alternating latch writes or sensing DAC phase prior to write. However, gains are minor because jitter (and race conditions) may remain. An effective technique to reduce error is to synchronously write upper nybbles first and wire latches appropriately. This requires zero additional hardware while incurring zero additional jitter. In particular, it keeps one source of transient error outside of the four most significant bits.