/*
See: https://www.gadgetronicx.com/attiny85-timer-tutorial-generating-time-delay-interrupts/$0
There are two timers on ATtiny85 Timer0 and Timer1.
Timer0 is a 8 bit timer, it can count from 0 to 255.
Configuration of Timer0 register can be done using two registers TCCR0A and TCCR0B
** Steps to configure Timer and use 'Interrupt' to generate delay:
1. Select the normal mode of operation for timer0
2. Prescale the internal clock by a factor of 1024
3. Enable Global interrupt enable I bit in SREG register
4. Enable TOIE0 bit in TIMSK register to enable Timer0 interrupt.
5. Write the Interrupt service routine to repeat the counting operation 63 times to obtain a delay of 1 second.
6. Toggle the LED connected to PB1 pin.
Sketch assumes ATTiny85 at 8.0 MHz
Use calculator at https://eleccelerator.com/avr-timer-calculator/
*/
#include<avr/io.h>
#include <avr/interrupt.h>
#include <TinyDebug.h>
#define F_CPU 8000000UL
#define LED1 PB1 // output
volatile uint8_t intr_count = 0;
volatile uint8_t ISR_done = 0;
ISR (TIMER0_OVF_vect) { // Interrupt vector for Timer0
intr_count++;
if (intr_count == 30) { // 30 flags = 1 sec, value per https://eleccelerator.com/avr-timer-calculator/:
//PORTB ^= (1 << PB1); //toggle on 1 sec, toggle off 1 sec
ISR_done = 1;
intr_count = 0; // set count back to zero
}
}
void timer_setup() {
DDRB |= (1 << LED1); // Set Port B, pin PB1 as output
// TCCR0A – Timer/Counter Control Register A
// We want 'Mode of Operation' set to 'Normal' so all bits are set to 0
TCCR0A = 0x00; // Set bits WGM00 and WGM01 to 0 for 'Normal' mode
// TCCR0B – Timer/Counter Control Register B
// This line of code isn't really needed, or could use -
// TCCR0B &= ~(1 << WGM02);
TCCR0B = 0x00; // Set bit WGM02 to 0 for 'Normal' mode
// CS02 CS01 CS00
// 1 0 1
TCCR0B |= (1 << CS00) | (1 << CS02); // prescaling with 1024
/*
SREG – AVR Status Register
Bit 7 – I: Global Interrupt Enable
This bit must be enabled in order to use any interrupt on ATtiny85
SREG |= (1 << 7);
or
SREG = SREG | 0b10000000;
or
*/
sei(); // enabling global interrupt
// TCNT0 – Timer/Counter Register - 8 bit
/*
This is a 8 bit data register at which the timer value gets stored.
Being a 8 bit register this register can hold values from 0 to 255.
Upon completion of this count in TCNT0 register timer sets the Overflow flag
*/
TCNT0 = 0;
/*
TIMSK – Timer/Counter Interrupt Mask Register
Responsible for activating and deactivating interrupts associated with Timer0 and Timer1 of ATtiny85.
The bit TOIE0 enables / disables Timer0 interrupts. Writing one to this bit enables the interrupt.
*/
TIMSK |= (1 << TOIE0); // enabling timer0 interrupt
PORTB |= (1 << PB1);
}
int main () {
Debug.begin();
timer_setup();
while(1) {
if (ISR_done) {
Debug.print("if start: "); Debug.println(ISR_done);
PORTB ^= (1 << PB1);
ISR_done = 0;
Debug.print("if end: "); Debug.println(ISR_done);
}
}
}