📜 ⬆️ ⬇️

Old school, hardcore, AY-3-8912. "Iron" chiptune with sequential input



Clone Spectrum 128K, equipped with a music coprocessor AY-3-8910 (YM2149F) I did not have. There was 48K with an extended keyboard and a poor power supply that overheats the insides in an hour or two of work. From this, I remember. houses in the middle of the sea in Sim City were formed and other funny artifacts. But these memories are irrelevant. Inspired by the tronix286 material , I decided to fill the gap in retro-education and rivet something on the legendary (and at the same time, easily mined and inexpensive) chip.

During the study of various handicrafts, the idea was formed as follows: it is necessary to make a module with a serial (UART) input. So that it can already be connected with minimal cost to any device, thereby adding +146 to the chip tune. In the process, it was also decided to master a couple of additional skills, such as programming AVR and making printed circuit boards using photoresist.
')
I will immediately describe the results: the module has been developed and crooks, side skills have been pumped up, rakes have been collected, you can be happy, expand and deepen.

Synthesizer

AY-3-8910 is a big beautiful 40-foot DIP chip. In addition to the necessary things, there are two more 8-bit ports that are not used by normal people (who are not trying to make a hellish analog of Covox) for sound output. AY-3-8912 is not less beautiful, but one “extra” port is deprived and packed already in DIP28. And still happens AY-3-8913, generally without a parallel port (DIP24). And this is only General Instrument / Microchip. Yamaha riveted even more variations: from YM2149F (analogue AY-3-8910 with a clock frequency divider) to YMZ284 (DIP16, one mixed output channel). Learn more about chips on the wiki .

Control

To download data using an 8-bit parallel port. Plus, three control lines (one, which is BC2, we pull up to the power supply). The logic is as follows:

1. The initial state - BC1 = 0, BDIR = 0.
2. Set the address of the register on the legs of the port AY.
3. BC1 = 1, BDIR = 1. Download address. The delay between switching on the lines should be no more than 50 ns, so any slow twitching of the legs (such as Arduinsky DigitalWrite) is not suitable, for example, PORTC | = 0b00110000;
4. BC1 = 0, BDIR = 0.
5. Set the value of the register on the legs of the port AY.
6. BC1 = 0, BDIR = 1. Loading values.

Repeat the sequence 14 times (for each desired register). And all this - 50 times per second. We get the music.

Choosing a specific iron

In my case the following:
1. AY-3-8912 - was cheaper.
2. Atmega8A (DIP28) - available, enough conclusions.
3. Quartz oscillator at 4 MHz - for clocking AY.
4. Counter K555IE5 - as a frequency divider for clocking AY.
5. Quartz at 16 MHz - for Atmega8A.
6. For connection to PC - USB UART on FT232R.



Fee divorced just for this business. In the process of debugging and more thoughtful study, the following thoughts emerged:

1. If you use YM2149F, then you do not need a counter, because This chip has a built-in frequency divider by 2.
2. It seems that Atmega does not need quartz either - everything works decently from the internal 8 MHz generator.
3. In theory, you can try to get rid of the quartz oscillator for AY altogether, if you look through the hardware timers and Atmega counters. But! In this case, we can only clock AY at 2 MHz. And in a good way, you must be able to clocking at 1.7 (many digits) MHz - as is done in the Speccy. I have a 4 MHz crystal oscillator in a DIP-block in order to replace it with 3.5 (many digits) MHz.

The sound output is sketched at tronix286 , there are a handful of resistors and two capacitors.

Soft

This inspiration has been studied for inspiration. It describes the general principle of operation of the “source - UART - Atmega - AY” bundle, but the use of the Arduino loader on the mega in this case seemed to me completely superfluous. Well, the program on the PC, written in C #, I did not like. Sharp here is about as “needed” as the Arduino. YM format is laid out here .

Atmega firmware

The source code and hex are available on the githab (link at the end of the material), I’ll just go over the main functions.

valToPort - write an 8-bit value to the “port”, consisting of half port B and half C. It was more convenient to plant.
sendToAY - write an 8-bit value to the AY register. Here the logic described in the “Control” section is implemented.
setup - initialization of ports and UART.
main - looped "get 16 bytes - write to AY".

Demo on PC



Written in Python 3 using PySerial. Like the firmware, it lies on the githaba. Takes the 1.ym file (uncompressed!) From the current directory, parses it and pushes it into COM6. For the sake of interest, the example has been tested on OS X, it works out of the box, you just need to change the port name. I suspect that it will work just as successfully on Linux, incl. on the "raspberry".

In issuing a dump of registers on AY there is one nuance. The YM format stores data in the form of “all register values ​​0, all values ​​of register 1 ...”. This is very correct in terms of further compression. I work with uncompressed YM, and I need to issue packets of bytes "register 0, register 1 ...". For a PC, the problem is solved in the forehead - we read the data from the file in the right order into a large array, then from it we consistently give it to the controller. When you need to make a "head unit" based on a chip with a small memory size, you will have to invent some kind of buffers.

Total

It is worth remembering that before starting playback, it would be nice to reset “megu” and AY. Because if there is something in the controller's buffer, when transferring new data, the entire stream will shift, and the sounds will be truly heartbreaking. A reset pin on the module is provided, but is not used in the demo. The reset is carried out by poking the wire into the quartz oscillator case sitting on the ground.

There is also a misunderstood bug. Which, probably, hides somewhere around "Windows 10 - Python 3 - UART". Periodically, the update rate drops from 50 Hz to 20 (oscilloscoped). The system was not detected in the phenomenon, the glitch was not reproduced on another computer. If I catch sometime, I will do UPD.

In the future, the module will be bolted to the handicraft development, an article about this in the relatively foreseeable future. Well, and to the "Malinka" should try to pick up. There is room for experimentation.

Sources, board layout (SL6), module scheme (Eagle) on github.

UPD1. Convert to YM with AYEmul .
UPD2. Here is taken the .torrent to download the archive Modland.com. There are many.
UPD3. ProjectAY . There is a lot of music in AY. At the time of publication the site lay.

Now everything is more or less cultural

UPD4. 03/18/2015 redid the Atmega code and demo (pythonium). Now the logic is this: Atmega requests data from the host, fills the ring buffer (512 bytes), then as half loses, asks for more (i.e. request points 256 and 512 (0)). The host responds to the request with a packet of 256 bytes, Atmega consumes them through an interrupt handler. Not everything is polished, but it plays much more stable than the original version.

UPD5. I tried on the malinka. Works almost out of the box.
0. Disable the console on the serial port (etc / inittab at the end).
1. comPort = "/ dev / ttyAMA0" (serial port)
2. regState = bytes ([registerDump [currentPos + currByte]]) (so serial.write works fine)

Source: https://habr.com/ru/post/253069/


All Articles