Sound on an AY-3-8910 chip (or Yamaha YM2149F) comes from the ZX Spectrum on a PC via USB

    About a year has passed since the successful connection of the YM2149F music synthesizer to the LPT port of the computer . LPT is certainly good, but time does not stand still, and finding a computer or laptop with an LPT port is becoming more and more difficult. Yes, and the author himself (that is, I) was tired of climbing every time under the table where the system unit is standing, and sticking the LPT board onto something else, for example a programmer (I have a Willem LPT programmer, well, that’s not the point). Therefore, this time we will connect the YM2149F chip to USB. And of course, in order to meet the era, we will do it on the penny ancient microcontroller PIC16F628 .

    image

    In short, YM2149F (or its functional counterpart AY-3-8910) - a three-voice synthesizer microchip used in old computers such as Atari ST, Amstrad CPC, ZX Spectrum, MSX and some others for playing music. In Russia, the chip has gained some fame due to the installation in various clones of the ZX Spectrum. During the procession of the ZX Spectrum in the former USSR, musicians wrote thousands of tunes for this sound programmable generator. And now you can quite find people creating music specifically for this chip. At the end of the article, links will be given to the huge archive of chip tunes for YM / AY for hundreds of hours of continuous listening.

    Demo


    Like the last time, before starting, I immediately give a link to listen to the final result: https://soundcloud.com/tronix286 The latest entries are made just from this device. I recorded it so-and-so with a player that writes a maximum of 128Kb / s MP3, so in reality the device sounds “brighter”. But a general idea of ​​sound is possible.

    Iron


    Why such a strange choice of controller? Why not AVR / ARM / iCore i7 / FTDI at worst? Partially the answer to this question is given at the beginning of the topic: to the retro synthesizer - a retro microcontroller! Moreover, AY-3-8910 and Microchip, we can say, have common roots. In general, this is a series of strange circumstances. Firstly, I stumbled on the Internet on a library that implements the software (software) USB 1.1 stack for PIC16F628 microcontrollers - this library: 16FUSB . Secondly, a couple of PIC16F628A, which I did not know where to put, had been lying and gathering dust for a long time. Thirdly, the computer already had configured software (MPLABX, MPASM) and there is a programmer for PIC. Well, unlike the V-USB software stackOn AVR, known to many, on PICs without hardware USB projects, there are few or even none at all. And this means that historical injustice must be restored.

    Here is a typical inclusion diagram from the 16fusb library site:

    image

    The 16fusb library comes with a good example called “direct-io”. The meaning is simple - send via USB byte and it is "displayed" on eight legs of the microcontroller. You can also send an additional two control signals, that is, two more bits (or two legs). And in the opposite direction, that is, from the controller to the host (computer).
    image

    An eight-bit data bus D0-D7 and three control signals BC1, BDIR and RESET are used to control the YM2149F. BC1 and BDIR control the choice of the register address and its value, as well as put the chip in an inactive state. The RESET signal is used to reset all registers to their original value. Thus, reading from the PIC to the computer is not necessary; all you need is the ability to send commands to YM. And we need another third control signal, which means another MK leg.

    In its firmware for controlling specifically YM2149F, the following was done:
    • everything that is connected with reading signals from the PIC to the host (computer) is thrown to increase the speed of processing USB requests;
    • the state of the directions of the input-output ports is hard-set during initialization of the MCU and does not change in the procedures for issuing a byte to its feet.
    • a 64 byte ring buffer is organized. When decoding a request from the host, the bytes are added to the buffer. When there is free time, data from the buffer is issued on YM.
    • optimized speed of issuing bytes to MK legs. Partly due to the hard-pointed I / O directions, partly due to the fame of the previous state of the control bits.
    • fixed a bug with PIC looping through several thousand packets (the RxLoop loop in the isr.asm file is deployed, instead of goto RxLoop, a check for the sign of the end of the packet is inserted)
    • something else i don't remember


    As mentioned above, there is a need for another control signal - RESET, and there are no more free legs. Therefore, a quartz oscillator, rather than quartz, was used to clock the PIC, thereby releasing one MK leg (RA6) needed to control the RESET signal. Leg RA5, sticking out in the air, in this family works only on the input and cannot be used to control the output signal. It would be possible to shift the functionality for catching the end of the USB packet (EOP) from the RB2 leg to it, but this is not so simple - unlike the RB2 leg, the RA5 leg shares the functionality with MCLR and VPP for programming and the input is organized inside as a Schmitt trigger. He simply does not have enough voltage after the diodes to trip. On the other hand, for clocking the YM2149F, an oscillator based on a 74HC02 chip and 3.579545 MHz quartz was assembled. One could try to use the second free half of the microcircuit to build a similar generator and for PIC, but it stopped two things: 1) I do not have 24 MHz crystal (and there was a crystal oscillator from some ancient mother) 2) I do not know how 74HC02 will behave if it has different frequencies from “different sides”, and one of them is quite high (24 MHz is still a very high frequency). Another option for freeing the RA6 leg for quartz: BC1 and BDIR signals only take these values: and one of them is quite high (24 MHz is still a very high frequency). Another option for freeing the RA6 leg for quartz: BC1 and BDIR signals only take these values: and one of them is quite high (24 MHz is still a very high frequency). Another option for freeing the RA6 leg for quartz: BC1 and BDIR signals only take these values:

    BC1    BDIR
     0       0
     0       1
     1       1
    

    And never BC1 = 1, BDIR = 0. This can be used as RESET by adding NOT and NOR logic from the half of the 74HC02 chip and inverting the output signal using a transistor. Of course, to issue BC = 1 and BDIR = 0, you need to tweak the firmware a bit.

    And yet, the RA4 leg, which controls the BDIR signal, is with an open collector, so it must be pulled up to the power supply - in the diagram it is a 10K resistor R5.

    Software


    On the computer side, an excellent cross-platform player for the ZX Tune chip tunes acts as a music player :

    image

    Directly, it does not support USB, but if it finds one of the dlportio.dll / inpout32.dll / inpoutx64.dll libraries in its directory, then allows you to switch in the sound output settings to YM-LPT ( for the previous project), and then uses the __stdcall void function DlPortWritePortUchar (unsigned short port, unsigned char val); for issuing bytes YM2149. Port 0x378 data, Port 0x37a transmit control signals (D1 - ~ BDIR, D2 - BC1, D3 - ~ RESET). Thus, you can write a small stub library with one single function, DlPortWritePortUchar, in which to redirect the output of bytes to a USB device, which was done. I just took the source code of the inpout32 library as a basis and wrote a stub function to redirect the output of bytes to this device. As a result, it is enough to put this stub library inpout32.dll or inpoutx64.dll , depending on the version of the player (x86 / x64) used, in the same directory with the ZX Tune player, launch it and in the sound settings move the aylpt device to the very top (as in the screenshot above).

    Download for free and without SMS


    Drivers for Win XP, Win 7 (x32 / x64) can be downloaded here: 16FUSB_driver-libusb-win32-1.2.6.0.zip Device

    diagram: ym-usb_scheme_1.0.rar
    Compiled firmware (.hex) and compiled DLL stubs: ym -usb_firmware_and_DLLs_v1.2.rar
    starting firmware codes: ym-usb_PIC16F628A_source_v1.2.rar
    starting library stub codes: inpout32-64_DLL_source_v1.2.rar
    General Instruments AY-3-8910 / 8912 Sound Generator Programmable (PSG) data Manual: http: //bulba.untergrund.net/AY-3-8910.rar
    Topic on the ZX.PK.ru forum from which the device was “born”: http://zx-pk.ru/showthread.php?t=22202

    Huge archive Tracker Music: Modland (FTP )
    ZX music online: http://zxtunes.com/

    Good to all!

    Also popular now: