ATtiny13 – 8bit mono class D amplifier

I always wonder whether it is possible to make an amplifier of class D on ATtiny13 or not. Some time ago I found George Gardner’s project based on ATtiny85 – TinyD. It was a sign to start challenging it with ATtiny13. It took me a few hours but finally I made it! The code is very short and useses a lot of hardware settings which has been explained line-by-line in the comments. The project runs on ATtiny13 with maximum internal clock source (9.6MHz). It gave me posibility to use maximum of hardware PWM frequency (Fast PWM mode).

F_{PWM} = \frac{F\_CPU}{N \cdot 256} = \frac{9.6\mathrm{MHz}}{1 \cdot 256} = 37.5\mathrm{kHz}
 
The PWM freqency of class D amplifiers should be of course much higher, a hundreds of kHz (some sources says 8 times more than sampling frequency). Unfortunately, in case of ATtiny13 it’s not posible to achieve such parameters. However, for experimentally selected settings of ADC sampling rate (~10kHz) and PWM frequency (37.5kHz) the amplifier sounds very good! The code is on Github, click here.

Software

This code is written in C and can be compiled using the avr-gcc. All information about how to compile this project is here.

/**
 * Copyright (c) 2019, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
 * ATtiny13/052
 * Example of 8bit mono class D amplifier.
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define	AUDIO_IN	PB2
#define	AUDIO_OUT	PB0

int
main(void)
{

	/* setup */
	DDRB |= _BV(AUDIO_OUT); // set AUDIO_OUT pin as output
	TCCR0A |= _BV(WGM01)|_BV(WGM00); // set timer mode to FAST PWM
        TCCR0A |= _BV(COM0A1); // connect PWM pin to channel A
	TCCR0B |= _BV(CS00); // set prescaler to 1
	ADMUX |= _BV(MUX0); // select ADC1 (PB2)
	ADMUX |= _BV(REFS0); // set internal 1.1V reference voltage
	ADMUX |= _BV(ADLAR); // left adjust of ADC result
	ADCSRA |= _BV(ADPS1)|_BV(ADPS0); // set ADC division factor to 8
        ADCSRA |= _BV(ADEN)|_BV(ADIE); // enable ADC and interrupt
	ADCSRA |= _BV(ADATE); // set ADC auto-trigger
	ADCSRA |= _BV(ADSC); // start conversion
	sei(); // enable global interrupts

	/* loop */
	while (1);
}

ISR(ADC_vect)
{

	OCR0A = ADCH; // the magic
}

References

2 thoughts on “ATtiny13 – 8bit mono class D amplifier

Leave a Comment