DOS Synth - Powerful, Hands-on DIY Synthesizer
Final board with microcontroller connected.
This is a project created for the RISC-V design challenge, based on the CH32V307 RISC-V microcontroller running the RT-Thread real-time operating system. The project’s aim was to create a synthesizer which would be able to use recycled chips from vintage computers and consoles to create a powerful, available and low-cost system aimed at beginners in both electronics and music synthesis. These old synthesizer chips are controlled through large register sets which are usually completely hidden to the end user. Through this project, using the powerful capabilities of the CH32V307 and RT-Thread, these old synthesizer chips can be explored fully, with every single one of their settings available to be controlled through potentiometers and a graphical interface. This level of control has never been available before, and the system controlling it enables the use of many of these synthesizer chips at once, opening up the ability for musicians and programmers to create compositions with as many synthesized instruments as they have synthesizer chips.
New video with YM2612:
The synthesizer features a graphical interface with a 2.8 inch TFT color display, four potentiometers, two buttons, a MIDI-IN connector and a 3.5mm audio out connector. The sound is created through sound boards, which are small PCBs that contain a synthesizer chip and supporting circuitry. The main purpose of this project is to enable not only the exploration of synthesizer chips, but the usage of multiple ones, even of different kinds, simultaneously. Currently, because of availability, only YM3812 chip support is demonstrated, however it is possible to control other chips as well, including:
- YM2413 (OPLL)
- YM2151 (OPM)
- YM2612 (OPN2)
- YM3438 (OPN2-C)
- YM3526 (OPL)
- YM3812 (OPL2)
Because of the use of a standard 8-bit data bus, it is also possible to write code to interface non-Yamaha synthesizer chips, most notably the SN76489 and the MOS 6581/8580 SID chip.
Since none of these chips are produced anymore, it is expected that the user will source them either from their old vintage equipment, which often contains these chips, or purchase them online. A positive side effect of this is the reduction of both old e-waste, and the usage of parts the user already has, rather than brand new ones, which would contribute to more waste being eventually created. The design and color scheme, as well as the name, are inspired by the MS-DOS operating system, which ran on computers that usually had the YM3812 chip installed, in the form of the AdLib sound card. The reason the YM3812 was chosen as well, is the fact that AdLib sound cards and derivatives were very common, thus they can be found very easily, and many users may even have them at home.System Overview
One of the main design goals of the project was modularity and the possibility for the user to build the project using any method they wish. The example provided uses two YM3812 chips on custom PCBs (not required), mounted on a perfboard with the rest of the components connected, however that is only what was most convenient for me. Modular schematics are provided, and with a little hardware and software modification, any combination of chips is possible.
The TFT display shows the value of each register of the chips controlled, and a menu provides simple navigation using the two buttons. On each page four registers are shown, and each can be controlled through a potentiometer.
The synthesizer chips on the boards are controlled through a serial-to-parallel converter and some control signals. Due to the chips being TTL-compatible, interfacing them with a 3.3V system is not an issue. Because of the similarities of the control signals for the chips, them being made for an 8-bit data bus, connecting many chips only involves adding one more line (as a chip-select/write-enable), and potentially another address signal (for the more advanced chips).Construction
Through optimization of slew rates and peripheral speeds, this circuit can be built on a PCB, perfboard and even breadboard. By following the schematic and the list of connections, any reasonable construction method is usable. The schematic shows the bare microcontroller itself being used with surrounding components to control the system, however it is recommended for the builder to use the CH32V307 evaluation board, and the board is listed in the BOM. The board contains some supporting circuitry and power regulation that would only increase the BOM if the chip was used on its own. Still, the connections to the microcontroller in the schematic are the same as the ones with the board, which is why the microcontroller itself was used in the schematic, while enabling those who want to design their own PCB to apply the schematic directly.
In the example design, each YM3812 sound chip has its own board and supporting circuitry, however it is also possible to simply place the chips on a breadboard/perfboard with their supporting circuitry, and even reuse parts of it for multiple chips, such as the clock generator and serial-to-parallel converter. The design for the YM3812 PCB is provided, and the PCB contains a header to attach to the main board.
All of the chips in the project (apart from the ones on the CH32V307 board) are intentionally in a DIP packaging, to allow the usage of sockets, which are optional, but recommended. This is particularly important with the YM3812 and Y3014B chips for the sound generation, as they can die from their old age, even though in my experience this is rare.
To conclude, even though a perfboard following the schematic was used in the example, it is possible for the user to use any possible combination of construction techniques, including simply even connecting all the parts with wires floating in the air, provided the sound chips have their own PCBs. These are the connections necessary for a minimal working system:
- PA1 -> ADC1
- PA2 -> ILI9341 LED
- PA3 -> ILI9341 CS
- PA4 -> ILI9341 DC
- PA5 -> ILI9341 SCK
- PA6 -> ILI9341 MISO
- PA7 -> ILI9341 MOSI
- PA8 -> ILI9341 RST
- PB11 -> UART RX
- PD1 -> Left button
- PD2 -> Right button
- PD3 -> CD4051 A
- PD4 -> CD4051 B
- PD5 -> CD4051 C
- PE0 -> YM3812 SDA
- PE1 -> YM3812 SCK
- PE2 -> YM3812 WR/CS
- PE3 -> YM3812 A0
- PE4 -> YM3812 IC
For more details, follow the provided schematic.How The System Works
As power is connected and the power connector on the board (provided it is used) is set to "on", the CH32V307 initializes the display and the chips to a predetermined state. The CH32V307 keeps a copy of the register set of each of the chips it controls, called a shadow register set. Every 100 milliseconds, the code polls the potentiometers and buttons, which have their own callback functions. The button presses change the current menu page, and each menu page sets the potentiometers to have a different callback function, relating to the registers associated with that menu page. For example, in the menu which is supposed to change the parameters Attack, Decay, Sustain, Release (ADSR) - each change in the position of Potentiometer 1 will change the Attack, Potentiometer 2 will change the Decay and so on. However, only if the microcontroller detects a significant enough difference in the potentiometers are the values changed. This protects from noise, small accidental brushes and unwanted changes to the registers. When a difference is detected, the microcontroller updates both the value of the register in the shadow register set, and the selected chip's own register set.
Initial shell, with interrupt logged.
The microcontroller also checks the UART peripheral for any received MIDI messages and uses them to play appropriate sounds. MIDI is a protocol for connecting synthesizers together, and is mainly used to enable one keyboard to control another synthesizer, defined as simply 31250 baud UART. Due to the high costs and difficulties of building a DIY keybed, MIDI was used, as most musicians have a MIDI-capable keyboard. For testing (and potentially sequencing) purposes, sounds can also be controlled though the debug shell, which can also perform tests and give back information on events in the system.
My phone camera has difficulties capturing the darker green text, however in real life it is very visible.
The microcontroller communicates with the display through SPI, set at a low enough speed to allow usage on a breadboard. The display is set to use a color scheme that is aesthetically akin to the MS-DOS operating system, and for aesthetic purposes all of the menus are drawn as ASCII art.
The sounds from the YM3812s are mixed with an operational amplifier, and for each additional YM3812 only another resistor of the same value as in the schematic needs to be added, in a standard operational amplifier active mixer setup. The mixer circuit also gives low-pass filter functionality. For driving headphones from the 3.5mm audio connector, it is recommended to add a 330 ohm resistor in series with a 10uF capacitor, to block DC and increase the resistance, so as to not damage them. However, most musicians would want to connect their 3.5mm audio jack to a separate audio mixer, in which case the resistor and capacitor are unnecessary.RT-Thread and the Code
Through the RT-Thread RTOS' extremely powerful scheduling and threading systems, coupled with an interrupt-driven system design, the main loop of the synthesizer code is completely empty! Everything either runs on software timers, interrupts or is automatically handled by the microcontroller's powerful peripheral set. This means that the system is deeply expandable and more code and functionality can be added easily. The code as it is now only uses about 63KB of flash memory, meaning that most of the rest is free to be used for added code, presets, capability for other synthesizer chips and more.
All the code is split into separate header files of variable length, depending on how complex their task is. The main "hotspots" are the YM3812 and ILI9341 code, with most of the other headers being quite small.
The entire main function.
The code is extensively commented, while some parts like low-level driver code contain less comments, as they are not meant to be changed.Story
The idea behind this project came from my experimentation with old synthesizer chips. I had seen them in many old systems, usually with some of the system being broken, however all of the sound worked. I had felt that these retro music-making devices had been left to decay, even though they could be used to make unique sounds. For most of these vintage synthesizer chips, regardless if they come from a broken music keyboard or computer, documentation is available and they are easy to control.
This gave me the idea to create something with which they can be controlled, however due to the specific needs of the chips, I could not find microcontrollers suitable enough to truly open up the chips for detailed usage, particularly for experimenting with their more obscure settings, which can create strange sounds as well. Once I found the CH32V307, I felt that I had found the ideal microcontroller for this purpose, as it could not only drive a display to show all the settings being changed, but it could also control a large number of these and contained features which would make life significantly easier for programming and storing the complex register sets these chips have.
I designed a PCB for one type of chip and ordered it well in advance (as in my country receiving PCB ordered from other countries takes 2-3 months). While I was initially unsure of my knowledge of real-time operating systems, I found that once I began using RT-Thread, code became significantly easier to write, and without RT-Thread this project would have been much more difficult to make. With an RTOS, programming on microcontrollers becomes an almost desktop-like experience, and I realized that I could just add C standard libraries in most places, provided I don't go overboard.
The project was designed and programmed over the course of a few weeks, despite a setback in the form of a lightning strike destroying much of my equipment. Finally, after a few weeks of work, including learning the WCH libraries and RT-Thread, I built a system that I felt confident with, and that I used to play some music myself, and found myself enjoying it very much.Contributing
One large difficulty I found when learning RT-Thread was the clunky English used in many of the explanations, and for this reason I decided to overhaul and rewrite many parts of the documentation, particularly the most important ones - regarding threads, which people are likely to see first and which will color their experience of RT-Thread itself. This led me to do hundreds of changes on many of the pages of the documentation, and I plan on doing more, both during the contest and after it. A common complaint I found online was that the documentation was difficult to read, and my plan is to help in fixing that. My contributions so far have all been accepted and merged into the official RT-Thread repository.