since I modified the timing register and the prescaler,
the 100% point in the duty cycle is 250, as stated in my code posted.
TCCR2B = TCCR2B & 0b11110000 | 0b00001011; // modifying timing register to double the PWM freq. from 490Hz to 980Hz
OCR2A = 0xFA; // fine tuning prescaler, slightly shorten pwm period from 256 to 250 steps to achieve exactly 1kHz
This was done to archive exactly 1kHz PWM frequency, but that's not what my post is about at all.
OCR2A has nothing to do with prescaler. It is compare value of Timer2 channel A. It will be changed any time when you use analogWrite() on Timer2 A channel
see the analogWrite() sourcecode:
void analogWrite(uint8_t pin, int val)
{
pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
else
{
switch(digitalPinToTimer(pin))
{
// .... other timers code skipped...
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A:
// connect pwm to pin on timer 2, channel A
sbi(TCCR2A, COM2A1);
OCR2A = val; // set pwm duty
break;
#endif
If you are bit-twiddling the WGM2 bit in TCCR2B, I'd go ahead and set the rest of the registers like TCCR2A and TCNT2, and instead of using analogWrite(...) I'd use OCR2B.
I didn't dig into it, but I'd suspect that the digitalWrite() from analogWrite(PWM_PIN,LOW) twiddles some of the registers, and lets TCNT2 count above OCR2A, giving you a one-shot behavior when you re-enable PWM.
that was indeed the case.
I'm now using OCR2B instead of analogWrite.
Had to rewrite some of my code, but the one shot behaviour is now gone.
I needed to get away from analogWrite() and learn how to properly use the registers.