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.