Download free music MP3s on genuine quality, the world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, The world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, stats, charts, biographies and concerts. stats, charts, biographies and concerts.
Monday, July 14, 2025
Arduino and AY-3-8910 – Part 4
After Part 3 I started to go back and add MIDI, and changed the waveform on the touch of a button, and then started to wonder if I could add envelopes and so on. And then it occurred to me, I didn't really need to re-implement my own synthesis libra…
After Part 3 I started to go back and add MIDI, and changed the waveform on the touch of a button, and then started to wonder if I could add envelopes and so on.
And then it occurred to me, I didn't really need to re-implement my own synthesis library, I could probably write a custom audio output function for Mozzi and get it to use the AY-3-8910 as a 4-bit DAC...
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
These are the key tutorials for the main concepts used in this project:
Either GadgetReboot's PCB or patch using solderless breadboard or prototyping boards.
5V compatible MIDI interface.
Jumper wires.
Mozzi Custom Audio Output
Mozzi supports a wide range of microcontrollers with a range of different output methods from PWM, built-in DACs, I2S, through to custom output options with DMA or something else.
The key option for me is MOZZI_OUTPUT_EXTERNAL_CUSTOM. There are a number of configuration options that must be set prior to include the main Mozzi file as follows:
This sets up the audio synthesis parameters to 8 bit audio with a sample rate of 16384Hz.
Implementing a custom audio output this way requires two functions. One for the audio output and one to tell Mozzi when it is time to call the audio output function.
I would rather have used MOZZI_OUTPUT_EXTERNAL_TIMED which handles the calling at the correct AUDIO_RATE for me, but that relies on the use of the ATMega328's Timer 1, but in this case Timer 1 is providing the 1MHz clock for the AY-3-3810.
But rather than implementing yet another timing routine, I just used the micros() counter to decide if it was time to generate audio or not.
void audioOutput(const AudioOutput f) { int out = MOZZI_AUDIO_BIAS + f.l(); ayOutput(0,out); }
unsigned long lastmicros; bool canBufferAudioOutput() { unsigned long nowmicros = micros(); if (nowmicros > lastmicros+58) { lastmicros=nowmicros; return true; } return false; }
To get samples produced at the required 16384Hz sample rate means there needs to be one sample produced 16384 times a second. There thus needs to be a sample every 60uS. If I implement the above function checking for nowmicros > lastmicros + 60 then the resulting sound is slightly flat (in tuning). I'm guessing this is related to the overheads of the function call and logic, so I've gone with lastmicros+58 and that sounds pretty good to me.
My ayOutput() routine takes an 8-bit sample and cuts it down to the 4-bits required for a level on the AY-3-8910.
FM Synthesis on the AY-3-8910 (sort of)
I wanted to try the FM synth mode just to see what would happen and thought it would be interesting to switch between the carrier sine wave signal and the modulated signal by pressing the button.
Unfortunately, I just could not get the button logic to work, even though I could see the state of the pin (A5) changing.
Finally after an hour or so of puzzling why such an apparently simple test of logic wasn't working, I realised what the issue must be. Mozzi, for the AVR microcontrollers, has its own fast ADC routines. It turns out that these were interferrng with using A5 as a digital input pin.
It is fairly easy to override the Mozzi fast ADC though by setting MOZZI_ANALOG_READ to NONE.
The Mozzi code has a carrier and modulator waveform running at audio rate and an index running at the control rate to bring the modulator in and out.
It is just about possible to see the FM modulation on the oscilloscope as shown below.
Of course, the AY-3-8910 isn't actually doing FM synthesis itself. It is just acting as a 4-bit DAC, but it is still quite fun to see.
Find it on GitHub here.
Closing Thoughts
This is all getting a little pointless really, as there is nothing being done that the Arduino Nano couldn't do better on its own, but it is a bit of fun to see where this thread ends up.
There are a number of interesting angles now. One of which would be to utilise all three channels. This could provide a form of additive synthesis, it could perform some fixed interval additional oscillators, or it could be used for 3-note polyphony.
Now that Mozzi is running it is also possible to do anything Mozzi can do, and that includes implementing envelope generation.
No comments:
Post a Comment