Categories
Blog Electronics

Drum synth fast PWM

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.

Leave a Reply

Your email address will not be published. Required fields are marked *