简易版  登录 注册

基于雅马哈YM2149的简单MIDI音源实现

LiuXIkun 2020/2/1 15:29:56 #1

基于雅马哈YM2149的简单MIDI音源实现

前言

​ 最近因为病毒的原因一直蜗居在家里,闲来无事想起去年买来放在家里落灰的YM2149,于是本着没事也得找事做的原则打算制作一个简易的MIDI音源。废话不多说,下面就来详细介绍一下该MIDI音源。(本文章分为芯片介绍,驱动编写和成品展示三部分。)

芯片介绍

​ YM2149是一款雅马哈研发的三通道软件控制声音发生器(SSG),通过CPU向寄存器中写入数据来控制芯片产生不同频率的方波/噪声。YM2149还内置了一个包络发生器,因此该芯片可以输出不同的音色。当然,最出名的还是YM2149的孪生兄弟AY-3-8910,在APPLE II和Atari 520ST等设备上都有使用。相比于AY-3-8910,YM2149拥有更高的输入时钟频率以及双分辨率但双速率的音量包络表。

驱动编写(建议配合数据手册查看)


  • 首先来看芯片管脚功能。
  • 总览

    点击此处打开图片

    1.DA7-DA0

    这八个脚是双向数据口,芯片通过这八个脚读取传入的命令/数据。

    2.BDIR,BC1和BC2

    这三个脚控制从双向数据口读取八位值是寄存器地址还是要写入寄存器地址的数据。通过下表来配置:

    点击此处打开图片

    注:Inactive为高阻模式,此时发送到双向数据口的数据均认为是无效。

    3.A8,A9

    地址选择脚。当A8和A9分别接5V和地时,芯片强制使用默认器件地址0000。芯片本身是有自己特定的器件地址的,但是我们无法知道一些来源不明的芯片的器件地址,因此我们只能使用默认地址来操作芯片。(注:可以通过编写特定的程序来测出芯片实际器件地址,但是我懒x)

    4.RESET

    把这个脚按照时序拉低一段时间就可以使芯片复位。

    5.CLOCK

    此脚接外部晶振,一般接4Mhz晶振即可。

    6.SEL

    该脚电平为高时,系统时钟不分频,为低时2分频。

    例:SEL为低,CLOCK脚外接4Mhz,那麽实际输入为2Mhz。

    7.ANALOG CHANNEL A-C

    音频输出口。

    8.IOA/B

    可以让芯片读取其他器件发来的数据,这里我们不使用。

    9.TEST

    测试脚,不使用。


  • 内部寄存器介绍
  • 总览

    点击此处打开图片

    1.R0-R5

    点击此处打开图片

    A-C通道输出的音频频率,计算公式如下:

    点击此处打开图片

    Ft是要得到的频率,fMaster是总时钟频率,TP是寄存器中的值。

    例如:要得到440HZ的输出频率,当fMaster = 2Mhz时通过计算可得TP = 284,转化为十六进制填入寄存器中即可。(注意一个通道由两个寄存器控制频率,前一个寄存器为低八位,后一个为高四位。)

    2.R6

    点击此处打开图片

    噪声输出频率,计算方式同上,但注意频率仅由R6寄存器的低五位控制,注意取值范围。

    3.R7

    点击此处打开图片

    混合器(直译),可以将噪声与音乐混合输出,每个通道都可以独立配置。写“0”为输出,写“1”为禁止输出。

    例如:A通道只输出噪声,就把B3置“0”,B0置”1“,以此类推。

    4.R8-RA

    点击此处打开图片

    配置音频输出音量大小,每个通道均可独立配置。B4为模式位,置0时音量大小由B0-B4的值控制,置1时由包络控制(这个包络控制比较复杂,我在这里不细说了,对此感兴趣的可以自己去了解)。

    5.RB-RC

    包络频率控制,没玩懂就不再这细述了。。。

    6.RD

    包络线样式控制,一共有10种包络可选。

    点击此处打开图片

    注意4,5,6是要连在一起去了解的,由于没有相关的专业知识我也不知道该如何去调制,这里就不再细讲了


  • 软件部分编写
  • 终于到了激动人心的驱动编写时刻,我使用的是德仪的TM4C123系列单片机进行控制,由于这款单片机过于小众,我就不把代码放出来了,主要是通过自然语言+伪代码的方式来说明。

    如何往地址中写入数据

    首先来看芯片的时序表:

    点击此处打开图片

    然后看芯片写寄存器地址时序:

    点击此处打开图片

    注意这里有两点要关注,一是地址设置时间tAS,二是地址保持时间tAH。这里我们可以这样去编写:

    BDIR = 1;BC1 =1;BC2 = 1;进入地址模式

    发送地址数据到双向数据口

    BDIR = 0;BC1 =1;BC2 = 0;进入高阻模式

    以上三步即可使芯片读取到正确的寄存器地址并进入。

    接下来是写入数据

    点击此处打开图片

    注意这里有三点点要er关注,一是数据设置时间tDS,二是数据信号时间tDW,三是数据保持时间tDH。这里我们可以这样去编写:

    发送数据到双向数据口

    BDIR = 1;BC1 =0;BC2 = 1;进入数据写模式

    BDIR = 0;BC1 =1;BC2 = 0;进入高阻模式

    以上三步即可使芯片读取到正确数据并写入前面进入的寄存器地址中。

    如此,即可完成一次对寄存器的写操作

    剩下的工作就是按照功能编写相应函数进行封装即可。

    如何复位

    点击此处打开图片


    进行MIDI通讯

    我是参照这两个来编写的

    Arduino模拟MIDI键盘

    用步进电机搭建MIDI播放设备


    成品展示

    组装好的样子:

    点击此处打开图片

    原理图
    点击此处打开图片

    PCB正面
    点击此处打开图片

    PCB背面

    点击此处打开图片

    音频播放展示
    https://cdn.jsdelivr.net/gh/Lyxikun/lanthanum-database/AUDIO/YM_2149-9dewanmeisuanshujiaoshi.mp3


    第一次在网上码了这么多字,如果由描述不当/错误的地方还请大家多指教

    ZephRay 2020/2/5 22:32:18 #2

    很强啊 单片机确实有点小众 之后可以试试集成到一块板上弄个小盒子

    LiuXIkun 2020/2/13 13:54:17 #3

    回复给ZephRay: 板子已经做出来了但是还没发货。。。外壳的话最近在做基于YM3812的MIDI音源,所以这个YM2149的板子就当成是个练习用的板子就不做壳了

    pingatsky 2020/2/15 02:11:42 #4

    厉害。如果能同时控制多块芯片,可玩性肯定大大增加。

    C_Gear 2020/2/16 10:12:35 #5

    赞!

    YM3812,OPL2啊。这个弄好了可以当作DOSBOX的外置硬件音源吗?
    此外,会不会继续考虑OPL3(YMF262或者后来的升级版YMF289)?毕竟支持更多的FM合成algorithm和立体声。

    LiuXIkun 2020/2/16 11:05:38 #6

    回复给C_Gear: OPL3后面会做,至于DOSBOX目前还没有研究但也可以安排上(大坑)

    C_Gear 2020/2/16 15:07:16 #7

    话说,有没有可能把PCM直接以数字方式引出?

    现在好像就是没有OPL2、OPL3硬件输出的数字信号直接输出的硬件方案。雅马哈的YMF724声卡输出的数字信号经过了重采样,从原生49716Hz降低到了48000Hz。虽然音质损失基本可以忽略,但毕竟是理论存在的。如果有硬件方案直接输出49716Hz的原始数字信号就有意思了。

    LiuXIkun 2020/2/16 15:38:35 #8

    回复给C_Gear: 是这样的,OPL2和OPL3是通过相匹配的DAC(如Y3014B)把芯片输出的数字信号转化成模拟信号再输出的,不通过DAC直接输出的数字信号根本没法听。而相匹配的DAC取样率有限(如Y3014B有效取样位数只有13位)则限定了音质(大意)。而YMF724的采样率变低我觉得是跟ADC有关。

    ZephRay 2020/2/16 21:48:17 #9

    回复给LiuXIkun: 我觉得可以做到。我的理解,他的意思是能否转换OPL输出给Y3014B的信号为普通的如SPDIF或者I2S的信号,再输出给现代的DAC,以避免Y3014B带来的音质损失或者是ASRC带来的音质损失。这里无非是两个问题,一个是,OPL输出的是浮点信号,这个可以通过CPLD/FPGA轻松转换为现在DAC用的整数/二位补码信号(当然还是13位有效位,16位动态范围)。另外一个则是49716Hz的信号,虽然说用CPLD/FPGA输出一个49716Hz的信号不成问题,但是接收设备(解码/DAC)能否接受这个信号就不一定了。如果要说稳妥一些,可以选择向上转换到96kHz或者192kHz,虽然肯定还是存在损失,但是肯定是可以忽略的程度了。毕竟整个系统内到处都存在失真,如果DAC只有96dB的SNR,那在ASRC上从110dB提升到120dB可能意义并不那么大。

    gaoyf1997 2020/2/17 17:29:36 #10

    回复给C_Gear: 硬件音源具体怎么做,是不是使用硬件音源播放时就无法同时播放波形声音,比如仙剑的voc,谢谢!

    gaoyf1997 2020/2/17 17:30:34 #11

    回复给LiuXIkun: DOSBOX要用特定的版本,推荐DOSBox ece的最新版,因为最新版是支持hardware-passthrough的。

    C_Gear 2020/2/17 18:57:38 #12

    回复给gaoyf1997:

    硬件音源?您指的是楼主的这个项目还是以前的AdLib卡 / Sound Blaster声卡?
    后者的话,应用软件层面的操作就是向特定的端口组按顺序写入数据到指定寄存器。接下来的事情就和应用软件无关了。
    至于波形声音,OPL2和OPL3芯片据我所知没有播放波形声音的机能。世嘉MD的YM2612倒是可以(但是这个功能很原始,就是这边写入采样数据那边模拟输出电平相应变化)。至于Sound Blaster声卡,它的波形播放似乎是独立的机能,和OPL2以及OPL3无关。因此仙剑的VOC并不和FM部分有什么冲突。

    Designed by @ZephRay. Made by @ntzyz.
    Copyright (c) 2016-2020 cnVintage Team.