Reversing Pins 3 & 11 For Interrupt

I have some code that makes use of digital pin 11 for PWM on Timer2:

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  // ..later on in setup()
  sbi (TIMSK2,TOIE2);
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);
  cbi (TCCR2A, COM2A0);
  sbi (TCCR2A, COM2A1);
  sbi (TCCR2A, WGM20); 
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);

My problem is that I'd like to free up 11 so I can use it for in circuit programming. And while I understand you can swap 3 & 11 for PWM in this case, I have no ideal of how to manage the registers at this low level. So my question is two part:

  • Does anyone know how to reverse this code so pin 11 is 'normal' and pin 3 does the PWM?

  • Can anyone recommend a web page/site that discusses the ATMEGA registers in enough detail so that I can decode/change the code myself? I need something easier than their chip's pdf, which is a tough read.

Any real help appreciated.

Output Compare A controls pin 11, B controls pin 3

Try

  sbi (TIMSK2,TOIE2);
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);
  cbi (TCCR2A, COM2B0);
  sbi (TCCR2A, COM2B1);
  sbi (TCCR2A, WGM20); 
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);

This is more concisely (and correctly - you want to configure ALL the bits in the timer control registers so you don't leave state from before unless you are certain of previous state):

  TIMSK2 = 0b00000001 ;  // TOIE2 bit
  TCCR2A = 0b00100001 ;  // COM2B bits = 10, WGM20:1 = 01
  TCCR2B = 0b00000001 ;  // WGM22 = 0, CS2 = 001  (clock select prescale divide-by-1)

You'll also have to configure pin 3 as an output of course.

BTW most of this configuration is not needed in the standard Arduino set-up as the timer2 is already set up for phase-correct PWM - you just need to change the clock select:

  sbi (TIMSK2,TOIE2);  // enable overflow interrupt (will run every 31.875us)
  TCCR2B = (TCCR2B & 0xF8) | 0x01 ;  // change prescaler from divide-by-64 to divide-by-1 (PWM at 31kHz approx)

should be sufficient, thereafter use analogWrite (3, ...)

MarkT:
Try
...

  TIMSK2 = 0b00000001 ;  // TOIE2 bit

TCCR2A = 0b00100001 ;  // COM2B bits = 10, WGM20:1 = 01
  TCCR2B = 0b00000001 ;  // WGM22 = 0, CS2 = 001  (clock select prescale divide-by-1)

Thanks very much Mark - it worked as soon as I plugged it in! Now I've freed up digital pins 10-13 for icsp - very much appreciated.

By the way, where did you go to get your understanding of the mega's register details? I'm looking to learn more about them...

I read the datasheet sections (mainly for the ATmega328, the 1280 and 2560 just have more 16-bit timers), experimented and read other peoples code.