The YM2413 FM OPLL
An update. Finally! This time I've been playing around with FM sound for the MC3. FM sound generation is a bit more complex than my previous sound generation attempt with the YMZ284 (one of the smallest AY-3-8910 / YM2149 clone there is). Ideally I wanted to build a small board that would fit on my MC3 I/O bus. Most FM chips come too big packages for this but after some digging I realized that the YM2413 would be perfect for this. It is a low-cost version of Yamaha's other OPL chips and is often referred to as the OPLL. It comes in a small DIP-18 package! Originally I think it was intended for video and arcade games and it was also used in a few game carts for added sound capabilities. To name a few it was used in the MSX2+, MSX turboR and the Japanese version of the Sega Master System. This is the bock diagram of the YM2413. It has a simple 8 bit bus interface with one address line. A quite common interface for this kind of device. This way the chip has two registers. One for selecting among the 271 internal register bits of audio generating goodies and one for writing data to them. There is no way to read back anything usual from the YM2413 so I consider it as a write only device. On the analog side there are two outputs. One for melody and one for percussion. I suspect the reason for this is to keep them on separate audio paths for filtering and mixing but really all designs I have seen treats them equally and mixes them together. Below is the board I ended up with. It could have been made using fewer chips but as with the YMZ284 board I wanted to isolate the YM2413 from the bus as much as possible. Have a look at the schematics below. U1 and U2 could have been excluded for simplicity but they do wonders for suppressing audible noise from the bus. They also protects the YM2413 from the outside world. On the analog side of the YM2413 I have mixed together the MO (melody output) and RO (rhythm output) signals as suggested in the application manual. They are then fed into a high impedance voltage following TL072 op-amp to maintain as much of the signal integrity as possible. Some designs suggest adding a capacitor to make up a passive low-pass filter to get rid of high frequency sampling products but I did not want to put additional strain on the outputs. This kind of filtering can be done at a later stage if needed. Following the high impedance buffering stage I had to add an amplification stage since the signal levels coming from the YM2413 is actually pretty low. This stage is made up using the second part of the TL072 working as an AC-coupled inverting amplifier centered around Vcc/2. I had to make the amplification a factor of 10 to achieve decent line levels on the output. I was a little surprised about this but looking at other designs this seems to be normal. The output of the YM2413 is a lot lower than the YMZ284. Because of all this amplification the YM2413 is noisier than the YMZ284. But then again, It's a totally different chip. One could reason that given the many channels in the YM2413, more headroom is needed and therefore a lower total output per channel. I mentioned earlier that this was a cost reduced version of the Yamaha OPL. One main reason is that it has 16 selectable instruments out of which only one is customizable. The other 15 are stored in the built-in ROM. This of course reduces the flexibility of the chip but it also makes it easier to get started. The table of instruments can be seen above. Instrument 0 is the user customizable instrument. The others are preset by Yamaha and it's not really a bad thing. They are well made and well known from other Yamaha keyboards and General MIDI. Since FM generation is not very good for creating percussion sounds there is a separate percussion module in the YM2413. It consists of the basic kit of base drum, snare drum, tom-tom, top cymbal and high hat. This is the register layout of the YM2413. FM sound generation can get pretty complex but this is about as straight forward as it can be. Please read the datasheet and application manual for more info. I really wish the application manual had more examples. I still have a lot to figure out. YM2413 datasheet YM2413 application manual

How does it sound?

To get some feeling for the YM2413 and to verify that my design was working I created a music player for VGM files. VGM is an attempt to make a general file format for video game music. It is common for archiving Sega and MSX music among others. Quite a bit of YM2413 tunes exists in this format. Perfect for this project! VGM files in their standard form is a bit heavy for my MC3 to handle so I created an intermediate file format and associated converter and playback programs. The intermediate format is simply a dump of all registers sampled at 50Hz. More manageable for the MC3 than VGM. This is the work flow: [VGM file] ---> [converter program on a Linux PC] ---> [intermediate format] ---> [player program on MC3] ---> [YM2413] The conversion program for the PC is written in C and the player on the MC3 is of course written in assembly. I will put everything online as soon as I have cleaned up the code a bit but for now I will leave you with raw recordings generated by this interface. This is from the game Xak for the MSX2+. Composed by Ryuji Sasai and Tadahiro Nitta. Possibly some of the most well written YM2413 music out there. All files recorded from and generated by the interfaced described above. Town of fearless Battle field Verdant land Evil tree Path to the fort Water dragon Town of Nomana Fire elemental & Water elemental Combined elemental Toen of Nemnu Land of flames and sky Maker message
Transceiver build - part 2
I'm happy to admit that while progress has been slow, the transceiver project is not forgotten. As always, many things are competing for their share of my spare time. It will be finished. Eventually. In part one I presented the basic concept, first prototype and the main analog parts for the receiver (some of which will be used for transmit as well). While I have the basic analog concept working, my transceiver will not be of much use in the shack without a pretty box and a good way of controlling it. This part of the build is about the microcontroller, LCD and buttons. The first thing I did was to locate a suitable enclosure. The loose-boards-all-over-the-desk-design was getting difficult to manage even for a prototype build. Ideally a metal enclosure would be better but I went for plastic simply because it's easier to work with and I'm counting on not getting everything right the first time anyway. One basic requirement I had with this design was that I wanted the ability to control all of the transceiver functions remotely from an external computer. That includes various analog gains and volumes. It would need some extra work but in the end I think it will be worth it. The first prototype used a 4x20 character LCD but I've now changed it to 2x40 character LCD to make better use of front panel surface area. To keep it simple I also wanted to base the logic around the Atmega 328 since it's a very common microcontroller today. It may be a bit under powered for what I want to do but with some efficient code I think I can pull it off. I'm not a huge fan of the Arduino so software will be written in C directly for the Atmega using avr-gcc that hopefully also saves me some program space. Not entirely knowing yet how I want the user interface to work I just mounted a set of eight buttons. There is still room for more if there is a need for it. All buttons are momentary. Also on the front are two stereo jacks for headphones and microphone with PTT button. The inside is divided into two stacks of half size euroboards. The left stack above contains three boards for the RF parts (top board currently empty) and the right side will be a stack of two boards for the digital and audio parts (only the digital board is in the picture). In the space between the stacks I will squeeze in a vertical board for the crystal filters (not sure how many I will be able to fit in there but hopefully at least two). On the rear panel I have mounted three BNC connectors. Not yet sure how they will be used but hopefully switchable antennas and IF in/out. Also on the back is a DB9 for RS-232 that will be connected to the Atmega 328 UART for remote control. Of course there is also a DC-jack. As mentioned in part one of the project I have chosen the Si5351 frequency generator for VFO and BFO. Controlled by I²C it's a good match for the Atmega 328. Adafruit has a nice little board for this chip that contains a pretty decent reference oscillator, I²C level converters and it's own 3.3V regulator. The Si5351 has three outputs but there are actually only two PLLs inside meaning that I can only get two totally independent frequencies out of this chip but it will be enough. My plan is also to glue a suitable I²C thermometer to the board and isolate it in it's own little enclosure. That way I can compensate for temperature related frequency variations in software. Above is my current draft schematic for the digital controller board. I tried to make decent use of the Atmega 328 I/O pins. Front panel buttons are connected to a '174 encoder that gives me a total of nine buttons on only four I/O pins. Pretty efficient with the downside that only one button can be pressed at a single time. User interface will have to be designed around this limitation but I don't think it's a big issue. The encoder knob is connected to the INT0/INT1 pins that have flexible interrupts. Decoding in software really needs to be interrupt driven not to mis a step. On the I²C bus I have the Si5351 board, a DAC/ADC (PCF8591) and an EEPROM. My plan is to use the DAC/ADC for reading incoming signal level, RF power etc and for software based AGC. Still need to work out how to do this in detail. EEPROM will be used for settings and calibration data. Another suitable multichannel volume control chip will also be connected to the I²C bus for the audio routing and levels. The four '164 shift registers provides a total of 32 outputs for controlling various functions. The PTT and CW key have their own pins so that they are not interfered by other key presses. I have written rudimentary code to test and verify all parts but it's not release-ready. From the image above you can get the basic idea of what the interface looks like right now. That's about it for now! Hopefully the next update will not be that very far away this time.
68xx cross assembler
I've gotten quite a few questions now about my assembler and workflow for the MC3. I've used the same old 6800/01/04/05/09/11 assembler for years. I think it's made by E J Rupp originally. It's very basic and does not handle macros and such but it's clean and I do have the source code and have made a few modifications over the years. Mainly adding a version (as1h) that supports the very useful XGDX opcode for 6301/6303. The output is Motorola S-record (S19) that is directly compatible with most monitors and PROM programmers. Below is an archive of the assembler with both source and Linux binaries. Download assembler source and binaries I have included a build script (build.sh) for compiling under GCC. Assemble and generate s19-file $ as1h program.asm Assemble and generate listing + s19 $ as1h program.asm -L > program.lst As for assembler editor I use Emacs all the way. It handles 68xx assembly nicely.
MC3 monitor 1.4.1
This is a minor bug-fix release of the 1.4 monitor improving stability of the the single step function and improves stack handling and coherency in printout. This is the correct single step code. Silly me forgot to clear the interrupt mask on stack before RTI. *************** * DO SINGLE STEP SSTEP JSR PCRLF STEP LDS SP RESTORE PROGRAM STACK POINTER TSX LDAA ,X LOAD CC ANDA #$EF CLEAR INTERUPT MASK BIT STAA ,X SAVE CC LDAB #$1F STPWAI DECB WAIT FOR EVENTUAL SCI XFER CMPB #$00 BEFORE TIMER INIT BNE STPWAI LDX #STOP SET INTERRUPT VECTOR STX TMOFVEC+1 LDX #$FFED RESET COUNTER VALUE STX COUNTHI LDX TIMECON CLEAR INTERRUPT BIT IN TIMER CTRL REG LDAA #$04 ENABLE TIMER OVERFLOW INTERRUPT STAA TIMECON RTI *************** * SINGLE STEP INTERRUPT ENTRY STOP STS SP SAVE PROGRAM STACK POINTER LDX #INTSEQ RESTORE INTERRUPT VECTOR STX TMOFVEC+1 LDX TIMECON CLEARS INTERRUPT BIT IN TIMER CTRL REG LDAA #$00 DISABLE TIMER INTERRUPT STAA TIMECON LDX SP EXTRACT PROGRAM STOP ADDRESS LDAB #6 ABX LDX ,X CPX #$C000 BHI STEP NO STOP IN ROM STX XTEMP LDAB XTEMP CMPB #$7F BEQ STEP NO STOP IN PAGE $7F LDX #STOPTX JSR PDATA JMP PRTREG PRINT REGS AND GO TO PROMPT Monitor 1.4.1 ($C000-$C7E8) - source - listing - s19
Buffered I²C interface
I²C is a fun protocol. It's great for interfacing to real time clocks, sensors, displays etc. My personal favorite right now is the Si5351 frequency generator chip. In a world of ever increasing number of I²C compatible micro-controllers, I though that my MC3 should learn to speak I²C as well. I have chosen a chip from Philips that is a self-contained I²C interface. It's much faster than bit-banging an I/O port. The chip, PCF8584, can still be obtained from various suppliers but I don't think it's being manufactured anymore. Therefore I have taken extra care to protect it. The interface schematic can be seen below. The tricky part about buffering I²C signals is that they are bi-directional (the PCF8584 can work as both master and slave). A buffer that is both bi-directional and has open collector input/outputs needs some extra thinking. It is not possible to just put to buffers back to back and expect it to work. As soon as one of the buffers trigger the opposite buffer will also trigger and the circuit will enter a locked state. To solve this I have designed the buffer stages using two comparators (LM339) with open collector outputs. By using comparators it is possible to carefully adjust the trigger levels so that one buffer does not affect the buffer in opposite direction. A reference voltage of 0.65V is used for the comparators, but the output from the comparators facing the PCF8584 has a series resistor that together with the pull-up resistor creates a voltage divider. When the comparator tries to pull the line low the divider will limit the voltage to around 1.2V, enough for the PCF8584 to register a 'low' level but not enough to trigger the opposite comparator. This is the finished MC3 I/O board. I added an 8-pin socket (not in the schematic) for connecting EEPROMs directly on the board. As always, don't forget to add 100nF decoupling capacitors across the supply on all chips. Sample program for testing the interface This program interfaces to a DS1307 RTC chip but I have made the I²C driver routines generic so they can be used for accessing any other I²C device as well. - source - listing - s19
[show older articles]