PWM - special cases on Timer2 and Timer0

I am relatively new to writing arduino code so I have had great difficulty sorting out what appear to be errors in the documentation from misconceptions in my own understanding of what I should expect from code execution.

In writing motor driver code for a project, I needed to get the PWM frequency up above the audible range but still stay under the maximum frequency that my H-bridge would support. I am using Timer1 to manage long, variable delays with interrupts to dial down the motor speed, while depending on an external interrupt to turn the motor off. The sequence is to set the motor to max speed, then (on a Timer1 interrupt) cut the PWM duty cycle by 50%, and when the external interrupt occurs, set the duty cycle to 0.

So I was trying to use Timer2 in the phase correct PWM mode with OCR2A as TOP to set the frequency by using the divide by 8 prescaler and setting OCR2A to 60 to achieve a PWM frequency of 16,393.4Hz.

What surprised me was that when the ISR triggered by the external interrupt set the duty cycle to zero with an analogWrite(3,0), OCR2B did not change even though the motor shut off. When I looked at TCCR2A I discovered that whenever the command was for zero duty cycle, COM2B1 was cleared, apparently by the hardware microcode, but OCR2B was left unchanged. This seems to disable the output (pin3) (possibly putting it into a tri-state mode). When I tried Timer0 I found exactly the same behavior so it is clearly a feature rather than a bug. What I suspect, but am not equipped to measure, is that in this mode there is no way to get a 1/OCR2A PWM duty cycle.

Here is the test sketch demonstrating the behavior (you can change all of the Timer2-unique variables into Timer0 equivalents and see the behavior on Timer0 (independent of whether you are truly masochistic or just a skeptic).

int sample;
void setup() {
  //initialize Timer2 in phase correct PWM Mode 5 { WGM2[2:0] = B101 } using TOP (OCR2A) to control the PWM frequency
  //and OCR2B to set the PWM duty cycle [implicit in analogWrite(pin,duty-cycle x OCR2A)]
  //set mode to Toggle on Compare Match" by setting the COM2A[1:0] bits to B01
  //set output to Clear OC2B (pin3) on Compare Match when up-counting and Set OC2B on Compare Match when down-counting
  //by setting COM2B[1:0] = B10

  Serial.begin(115200);//use relatively high serial port speed to speed things up
  delay(500);
  pinMode(3, OUTPUT); //connect pin3 to Enable pin on external H-bridge motor controller

  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS21);
  OCR2A = 60;//PWM values must be in [0,60]

  sample = 1;
  analogWrite(3, 60); //turn motor on at 100% PWM duty cycle
  Serial.println("\tcase\tTCCR2A\tTCCR2B\tOCR2A\tOCR2B");
  Print1();

  sample = 2;
  analogWrite(3, 30); //reduce motor drive to 50% duty cycle
  Print1();

  sample = 3;
  analogWrite(3, 0); //turn motor off by reducing duty cycle to 0
  Print1();

  sample = 4;
  analogWrite(3, 1); //turn motor on to minimum non-zero duty cycle
  Print1();

  sample = 5;
  analogWrite(3, 0); //again turn motor off
  Print1();

  sample = 6;
  OCR2B = 0;//force OCR2B to zero
  Print1();

  sample = 7;
  analogWrite(3, 1); //turn motor on to minimum non-zero duty cycle
  Print1();


}

void loop() {
  // put your main code here, to run repeatedly:
}

void Print1() {
  Serial.print("\t"); Serial.print(sample);
  Serial.print("\t"); Serial.print(TCCR2A, BIN);
  Serial.print("\t"); Serial.print(TCCR2B, BIN);
  Serial.print("\t"); Serial.print(OCR2A, BIN);
  Serial.print("\t"); Serial.print(OCR2B, BIN);
  Serial.println(" ");//add CR after the last print
}

And here are the printed results for the first 5 cases:

case TCCR2A TCCR2B OCR2A OCR2B
analogWrite(3,60) 1 1100001 1010 111100 111100
analogWrite(3,30) 2 1100001 1010 111100 11110
analogWrite(3,0) 3 1000001 1010 111100 11110
analogWrite(3,1) 4 1100001 1010 111100 1
analogWrite(3,0) 5 1000001 1010 111100 1

Note that commanding PWM = 0 changes only COM2B1 from 1 to 0 and does not change OCR2B
And commanding any other (non zero) PWM value restores COM2B1 to 1

If you set OCR2B to zero, it will change nothing in any of the other registers.

Can someone confirm that it is a special case that the microcode discovers and acts on in realtime?
Or is it something behind the curtain in the compiler that adds code to check for the zero duty cycle case?

And who do I engage to fix the MANY typos in the data sheet that deal with the PWM behaviors. I see that some of them have been picked up and fixed between 2016 and the 2018 release but some new ones were introduced and many were not fixed. Or it could still be that I don't understand what they are trying to tell me.

Can someone confirm that it is a special case that the microcode discovers and acts on in realtime?
Or is it something behind the curtain in the compiler that adds code to check for the zero duty cycle case?

Here is the explanation for what you are seeing.

The source code for analogWrite() is found in C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring_analog.c

There you will find that analogWrite(pin,0) is executed as digitalWrite(pin,0).

The source code for digitalWrite() is found in C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring_digital.c

There you will find this comment and the code which turns off the pwm output.

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.

Thanks. Logical, but arcane. That could easily be included in a tutorial under Special Cases (of which there seem to be many, all of them hard to understand until you have to use them).

For those on a Mac find the Arduino icon in the Applications folder, and right click, and select Show PackageContents, then navigate to Contents, Java, hardware, arduino, avr, cores, arduino, and there you find wiring.analog.c