With this code you can change top by adjusting OCR0A and then adjusting the duty cycle using OCR0B giving you control over pwm frequency and duty cycle.
My questions are:
Is this the way Fast PWM Mode 7 is meant to work on Timer0?
You need to read the data sheet very carefully. For example
When OCR1A or OCR1B contain $00 or the top value, as specified in OCR1C register, the output PB1(OC1A) or
PB4(OC1B) is held low or high according to the settings of COM1A1/COM1A0. This is shown in Table 12-2.
It should be obvious that if you want to use an OCR register to set TOP (the period), it can't also be used as a compare register to set the PWM percentage. Choose another mode.
Thanks @Kai-R@ZX80. The information you provided seems to confirm what I was experiencing.
To sum up it up - this is how I understand Timer0 PWM mode 7 to work on the ATtiny85:
In Fast PWM mode 7 OC0A will only ever output a PWM signal when the Reserved compare output mode is selected (row 2 in the table below). No other compare output modes will produce any PWM output onOC0A(in Fast PWM mode 7). This compare output mode produces a PWM signal with a fixed duty cycle of 50% at variable frequency. The frequency can be adjusted by settingOCR0A which acts as the counter TOP. The output for this PWM signal will beOC0A.
OC0B is able to output a PWM signal in non-inverting or inverting compare output mode (in Fast PWM mode 7). This requires the use of registersOCR0AandOCR0B.OCR0A acts as the TOP for the counter and OCR0B is the value at which a compare match is made. This allows for adjustment of PWM frequency and duty cycle.The output for this PWM signal will beOC0B.
The datasheet doesn't seem to document Fast PWM mode 7 clearly enough. From the documentation it seems like OC0A should also be able to work in non-inverting or inverting compare output mode (row 3 - 4 in the table above) but it does not. It only works in theReservedcompare output mode (row 2 in the table above). For other compare output modes in PWM mode 7 you have to use OC0B as the output of your PWM signal.
Just out of curiosity, does your program require delay functions or millis()? Changing timer 0 on the ATmega328p and ATmega2560 can cause the specified functions to not work properly.
I've actually made a program to investigate five of the PWM modes. In the virtual oscilloscope attached below, the OCRXX register is set to 78.4% duty cycle From what I've found, analogWrite() is equivalent to 8-bit phase correct PWM with clock divisor 64.