Move from 328P to 32U4, timer setup issues

I try to adopt this code to run on my arduino pro micro. 32U4 doesn’t have timer 2, so I’m moving to timer 4.

Original timer 2 setup:

namespace timer_2 {
    // 16000000 / 77500 = 206 + 70/155 = 206 + 14/31
    const uint8_t ticks_per_period = 206;
    // fractional ticks
    const uint8_t nominator = 14;
    const uint8_t denominator = 31;
 
    const uint8_t pwm_full_carrier      = ticks_per_period / 2;  // ~50  %   duty cycle
    const uint8_t pwm_modulated_carrier = ticks_per_period / 32;  // 1/4 Amplitude = 1/16 Power
 
    void setup() {
         // disable timer2 interrupts during setup
        TIMSK2 = 0;
 
        // enable OC2B pin for output (digital pin 3)
        DDRD |= 1<<3;
 
        // The fast Pulse Width Modulation or fast PWM mode (WGM22:0 = 3 or 7) provides a high fre-
        // quency PWM waveform generation option. The fast PWM differs from the other PWM option by
        // its single-slope operation. The counter counts from BOTTOM to TOP then restarts from BOT-
        // TOM. TOP is defined as 0xFF when WGM2:0 = 3, and OCR2A when MGM2:0 = 7. In non-
        // inverting Compare Output mode, the Output Compare (OC2x) is cleared on the compare match
        // between TCNT2 and OCR2x, and set at BOTTOM. In inverting Compare Output mode, the out-
        // put is set on compare match and cleared at BOTTOM.
 
 
        TCCR2A = 1<< WGM20 | 1<<WGM21 | // Fast PWM
                 1<<COM2B1;             // Clear OC2B on Compare Match
 
        TCCR2B = 1<<CS20 | // no Prescaler
                 1<<WGM22;  // Fast PWM
 
        OCR2A = ticks_per_period - 1;  // period length
 
        OCR2B = pwm_full_carrier;  // duty cycle
 
        TIMSK2 = 1<<OCIE2A;  // enable match interrupts
    }
}
 
ISR(TIMER2_COMPA_vect) {
    static uint8_t accumulated_fractional_ticks = 0;
 
    accumulated_fractional_ticks += timer_2::nominator;
    if (accumulated_fractional_ticks < timer_2::denominator) {
        OCR2A = timer_2::ticks_per_period - 1;
    } else {
        OCR2A = timer_2::ticks_per_period;
        accumulated_fractional_ticks -= timer_2::denominator;
    }
}

New timer 4 setup:

namespace timer_4 {
    // 16000000 / 77500 = 206 + 70/155 = 206 + 14/31
    const uint8_t ticks_per_period = 206;
    // fractional ticks
    const uint8_t nominator = 14;
    const uint8_t denominator = 31;

    const uint8_t pwm_full_carrier      = ticks_per_period / 2;  // ~50  %   duty cycle
    const uint8_t pwm_modulated_carrier = ticks_per_period / 32;  // 1/4 Amplitude = 1/16 Power
 
    void setup() {
         // disable timer4 interrupts during setup
        TIMSK4 = 0;
 
        // enable OC4D pin 6 for output (27    (T0/OC4D/ADC10) PD7    Digital Pin 6 (PWM))
        DDRD |= (1 << 6);
 
        // The fast Pulse Width Modulation or fast PWM mode (WGM22:0 = 3 or 7) provides a high fre-
        // quency PWM waveform generation option. The fast PWM differs from the other PWM option by
        // its single-slope operation. The counter counts from BOTTOM to TOP then restarts from BOT-
        // TOM. TOP is defined as 0xFF when WGM2:0 = 3, and OCR2A when MGM2:0 = 7. In non-
        // inverting Compare Output mode, the Output Compare (OC2x) is cleared on the compare match
        // between TCNT2 and OCR2x, and set at BOTTOM. In inverting Compare Output mode, the out-
        // put is set on compare match and cleared at BOTTOM.
 
 
        TCCR4A = 1<< WGM40 | 1<<WGM41 | // Fast PWM
                 1<<COM4D1;             // Clear OC4D on Compare Match
 
        TCCR4D = 1<<CS40 | // no Prescaler
                 1<<WGM41; // Fast PWM
 
        OCR4A = ticks_per_period - 1;  // period length
 
        OCR4D = pwm_full_carrier;  // duty cycle
 
        TIMSK4 = 1<<OCIE4A;  // enable match interrupts
    }
}
 
ISR(TIMER4_COMPA_vect) {
    static uint8_t accumulated_fractional_ticks = 0;
 
    accumulated_fractional_ticks += timer_4::nominator;
    if (accumulated_fractional_ticks < timer_4::denominator) {
        OCR4A = timer_4::ticks_per_period - 1;
    } else {
        OCR4A = timer_4::ticks_per_period;
        accumulated_fractional_ticks -= timer_4::denominator;
    }
}

The entire code is available here, I’m going to keep it up to date.

This modification didn’t really work, I have no reasonable output – there’s a led connected and it’s dead.

I’ve googled a library that users the same set of timers on these MCPUs, so it should be possible to set up things properly. I’ve tried to compare timer’s documentation and they seem to be very different and I’ve no idea what makes sense here. For example:

328P:
– Two 8-bit Timer/Counters with Separate Prescaler and Compare Mode
– One 16-bit Timer/Counter with Separate Prescaler, Compare Mode, and Capture Mode

32u4:
– Two 16-bit Timer/Counter with Separate Prescaler, Compare- and Capture Mode
– One 10-bit High-Speed Timer/Counter with PLL (64MHz) and Compare Mode

So do these bits matter? What else can be an issue? Do I have to edit other timers?

I’m not sure about the PWM setup due to lack of understanding and digging through documentation about it.

Datasheet also mentions a known issue with timer 4:

32u4 datasheet:
7. Timer 4 11-bits enhanced PWM mode
Timer 4 11-bits enhanced mode is not functional.

But it’s not setup in 11-bit more in this code, is it?