An update whilst getting the drum synth code together. The output is 8 bit at 31.25kHz, a frequency derived from the 8Mhz clock speed divided by 256 – the number of clock cycles it takes for the PWM ramp to go full cycle.
Interrupt initialisation including analogue input for potentiometers and piezo:
int main(void)
{
// PWM output on PORTB0 = pin 5.
DDRB = _BV(0);
// PWM init, 8Mhz / 256 gives 31.25kHz
TCCR0A =
_BV(COM0A1) | // Clear OC0A/OC0B on Compare Match.
_BV(WGM00) |_BV(WGM01); // Fast PWM, top 0xff, update OCR at bottom.
TCCR0B = _BV(CS00); // No prescaling, full 8MHz operation.
TIMSK = _BV(OCIE0A); // Timer/Counter0 Output Compare Match A Interrupt Enable
// Analogue init.
ADCSRA |=
_BV(ADEN) | // ADC Enable
_BV(ADPS1) | _BV(ADPS0); // Div 8 prescaler
// Enable interrupts.
sei();
// Main loop.
for (;;)
{
// ** Get user input **
}
}
ISR sample update code, the sample is set as the PWM output, the sample update code sets it for the next time around:
uint8_t g_sample = 0;
ISR(TIM0_COMPA_vect)
{
// 8 bit playback at 31.25kHz.
OCR0A = g_sample;
// ** Sample update code here **
}
Not the most cutting edge audio player, 8 bit and no fast buffering of any kind but good enough for now. The sample generation code is tricker than expected; using an ATTINY45 means that efficient multiplication is not an option I’m in bit-hacking domain.