// Timer1Excerciser -- Experiment with Timer1
// Code: https://wokwi.com/projects/328669448533705299
//
// Using TimeHelpers from http://www.gammon.com.au/timers
// Uno 328 DSatasheet http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
// Uno source https://store-usa.arduino.cc/products/arduino-uno-rev3
//
// This is intended to excercise the different options of Timer1 CTC(OCR1A)
// for https://github.com/wokwi/avr8js/issues/122
//
#include "TimerHelpers.h"
/* ---------------------------------------------------------------
Test sketch
--------------------------------------------------------------- */
// pins
const byte OC1B_pin = 10; // this is OC1B (timer 1 output compare B)
const byte OC1A_pin = 9; // this is OC1A (timer 1 output compare A)
const byte OVF_LED = 8; //
const byte MATCH_LED = 7; //
// state vars
bool T1IntsOn = false;
volatile bool overflowed = false, matched = false;
volatile uint32_t overflow_time, match_time;
void setup() {
Serial.begin(115200);
pinMode (OC1A_pin, OUTPUT);
pinMode (OC1B_pin, OUTPUT);
digitalWrite (OC1B_pin, HIGH);
pinMode(OVF_LED, OUTPUT);
pinMode(MATCH_LED, OUTPUT);
TCCR1A = 0; // reset timer 1
TCCR1B = 0;
// set up Timer 1
TCNT1 = 0; // reset counter
OCR1A = 65535; // compare A register value
OCR1B = 32767; // compare A register value
ICR1 = 65535;
// Mode 4: CTC, top = OCR1A
Timer1::setMode (4,
Timer1::PRESCALE_256,
Timer1::TOGGLE_A_ON_COMPARE | Timer1::TOGGLE_B_ON_COMPARE);
/*
//
Timer1::setMode (1,
Timer1::PRESCALE_256,
Timer1::SET_A_ON_COMPARE | Timer1::CLEAR_B_ON_COMPARE);
*/
TIFR1 |= bit (OCF1A); // clear interrupt flag
TIMSK1 = bit (OCIE1A) | bit(TOIE1); // interrupt on Compare A Match & overflow
T1IntsOn = true;
} // end of setup
ISR(TIMER1_OVF_vect)
{
overflowed = true;
overflow_time = micros();
// digitalWrite(OVF_LED, !digitalRead(OVF_LED));
// TCCR1B = 0; // kill the timer
} // end of TIMER1_COMPA_vect
ISR(TIMER1_COMPA_vect)
{
matched = true;
match_time = micros();
//digitalWrite(MATCH_LED, !digitalRead(MATCH_LED));
} // end of TIMER1_COMPA_vect
void toggleTimerInterrupt(void) {
const unsigned long interval = 5000000UL;
static unsigned long last = -interval;
unsigned long now = micros();
if (now - last >= interval) {
last += interval;
T1IntsOn = !T1IntsOn;
if (T1IntsOn) {
TIFR1 |= bit (OCF1A); // clear interrupt flag
TIMSK1 = bit (OCIE1A) | bit(TOIE1); // interrupt on Compare A Match & overflow
} else { // off
TIFR1 |= bit (OCF1A); // clear interrupt flag
TIMSK1 &= ~(bit (OCIE1A) | bit(TOIE1)); // clear interrupt on Compare A Match & overflow
}
Serial.print(now);
Serial.print("us Timer1 Interrupts ");
Serial.print(T1IntsOn ? "on" : "off");
Serial.print(", TCCR1A = 0b");
Serial.print(TCCR1A,BIN);
Serial.print(", TCCR1B = 0b");
Serial.println(TCCR1B,BIN);
}
}
void doOcr1aChanges(void) {
static uint16_t OCR1Astate = 0;
const unsigned long interval = 10000000UL;
static unsigned long last = 0;
unsigned long now = micros();
if (now - last >= interval) {
last += interval;
if (OCR1A == 0 ) {
OCR1A = 0xFFFF;
} else {
OCR1A = OCR1A >> 1;
}
Serial.print(now);
Serial.print("us OCR1A = 0x");
Serial.println(OCR1A,HEX);
}
}
void loop() {
if (overflowed) {
noInterrupts();
overflowed = false;
interrupts();
digitalWrite(OVF_LED, !digitalRead(OVF_LED));
Serial.print(overflow_time);
Serial.print("us Overflow TCNT1 = 0xFFFF\n");
}
if (matched) {
noInterrupts();
matched = false;
interrupts();
digitalWrite(MATCH_LED, !digitalRead(MATCH_LED));
Serial.print(match_time);
Serial.print("us Matched TNCT1 == OCR1A == 0x");
Serial.println(OCR1A,HEX);
}
toggleTimerInterrupt();
doOcr1aChanges();
} // end of loop