Hey all, sorry about the delay. I've uploaded a preview video of my homemade Arduino YM2151 here (also has some chill background music); turn on captions if you have trouble hearing me, and keep in mind I mistakenly say "ampersand" when I clearly mean "exclamation point." I'll be uploading my sketch and Fritzing soon, just gotta finalize the wiring to fix any looseness.

For what it's worth, the original Ishii downloads can be found at his old Googlesite.

Charbot wrote:

Great.   You should post your final schematic and code.

Yea, I'm Fritzing-ing the board currently and will GitHub the cleaned up code after.

Charbot wrote:

You will prob want an amplifier of some kind to drive a speaker (effectively).   Personally, Id have at least a line out jack on there too, for  if you every wanted to record or perform/play at any volume

Re amplifier - would it connect directly to the 3 OUT and 4 OUT of the op-amp or does it need to be after the capacitor like the stereo jack?

Re line out - wouldn't the existing stereo jack and circuit work for line out or would I need a different jack and circuit?

Update: I got it to work!!!! I had read the MSX expansion sound card SFG-01/05 schematic today (here, here, here, here) and the key wiring difference between the SFG schematic and previous incarnations of the Arduino/Raspberry Pi YM2151+YM3012 schematic I've read (especially any based off the original design) is the wiring to the op-amp.

Basically, other than the photocoupler wiring which is apparently used for the MIDI input that would drive activation of the overall circuit, every non-SFG schematic had one significant thing different from the working SFG-based approach I used: the YM3012-to-op-amp connection was wired differently.

Every non-SFG schematic had op-amp 1 output bridged with op-amp 1- and one connection to YM3012 pin 13 (V/2 or MP) bridged with pin 14 (BIAS1 or BC). YM3012 pins 9 (ch 1) and 10 (ch 2) connected to op-amp 3+ and 4+ through resistors in series, with capacitors as noted.

The SFG had both sides of the YM3012-to-op-amp 1 connection unbridged, op-amp 1 output to YM3012 pin 13, and op-amp 1- to YM3012 pin 14. YM3012 pins 9 and 10 connected directly to op-amp 3+ and 4+ without any resistors in between, with relatively no change to locations of capacitors in the circuit.

Regarding the op-amp-to-audio output, I found that one could get similar working results by either connecting the final capacitor's ground to the audio output's channel in series or by grounding that capacitor and instead connecting the final resistor to the audio's channel. In practice, I could not perceive any significant difference in resulting audio volume through the headphones.

So! After connecting the membrane button strip, my final step before eventually putting everything into the piano housing is to connect the audio output to speakers. I have two 4 ohm 3W piezo speakers that as of yet do not work with the circuit I as I currently have it. How should I fork the op-amp's output to successfully play through the speakers? Do I need an external amplifier circuit like this MAX98306 I bought from Adafruit and if so what's the recommended wiring from the op-amp to the MAX98306?

I switched the wires and code back to the direct I/O version and swapped back in the 3.5mm stereo jack with headphones instead of LED. Still no audio output and while running Serial Monitor ym_read (and the read status loop) still returns the last data written by ym_write.

@Charbot - I would love to eventually do something like that, but I'm limited to what I currently have (all the pieces from the original BOM without MIDI) due to money reasons. To actually have enough I/O pins for my project (which also includes an LCD shield that has an MCP of its own, so no extra pins needed) I had a choice between hooking the YM or the 5*8 membrane buttons to the MCP and I chose the YM, though nothing is soldered in stone yet so to speak. I tried doing the original schematic and code with direct port manipulation but no sound came out, and the only MIDI keyboard I have is a Korg K49 USB MIDI keyboard.

I know the pins themselves and the MCP work because everything but the sound generation actually does what I intended.

Hey dudes! Fair warning, somewhat long post ahead.

I'm trying to build an Arduino YM2151 of my own, but I have an Uno R3, Protoshield v6 R3, and am using an MCP23017 because I need the inputs for a 37-key "keyboard" (5*8 multiplexed membrane buttons, to be exact, from a $30 "toy" electric piano from Rite Aid). I do not have the optocoupler anywhere in the circuit, as I don't see where in the original schematic it connects to the actual YM2151+YM3012+op-amp+audio output section of the circuit. I'm prototyping on a breadboard until I get audio.

The problem I have is I'm not getting audio!

I've spent a few hours cutting new wire because apparently my jumper wires from the YM3012 to the TLC2274 op-amp were frayed or something and I'm going over my code, modified from the various updates of the original Yukio Ishii code because I'm not doing direct I/O. The key difference is using the MCP for I/O instead of direct Arduino port manipulation, and my MCP-based ym_write is below:

// ... stuff ...

#define   RD_HIGH   (ym_pin_mask = ym_pin_mask | MUX_YM_RD)
#define   RD_LOW    (ym_pin_mask = ym_pin_mask & ~MUX_YM_RD)
#define   WR_HIGH   (ym_pin_mask = ym_pin_mask | MUX_YM_WR)
#define   WR_LOW    (ym_pin_mask = ym_pin_mask & ~MUX_YM_WR)
#define   A0_HIGH   (ym_pin_mask = ym_pin_mask | MUX_YM_A0)
#define   A0_LOW    (ym_pin_mask = ym_pin_mask & ~MUX_YM_A0)
#define   IC_HIGH   (ym_pin_mask = ym_pin_mask | MUX_YM_IC)
#define   IC_LOW    (ym_pin_mask = ym_pin_mask & ~MUX_YM_IC)

#define MCP_LED_HIGH 0x80
#define MCP_YM_STATUS 7

// ... stuff ...

//// on MCP23017, set A pins have YM2151's IC, A0, WR, RD, and an LED
//// set B pins have YM2151's 8 data pins

void ym_write(byte addr, byte data) {
    //// TODO: wait for not busy
#if DEBUG_YM
    Serial.print("ym_wr:"); Serial.print(addr,HEX); Serial.print(","); Serial.print(data,HEX); Serial.println("...");
#endif
    bool waiting = 1;
    unsigned wait_limit = 64, wait_i = 0; // hard-limit status waits to prevent potential infinite loops
    byte can = MCP_LED_HIGH;
    mcp.setPinModes(0, 0xff); // set I/O A pins to output/write, B pins to input/read
    A0_LOW;
    RD_LOW;
    mcp.write_one_a(ym_pin_mask|can);
    wait(4);
    while (waiting) {
        wait(4);
        //RD_LOW; // commented out because don't need?
        mcp.write_one_a(ym_pin_mask|can);
        wait(4);
        can = mcp.read_one_b();//&_BV(MCP_YM_STATUS);    // ym_read_pin(D7) returns 1 while busy
        //RD_HIGH; // commented out because don't need?
        mcp.write_one_a(ym_pin_mask|(can&_BV(MCP_YM_STATUS))); // light LED if busy
        wait(4);
#if DEBUG_YM
        Serial.print("...wait:"); Serial.print(wait_i); Serial.print(","); Serial.print(can,HEX); Serial.println("...");
#endif
        if (can==0) {waiting = 0; /*Serial.print(wait_i); Serial.println(":done waiting");*/}
        else wait(4);
        wait(12);
        ++wait_i;
        if (wait_i>16) wait(4);
        if (wait_limit) {
            if (wait_i>wait_limit) waiting = 0;
        }
    }
    wait(4);
    RD_HIGH;
    mcp.write_one_a(ym_pin_mask);
    wait(4);
#if DEBUG_YM
    if (wait_limit&&wait_i>wait_limit) Serial.println("Too long reading, early break");
#endif
    mcp.setPinModes(0, 0); // set I/O A pins to output/write, B pins to output/write
    A0_LOW;    // addr mode
    mcp.write_one_a(ym_pin_mask|MCP_LED_HIGH);
    mcp.write_one_b(addr);
    wait(4);
    WR_LOW;
    mcp.write_one_a(ym_pin_mask|MCP_LED_HIGH);
    wait(4);
    WR_HIGH;
    mcp.write_one_a(ym_pin_mask|MCP_LED_HIGH);
    wait(2);
    A0_HIGH;    // data mode
    mcp.write_one_a(ym_pin_mask|MCP_LED_HIGH);
    wait(2);
    mcp.write_one_b(data);
    wait(4);
    WR_LOW;
    mcp.write_one_a(ym_pin_mask|MCP_LED_HIGH);
    wait(4);
    WR_HIGH;
    mcp.write_one_a(ym_pin_mask);
    wait(2);
}

The debug serial prints are telling me that the status loop at the beginning of ym_write isn't executing properly, usually displaying the value of the previous data write as if it was latched by the MCP or something before write instead of the proper status value. I also have an LED attached to the two audio outputs that's glowing a constant dim red as if there's some modulated output.

Anyone here have any ideas on how to fix it?

Aly James wrote:

IIRC I remember to tweak your java web based operators one years ago smile .I'll b glad to share my CSM documentation if needed wink

I really do need to go back and fix the JavaScript YM2612, it's actually quite broken. I must have gotten something basic completely wrong and I left it sit all this time.

Aly James wrote:

by the way it can be cool to add tfi >> opm and opm >> tfi to your converter smile in this case your blank windows on the right could display whats in the presets...

I did plan on adding format conversion to a future version, but didn't yet have an idea for where to put it on the interface. That's a good idea, thanks!

Aly James wrote:

knowing your YM2612 involvement, If you want to help at some point, just PM me wink

No problem, and if/when I get my MacBook Pro up and running again I'll definitely be doing something along the lines of a YM2612 AU myself smile

@Aly James - for porting to Mac you'll basically need a "programmed completely in C++ and/or Obj-C" solution since there's nothing like SynthEdit (though IIRC there might be a Mac version of Outsim SynthMaker, a tool far superior to SynthEdit). Given how much custom code you've made from scratch it might actually be easier to port since the syntax is almost one-to-one. XCode is free and almost any SDK you choose (Apple's Audio Unit SDK, JUCE, VST) will be free.

12

(2 replies, posted in Sega)

Hello all! I've posted this elsewhere, and only now it has occurred to me that I've sadly neglected to include chipmusic.org...until now!

I present VGM2PRE, an open-source FM instrument preset dumper inspired by shiru's VGM2TFI utility! Currently it takes VGM/VGZ files that contain YM2612 events and converts any FM presets to files usable in FMDRIVE, GENNY VSTi, TFM Maker and VGM Music Maker, MVS Tracker, DefleMask, the Echo Sound Format, and MID2SMPS; each of those formats can be toggled on or off. Planned enhancements include dumping
YM2151 presets to OPM format for VOPM and dumping AdLib presets to AdLibTracker-compatible formats, among other things.

Source to build from scratch/on non-Windows (MIT licensed, GCC>=4.7.1, also MinGW compatible): https://github.com/vgmtool/vgm2pre

Stable versions (no GUI):
32-bit Windows binary
64-bit Windows binary

Testing versions (GUI, newer than stable):
32-bit Windows binary
64-bit Windows binary

The GUI is not finalized, but it's usable. The following menu items are usable:

  • File->Open File: Dump from a single file.

  • File->Open Directory: Dump from VGM/VGZ files in a single directory.

  • File->Quit: Quit the program.

  • Tools->Preferences: Toggle which formats get dumped for the given chips. Disabled checkboxes mean those formats aren't supported yet.

  • Help->About: Show program info.

You can also drag-and-drop multiple files and/or directories at once onto the GUI instead of opening one file/directory at a time. The list view on the left will update with the list of files that will be processed then the "Dump" button on the bottom will be enabled. Clicking it will dump whatever formats were checked on in the preferences if a given chip can dump to those formats (eg, VGI can be dumped from YM2612 but not from YM2151 for now).

Once I clean up the GUI I'll update the stable version. Meanwhile, I'm open to constructive suggestions on what info could be added to the right column in the GUI. The tool is currently standalone, but I'll very likely add this functionality to the eventual update of VGMTool.