Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timer2 WGM2=5 OCR2B/OC2B/OC2A output doesn't work #119

Closed
drf5n opened this issue Mar 22, 2022 · 2 comments
Closed

Timer2 WGM2=5 OCR2B/OC2B/OC2A output doesn't work #119

drf5n opened this issue Mar 22, 2022 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@drf5n
Copy link

drf5n commented Mar 22, 2022

I was trying to generate a 32768Hz clock on OC2B by using WGM mode 5: Phase Correct,TOP=OC2A mode but I was unable to control OC2B in the mode.

Here is a sketch on the Uno: https://wokwi.com/projects/326859205681087060

The code is:

// simulate a 32kHZ clock on 3, read it into timer1 T1 on 5
// then divide timer1 by 32k and output on 10

// Does WGM=5, Phase Correct TOP=OC2A work on Timer2 in Wokwi?

const int mode = 0; // 1 = test, 0 = sim

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:

 pinMode(5,INPUT); // T1 clock input
 pinMode(10,OUTPUT); // pin 10/OC1B 
 pinMode(11,OUTPUT);
 // WGM = 8 Phase & Freq Correct PWM TOP=ICR1
 TCCR1B = 0; // halt clock
 TCCR1A = 0b10 <<COM1B0;  // output on OCR1B
 ICR1 = 16384; // F_OC1B = F_T1/(2*ICR1) for up and down count
 TCNT1 = 0 ; // phase adjust?
 OCR1B = 8192 ; // 50% duty cycle on OC1B 
 //TCCR1B = 0b10<< WGM12 |  0b101 << CS10; // Clock from T1 Rising edge
TCCR1B = 0b10<< WGM12 |  0b111 << CS10; // Clock from T1 Rising edge

 pinMode(3,OUTPUT);

if(mode == 0){  // simulate a clock on timeer2/OC2B
// PIN 3 = OC2B, 32KHZ:  16MHz/32kHz = 500, so toggle every 250
// WGM=5 Phase Correct PWM(OCR2A); 
//
// XXXXXXXX
// Choose one:   WGM=5 doesn't work ????
//const byte myWGM = 0;  const byte myCOM2B = 0b01; // Normal 0xFF toggle OC2B
//const byte myWGM = 1;  const byte myCOM2B = 0b10; // PC 0xFF: clear OC2B on match 
//const byte myWGM = 2;  const byte myCOM2B = 0b01; // CTC OC2A: toggle OC2B on match 
//const byte myWGM = 3;  const byte myCOM2B = 0b01; // Fast 0xFF: toggle OC2B on match 
// ************ These don't work:  
//const byte myWGM = 5;  const byte myCOM2B = 0b00; // PC OC2A: do nothing on match 
//const byte myWGM = 5;  const byte myCOM2B = 0b01; // PC OC2A: reserved OC2B on match 
const byte myWGM = 5;  const byte myCOM2B = 0b10; // PC OC2A: clear OC2B on match 
//const byte myWGM = 5;  const byte myCOM2B = 0b11; // PC OC2A: set OC2B on match 
// ************ 
//const byte myWGM = 7;  const byte myCOM2B = 0b10; // fast OC2A : clear OC2B on match 

const byte myCOM2A = 0b01 ; // toggle OC1B //11 in WGM{0,2,5,7} 

const byte myWGMlow2 = myWGM &0b11;
const byte myWGMhigh2 = myWGM >>2;
 TCCR2B =  0;
 TCCR2A = (myCOM2B << COM2B0) |(myCOM2A <<COM2A0) | (myWGMlow2 << WGM20); //   
 OCR2A = 250;  // OC2B = pin 11 is some WGM modes
 OCR2B = 125;  // OC2B = pin 3
 TCCR2B = (0b001 << CS20) | (myWGMhigh2 << WGM22); 
 //digitalWrite(3,HIGH);
}
}

void report(){
  const unsigned long interval = 250000UL+7*21;
  static unsigned long last = - interval;
  if(micros() - last >= interval){
    last += interval;
    Serial.print("TCNT1: ");
    Serial.print(TCNT1);
    Serial.print(", TCNT2: ");
    Serial.print(TCNT2);
    Serial.print(", tccr2A=0b");
    Serial.print(TCCR2A,BIN);
    Serial.print(", tccr2B=0b");
    Serial.print(TCCR2B,BIN);
    Serial.print("; \n");
  }
 
}

void loop() {
  // put your main code here, to run repeatedly:

report();
  //delay(0);
  if( mode == 1){
    digitalWrite(3,!digitalRead(3));
  }
}

In the other WGM modes, I was able to generate a clock on pin 3/OC2B, which I could then count from T1, divide, and re-output on pin 10. If you change the commenting to try a different WGM mode, the LEDs toggle, and the T1 count increases.

To get my 32768Hz from 16MHz needs a divide by 500, which I could fit in a phase-correct PWM mode with OC2A=250 up and down, or a toggling mode WGM=2 CTC mode works to get the right frequency, and WGM=7 mode works, but at double the frequency.

--
Also OC2A output doesn't appear to work in Timer2 WGM=5 Maybe it's all Timer2 WGM=5 outputs?

@drf5n drf5n changed the title Timer2 WGM2=5 OCR2B doesn't work Timer2 WGM2=5 OCR2B/OC2B/OC2A output doesn't work Mar 22, 2022
@urish urish added the bug Something isn't working label Mar 22, 2022
@urish
Copy link
Contributor

urish commented Mar 22, 2022

Thanks for the detailed report!

I tested this on a physical Arduino (connecting a logic probe to pin 3), these are the results:

image

  1. const byte myWGM = 7; const byte myCOM2B = 0b10;
  2. const byte myWGM = 5; const byte myCOM2B = 0b11;
  3. const byte myWGM = 5; const byte myCOM2B = 0b10;

The other two myWGM = 5 configurations show no output as expected (do nothing/reserved). So I can confirm this is a bug in the simulator.

@urish urish self-assigned this Mar 22, 2022
@urish
Copy link
Contributor

urish commented Mar 22, 2022

Fix released as AVR8js 0.18.10, and also updated on wokwi.com.

Thanks again for the super detailed report, it's been very helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants