One possible way to implement PWM is using ring modulation (XNOR) between two channels running at the same frequency but different phase:
[ Guests cannot view attachments ]
To delay channel 2 relative to channel 0 by a known amount of time, the sync bits of port A7h are used, they force the outputs of both channels to zero and reload the counters. Before doing this, channel 2 is set up to run at a higher frequency (which determines the pulse width), then once the counters are allowed to run again by writing 0 to port A7h, the channel 2 frequency is set to the same value as that of channel 0.
I think I've found Istvan's code that you mentioned - it's in the source for sndplay in initDAC procedure. But I will need some more time to actualy understand what's going on there ;P. Something with forcing the noise channel to always output on state etc... Looked only briefly...
It basically uses the output of channel 3 as the noise clock, that is possible by enabling ring modulation on channel 1, and then channel 1 (which is forced to 0 state with the sync bit) is set to be the clock source. The ring modulation is periodically toggled on and off a number of times, and finally the clock source is set to channel 2 that always outputs 0 because of the sync bit. Channel 1 can then be used for other purposes. The trick is to create a stable state only when the noise output is 1:
- if channel 3 outputs 0, then the result of the ring modulation with channel 1 (= 0) is 0 XNOR 0 = 1
- if channel 3 outputs 1, then it is 1 XNOR 0 = 0
- when the ring modulation is disabled or the input is channel 2, the noise clock is 0
So, when the noise channel outputs 0, its input becomes a square wave, otherwise it is a stable 0 to keep the 1 output level that has already been found. Since the noise generators are implemented using LFSRs, they are guaranteed not to output runs of 0's or 1's longer than the size of the shift register, and more than that number of ring modulation on/off cycles will always find a 1 in the sequence.