kannst ja mal folgendes ausprobieren, da hast du 0 code in der main routine aber die auslastung ist schon heftig (hab ich aufm ATMEGA8 @8MHz intern geschrieben)
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/timer.h>
#include <avr/signal.h>
#include <avr/sleep.h>

#define ON 1
#define OFF 0
#define ULONG_MAX 199

volatile unsigned char OFVal;
unsigned char LED1Duty;
unsigned char LED1Stat;




SIGNAL(SIG_OUTPUT_COMPARE2)
{
   if (OFVal++ == 200) OFVal = 0;
   LED1Duty = (ADC*10)/(1024/10)-1;
   if (LED1Stat == OFF && (ULONG_MAX-LED1Duty) == OFVal)
   {
      PORTB |= BV(PB1);
      LED1Stat = ON;
   }
   if (LED1Stat == ON && ULONG_MAX-(ULONG_MAX-LED1Duty) == OFVal)
   {
      PORTB &= ~BV(PB1);
      LED1Stat = OFF;
   }
}

int main(void)
{
   cli();
   OFVal = 0;
   DDRB = BV(PB1)|BV(PB2)|BV(PB3)|BV(PB4);
   TIMSK = BV(OCIE2)|BV(TOIE2); //TOIE2 musste ich mit einschalten hat sonst nciht fuinktioniert (komisch ....)
   TCNT2 = 0;
   OCR2 = 100; //damit kannste die auflösung einstellen 100% sind wegen der ADC formel notwendig
   TCCR2 = BV(WGM21)|BV(CS20); //CTC modus, prescaler 1
   LED1Duty = 1;
   LED1Stat = OFF;
   ADCSRA = BV(ADFR) | BV(ADPS2) | BV(ADPS1); // ADC einstellungen
   ADMUX = BV(REFS0);
   ADCSRA |= BV(ADEN);
   ADCSRA |= BV(ADSC);
   sei();
   while(1) ;
}
die duty berechne ich in der ISR weil ich mir den ADC wert zum eistellen geholt habe, kannste aber theoretisch zwischen 0 und 100 variieren.
Wenn du OCR2 auf 256 stellst sollte mehr rechenzeit frei werden, aber die frequenz sinkt dann, musste einfach mal rumprobieren

PS: Bitte um kommentare zur optimierung des code