I'm writing a MIDI - to square wave converter designed to interface between a MIDI instrument and a musical Tesla coil. Essentially, this should act like a monophonic MIDI synthesiser, but the requirements are slightly different to most projects:
- I only want to generate (audible frequency) square waves.
- It is essential that the pulse on time not exceed a configurable constant value, e.g. 160 microseconds.
- I'd like to map the 'velocity' of a given note to the duty cycle, scaled appropriately.
- Ideally, I'd like to generate envelopes for the pulse width with configurable attack, decay, sustain, release parameters.
- I'd like to write the audio generation code "from scratch" for the sake of my own understanding of how timing registers work.
The gist of what I want is this (untested) sketch, but it obviously doesn't allow for control of the on time.
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
const static int out_pin = 9;
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
tone(out_pin, pitch);
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
}
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
noTone(out_pin);
digitalWrite(13, LOW); // turn the LED off
}
void setup() {
MIDI.setHandleNoteOn(handleNoteOn);
MIDI.setHandleNoteOff(handleNoteOff);
MIDI.begin(MIDI_CHANNEL_OMNI);
}
void loop() {
// put your main code here, to run repeatedly:
MIDI.read();
}
My question is essentially, what the best way to achieve this kind of musical pulse-width control is. The ideas I had were either a) A large number of manual register-sets to bit-bang the required signal out at the highest frequency I can get, probably in the kHz b) Create each pulse using a custom pulseOut function, using timer0 for microsecond delays
I'd also be open to using external analog circuitry, e.g. a voltage controlled pulse shortener.
The load here is an LED, so no special allowances need to be made for its behavior.