/*
Project: Simple Tone Generator with ATtiny85
š§ What it does:
1. Outputs a square wave (audio tone) on a pin (e.g. PB0)
2. Tone frequency is set by OCR0A and the prescaler
3. Can cycle through musical notes or respond to inputs later (like a button)
š§ How It Works: Using Timer0 in CTC Mode
1. Timer counts up to OCR0A, then resets to 0.
2. OC0A toggles on each compare match ā square wave output!
3. Frequency is determined by:
fHz = f_CPU / 2 x N x (OCR0A + 1)
fHz = 8000000 / 2 x 256 x (59 + 1) = 260.4
Where:
1. f_CPU = 8 MHz
2. N = prescaler
3. fHz = frequeny
4. Multiply by 2 because it takes 2 toggles per cycle
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <TinyDebug.h>
#define SPEAKER_PIN PB0 // OC0A
// Play a square wave on OC0A (PB0)
void play_tone(uint8_t ocr_val, uint16_t duration_ms) {
DDRB |= (1 << SPEAKER_PIN); // Set OC0A (PB0) as output
// CTC mode, toggle OC0A on compare match
TCCR0A = (1 << COM0A0) | (1 << WGM01);
TCCR0B = (1 << CS02); // Prescaler = 256
OCR0A = ocr_val;
while (duration_ms--) {
_delay_ms(1);
}
// Turn off timer and output
TCCR0B = 0;
PORTB &= ~(1 << SPEAKER_PIN);
}
int main(void) {
Debug.begin();
while (1) {
play_tone(59, 500); // C4 (~262 Hz)
_delay_ms(100);
play_tone(53, 500); // D4 (~294 Hz)
_delay_ms(100);
play_tone(47, 500); // E4 (~330 Hz)
_delay_ms(100);
play_tone(45, 500); // F4 (~349 Hz)
_delay_ms(100);
play_tone(40, 500); // G4 (~392 Hz)
_delay_ms(100);
play_tone(35, 500); // A4 (~440 Hz)
_delay_ms(100);
play_tone(32, 500); // B4 (~494 Hz)
_delay_ms(100);
}
}