I am trying to use hardware PWM on an ATmega2560 using TC0 (8-bit timer) in fast PWM mode. I need to dynamically adjust the duty cycle, and this includes a zero duty cycle. However, this does not seem simple or even possible. Quoting the table:
The extreme values ββfor the OCR0A register are special cases when generating a PWM output signal in fast PWM mode. If OCR0A is set to BOTTOM, the output will be a narrow spike for each MAX + 1 clock timer. Setting OCR0A to MAX will result in a constant or low output (depending on the polarity of the output set with COM0A1: 0 bits).
So, setting OCR0A to 0 (= BOTTOM) will not actually result in a zero fill cycle, and my tests confirm this. A different approach needs to be used.
First, I taught to use the special case OCR0A = MAX, as described in the above quote. In combination with a temporary switch to inverted mode, this will lead to a zero filling cycle. However, since the COM0A1: 0 bit is not double buffered (and is not synchronized with OCR0A), this can lead to a failure in the output if the mode switches when the output signal is high (it will remain high until the next overflow). It does not seem to matter what order the OCR0A changes and the mode change is executed, both may fail.
I also considered another solution to disable PWM by setting COM0A1: 0 = 0. This will immediately set the output to a value in the PORT register, which will be zero. But there still remains the problem of returning from zero output to a non-zero filling cycle. From what I read in the datasheet, setting COM0A1: 0 to re-enable PWM will immediately switch the output to PWM, which may be the wrong value until the next comparison or timer overflow. Hence the failure.
Inverting the common PWM may be applicable, but then the problem simply becomes the achievement of a complete duty cycle with symmetrical problems.
Please note that it is not possible to disable PWM wave generation during forced output of output via PORT, as described in the data table:
The Compare Output mode bits (COM0x1: 0) have two functions. The signal generator uses the COM0x1: 0 bit to determine the output Compare (OC0x) in the following comparison. In addition, COM0x1: 0 bits control the output source of the OC0x output.
It is not possible to start PWM in a cycle or so on and switch to it when it is ready - turning on PWM immediately forces output to be output.
UPDATE. In the phase (with center alignment) PWM mode, this problem is absent, and in my case this is acceptable. I tried this and confirmed that it works for both zero and full duty cycle.