1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <avr/io.h>
#include <avr/interrupt.h>

#define LEDOFF do { PORTB &= ~(1<<PB1); } while(0)
#define LEDON do { PORTB |= 1<<PB1; } while(0)

int
main(void)
{
	/* Setup: ATtiny2313 with LED on PB1 and scope on PB3 */

	DDRB |= 1<<DDB1 | 1<<DDB3; // debug LED and PWM output

	/* pwm frequency (fixed at 50% duty cycle) */
	OCR1A = 0x1000;

	/* enable timer compare match interrupt for visible feedback */
	TIMSK |= 1<<OCIE1A;

	// Set phase-and-frequency-correct PWM on timer 1:
	// Mode  WGM13  WGM12(CTC1)  WGM11(PWM11)  WGM10(PWM10)  Timer/Counter Mode of Operation   TOP     Update of OCR1x at  TOV1 Flag Set on
	// 9     1      0            0             1             PWM, Phase and Frequency Correct  OCR1A   BOTTOM              BOTTOM
	TCCR1A |= 1<<WGM10;
	TCCR1B |= 1<<WGM13;


	// Setup inverted PWM on OC1A (PB3)
	// COM1A1/COM1B1  COM1A0/COM1B0  Description
	// 0              0              Normal port operation, OC1A/OC1B disconnected.
	// 0              1              WGM13=0: Normal port operation, OC1A/OC1B disconnected. WGM13=1: Toggle OC1A on Compare Match, OC1B reserved.
	// 1              0              Clear OC1A/OC1B on Compare Match when up- counting. Set OC1A/OC1B on Compare Match when downcounting.
	// 1              1              Set OC1A/OC1B on Compare Match when up- counting. Clear OC1A/OC1B on Compare Match when downcounting.


	// bug?  output stays low all the time, timer
	// is running though (LED blinks):
	TCCR1A |= 1<<COM1A1 | 1<<COM1A0;

	// the following on the other hand does work, LED blinks
	// and square wave on PB3
	//TCCR1A |= 1<<COM1A0;

	sei();

	/* enable timer clock */
	TCCR1B |= 1<<CS10;

	for (;;);
}

ISR(TIMER1_COMPA_vect)
{
	/* toggle the LED every 256 compare matches */
	static unsigned char foo;
	static unsigned char on;
	if (!++foo) {
		if (on) LEDON;
		else LEDOFF;
		on = !on;
	}
}