2023/6/17 18:00 携帯FM音源プレイヤー または FM2608音源ボード基板頒布Project

2151ファームウェアへ  2608ファームウェアへ
2023/6/17 ・携帯FM音源プレイヤー v1.81ファームウェア追加
2023/3/9  ・携帯FM音源プレイヤー v1.80ファームウェア追加
2022/11/26 ・携帯FM音源プレイヤー v1.73ファームウェア追加
2022/3/18 ・携帯FM音源プレイヤー v1.72ファームウェア追加
2021/7/8  ・携帯FM音源プレイヤー v1.71ファームウェア追加
2020/8/17  ・携帯FM音源プレイヤー v1.70ファームウェア追加
2020/2/15  ・YM2608FM音源ボード v1.62(実験版)ファームウェア追加
2019/10/22 ・携帯FM音源プレイヤー v1.62(実験版)ファームウェア追加
2019/9/28  ・携帯FM音源プレイヤー v1.61ファームウェア追加
2019/9/28  ・YM2608FM音源ボード v1.61ファームウェア追加
2019/9/22  ・YM2608FM音源ボード v1.60ファームウェア追加
2019/9/21  ・携帯FM音源プレイヤー v1.60ファームウェア追加
2019/9/16  ・YM2608FM音源ボード v1.6の補足(回路図差分、v1.6の部品配置図)を追記
2019/4/13  ・携帯FM音源プレイヤー v1.55ファームウェア追加
2019/3/28  ・YM2608FM音源ボード v1.56ファームウェア追加
2019/3/26  ・携帯FM音源プレイヤー v1.54ファームウェア追加
2019/3/9  ・YM2608FM音源ボード v1.55ファームウェア追加
      ・携帯FM音源プレイヤー v1.53aファームウェア追加
2019/2/23  ・YM2608FM音源ボード v1.54、v1.54aファームウェア追加。
2019/2/22  ・携帯FM音源プレイヤー v1.53ファームウェア追加。正式版
2019/2/19  ・携帯FM音源プレイヤー v1.52cファームウェア追加。再調整
      ・携帯FM音源プレイヤー v1.52bファームウェア追加。全体的にウェイト調整。VGM再生をサンプル値制御に変更
2019/2/16  ・携帯FM音源プレイヤー v1.52ファームウェア追加。ディレクトリスキップ追加
      ・YM2608FM音源ボード v1.53ファームウェア追加。ディレクトリスキップ追加
2019/2/15  ・携帯FM音源プレイヤー v1.51ファームウェア追加。不具合修正
      ・YM2608FM音源ボード v1.52ファームウェア追加。不具合修正
2019/2/10  ・YM2608FM音源ボード v1.51ファームウェア追加。ウェイト調整メニューを追加
2019/2/9  ・YM2608FM音源ボード v1.50ファームウェア追加。サブディレクトリ対応
      ・携帯FM音源プレイヤーv1.50ファームウェア追加。サブディレクトリ対応、S98再生の調整
2019/2/3  ・YM2608FM音源ボード v1.43ファームウェア追加。フェードアウト処理修正
2019/2/2  ・YM2608FM音源ボード v1.42ファームウェア追加。s98,VGM再生を再調整。他
2019/1/30  ・携帯FM音源プレイヤー v1.42ファームウェア追加。VGM形式ファイルの再生分解能を再調整しました
2019/1/27  ・YM2608FM音源ボード v1.41ファームウェア追加。VGM形式ファイルの再生分解能を変更しました
2019/1/27  ・携帯FM音源プレイヤー v1.41ファームウェア追加。VGM形式ファイルの再生分解能を変更しました
2019/1/26  ・YM2608FM音源ボード v1.40ファームウェア追加。SPFM Lightモードを追加しました。
2019/1/26  ・携帯FM音源プレイヤー v1.40ファームウェア追加。s98形式の再生追加、ボリューム変化量調整、SPFM Lightモードを追加しました
2019/1/21  ・YM2608FM音源ボード v1.33ファームウェア(実験版)追加。VGM形式の再生時、ループポイントで正常にループしない場合がある問題に対処
2019/1/20  ・YM2608FM音源ボード v1.32ファームウェア(実験版)追加。VGM形式の再生を追加
2019/1/20  ・YM2608FM音源ボード v1.31ファームウェア(実験版)追加。S98ファイル形式によって再生できない問題を修正
2019/1/19  ・YM2608FM音源ボード v1.30ファームウェア(実験版)追加。S98ファイルの再生を追加
2019/1/17  ・携帯FM音源プレイヤー用ファームウェアv1.31(実験版)追加。VGM再生の切り替わり時にフェードアウトするようになりました
2019/1/15  ・携帯FM音源プレイヤー用ファームウェアv1.3(実験版)追加。SDカードからのVGM再生に対応しました
      ・YM2608FM音源ボード v1.22ファームウェア実験版追加。SPFMウェイト値を再度調整
      ・YM2608FM音源ボード v1.4旧基板の補足情報を追加
2019/1/14  ・YM2608FM音源ボード v1.21ファームウェア実験版追加。SPFMウェイト値を調整
       ・c95のチラシpdfを追加
2019/1/10  ・携帯FM音源プレイヤー v1.3基板部品配置捕捉追加
2019/1/4  ・携帯FM音源プレイヤー v1.2基板用v1.2ファームウェア追加。ボタン配置が逆な問題対策用です
2019/1/4  ・YM2608FM音源ボード v1.2ファームウェア実験版追加。SPFMインタフェースを追加
2019/1/4  ・携帯FM音源プレイヤー v1.2ファームウェア実験版追加。SPFMインタフェースを追加
2019/1/3  ・YM2608FM音源ボード ADPCM読込み対応 v1.1ファームウェア実験版追加。ADPCM読込みについての説明追加
2019/1/2  ・携帯FM音源プレイヤー v1.1ファームウェア更新。メニューにバックライト制御項目を追加
2019/1/2  ・携帯FM音源プレイヤー基板v1.2で作成される方へ向け説明を追加
2018/12/30 ・YM2608FM音源ボード PMD曲データ作成支援プログラム追加


■はじめに

このドキュメントは携帯FM音源プレイヤーまたはFM2608音源ボードを製作する為に必要な情報を記述したものです。
製作に当たってはこのドキュメントをよく読み、用法用量を守って正しくお使いください。

C96で配布説明書PDF(C96用説明書)

C95で配っていた説明書のPDF(C95用説明書)

・基板頒布Projectとはなんですか?

基板は10枚単位で作っています。
基板製造サービスがこの単位で作れるもので、1枚と値段が変わらないのです。
#厳密には重さが変わるので、輸送費に影響が出てるかもしれません

この余りを放出するもののことです。

・作るまえの注意点

部品は付属していませんので、集めてください。部品リストについては下のほうに説明を記述しています。
現行部品はほぼ秋月電子で購入できますが、一部取り扱いが終了しているものがあるので、他の店でも探す必要があります。
工具はある程度あった方がよいと思います。
主に使っているディスクリート部品は表面実装ではないのですが、マイコンの半田付け確認等にルーペがあると便利です。

ほとんどの部品は秋月電子で手に入ると思います。
抵抗は100本入りで100円で売られています。1本あたりの単価は1円なのですが、100本も不要な場合は他の部品屋で狙ってみてください。ただ、他だと1本10円とかします。
それ以外だと千石電商や通販(RS Online)で手に入れています。
FM音源チップは入手が面倒ですが、海外通販や家電のケンチャンで手に入ります。
家電のケンチャンには店内に置いてあります。通販だとないです。ガチャガチャでもFM音源チップが手に入りますが、狙うのは面倒だと思われます。

RS Online等では、1つ1つ丁寧にパッケージされている部品と、産業用のトレイやレールに詰まって売っているもの等、複数種類あります。
1個単位で買えるものもありますが、数個まとめて買わないといけないもの、数を買うと大幅に安くなるものがあります。
単価が安くても、最低注文個数を確認してください。産業用レール売りなどの部品は25個単位などでしか買えず、高い場合があります。(〜パッケージとか書いてあります)

なお、ファームウェアを書き込むのにPICKIT3が必要です。
#PICKIT4でもいけると思いますが、試した事はありません。あ、MPLAB SNAPで試したところOKでした。

MPLAB IPEでHEXファイルを書き込んでください。
PICKITから電源供給するのチェックボックスを有効にしてください。(MPLAB SNAPだと電源供給は別にする必要があるみたいです。USBケーブルがさせるまで組み立てないと書き込みできないって事です)
ちなみにこのMPLAB IPEですが、画面の高さが最低768pxはないと、ボタンが押せない場合があります。
LATTEPANDAの1024x600で、PICKITから電源供給するのチェックボックスを押すのが至難の業でした。

また、基板にマイコンを実装してプログラムを書き込むのに、ピンヘッダを軽く押し付けながら20秒程度じっとしないといけません。
この時に動いて接触不良になったりすると、マイコンが使用不可能になります。
自信がない場合は、基板にピンヘッダ端子を半田付けすると楽ですが、邪魔です。仕方がありませんが。

※ファームウェア書き込みについての詳細は、後ほど記載しています。

表面実装部品であるマイコンは、コテ先が平らになっているものの方がつけやすいようです。
ざっと半田を溶かしながらなぞれば、端子意外はレジストで弾かれて半田が載らない筈ですが、半田付けはうまくないのでその域まで達していません。液体フラックスとかいろいろテクが必要みたいです。
ねちゃっとつけて、はんだ吸い取り線で吸い取っています。

#結構ヤニで汚くなるので、イソプロピルアルコールで拭いています。
 無水アルコールでないのは、買いに行った時の在庫の都合です。


この基板は以下を有している方を対象としています。

・半田付けの知識
・FM音源の知識
・部品を調達できる
・曲データを準備できる

・あると便利な工具など

・ニッパー
・ラジオペンチ
・はんだごて(20wくらい)
・ヤニ入り有鉛はんだ …※
・はんだ吸い取り線
・ドライバー

※Pbフリーなものより有鉛半田のがつけやすいです。確実に。最近のは良くなったのかと使ってみましたが、やっぱりダメでした。詳しい人に聞くと、なんでそんなものを使ったんだとばかりに言われました。ちなみに高密度実装だとPbフリー半田はヒゲ(ウィスカ)が生えて短絡するとの事です。この基板はそんなに高密度ではないので関係ないですが。

・必須

・PICKIT3(http://akizukidenshi.com/catalog/g/gM-03608/)または相当品(MPLAB SNAP等http://akizukidenshi.com/catalog/g/gM-13854/ )
・MPLABX(https://www.microchip.com/mplab/mplab-x-ide ※MPLAB IPEが必要です 下のほうにDL用の説明を用意しています)
・PC
・勇気か根気
・曲データ

■内容物 (C96配布物)

・携帯FM音源プレイヤー 3枚組

・メインボード基板 v1.5,v1.5a(黒、白)
・カバー基板
・電池基板
※v1.5は、缶パッケージの水晶を使うバージョンです。
v1.5aは、大真空社製の水晶を使うバージョンです。
 v1.5基板でも足を延ばして配線すれば大真空社製水晶を使うことができます。(逆はめんどくさそうです)
 

・YM2608サウンドボード

・YM2608音源ボードV1.6

■作るための注意点

・作る順番

基本的に背の低い部品、特に表面実装からつけていきます。が、安い部品からつけていくこともあります。
また、全部つけ終わった後に肝心な部品をつけるのに失敗していると非常にがっくりします。
何回かそういう事があってから、表面実装なマイコンを使う場合は、マイコンの動作確認をする為の部品一式をまずつけるようにしています。

具体的には、

マイコン→マイコン用パスコン、レギュレータコンデンサ、クリスタル+クリスタル用コンデンサ、
3.3V電源周り(レギュレータ、コンデンサ、ポリスイッチ)、USBコネクタ、PICマイコンのMCLR用抵抗(10kΩ)、LED、
LED用電流制限抵抗

あたりから作業しています。
SDカードなどが検出されない場合、現在のファームウェアはLEDを点滅させます。なので、この段階で点滅しなければどこかがおかしいということになります。

また、ファームウェアはUSBシリアルポートとして認識されます。PCに接続してCOMポートが認識されるか確認してください。
認識されない場合は、マイコンの半田付け不良の可能性があります。
特に携帯FM音源プレイヤーの場合は、液晶が上に載るために、液晶を載せてからの不良が判明した場合、修正が困難になります。
液晶を載せる前にUSB COMデバイスが認識されるか確認してください。

製作方法の参考に(なるかどうかはわかりませんが)ぶろぐ記事をご覧ください。
基板リビジョンが違うものだったりしますが、大体作る順番のイメージがつかめると思います。

・携帯FM音源プレイヤーのぶろぐ記事

【基板作成編】携帯FM音源プレイヤーの製作(OPM YM2151)
https://asmpwx.at.webry.info/201705/article_2.html

【基板作成編】携帯FM音源プレイヤーの製作2 (OPM YM2151)
https://asmpwx.at.webry.info/201707/article_7.html

【基板作成編】携帯FM音源プレイヤーの製作3 (OPM YM2151)
https://asmpwx.at.webry.info/201808/article_1.html

【基板作成編】携帯FM音源プレイヤーの製作3-2 (OPM YM2151)
https://asmpwx.at.webry.info/201809/article_1.html
です。

動画
https://www.nicovideo.jp/watch/sm33827203


・YM2608音源ボードのぶろぐ記事

【基板作成編】 FM音源ボードOPNA(YM2608B)
https://asmpwx.at.webry.info/201612/article_1.html

【基板作成編】FM音源OPNA(YM2608B)ボードの製作
https://asmpwx.at.webry.info/201706/article_1.html

【基板作成編】FM音源(OPNA YM2608)ボード リフレッシュ編
https://asmpwx.at.webry.info/201801/article_1.html
です。

動画
https://www.nicovideo.jp/watch/sm32681548

・携帯FM音源基板の注意点

・10mmの金属スペーサーだと、YM2151とカバー基板との間に隙間があります。
秋月で売っている円柱の金属スペーサーが7mmの次が10mmになるので仕方ないのですが、放熱の為にYM2151に
サーマルパッドを入れてカバー基板から放熱するためには、厚めのパッドでも2枚重ねくらい必要になります。
サーマルパッド、ものによっては臭いです。我慢してください。秋月の商品写真からでは匂いまではわかりません。

・4MHzのクリスタルは秋月での取り扱いが終了しています。前は売っていたようですが今現在はありません。
YMZ294+4MHz水晶発信器セットでも手に入れる事ができましたが、これもセット売りが販売終了になっています。

・そういえばこの基板、奮発してENIG(金メッキ)で仕上げてます。高いです。

・液晶はマイコンの上にかぶせて使います。マイコンが正しく動作するのを確認してから液晶を載せる方がよいでしょう。
液晶は一度つけると、取り外すのが困難であり、非常に割れやすいです。

注意!! 電池基板をつける場合、電池基板の電源をONにした状態でUSB端子にUSBケーブルを接続しないでください。

・YM2608基板の注意点

注意!! 電源はUSB端子又はDCジャックから供給可能になっていますが、DCジャックから給電する場合は、USB電源のジャンパは外してください。
ACアダプタとUSB端子にUSBケーブルを同時に接続しないでください。

メモリはFM音源の下に配置されています。製作する順番を間違えると完成が非常に困難になります。

・共通の注意点

・出力段の最後に3.9kΩの抵抗とコンデンサが入っていますが、抵抗はイヤホンで聞く場合は1kΩくらいでないと音が少し小さく感じるイヤホンなどがあります。
アンプに接続するならば、参考(というかOPAMP回りそのまま)にしたooISHoo氏の回路の数値3.9kΩのままでも大丈夫です。
イヤホンによっては1kΩ等にした方がいいかもしれません。
ただし、抵抗を下げるとPCのUSB電源で利用する場合、ノイズに非常に弱くなります。
PCなどのUSB電源はかなり酷いノイズが含まれています。PCだと動画再生など負荷がかかった状態だとノイズがさらににぎやかになります。
利用シーンに合わせて調整してください。

・液晶の端子は非常に繊細です。注意して扱ってください。
端子に少しでも負荷をかけると、ガラスごと割れたり、端子とガラスとの接着面が外れて簡単に壊れます。
1列出なくなるとかザラです。軽く5つは壊したと思います。

・バックライトなしの液晶を使う場合は、バックライト制御用の部品は必要ありません。
FETのBS170、抵抗の10Ω、100KΩ、金属皮膜47Ωです。

・液晶をつけなくても動作しますが、I2C用のプルアップ抵抗(10kΩx2本)だけは省略しないでください。
I2Cの処理にウェイトが入り、著しく遅くなります。

・部品の向きについて

・マイコンの向きは絶対に間違えないでください。
基板の1番ピンの位置には丸いぽっちがつけられています。マイコンにも丸いぽっちがあります。
一致するようにつけてください。

・電解コンデンサは極性があります。電源と一部の音響コンデンサにのみ、極性があるコンデンサを使っています。

・ICにも向きがあります。1番ピンの位置はシルク印刷で欠けている方です。
現物の写真がありますので、よく見ながら接続方向を間違えないようにしてください。
ICソケットも間違えずにつけたほうが良いです。チップ自体の取り付けを間違えなければ大丈夫ですが、
いつか間違えます。
携帯FM音源プレイヤーのOPAMPチップは、シルク印刷が他のICのパターンと同じではありません。
なんか海外の部品ライブラリを使ったらへんなパターンになっています。1番ピンは星がある方向です。

・部品の向きがわからない場合は、実体写真を参考にしてください。

・正方形のクリスタルには向きがあります。1番ピンは丸みを帯びておらず、尖っているところです。
金属ケースにも丸がつけられています。

・LEDの向きについて
 LEDにも極性があります。
 ・携帯FM音源プレイヤー
 
 右側がカソード(足が短い方で樹脂内部は受け皿の形状:GND側)です。
 
 ・YM2608音源ボード
 
 左側がカソード(足が短い方で樹脂内部は受け皿の形状:GND側)です。

・YM2608音源ボードのメモリについて

YM2608の下に入ります。なので、YM2608用のソケットをつけた後では修正が非常に困難です。
しかもチップはSOJなので貼り付けは大変です。
つけた後に念入りに確認してください。
今のファームウェアでは、音源ボードのプログラムからADPCMを鳴らす処理が入っていませんので、
無理してつけなくてもいいとは思いますが、組み立てた後でチップつけるの無理ですね。こりゃ。
#SPFMモードを搭載した事により、MUCOM88からADPCMを使うことができるようになりました。
 動作確認にご利用ください。

・PICKITとの接続について

2番が電源です。3番中央がGNDです。
なので、どちらの方向にさすのかは、2番ピンがどちらにあるのかで確認する事できます。
電源やGND配線は、周りの信号線の配線よりやや太めになっているので、太いほうがどちらに寄っているかで見分ける事ができるのです。
左側にあるときは、必然的にPICKITを裏返しにして接続する事になります。
と、言われても困ると思うので、接続方向については後で解説します。

・アクリル板でカバーをつける場合は

秋月のアクリル板ですが、微妙にBタイプ(http://akizukidenshi.com/catalog/g/gP-10243/)も、
Cタイプ(http://akizukidenshi.com/catalog/g/gP-09853/)もサイズが合いません。
部品配置が厳しくて、穴の位置が合いません。
あきらめるか大きめのAタイプ(http://akizukidenshi.com/catalog/g/gP-10706/)でなんとかしてください。

・音源チップとマイコンの接続について

音源の割り込みは使えません。
配線されていません。正確にはYM2608ボードではプルアップ抵抗と接続用ジャンパのパターンはあるのですが、使っていません。

音源チップからデータが読み込めないためです。マイコンと音源チップの駆動電圧が違うから。
マイコンは3.3Vで動いていますが、音源は5Vです。
マイコン→音源チップはこのままでも問題ありませんが、音源チップ→マイコンをやると壊れます。

74LCX245でI/O電圧変換をやっていたリビジョンの基板もあったのですが、このチップが秋月で売っていない上に、
SSOPだったため、半田付けが非常に面倒困難だったのでやめました。
表面実装は悪です。

なので、音源とのBUSY情報は処理時間だけで何とかしています。意外とできるものです。

・絶縁について

!!絶縁は重要です!!
携帯FM音源プレイヤー及びYM2608FM音源ボード基板は、裏面が絶縁されていません。
金属板の上に置いたり、コインなどが接触した場合、ショートして重大な事態を引き起こす可能性があります。
必ず絶縁の為の処置を行ってください。
金属端子が触れないように、アクリル板をつけたり、ケースに入れたり、絶縁テープやコルクボード等で絶縁してください。
アクリル板で絶縁 ポリイミドテープで絶縁 ポリイミドテープで絶縁2 ポリイミドテープ コルクボード

秋月で液晶などの小さいデリケートな部品を買うと、小型のプラスチックケースに入っています。

プラスチックケース

このケースをはさみで切り開き、基板裏にホットボンドでつけると、丈夫な絶縁シート代わりにすることができます。
特に携帯FM音源プレイヤーの、メイン基板と電池基板の間は15mmしかないため、なるべく飛び出した端子を短く処理し、しっかりと絶縁することをお勧めします。移動中や衝撃で電池が動いた場合、メイン基板と接触しショートしかねません。
!!かならず絶縁対策を行ってください!!

お勧めはやっぱりプラスチック板を使うことです。


ポリイミド+プラスチック版で絶縁

別の基板でプラスチックケースで対策を行っている様子と秋月のプラスチックケース

■部品リスト共通のお約束について

部品リストには、部品とコメント、調達用のリンクが記載されています。
リンクは一例であり、必ずしもリンク先で購入しなければならないわけではありません。
ひょっとしたらリンクが間違っているかもしれません。必ず回路図などでも確認するようにしてください。
部品にはまれに数量が大量のものがあり、そのリンクの場合もあります。数も確認するようにしてください。
#単品ではなく数個入っている部品もありますので、余った部品は何かに活用してください。

部品の足のピッチが2.54mmの場合と5mmの場合の2種類あります。
基板は部品ピッチを2.54mmで設計しているので、購入した部品が5mm品であった場合は、足の幅を狭めてから実装してください。
#2.54mmが売っていないので仕方ありません…

携帯FM音源プレイヤーと同時に解説していますので、同じ部品は携帯FM音源プレイヤーのみで解説し、省略しています。

また、部品はセクション別に記述しているので、同じ部品が再度登場します。
注文用に数をカウントする場合は注意してください。

■携帯FM音源プレイヤー部品リスト

携帯FM音源プレイヤーの部品リストなどの情報です。

回路図

※v1.4ですが、v1.5との違いはバッテリー基板からポリスイッチを経由して接続している変更のみ
 v1.5aはクリスタルのパッケージがTO-92に変更されたのみ

部品配置


 #v1.2基板や、v1.3基板を利用の方は一番下に各バージョンの差異を記述しています。一部部品配置が違うので注意してください
  v1.5基板の部品配置は以下の配置と変わりありません

全体

v1.5a基板差分

メインパーツのみ抽出

抵抗のみ抽出

コンデンサのみ抽出

サブパーツのみ抽出

物理配置図

電池基板

電池基板物理配置図


実際の部品配置などは、https://asmpwx.at.webry.info/201808/article_1.htmlをご覧ください。
携帯FM音源プレイヤーはスペースの都合により、いくつかの部品が重なっています。
また表と裏面の両方に部品を実装する必要があります。
裏面はマイクロSDカードスロットのみ配置されます。
マイコンの上に液晶ユニットが配置されます。マイコン端子の半田付け不具合に注意してください。

・基板

小型なので費用は余りかからないはずだったのですが、基板のフィニッシュをENIG(金メッキ)にしたため、実は高かったりします。
見た目はいいんですけど、半田ののりは微妙です。見た目はいいんですけど。(大事なことなので2回いいました)

・PIC32MX270F256D

https://jp.rs-online.com/web/p/microcontrollers/8417576/

端子の多いD型番は残念ながら秋月では取り扱っていません。
秋月で取り扱っているB型番は皆大好きDIP品なので違います。

マイコンは1番ピンの方向に丸のぽっちが点いています。基板のシルク印刷でもマークがついていますので、
位置と方向を合わせて実装してください。
#リンク先にはなんか新低価格と書いてあるリンクを貼っておきました。

・8MHz水晶発振子

http://akizukidenshi.com/catalog/g/gP-08667/
以前は10個単位での販売だったのですが、最近は1個から買える様になりました。
小さい割には地味に高い部品でもあります。

・22pF x 2

http://akizukidenshi.com/catalog/g/gP-04060/
マイコン用水晶の発振用コンデンサです。

・0.1uF

http://akizukidenshi.com/catalog/g/gP-00090/
パスコン、マイコン内蔵レギュレータ用コンデンサは、みんな大好き村田の積層セラミックコンデンサ(MLCC)です。
海外メーカー品と比べて、大きさがかなり均一に作られています。
#データシートにはサイズの範囲が書かれているくらい誤差があるのですが、村田製はほぼ均一サイズです。
Dマークがついてディスコンになったのが非常に悲しいです…
世界的に積層セラミックコンデンサ(MLCC)が不足しており、製造能力がすべてチップタイプのMLCCに振り分けられている為でしょうか。
ちなみにラジアルリード型は片側のみ端子が出ているタイプです。両側から出ているのはアキシャルリード型です。(主に抵抗がアキシャルリードタイプです)

・10uF

http://akizukidenshi.com/catalog/g/gP-05103/
10uFと大容量なのに積層セラミック。値段も0.1uFの3倍です。30円ですけど。
マイコンの内蔵レギュレータ用のコンデンサです。このマイコンのコアは実際は1Vちょいで動作しているようです。

・10kΩ x3

http://akizukidenshi.com/catalog/g/gR-16103/

マイコン用MCLR用抵抗、I2Cバス用抵抗x2です。I2C液晶駆動用です。
使用している液晶は低消費電力設計なので引き込み可能な電流が極めて小さく、I2Cバスのプルアップ抵抗には10Kが最低でも必要になります。
初期のラズパイはI2Cプルアップ抵抗が2Kくらいだった為に、電流を引き込みきれず、AQM0802液晶が使えませんでした。

・タクトスイッチ x5

http://akizukidenshi.com/catalog/g/gP-07193/

アルプス電気のタクトスイッチです。垂直取り付け用タイプです。
ノーブランドよりは耐久性があります。が、すべからくタクトスイッチそのものに耐久性には難がある気がします。

・USB miniB

http://akizukidenshi.com/catalog/g/gC-02235/

安心のスルーホールタイプ(基板貫通タイプ=表面実装でない)です。
基板に実装するときには、ちょっと斜めにしながら入れる必要があります。
信号端子が細い為、きちんと穴に入っていないと、押し込んだ時に非常に曲がりやすいです。
外装のGND端子だけでなく、5本の端子がきちんとスルーホールに入っているか見ながらゆっくり挿入してください。

・OSB5XA7DA4B-GH(青LED)

http://akizukidenshi.com/catalog/g/gI-02754/

安くて安心の青LEDです。
20本入り。たまに不良に当たると点かない事も。
#前に3本死んでたんですが保管が悪かったのかなー

・680Ω

http://akizukidenshi.com/catalog/g/gR-16681/

LED用の電流制限抵抗です。
まぶしくない明るさにしていますが、明るくしたいならもうちょっと低い抵抗を利用してください。

・DM3AT-SF-PEJM5

http://akizukidenshi.com/catalog/g/gC-02395/

ヒロセのマイクロSDカードスロットです。
表面実装な上にピッチが狭く、樹脂部分も多いため、半田付け時の熱にも注意が必要です。
カード挿入検出スイッチは側面にあります。割と金属板がむき出しなので、半田付け作業時ここにフラックスなどがかからないようにしてください。
SDカードの挿入検知ができなくなる場合があります。
カードを挿入しても反応せず、この部分を爪で押さえたりすると検知する場合、ここが接触不良です。

・24ピンICソケット

http://akizukidenshi.com/catalog/g/gP-00032/

・16ピンICソケット

http://akizukidenshi.com/catalog/g/gP-00029/

・14ピンICソケット

http://akizukidenshi.com/catalog/g/gP-00028/

丸ピンICソケットを利用してください。
安い板バネ式もありますが、正直直ぐ壊れます。ちょっとでも力をかけようものならすぽっと抜けていくのです。
なお、物によっては幅が600milと300milがある場合があるので、注意してください。

・YM2151

・YM3012

FM音源チップと専用DACです。
何とか手に入れてください。

・TLC2274AIN / TLC2274IN

https://jp.rs-online.com/web/p/op-amps/3312182/
OPAMPです。秋月では取り扱いがありません。
4回路入力なRailtoRailであれば、他のOPAMPでも大丈夫のようです。
NUJ7044Dhttp://akizukidenshi.com/catalog/g/gI-02371/とか。
#ピンアサインが同一であるか確認してください

・水晶発振器4MHz

・大真空社製TO-92型水晶発信器(v1.5a基板の場合)
http://akizukidenshi.com/catalog/g/gP-10387/
TO-92型の水晶発振器です。
秋月で取り扱いがあるのが嬉しいですね。
世の中の部品には2種類あります。
秋月で取り扱っているか、そうでないか。

・缶パッケージ型 (v1.5a以外の基板の場合)
https://jp.rs-online.com/web/p/crystal-oscillators/7675311/
秋月では取り扱いが終了しています。
意外とクリスタルは高いです。

・10uF

http://akizukidenshi.com/catalog/g/gP-08377/

音響用のコンデンサです。YM2151の近所に取り付けるところに使います。
極性があります。
カバー基板には、ちょうどこのコンデンサの上辺りにYM2151のロゴがあり、穴を開けるわけにはいきませんでした。
なので背の低い部品になっています。

・MUSE 10uF x2

http://akizukidenshi.com/catalog/g/gP-04638/

音響用のMUSEコンデンサです。
50V品を使っています。大きいのですが、安定感があります。
無極性の為、どちら向きに取り付けても問題ありません。

積層セラミックの10uFと極性ありの10uFと無極性だけど大きい10uFの3種類あったりします。
間違えないようにしてください。

・MUSE 4.7uF x2

http://akizukidenshi.com/catalog/g/gP-04637/

音響用の4.7uFです。こちらも50V品を使っています。
25V品は細くて。

・MJ-8435

http://akizukidenshi.com/catalog/g/gC-09060/

ステレオミニジャックです。
一時期部品が欠品していて、半年以上入手できなかった部品ですが、ようやく普通に手に入るようになりました。
次の商品入荷計画が立っていないので推奨しないとありましたが、在庫50000個くらいありますよね?
今見たら推奨しないが消えてました。

・8.2kΩ x4

http://akizukidenshi.com/catalog/g/gR-16822/

・1kΩ 〜 3.9kΩ x2

http://akizukidenshi.com/catalog/g/gR-16102/
http://akizukidenshi.com/catalog/g/gR-16392/

・270Ω

http://akizukidenshi.com/catalog/g/gR-16271/

OPAMP周りの抵抗です。LPF等を構成しています。
YM2151Shieldの作者様の回路を参考にしています。というかそのままです。色々やったのですが、USBのノイズが大きいためにあきらめました。。
フィルタ特性を持たせたボルテージフォロワを構成しています。

1K〜3.9Kの抵抗ですが、幅を持たせたのは繋げるイヤホンによっては変更したほうがよい為です。
3.9Kだとイヤホンによっては音が小さいと感じるかもしれません。ライン出力用がメインです。
音量が小さいと思った場合は、1K程度まで落としたほうがよいでしょう。
しかし、USB電源で駆動する場合、3.9kΩから抵抗を小さくするとUSB電源からのノイズに弱くなります。

・0.1uF x2

http://akizukidenshi.com/catalog/g/gP-00090/
他でも使われているので説明は省略。

・1000pF x4

http://akizukidenshi.com/catalog/g/gP-07673/

音響に良いとされているフィルムコンデンサです。
値段も安くて良いのですが、ちょっと高さがあります。

・1500pF x2

http://akizukidenshi.com/catalog/g/gP-08133/

1500pFのコンデンサです。フィルムコンデンサがない為、
積層セラミックコンデンサになっています。
5mmピッチなので、足を補正して2.5mmに直してください。

・NJM2845DL1-33

http://akizukidenshi.com/catalog/g/gI-11299/

3.3Vのレギュレータを使っています。
ただし、この部品は前半が同じ型番で、後半の33の部分だけが異なる部品があります。
05の5V版と18の1.8V版(秋月では廃盤のようなので出てきません)と間違えないでください。

#まれに間違える人がいるのですが、原因がわかりました。該当の品は1個単位でしか売っていません。下に4個セットが推奨で表示されますがそれは5V版です。複数個欲しいからとセットを買うと間違えます。
前は3.3Vの4個セットも売っていたのですが、セット売りは廃盤になりました。

・0.1uF x2

http://akizukidenshi.com/catalog/g/gP-00090/

他でも使われているので説明は省略。

・100uF

http://akizukidenshi.com/catalog/g/gP-08290/

高さ制限があるため、高さがある部品は使えません。
ここはOSコンを利用しています。色もいいですし。
上にカバーがあるので見えませんけど。

・MF-RX040

http://akizukidenshi.com/catalog/g/gP-13077/

ポリスイッチです。
MF-R050(http://akizukidenshi.com/catalog/g/gP-12628/)の500mA型番でも大丈夫です。 高さがあるので、足の曲がっているところをまっすぐにして、奥まで押し込むか、
取り付けた後にぐにっと曲げる必要があります。
でも、この曲がりまっすぐにしてよいものかとも思いますが、気にしない事にします。

・BS170

http://akizukidenshi.com/catalog/g/gI-09724/
液晶のバックライト制御用のFETです。

・100kΩ

http://akizukidenshi.com/catalog/g/gR-16104/
液晶のバックライト制御用FETのゲート放電用です。

・10Ω

http://akizukidenshi.com/catalog/g/gR-16100/
液晶のバックライト制御用FETのゲートへの突入電流制限用です。
マイコン保護用に入れてます。
#YM2608ボードでは金属皮膜抵抗の10Ωも利用していますので、そちらがあるならこの炭素皮膜は不要です。

・47Ω

http://akizukidenshi.com/catalog/g/gR-08518/
液晶のバックライトLED用の電流制限抵抗です。
1/6Wサイズですが、許容電流が1/4Wな金属皮膜抵抗を利用しています。

・1uF x2

http://akizukidenshi.com/catalog/g/gP-04066/
液晶内蔵のレギュレータ用のコンデンサです。
0.1uFでもいけそうなんですが、液晶の説明書には1uFと書いてあるのでそのままです。

・AQM0802A-FLW-GBW

http://akizukidenshi.com/catalog/g/gP-09422/

非常に高価で脆いバックライト付きI2C接続キャラクタ液晶です。
液晶本体は非常にデリケートです。液晶の端子に少しでも負荷をかけると直ぐ壊れます。
ぱきっとか音が鳴ったらもう壊れています。
この液晶はマイコンの上にかぶせる形で配置されます。この液晶をつけてからマイコンの接触不良が判明した場合、修正時に液晶の取り外しが必要になります。
液晶は必ず最後に取り付けるようにしてください。
PCに接続して、COMデバイスが認識されるか動作を確認するなど、マイコンが完全に動作することを確認してから取り付けるようにしてください。

・ピンヘッダ等

http://akizukidenshi.com/catalog/g/gC-05779/
http://akizukidenshi.com/catalog/g/gC-02960/

電池基板とメイン基板の間を繋ぐピンヘッダです。
通常のピンヘッダ(http://akizukidenshi.com/catalog/g/gC-00167/)では、 電池基板との間のスペースである15mmに対応できません。
この為、長めの部品を15mmに加工して利用しています。
その昔、かつての場所にあった千石電商ではそのものずばりの15mmがあったのですが、何処に消えたのか見つかりません。
あ、PICKIT3接続用のピンヘッダも用意してください。

・RFB3-10 x4

http://akizukidenshi.com/catalog/g/gP-07475/
金属スペーサーです。100個入りと間違えないでください。
両端ともメネジとオネジ・メネジなどの違いがあります。
10mmじゃなくて8mmくらいがあるといいのですが。

・RMB3-15 x4

http://akizukidenshi.com/catalog/g/gP-07482/
金属スペーサーです。100個入りと間違えないでください。
先頭の型番で両端ともメネジ、片側がオネジ・メネジなどの違いがあります。
金属スペーサーなので、基板の端子に接触させたり、レジストが剥がれた状態で基板に接触させないでください。
芋半田などしなければ接触しませんし、基本GNDパターンの上に配置されています。
心配な場合は、ポリワッシャー(https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=2AME-MAEH)を追加してください。

・M3x10 x8

http://akizukidenshi.com/catalog/g/gP-10245/
金属なべ小ねじです。
長さが異なるものがいくつか売られています。
リンク先は6mm品です。実際には5mmを使っていますが、100個入り(http://akizukidenshi.com/catalog/g/gP-07325/)なのです。
たぶん問題ないとは思うのですが、心配なら5mm品を調達してください。

・シリコンサーマルパッド

http://akizukidenshi.com/catalog/g/gP-06909/
厚みが足りないために、2枚重ねで使っています。
製品によっては妙に臭いものがあります。性能は高いのでしょうけど、
携帯して持ち運ぶのでこだわりたいところですが、匂いは注文画面から伝わってきません。

・AE-XCL102D503CR-G

http://akizukidenshi.com/catalog/g/gK-13065/
5V昇圧コンバーターです。
5V未満の電圧しか対応していませんので、電池ボックスを4本にした場合、
Eneloopではなくアルカリ電池を4本入れると許容電圧をオーバーします。注意してください。

・SK-12D01-VG4

http://akizukidenshi.com/catalog/g/gP-08789/
基板取り付けのスライドスイッチです。

→残念ながら取り扱い終了した模様です。
後継部品ではありませんが、
https://akizukidenshi.com/catalog/g/gP-15703/
が使えます(ちょっとスイッチの樹脂部分が短いです)

・6ピンICソケット

http://akizukidenshi.com/catalog/g/gP-08617/
6ピンものなんてあったんですね。
8ピンを加工するのも汚くなるので省略。

・BH-431-1A150

http://akizukidenshi.com/catalog/g/gP-03195/
単4x3本の電池ボックスです。
4本ものでもたぶんスペース的に問題なく収まると思いますが、昇圧コンバーターの説明文を読んでください。注意点があります。
間違えて単3バージョンの電池ボックスを買わないでください。15mmに収まりません。

・0.1uF

http://akizukidenshi.com/catalog/g/gP-00090/
他でも使われているので説明は省略。

・耐熱テープ(ポリイミドテープ幅)15mm幅

http://akizukidenshi.com/catalog/g/gT-09380/
携帯して持ち運ぶなら、絶縁の為に電池基板の背面の端子を絶縁したほうがよいです。
また、メイン基板の裏も電池と接触する危険性があるのでこちらも絶縁してください。
ビニールテープ等は汚くなるので、頑丈なポリイミドテープを使っています。


■YM2608音源ボード部品リスト

部品は、セクション別に記述しているので、同じ部品が再度登場します。
注文用に数をカウントする場合は注意してください。

#v1.4基板で挑戦される方は補足情報を一番下に記載しています。そちらも参照してください

回路図

#v1.6基板は出力部分でL/Rが反転しているのみ
2019/9/16 追記:ノイズ対策部品が追加されていることが発見されました
rev1.6差分 C7は100uFって書いてありますけど実際は10uFです

部品配置

  #v1.6基板の部品配置はv1.5と変更ありません

全体

メインパーツのみ抽出

抵抗のみ抽出

コンデンサのみ抽出

rev1.6差分

物理配置図


基板スペースが大きいため比較的楽に部品を半田付けできると思います。
マイクロSDカードスロットを実装する時に、電源用レギュレータと隣接しているため、
使用する半田ごてによっては、半田付けの順番を考慮してください。
また、ADPCM用のメモリはYM2608の下に配置されるため、この部分で不良が出た場合、
かなり修正が難しいです。

・基板

普通の黒レジスト、有鉛ハンダレベラー仕上げです。
ENIG(金メッキ)より安価ではありますが、非常に半田付けしやすいです。

・PIC32MX270F256D

https://jp.rs-online.com/web/p/microcontrollers/8417576/
2608ボードでは、マイコン→FM音源チップの配線がうまく配線できているかは、USBコマンドで信号線テストを行うことでも確認することができます。
簡単なCOMポート用のプログラムを作成し、各制御信号線、データ線を1,0してみて電圧が3.3Vもしくは0Vになるかをテスターにより確認することができます。USBのコマンドについては下にあるUSBコマンド表を参照してください。

・10uF

http://akizukidenshi.com/catalog/g/gP-05103/

・水晶8MHz(PIC用)

http://akizukidenshi.com/catalog/g/gP-08667/

・22pF x2

http://akizukidenshi.com/catalog/g/gP-04060/

・10kΩ

http://akizukidenshi.com/catalog/g/gR-16103/

・0.1uF

http://akizukidenshi.com/catalog/g/gP-00090/
上記部品群は、携帯FM音源プレイヤーと同じなので省略します。

・タクトSW

http://akizukidenshi.com/catalog/g/gP-03648/
1つ10円(100個詰め合わせだと7円)のタクトスイッチ。
結構耐久性に欠ける気がしてならないのですが、そこまで押さなければたぶん大丈夫。
ここではリセットスイッチと、曲周りのスイッチの計4つ使っています。
リセットスイッチは省略してもかまいません。

・YM2608B

・YM3016D

OPNAチップと専用DACです。
これもYM2151と同様に手に入れてください。

・74HC04

http://akizukidenshi.com/catalog/g/gI-08596/
インバーターです。YM2608のメモリアクセスは正論理なのです。なぜか。
一般的なチップのCEは負論理なので、反転が必要なのです。

・TLC2274AIN

https://jp.rs-online.com/web/p/op-amps/6611612/
これも携帯FM音源と同じです。(ピン互換があるOPAMPでも大丈夫です)
TLC2274INとTLC2274AINを混じって買っているので、これにはAIM型番がつけられていますが、どっちでも大丈夫です。
#A型番は計測器用に差動回路が非常に敏感になっていると製品だと思います

・M11B416256A-35J(4Mbit)

http://akizukidenshi.com/catalog/g/gI-01451/
4MBit(512KB)のDRAMです。
YM2608のADPCM用です。256KBでよいので実際には半分しか使っていません。
なのでYM2608にDRAMに書き込みをさせつつ、マイコンで余っている1ビットを制御してやれば
実は2バンク使えるのではないかとも思いましたが、やってないところを見ると、このメモリアドレス線は256KB分しかなく、16ビット接続で512KBだった気がします。たぶん面倒になってやめました。

・0.1uF

省略

・水晶8MHz(YM2608用)

https://jp.rs-online.com/web/p/crystal-oscillators/7675333/
正方形タイプの水晶発振器です。
秋月の取り扱いが・・今現在終了しています。別で手に入れてください。
うー秋月…
実はマイコンの8MHzと同じなので、そっちから引っ張っても良かったかも。

・ソケットS64ピン

http://akizukidenshi.com/catalog/g/gP-04602/
64ピンはピン間1.778mmのシュリンク品です。1つ200円もする高価な部品です。
板バネ式は50円と脅威の価格差です。

・ソケット14ピン x2

http://akizukidenshi.com/catalog/g/gP-00028/
丸ピンICソケットです。
14ピン,16ピンは携帯FM音源プレイヤーと同じですので省略します。

・ソケット16ピン

http://akizukidenshi.com/catalog/g/gP-00029/
丸ピンICソケットです。
14ピン,16ピンは携帯FM音源プレイヤーと同じですので省略します。

・0.1uFx4

http://akizukidenshi.com/catalog/g/gP-00090/
省略

・10kΩx8

http://akizukidenshi.com/catalog/g/gR-16103/
ADPCM用メモリチップのプルダウン用抵抗です。
なくても動く気がしますが、未接続は誤動作の元なので処理しています。
※10kΩの抵抗は別の場所でも使われています。数をカウントする場合は必要な数を合計してください

・MUSE50V 10uFx3

http://akizukidenshi.com/catalog/g/gP-04638/

・MUSE50V 4.7uFx5

http://akizukidenshi.com/catalog/g/gP-04637/

・1000pfx4

http://akizukidenshi.com/catalog/g/gP-07673/

・1500pfx2

http://akizukidenshi.com/catalog/g/gP-08133/

・8.2kΩx4

http://akizukidenshi.com/catalog/g/gR-16822/

・1kΩ〜3.9kΩx4

http://akizukidenshi.com/catalog/g/gR-16102/
http://akizukidenshi.com/catalog/g/gR-16392/
携帯FMと同じなので省略します。
基板のシルク印刷には極性が印刷されていますが、MUSEコンデンサは無極性なのでどちらの方向でもかまいません。
3.9KΩはアンプのライン入力に接続する場合に使ってください。
イヤホン等の場合は1K(それでも小さく感じる場合は470Ω等)にしないと、音が小さいかもしれません。
USB電源で駆動する場合、3.9kΩから抵抗を小さくするとUSB電源からのノイズに弱くなります。
#抵抗を小さくしたけどやっぱ小さいです。あきらめてアンプ前提ですね。

・10Ω(5V用)

http://akizukidenshi.com/catalog/g/gR-08515/
10Ωですが、金属皮膜の大電流用です。
こちらは5VのUSB電源からDACのアナログ系に流れるところでノイズ低減の為に入れています。

・1kΩ(SSG用)

http://akizukidenshi.com/catalog/g/gR-16102/
SSG音源はある程度電流を流さないと出力が出てきません。
電流を流すための抵抗です。

・270Ω

http://akizukidenshi.com/catalog/g/gR-16271/
DAC用です。携帯FMと同じなので省略

・4.7KΩ

http://akizukidenshi.com/catalog/g/gR-16472/
DACに使っています。

・3.5φS-MiniJack MJ-8435

http://akizukidenshi.com/catalog/g/gC-09060/
省略します。

・10kΩ半固定抵抗

http://akizukidenshi.com/catalog/g/gP-06063/
SSGのミキシングボリュームに使っています。
これもオリジナル部品を作っていたメーカーがディスコンになったので、セカンドソースメーカーに切り替わっています。
電子ボリュームチップ(2500円)は高いのです。
ちなみに英語名はポテンショメータです。微妙に覚えてない名称で困ります。

・OSB5XA7DA4B-GH

http://akizukidenshi.com/catalog/g/gI-02754/

・680Ω

http://akizukidenshi.com/catalog/g/gR-16681/
LEDと電流制限抵抗です。携帯FM音源と同じなので省略します。

・AQM0802A-FLW-GBW

http://akizukidenshi.com/catalog/g/gP-09422/

・BS170(FET)

http://akizukidenshi.com/catalog/g/gI-09724/

・100kΩ

http://akizukidenshi.com/catalog/g/gR-16104/

・47Ω

http://akizukidenshi.com/catalog/g/gR-08518/

・10Ω

http://akizukidenshi.com/catalog/g/gR-16100/
上に5V用と書かれた大電流用の抵抗でも構いません。

・1uFx2

http://akizukidenshi.com/catalog/g/gP-04066/

・10kΩx2

http://akizukidenshi.com/catalog/g/gR-16103/
LCD及びバックライト制御、I2C抵抗です。
携帯FMと同じなので省略します。

・タクトSW x3

http://akizukidenshi.com/catalog/g/gP-03649/
http://akizukidenshi.com/catalog/g/gP-03651/
http://akizukidenshi.com/catalog/g/gP-03650/
リセットSW側で出てきたので省略します。

・USB-MiniB

http://akizukidenshi.com/catalog/g/gC-02235/

・DM3AT-SF-PEJM5

http://akizukidenshi.com/catalog/g/gC-02395/
USBMiniBコネクタとマイクロSDカードスロットです。
携帯FM音源と同じです。

・ピンヘッダx2

・ピンヘッダ2x2

http://akizukidenshi.com/catalog/g/gC-00167/
または
http://akizukidenshi.com/catalog/g/gC-00082/
携帯FMで解説しています。
ロングピンではなく、通常のピンでOKです。
USB側の電源のみでACアダプタを使わない場合は、省略し、ジャンパ線でショートさせてかまいません。
PICKIT3接続用のピンヘッダも用意してください。

・ジャンパピンx2

http://akizukidenshi.com/catalog/g/gP-03689/
ACアダプタを使わず、USBから供給する場合はピンヘッダにジャンパピンをセットし、電源を供給してください。
ジャンパが不要な場合は、直接ブリッジしてもかまいません。

・DCジャック

http://akizukidenshi.com/catalog/g/gC-01604
シンガトロン社製のジャックです。
マル信のでもかまいません。(http://akizukidenshi.com/catalog/g/gC-00077/)
が、ACアダプタを使わずUSB接続だけで電力供給するならば要りません。
あ、接続するACアダプタの電圧は5Vで、センタープラスになります。今時のACアダプタ(http://akizukidenshi.com/catalog/g/gM-01801/)ならOKです。

・NJM2845

http://akizukidenshi.com/catalog/g/gI-11299/
省略。3.3V用を使います。

・OSコン16V 220uF

http://akizukidenshi.com/catalog/g/gP-08291/
OSコンの220uFバージョンです。別に100uFでも大丈夫だと思いますが、大きさ的に220uFがちょうどいいサイズにしています。
極性があります。

・0.1uF x2

・RXEF050

http://akizukidenshi.com/catalog/g/gP-01355/
500mA品です。


■ファームウェア

ファームウェアの書き込みにはMPLAB X IPEを使います。
https://www.microchip.com/mplab/mplab-x-ide
からダウンロードしてください。
表示されたページのやや下に、Features Downloads Documentation..のようなタブがあります。
Downloadに切り替えてください。
一番上にあるWindows MPLAB X IDE〜をダウンロードしてください。サイズは800MBくらいあります。でかい。

私が現在使っているバージョンは、MPLAB X IDE v3.2なので、結構昔のバージョンでした。
最新でもMPLAB IPEなら大丈夫だと思いますが、もしも最新にIPEが入っていない場合や同じバージョンを使いたい場合は、以下のアーカイブからDLしてください。
https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive
一番左の列 Windowsのv3.2になります。

インストールすると、MPLAB X IDEと、今回必要なMPLAB X IPEが入ります。
自分でオリジナルファームウェアを作成する場合は、IDEを使って開発することができます。
XC32コンパイラも同時にDLしてください。
#XC有料版だとコンパイラの最適化を有効にすることができます。無料版はいまいち最適化なので、実行サイズなどがまさしくいまいち

PICKITから電源を供給する設定を入れてください。
ファームウェアを読み込み、書き込みボタンを押します。
PICKIT3と基板の接続は、以下のように接続してください。
#逆に接続した場合チップが認識できません。速やかに外してください。とりあえず何回も間違えていますが、壊れてはいないようです。ヨカッタ

・接続の仕方:携帯FM音源プレイヤーの場合



PICKITにピンヘッダを接続し、1番ピンが写真と一致するように接続してください。
逆にも接続できてしまいますが、プログラムは書き込みできずエラーになります。

ある程度製作してから書き込む場合、完成した後ファームウェアを書き直す場合、
周りに部品が多いため、基板裏面の反対側から接続して書き込む方が楽だと思います。

・接続の仕方:YM2608サウンドボードの場合



PICKITにピンヘッダを接続し、1番ピンが写真と一致するように接続してください。
逆にも接続できてしまいますが、プログラムは書き込みできずエラーになります。

基板端から書き込みできるので、L字型のピンヘッダを使うのも楽だったりします。
#あれ、なんか微妙にPICKITがずれて映ってた…。ちゃんとさしてください。このまま書き込むと一発で壊します

・ファームウェアの書き込み方


PICKIT3をターゲットボードに接続する準備ができたら、MPLAB Xをインストールすると
一緒にインストールされるMPLAB IPEを起動します。

MPLAB IPEは古典的なダイアログベースのアプリケーションのように見えます。
画面サイズが1024x768くらいないと、ボタンが画面外に飛び出てしまい、押すのが困難だったりするのでなんとかしてください。
※画面キャプチャはLATTE PANDAでやっています。1024x600なので画面を回転させないと押せませんでした。

起動したらドロップダウンリストから以下を設定してください。

Familyは All Familes
Deviceは PIC32MX270F256D

を選びます。



PICKIT3が接続されていれば、ToolのところにPICKIT3とシリアルナンバーが出ます。
※上の画面では接続していないので、エラーになっています。

上部メニューからFile > Import > Hex
を選び、ファームウェアのHEXファイルを選びます



再び上部メニューSetting > Advanced Mode

を選びます。

なにやらUACのようなパスワード画面が出ます。管理者としてログインしてください。Logonボタンを押します。



左のメニューでPowerのボタンを押します。
下のほうにあるチェックボックス「Power Target Circuit from Tool」にチェックをつけます。(電源をPICKITから供給するのオプションです)
左のメニューでOperateボタンを押し、最初の画面に戻ります

接触不良にならないように、PICKIT3の端子をターゲットボードに接続します。
ちょっとだけテンションをかけてきっちりと接続するようにするとよいでしょう。
部品が実装済みである場合、ピンヘッダが届かないかもしれません。
その場合は、裏面からアクセスします。この場合は、左右が反転している事に注意してください。

Tool欄の右にあるConnectボタンを押します

正常に接続されたら、画面中央のProgramボタンが押せるようになります。

押してから、20秒ほどかかります。
書き込み中に少しでも接触不良になるとマイコンが破壊されます。
注意してください。
もしも不安があるのなら、書き込み用の配線を追加し、きっちりPICKITと接続してください。

参考に正常に書き込めた場合のログを貼り付けておきます。
2018-11-17T18:55:59+0900- Completed loading IPE.

2018-11-17T18:58:45+0900- Loading hex file. Please wait...
Loading code from C:\Users\LattePanda\Desktop\2151firmware.hex...
2018-11-17T18:58:46+0900- Hex file loaded successfully.


*****************************************************

Connecting to MPLAB PICkit 3...

Currently loaded firmware on PICkit 3
Firmware Suite Version.....01.40.13
Firmware type..............PIC32MX

Programmer to target power is enabled - VDD = 3.300000 volts.
Target device PIC32MX270F256D found.
Device ID Revision = A2
2018-11-17T19:09:01+0900- Programming...

The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x3f7ff
boot config memory
configuration memory

Device Erased...

Programming...
Programming/Verify complete
2018-11-17T19:09:25+0900- Programming complete
Pass Count: 2

書き込みが終わったら、Disconnectを押します。
PICKITを外します。
#Disconnectを押さずにそのままぱっと取っちゃいますが、たぶんこれが正式な手順なのでしょう

MPLAB IPEについて詳しく知りたい方は、Microchipのドキュメントを参照してください。
http://ww1.microchip.com/downloads/jp/DeviceDoc/50002227B_JP.pdf


・MPLAB最新版(v5.1)でのインストールについて


ためしに最新版(https://www.microchip.com/mplabx-ide-windows-installer)を入れてみました。

1.インストーラーを起動します。


2.利用規約に同意します。


3.インストール場所を選択します。


4.インストールオプションを選択します。
MPLAB IPEには最初からチェックがついていると思いますが、チェックがついていることを確認してください。
一番下のオプションはイヤなら外してください。


5.インストールします。


6.最後あたりにATMELの何かをインストールするか聞いてくるのですが不要です。キャンセルでOK。
デフォルトでしないにフォーカスが当たっていますし。


7.情報が出る場合があります。昔のも入っているとでるかも。
出た場合はOKを押します。


8.インストール後にコンパイラなどを入れるかを聞かれます。
MPLAB IDEで開発もします!って言う人は是非入れてみてください。

ファームウェアを書き込みたいだけの人はチェックを外して入れてください


9.MPLAB IPEを起動します。


10.MPLAB IPEが起動しました。
PICKIT3を接続しておかなかった場合は、この段階でPICKIT3を接続しておきましょう。
かってにToolのところが更新されます。
次に、チップを選んでおきましょう。「PIC32MX270F256D」を選択してください。


11.HEXファイルを読み込みます。

#なんだかグレーアウトして読み込めない事も多いみたいなので、そういう時は画面中央にあるHex File欄のブラウズボタンを押して読んだ方が早いです

12.チップを選択して「PIC32MX270F256D」を選択します。
※この時に違うチップとか選択した状態だと、実はちゃんと読み込めていません。
 スクリーンショットは読み込んだみたいに見えているのですが、チップを選択していない状態でHEXを読み、
 その後にチップを選択しています。すると、真ん中のグレーのエリアの「Hex file:」のところがグレーのままです。
 もうチップ選択から一度やり直しです。
 左のメニューみたいなのは、13以降で切り替えるAdvancedメニューの画面です


13.Advancedモードに切り替えます。


14.このときパスワードを聞かれますが、デフォルトは「microchip」と書いてあるので、入力してください。


15.左にメニューが追加されるので、「Power」ボタンを押してください。
右に電源設定メニューが出てくるので、「Power Target circuit from Tool」にチェックを入れてください。
終わったら「Operate」メニューに戻しておきます。


16.ターゲットボードにPICKITを接続して、Toolの横にあるConnectボタンを押します。
この時にPICKITが初期設定のままだと、PICKIT自体のファームウェア更新が開始されます。
数分程度またされます。
※この画面では、チップ選択を後から替えた為に、Hexファイルの表示がグレーアウトしたままです。


17.もし、Connectボタンを押した時点で、画面のようなメッセージ「電力不足」が出た場合は、以下の対策を行ってください。
・ターゲットボードからマイコン以外のチップを外す
・ターゲットボードのUSBから電源を供給する
製作途中の場合は、LEDの点滅を確認するために最低限マイコンが動作する部品をつけたところなどで確認していると思うので、
たぶんでないと思います。
ちなみに今回はチップを外すのが面倒だったので、USBコネクタから電源を供給しています。


18.Hexファイルが選択されていて、Connectにも成功していれば、Programボタンを押してください。
ファームウェアの書き込みが開始されます。およそ20秒ちょいかかります。
!!書き込み中に接触が悪くなるとマイコンが破壊されます!!


19.無事に書き込みが完了しました。
この時にLEDなどが実装されていれば、書き込み完了した瞬間からLEDが点滅を開始します。


・MPLAB最新版(v5.1)にしたついでにMPLAB SNAP(※書き込みにはかなり最新のMPLABが必要)でファームウェアを書いてみる




秋月で取り扱いが開始された激安PICプログラマ(兼デバッガ等)である、MPLAB SNAPでファームウェアが書き込めるかやってみました。

・初めて接続した時にデバイスドライバのインストールが実行されました。

・MPLAB IPEで初回コネクト時に、SNAPのファームウェアが更新されました。

・書き込みが、2秒程度で終わりました。PICKIT3の10倍くらい早いです。
 じっとしている時間が短くで済むのでいいかもしれません。
 #PICKIT4も早いらしいので、PICKIT3が遅いんでしょうか

とうわけでできるみたいです。
が、ひとつ気になったのは、ファームウェアの書き込み時に電力が不足していた場合でも、そうとわかる通知メッセージが出なかったことでした。
デバイスIDが0、ターゲットデバイスが検出できないといったエラーがでます。接続を間違えたのかと思いましたが、
ターゲットボードにUSBから電力を供給した状態にしたら無事認識。書き込みできました。
#今やったらデバイスのコード領域がプロテクトされていると出ました。やっぱり電力を供給してやりながら書き込めば成功しました
・・・ていうか、MPLAB SNAPってひょっとしてターゲットへの電源供給機能がない?
MPLAB IDEだと電源供給メニューが出てきません。


ちなみにSNAPは8本接続できるのですが、ターゲットボードには▲マークから5本分接続するだけでOKです。
ピンが余るのはPICプログラマの伝統みたいなものです。(余ったピンはPICに書き込む以外で使ったりします)

■ファームウェア・支援ソフトウェア

・PCに繋いだ場合と開発ツールについて

携帯FM音源プレイヤー及びYM2608音源ボードは、PCに接続すると仮想COMポートとして認識されます。
PCからはこのCOMポートを通じて制御することができます。
ドライバはそのまま標準ドライバで認識されると思うのですが、もし認識されない場合は、フェームウェアの
書き込みで使うMPLAB Xをインストールしていれば認識すると思います。

サンプルのプログラムは仮想COMポートが3もしくは4として認識されることを規定値にしています。
他のポートの場合は引数で指定するか、USBへの差込位置を変更して認識されるようにしてください。
同時に他の仮想COMポートを使用するソフトを利用していた場合、悪影響を与えることがありますので、
そういった場合は、他の仮想COMポートのソフトやハードを外してください。

※COMポートの設定はデフォルト値(9600bps等)で構いません。
9600bps設定のままでも、プログラムから叩く分には115200bps以上出ます。
これはこのボードが仮想COMポートそのものだからです。
このボードから外部に通信する場合は、設定を見て速度を決定しますが、ボードそのものがCOMポートなので
ボードへの通信は速度設定に影響されません。

Windows側のプログラムの開発には、VisualStudio 2010 C++ Expressでコンパイルしています。

https://visualstudio.microsoft.com/ja/downloads/
にアクセスします。
下のほうにある「以前のバージョン」を選びます。
出てきた画面からVisualStudio2010を選びます。
なんかMSアカウントを聞かれるのでログインします。
ダウンロードがありません。が出ます。
あれ?

しょうがないので「Expressをお探しの方は」を押して、後継製品であるVisualStudio2017CommunityをDLしましょう。
たぶんコンパイルできます。たぶん・・・

・VisualStudioランタイムについて

以下のコンパイル済みソフトウェアを利用する場合、msvcpr100.dll等のVisualC++ランタイムがないといわれる場合があります。
その場合は、以下のVisualStudio2010 Runtime再頒布可能パッケージを入れてください。
https://www.microsoft.com/ja-jp/download/details.aspx?id=5555

・携帯FM音源プレイヤー用 ソフトウェア

携帯FM音源プレイヤーファームウェア

■rev.2023/6/17 v1.81
2151firmware_v181.zip (基板バージョン1.4以上)
2151firmware_r12_v181.zip (基板バージョン1.2,1.3用)
・VOL+-ボタンをディレクトリ移動+-に変更するSwitchChangeオプションを追加
 今までは、ポーズ後に右ボタンでディレクトリをスキップできましたが、このオプションを有効にすると
 VOL+-ボタンで直接、次のディレクトリや前のディレクトリの先頭曲に移動することができます

※ブートローダー用のFWです。まずブートローダーを書き込んでから、ブートローダーを使った更新手順を使ってファームウェアを更新してください。

■rev.2023/3/9 v1.80
2151firmware_v180set.zip (基板バージョン1.4以上)
2151firmware_r12_v180set.zip (基板バージョン1.2,1.3用)
・ブートローダー対応のファームウェアになりました。更新にはWindowsPCが必要になります
 ファームウェアの更新方法が異なります。詳細については同梱している「ファームウェア更新方法.txt」を参照してください。

※ブートローダとは、一度PICKITで書き込めば、以降の更新はPICKITなしで更新ができるようになるファームウェアです。

■rev.2022/11/19 v1.73
2151firmware_v173.zip (基板バージョン1.4以上)
2151firmware_r12_v173.zip (基板バージョン1.2,1.3用)
・VGMファイルで正常にループしない場合がある問題に対処
・一部テキストをSCCIに修正
・従来のUSBモードを廃止し、OPNAM(4759)と同じシリアルコンソールモードに変更
SCCIには自動的に切り替わります

TeraTermなどのコンソールをご利用ください。改行コードはLFしか送ってきませんので、LF→CRLF変換してください。
基板作成時のピン半田付け確認などが便利に使えます。
下に使い方を記載しました。注意点もあるので、使う前にお読みください。

■rev.2022/3/18 v1.72
2151firmware_v172.zip (基板バージョン1.4以上)
2151firmware_r12_v172.zip (基板バージョン1.2,1.3用)
・8+3ファイル名でソートするオプションを追加

■rev.2021/7/8 v1.71
2151firmware_v171.zip (基板バージョン1.4以上)
2151firmware_r12_v171.zip (基板バージョン1.2,1.3用)
・v1.70で拡張した16バイトのconfig.cfgファイルを読み込まない問題を修正 (8バイト以上を読み込むように修正)

■rev.2020/8/17 v1.70
2151firmware_v170.zip (基板バージョン1.4以上)
2151firmware_r12_v170.zip (基板バージョン1.2,1.3用)
・PLL-IC(Si5351a)搭載版の基板用にI2Cにクロック制御情報を出力するようになりました。(有効になるのは1.6以上のみで、従来基板では切り替え情報は追加ハードウェアがないと無視されます)
・以下のメニューを追加しました。
 液晶のGEQもどきをOFFにするオプションを追加しました
 ハードリセットしないソフトリセット(キーオフのみ)オプションを追加しました
 Playlistファイルがあっても再生しないオプションを追加しました
 Holdオプションを追加しました(設定ファイルの内容を反映した後に、ボタンを押すまで何もしないモード)
 ハードリセットするマニュアルリセットメニューを追加しました
・USBのCOMポート制御を最新版に交換しました
・メニュー追加に伴い、設定ファイルのサイズが8バイトから16バイトに増加しました。
 動作がおかしくなりますので、一度マイクロSDカードからconfig.cfgファイルを削除してください。

■rev.2019/10/22 v1.62(実験版FW)
2151firmware_v162.zip (基板バージョン1.4以上)
2151firmware_r12_v162.zip (基板バージョン1.2,1.3用)
・VGM,S98再生時、EXT端子基板内側(RA10)に3.58MHz識別用信号を出力
 曲データに記録されている2151クロック情報が3.8MHz未満の場合にHレベル(3.3V)になります
・SDカード挿入待ちの時に右ボタン長押しで3.58MHz信号を有効・無効に切り替え

※EXT端子をGND代わりに使っている場合はご注意ください
 単純にNANDで組むと4〜8エレメントくらい必要になるんですがいいスイッチング素子ないですかね。なにかありそう

■rev.2019/9/28
2151firmware_v161.zip (基板バージョン1.4以上)
2151firmware_r12_v161.zip (基板バージョン1.2,1.3用)
・プレイリスト対応
 ■プレイリスト仕様
  ルートに置かれた2047バイト以下のplaylist.txtファイル。
  8+3ファイル名,コメント文<改行>
  8+3ファイル名,コメント文<改行>
  …
  8+3ファイル名のみです。パスは対応していません。ルートに演奏対象のファイルを置いてください。
  512エントリまで。(ファイルサイズ的に無理ですが)
  見つからないファイル、既定の書式に沿っていない行は無視します。
  1行は255バイトまで。使える文字コードについては、AQM0802のデータシートを参照してください。
  コメント文をGEQの代わりに液晶下段に表示する場合は、ConfigメニューのCommentを変更してください。
  ex.
  sample1.vgm,Theme of Sample 1
  smp2.mdx,samle file no.2
  sample03.s98,Sample of sound

■rev.2019/9/21
2151firmware_v160.zip (基板バージョン1.4以上)
2151firmware_r12_v160.zip (基板バージョン1.2,1.3用)
・CPUクロックを40MHzから48MHzに変更
・クロック上昇に併せて内部タイミング値更新。(s98,vgm,mdxのテンポ計算値、液晶更新頻度)
・I2C液晶の速度を4759と同じ数値に設定(16→18)
・SPFMモード時のCPU開放タイミングを4759と同様に変更(spfm 1ms,spfm light 1.5ms)

■rev.2019/4/13
2151firmware_v155.zip (基板バージョン1.4,1.5用)
2151firmware_r12_v155.zip (基板バージョン1.2,1.3用)
・パンを左右逆にするオプションを追加
・その他細かい修正(Config周りのバグ)

■rev.2019/3/26
2151firmware_v154.zip (基板バージョン1.4用)
2151firmware_r12_v154.zip (基板バージョン1.2,1.3用)
・SPFM、SPFMLightの速度を改善しました(4759ベースの処理にしました)
・ファームウェアのバージョン表示メニューを追加しました

■rev.2019/3/9
2151firmware_v153a.zip (基板バージョン1.4用)
2151firmware_r12_v153a.zip (基板バージョン1.2,1.3用)
・SD速度計測メニューを追加しました

■rev.2019/2/22
2151firmware_v153.zip (基板バージョン1.4用)
2151firmware_r12_v153.zip (基板バージョン1.2,1.3用)
・1.52cをSanDisk製MicroSDに対応させました
・ボタンウェイト時間を200msに変更しました
※たぶん従来使えていたSDカードがまた使えるようになったのではないかと思われます

■rev.2019/2/19 実験用 1.52b -> 1.52cに更新しました
2151firmware_v152c.zip (基板バージョン1.4用)
2151firmware_r12_v152c.zip (基板バージョン1.2,1.3用)
・SDカードアクセス時のウェイトをさらに減らしました。SDカードアクセスが問題ないか確認用です。
・LCD表示のウェイトを減らしました。(LCDが表示されなくなったら教えてください)
・VGM再生をウェイト制御からサンプル値制御に変更しました。
・S98,VGMファイル再生時のキャッシュ制御を削除しました。
・VGM再生を累積サンプリング値で処理されるように再度調整しました。(1.52c)
・mxdrvでないMDXドライバを削除しました。メニューからサウンドドライバ設定も合わせて削除しました。(1.52c) ※MDXが再生できなくなるわけではありません
・セーブ後にSDカードから読み込みができない問題に対処しました。(1.52c)
・キャッシュ読込みがない為、ボタン感度が良くなりすぎていたので250msのボタン操作後ウェイトを追加しました。(1.52c)
※現状のSDカードが使えなくなる可能性もありますので、実験協力できる人向けです
ちなみに動作確認は秋月のマイクロSDカード16GB(http://akizukidenshi.com/catalog/g/gS-13002/)で確認してます。
SPIモードなので、本来のカードの性能が発揮できるモードではありませんので、性能が良いカードが早いとは限りません・・・

■rev.2019/2/16
2151firmware_v152.zip (基板バージョン1.4基板用)
2151firmware_r12_v152.zip (基板バージョン1.2,1.3基板用)
・ポーズ中に進むボタンを押すことで、現在のディレクトリをスキップする機能を追加しました
※サブディレクトリ内のファイルを再生していない場合は効きません。サブディレクトリ設定が有効で無い場合は従来通りのファイル名表示のままです。

■rev.2019/2/15
2151firmware_v151.zip (基板バージョン1.4基板用)
2151firmware_r12_v151.zip (基板バージョン1.2,1.3基板用)
・s98,vgm再生時にループブレイカー設定をOFFにしても、2ループで中断される問題を修正
・ファイルスキャン時に容量制限でファイルがスキップされる場合がある問題を修正

■rev.2019/2/9 (実験版)
2151firmware_v150.zip (基板バージョン1.4基板用)
2151firmware_r12_v150.zip (基板バージョン1.2,1.3基板用)
・サブディレクトリに対応しました。第一階層のみ再生対象となります
・SDカードからの再生で表示される番号がディレクトリエントリからバッファ番号に変更になりました
・s98形式のファイルを再生する際の同期値を割り込みを使用して正確に計算するように変更しました
※なお、サブディレクトリにシャッフルは適用されません

■rev.2019/1/30 (実験版)
2151firmware_v142.zip (基板バージョン1.4基板用)
2151firmware_r12_v142.zip (基板バージョン1.2,1.3基板用)
・VGM形式のファイルを再生する際の同期値を割り込みを使用して正確に計算するように変更しました

■rev.2019/1/26 (実験版)
2151firmware_v140.zip (基板バージョン1.4基板用)
2151firmware_r12_v140.zip (基板バージョン1.2,1.3基板用)
・ボリュームの変化量を調整しました。中央値16近辺を細かく、最大値は音色が破綻するのでやや下げています
・YM2151用のs98ファイルの再生に対応しました(が、一部環境では再生されない現象が。謎)
・SPFM Lightモードを搭載しました。メニューから変更することができます。SDカードがある場合は設定値が保存できます
 SDカードがない場合は「sd plz insert」が表示されている最中に、左ボタンを長押しでlightモードとnormalモードを切り替えることができます。※scci configで任意にポート等の設定を変更したい場合にlightモードをお使いください

■rev.2019/1/17 (実験版)
2151firmware_v131.zip (基板バージョン1.4基板用)
2151firmware_r12_v131.zip (基板バージョン1.2,1.3基板用)
・SDカード内のVGMファイルの再生に対応しました。
 2ループ目の最後にフェードアウトを入れました。(1.31で対応)

■rev.2019/1/4 (実験版)
2151firmware_v120.zip
・SPFMインタフェースを追加しました。SPFMモードから通常モードに戻るにはUSBケーブルを外してください。(USB制御なので電池から電源を供給しないでください)
SPFMプレイヤーのサンプル曲で試しただけなので正常動作するかしら…

旧バージョン基板1.2では、ボタン配置が逆なことが判明しました。混乱する方は以下のファームウェアで更新してください。
2151firmware_r12_v120.zip

■rev.2019/1/2
2151firmware_v110.zip
・設定メニューにバックライト点灯時間の設定を追加しました。
 旧バージョンの設定ファイルがSDカードに残っている場合、点灯しないになってしまうので、設定しなおして「Save」で保存してください。
更新時の注意:ファームウェアの更新は失敗する可能性もあります。更新には十分注意してください。
電力が不足しているとよくわからないエラーが返って来ます。その場合は一度音源等の外せるチップを外すか、USBから電力を供給しながら更新してください。


■rev.2018/12/30 (安定版)
2151firmware.zip
MDXファイルを再生するプレイヤー用ファームウェアです。
PIC32MX270F256D用です。
ADPCMはありません。

マイクロSDカードはSDHC専用です。16GBの秋月電子のこのカードを利用しています。
FAT32でフォーマットされている必要があります。
SDXCも使えるかもしれません。(単なるSDはダメです)

左ボタンが戻る、真ん中が一時停止・再生、右ボタンが次へです。
左側にあるボタンは上と下はボリューム調整ですが、アナログボリュームではなくYM2151のTLパラメータの調整なので、
綺麗に増減しません。中央値16は無調整です。

再生中に一時停止して、戻るボタン(左ボタン)を押すと設定メニューモードに入ります。
2ループで抜けるか、曲ごとにYM2151をリセットするか等を設定できます。
※設定メニューのうち、ドライバ選択は上記ファームウェアでは変更できません。
Saveメニューで設定値をSDカードに保存します。(一瞬LEDが光れば保存されています)
#ですが保存処理は大変怪しいです。ファイルが少ないうちに一度セーブしてファイルを作成することをお勧めします
シャッフルは2000曲まで対応。unsigned shortで2000曲だと4K近くメモリを食うのです。

設定値はSDカードにファイルの形で保存されるため、SDカードが挿入されていない状態では設定が読み込まれていません。
#PIC32シリーズ(PIC24からのようですが)には、EEPROMである不揮発記憶領域がありません。MIPSコアになっていろいろ不都合があったのかと思われます

PCからMDXファイル転送プログラム

■rev.2018/12/30
2151play.zip

指定方法
ex.
2151play.exe sample.mdx
2151play.exe -com 3 sample.mdx
2151play.exe -com 3 -com 4 sample.mdx

PCから転送できるMDXファイルの最大サイズは50Kです。
キャッシュメモリとしてそれだけしか確保していない為です。
MDXの拡張フォーマットでは最大64KBなので、これよりサイズが大きい曲の場合は、
SDカードから読み込ませてください。キャッシュメモリに随時補充しながら演奏します。
プログラム本体とソースつき。オリジナルの制御PGを作るときは参考にしてください。

PCから携帯FMプレイヤーのSDカード制御プログラム

■rev.2018/12/30
2151sdtest.zip

PCから携帯FM音源プレイヤーに繋げられているSDカードを制御するためのプログラムサンプルです。
SDカードリーダーにもならなくもありません。
SDカードベンチマークの話をしよう(https://asmpwx.at.webry.info/201707/article_8.html)
の回でやっていたようなことができます。
使い方は・・ソース見てください。
ファイルロードなどはコメントアウトされていますが、たぶん使えると思います。
使い方忘れました。

・YM2608サウンドボード用 ソフトウェア

YM2608サウンドボード用ファームウェア

■rev.2020/2/15 v1.62
2608firmware_v162.zip
・タイマー周りのレジスタ書き込みを2608にも書き込むように変更

■rev.2019/9/28 v1.61
2608firmware_v161.zip
・USBからx86データの演奏開始コマンドを実行しても演奏が開始しない問題の修正
・SDカードアクセス時にLEDを点滅させないオプションの追加
・現在の2608がOPN(2203)モードかOPNA(2608)モードか確認・変更するオプションの追加
・プレイリストファイルの再生に対応
 ■プレイリスト仕様
  ルートに置かれた2047バイト以下のplaylist.txtファイル。
  8+3ファイル名,コメント文<改行>
  8+3ファイル名,コメント文<改行>
  …
  8+3ファイル名のみです。パスは対応していません。ルートに演奏対象のファイルを置いてください。
  512エントリまで。(ファイルサイズ的に無理ですが)
  見つからないファイル、既定の書式に沿っていない行は無視します。
  1行は255バイトまで。使える文字コードについては、AQM0802のデータシートを参照してください。
  コメント文をGEQの代わりに液晶下段に表示する場合は、ConfigメニューのCommentを変更してください。
  ex.
  sample1.vgm,Theme of Sample 1
  smp2.mdx,samle file no.2
  sample03.s98,Sample of sound

■rev.2019/9/22 v1.60
2608firmware_v160.zip
・CPUクロックを40MHzから48MHzに変更
・クロック上昇に併せて内部タイミング値更新。(s98,vgm,x86のテンポ計算値、液晶更新頻度)
・I2C液晶の速度を4759と同じ数値に設定(16→18)
・SPFMモード時のCPU開放タイミングを4759と同様に変更(spfm 1ms,spfm light 1.5ms)

■rev.2019/3/28 v1.56
2608firmware_v156.zip
・SPFM、SPFMLightの速度を改善しました(4759ベースの処理にしました)
・ファームウェアのバージョン表示メニューを追加しました
・LCD表示を分割処理し負荷を軽減しました
・ADPCMレジスタアクセス時のウェイト処理を対策

■rev.2019/3/9 v1.55
2608firmware_v155.zip
・2608データが含まれていないs98ファイルを再生するとそのデータを2608に流してしまう問題を修正

■rev.2019/2/23 v1.54,v1.54a
2608firmware_v154a.zip
・リズム音源のフェードアウト速度をADPCMと同じテーブルに変更(利きを強く)
・一時停止時のノートOFFのFM音源レジスタアクセスにウェイトが入ってなかったので追加
・メニュー中及び一時停止中にSDカードを抜いた場合にもエラー画面に遷移するよう変更。(カードによってはエラーに遷移せずに、10、11エラーを表示してハングするのでリセットしてください)
・メニューにSDカードのセクタアクセス速度表示を追加。ボタンを押すたびに計測します

2608firmware_v154.zip
・SDアクセスのウェイトを削減しました。
・LCDアクセスのウェイトを削減しました。
・ログ形式の再生時にキャッシュ制御を削除しました。
・再生時のボタン感度調整の為、200msのウェイトを追加しました。
・VGM再生を累積サンプル値制御に変更しました。

■rev.2019/2/16 v1.53
2608firmware_v153.zip
・ポーズ中に進むボタンを押すことで、現在のディレクトリをスキップする機能を追加しました
※サブディレクトリ内のファイルを再生していない場合は効きません。

■rev.2019/2/15 v1.52
2608firmware_v152.zip
・s98,vgm再生時にループブレイカー設定をOFFにしても、2ループで中断される問題を修正
・ウェイト値ちょっとだけ調整

■rev.2019/2/10 v1.51
2608firmware_v151.zip
・ウェイト調整メニューを追加しました。2608Bではなく2608の時に演奏が改善される可能性があります
※Heavyにすると2倍になります

■rev.2019/2/9 v1.50
2608firmware_v150.zip
・1階層目のサブディレクトに対応しました。Configから無効に設定することもできます
・SDカードからの再生で表示される番号がディレクトリエントリからバッファ番号に変更になりました
※なお、サブディレクトリにシャッフルは適用されません

■rev.2019/2/3 v1.43
2608firmware_v143.zip
・既知の不具合であったADPCMのフェードアウト処理を修正

■rev.2019/2/2 v1.42
2608firmware_v142.zip
・S98及びVGM形式のファイル再生を割り込みを使用して正確に計算するように変更しました
・S98ファイルのADPCMメモリ書き込みのウェイト値を増量しました
・YM2608をリセットした時にOPNAモードに強制的に変更するようにしました
・SDカードからの再生がうまくいかない環境向けに、SDカードの読込みタイムアウトを延長しました(1.41a)

■rev.2019/1/26 v1.41
2608firmware_v141.zip
・VGM形式のファイルを再生する際の同期値を1msを基準として計算するように変更しました

■rev.2019/1/26 v1.40
2608firmware_v140.zip
・SPFM Lightモードを追加しました。メニューから切り替えるか、「sd plz insert」表示中に左ボタンを長押しして切り替えることができます。
※ボードを2枚使用したり、携帯FM音源と組み合わせるなど、scci configで任意にポート等の設定を変更したい場合にlightモードをお使いください

■rev.2019/1/21 (実験版)
2608firmware_v133.zip
・VGM形式のファイルの再生を追加(YM2203,2608用) (1.32)
・VGM形式のファイルで正常にループしない場合がある問題に対処(1.33)

2608firmware_v131.zip
・S98形式のファイルの再生を追加しました
・S98形式のヘッダ値によって0除算で落ちるのを修正(1.31)
ループ曲のフェードアウトがリズム音源、ADPCM音源に有効じゃないかも。そのうち直します。

■rev.2019/1/15 (実験版)
2608firmware_v122.zip
・SPFMモード時にSSG音源レジスタアクセス後のウェイトを追加しました。(v1.22)
・SPFMモード時にFM音源レジスタアクセス後にウェイトを追加しました。(v1.21)
・SPFMインタフェースを追加しました。戻るにはUSBケーブルを外すか、基板左上のリセットボタンを押してください。
MUCOM88winで動作確認しました。
#液晶表示はいかしたままなのですが、実は液晶表示が一番重かったり。重大な問題に気が付いたかも。。音声出力の左右が逆かも…見なかった事にしよう…

■rev.2019/1/3 (実験版)
2608firmware_v110.zip
ADPCMロード機能を追加しました。
ヘッダ情報を追加することで、メインファイルの実行前にADPCMファイルをロードします。
詳細は下に記載しました。

■rev.2018/12/30 (安定版)
2608firmware.zip
PIC32MX270F256D用です。
ADPCMはファームウェアから制御するのは困難です。PCからのみです。。そのうちSDカードから読み込むのをつけます。
どんな制御実装がいいんでしょうねー
ヘッダエリアに、ADPCM読み込み用ファイル名があればロードされるというのを考えています。

内部はフルスクラッチしたx86エミュレータと98x1の音源I/Oポートエミュレータで構成されています。
ほとんどのI/Oアクセスは0x00を返したり何も処理しません。割と動くもんです。

マイクロSDカードはSDHC専用です。16GBの秋月電子のこのカードを利用しています。
FAT32でフォーマットされている必要があります。
SDXCも使えるかもしれません。(単なるSDはダメです)

左ボタンが戻る、真ん中が一時停止・再生、右ボタンが次へです。

音が小さいので、アンプでの再生をお勧めします。 SSGのミキシング音量は可変抵抗で調整してください。電子ボリュームチップは2500円もしてたのであきらめました。

2608サウンドデータヘッダエディタ

■rev.2018/12/30
2608fm_datedit.zip
制御ファームウェアがファイルデータを確認するためのヘッダ情報を設定するための支援ツールです。
1ループの時間を設定したり、タイマA及びBを使うかの設定をしたりします。
サウンドファイルを指定し、実行すればコマンドメニューが出てくるのでいじってください。

・フェードアウトするには

フェードアウトドライバー(がやらない)モードを有効に
フェードアウト時間(0.1秒単位で指定します。600なら1分になります)を、フェードアウトしたい時間の半分に設定。600を指定すれば、120秒で打ち切ります。

・指定した時間で打ち切るには

フェードアウト時間を、打ち切りしたい時間(0.1秒単位で指定します)に設定
制限終了フラグを有効に

にしてください。

2608PCから演奏ファイル転送プログラム

■rev.2018/12/30
2608play.zip
制御ファームウェアがファイルデータを確認するためのヘッダ情報を設定するための支援ツールです。
1ループの時間を設定したり、タイマA及びBを使うかの設定をしたりします。
サウンドファイルを指定し、実行すればコマンドメニューが出てくるのでいじってください。

2608ボードテストツール

■rev.2018/12/30
2608testtool.zip
2608ボードをテストするためのツールです。
ニコニコ動画でボードをテストします、で使っていたツールです。
ボードを製造した後、テストするための機能がそろっているので、このツールを使ってテストしてください。
ADPCM用のファイルを準備してください。MDXに入っていたファイルを、2608用に変換して使っていました。
ADPCM用データの作成には、たしかベクターにあったツールを使っています。懐かしのこうのたけし氏謹製のツールでした。今時のPCで動かないので、VirtualXPモードなどでやってました。
コンソール用のツールです。
・コマンド
q   終了
c   ボードに接続 COMポート3もしくは4
r   リセット
ry  リズム音源。ry 1などで対応した音色がなります。6ビット分なので全部を鳴らすのは63になります。
l   adpcm用ファイルの読み込みと転送
t   演奏用ファイルの転送
p   ADPCMの再生。番号で鳴らすADPCMを選択します
o   YM2608に直接レジスタとデータを転送します。o レジスタ番号 データみたいな感じで指定します
n   SDカードから演奏中の場合次の曲に進みます

詳細はソースを見てください。
他のCOMポートにする場合は、ソース編集して再コンパイルしてください。

2608ボード開発支援ツールx86

■rev.2018/12/30
2608x86.zip
指定方法
ex.
x86emu.exe -com 3
バイナリのみです。大変だったし、色々恥ずかしいところだらけなので。
起動時にCOMポートのYM2608FM音源ボードに接続し、リセットコマンドを送付します。
この時につながっていないと、以降繋ぐコマンドがありませんので、起動しなおしてください。
YM2608サウンドファイル開発支援の為の、x86エミュレータデバッガです。
音源ボード内と同じx86コアを内蔵していますので、ここでテストして動作すれば、おそらくボードでも動作するでしょう。
x86ツールのターゲットファイルは1MBです。まずは1MBのファイルを作成してください。
完成後、このファイルを最終的には32KBまで加工し、ヘッダを埋め込んでデータファイルにします。
#自信があれば最初から32KBでもOKです

DOS時代のデバッガ、SYMDEBやフリーのddeb等のツールを使っていた方は、大体似たような使い方ができます。
#結構アドレス指定は適当に組んで、もうこれでいいや状態なので、アドレス指定周りは動きが怪しいです

自分用のツールだったので、エラー的な指定やでかいファイルなどを指定した場合は異常終了します。たぶん。
・コマンド
q 終了
n アクセス用ファイル名を指定
l ターゲットファイルを読み込みます。ファイル名は省略可能です。
w ターゲットファイルを保存します。ファイル名は省略可能です。
wc ウェイトキャンセル機能の有効・無効を切り替えます。有効の場合loop $等をスキップします
wait (数値) 実行モード中の'wait'命令の時間を指定します
p 次の行にブレークポイントを設定し、実行します。サブルーチンを飛び越える場合に便利ですが、アセンブラだと帰ってこないとかよくあるので万能ではありません。
実行時にヒストリをクリアしてから実行します。ヒストリが32000に達したら停止します。
h 実行アドレスのヒストリをon/offします。実行したプログラムのアドレスがヒストリに保存されます。
ヒストリはxコマンドの実行時になどにhistory.txtでPG直下に書き出されます。
この記事を書いた後に、ヒストリーにフルバージョンを追加しました。
off→シンプル(この記事と同じモード)→フル→offのように切り替わります。
フルは大量に出力されますので注意してください。
hw ヒストリを追記書き出しし、ヒストリをクリアします。
g <停止アドレス> 現在のアドレスからPGを実行します。停止アドレスを指定した場合停止アドレスで停止します。
ヒストリ対応、ブレークポイント対応、int 3を見つけたら停止、ヒストリが32000に達したら停止します。
x <停止アドレス> 現在のアドレスからPGを実行します。停止アドレスを指定した場合停止アドレスで停止します。
xコマンド専用ヒストリ(命令などつき)を直接ファイルに書き出します。
実行中にQキーを検出すると停止します。(WinAPIのGetKeyStateを使っているので、フォーカスを失っていても別ウィンドウでもQキーが押されたら停止します)
bc ブレークポイントをクリアします。
be <番号> 指定した番号のブレークポイントを有効にします。省略時全有効。
bd <番号> 指定した番号のブレークポイントを無効にします。省略時全無効。
bp ブレークポイント一覧を表示します。
bp <アドレス> ブレークポイントを設定します。同じアドレスを指定するとクリアします。
t ステップトレースです。1命令実行します。
u <アドレス> 現在のアドレスから8行逆アセンブルします。アドレスを指定せずに連続して実行すると、前回アドレスから行います。
d <アドレス> 現在のアドレスからダンプリストを表示します。
アドレスを指定せずに連続実行すると、続きから表示します。
display I/Oアクセスを表示するようにします。トグル動作します。
e <アドレス> 指定したアドレスからデータ入力する入力モードになります。エンターキーで抜けます。
スペースとかタブキーとかでスキップしたりとか色々あります。
e アドレス <データ> データを指定したアドレスに入れ込みます。
r 現在のレジスタと実行アドレスの命令を逆アセンブルして表示します。
その他に現在アドレスのバッファなども設定するので、1回は実行してから処理してください。
r <レジスタ> レジスタの値を表示&入力するモードになります。
r <レジスタ> <データ> レジスタの値を設定します。
m 転送元 転送先 サイズ 転送元アドレスから転送先アドレスへサイズ分だけデータを転送します。
f 開始アドレス サイズ データ 開始アドレスから指定したデータで埋めます。
fs ファイルサイズ ファイルサイズを設定します
fr FM音源ボードへリセットコマンドを送信します。
fe FM音源ボードのYM2608へ、レジスタ0x29へ0x80を発行します。(2203→2608拡張モードへ切り替え)
c アクセスカバレッジ記録モードの有効・無効を切り替えます。
cc アクセスカバレッジをクリアします。
cs 現在のカバレッジ情報のサイズを表示します。
co 現在のカバレッジ情報を出力します。coverage.txtは毎回新規出力します。
コードカバレッジ(4桁)→メモリカバレッジ(8桁)の順番で出力されます。
io I/Oアクセスをiow.txtファイルに記録するモードを切り替えます。トグル動作します。

セグメントを意識しないコマンドなどもありますが、ほとんどはセグメントを意識して処理してください。
色々やっててしないほうが使いやすいところなどもあった為です。

x86エミュレーションは、もう本が何処へ行ったやらなのでWebで検索して解説見ながら作りました。
一部186相当まで実装されているかもしれません。
面倒な命令や使いそうにない命令(AAAとか)、使いそうにないフラグなどは実装していません。
なので、ひょっとしたらどこかおかしいかもしれません。
#下で解説しています

2608ボードサンプルサウンドファイル

2608snowdriver.zip
「実装例 雪だるま式FM音源ドライバを乗せてみる」で実際に作成したサンプルドライバファイルです。
もっといいサンプル作った方が良かったかなぁ。
#下で解説しています


・2608FM音源ボードの曲データの作り方について

#なんかこの章は自分でも書いててよくわかんなくなってきたので、実際の曲データ作成例である「実装例 雪だるま式FM音源ドライバを乗せてみる」を見てください。

・YM2608FM音源ボードのソフトについて

YM2608基板の基本ファームウェアにはシーケンサが載っていません。
なので、曲データはシーケンサ付きで用意する必要があります。
データサイズは最大32KBです。これ以内に、音源ドライバ+曲データが収まるようにしてください。
#収まればそのまま演奏できるって事です

当時はセグメントの壁があったし、メモリも潤沢ではなかったので、大抵のドライバと曲データは64KB以内に収まっていました。
メモリも節約していたので1曲は大体16KBもあれば十分だったと思われます。

先頭ヘッダエリア(0x400くらいまで)+データエリアのサイズに納めてください。

搭載されているx86エミュレータは、0000:0000のエリアからデータをロードすると前提で動作しています。
なので、INT命令もある程度は使えます。
#フルスクラッチで作ったので、音源に利用されなさそうな面倒な命令は処理していません。AAAとか。
 バグなども残っているかも


 普通はx86でマイコンの処理をエミュレーションするのですが、本ボードはその逆で、マイコンでx86を
 処理します。なので、処理時間は結構苦しい気がします。C言語で組んでありますし。

0x380あたりに制御用のヘッダが置かれています。
#ヘッダ情報については、「2608サウンドデータヘッダエディタ」を用意していますので、参照してください

その前は割り込みベクタに使っています。なので、割り込みベクタの後半部分がつぶされる構造になっています。
でも、98の音源割り込みはINT 14h等だったので、音源再生には使わないだろうとケチりました。

ヘッダ情報エリアには、音源の割り込みAを処理するか、割り込みBを処理するか、曲のループ回数、
曲の1ループの時間、曲の終了フラグ、フェードアウトが可能かのフラグ情報、音源処理部からの依頼などが設定されます。
#音源ドライバのタイマ割り込みは、音源チップで処理せず、マイコンのタイマで処理されるようになっています。
タイマへのI/Oはそのままマイコンのタイマ処理に回ります。電圧の関係で音源チップから情報を読み込めないからですが。


音源ドライバ側に機能がある場合は、機能を持っているフラグを設定し、音源処理部からの依頼があれば
その処理を実行してください。処理が完了したら完了フラグをセットしてください。
音源処理部はフラグの設定を持って、処理を次にステップに移行します。

たとえば以下のようなやり取りになります。

1曲の時間は0(処理はドライバでやります扱い)
フェードアウトはドライバ側に機能あり

1.音源ドライバは曲のループが1ループ完了したら、ループカウンタを1増加します。
2.音源ドライバに追加したIF部が、ループカウンタの内容を、ループバッファにコピーします
  (音源ドライバを改造するなら、直接バッファに変更してもよいとは思います)
3.音源処理部は、ループバッファを見て、2回を超えていたら、曲のフェードアウトを実行するために、
  ドライバの処理能力を確認します
4.ドライバがフェードアウト可能となっているので、フェードアウトを依頼するために、フェードアウトバッファにフラグをセットします
5.音源ドライバに追加したIF部は、フェードアウト依頼フラグが有効になっているので、フラグをクリアしつつ、音源ドライバのフェードアウト処理を実行します
6.音源ドライバフェードアウトを毎ループ実行しています
7.音源ドライバのフェードアウトが完了しました。I/F部はフェードアウトの完了を検出したので、曲の完了フラグバッファにフラグをセットします
8.音源処理部はドライバ側の処理が終了し、曲データの再生が終わったことを、完了フラグバッファで検出しました
  次の音源ドライバの読み込みに処理を移します

となります。

つまり、音源処理部はループブレイカーがONの設定になっている場合、2ループで曲を終了して次の曲に移る処理のため、曲データが2ループ
したかどうかを確認しようとしますが、音源ドライバ側の能力フラグがOnになっているために、2ループの検出も音源ドライバ側に任せ、
曲バッファの数値を確認するのみにしています。
(音源ドライバ側に能力がない場合は、1ループの時間設定を見て計算しています)
音源処理部は、音源ドライバとのやり取り用の曲ループカウンタバッファを見て、2ループ以上経過しているかを確認します。
2ループ以上確認した場合は、今再生している曲をフェードアウトさせ、次の曲に移行しなければなりません。
音源処理部は、音源ドライバの能力フラグを見て、フェードアウト機能を有していることを確認しました。
フェードアウト依頼バッファにフラグをセットし、曲の再生完了フラグが有効になるまでを待ちます。
音源ドライバは曲のフェードアウトが完了しました。
音源ドライバに追加したI/F部はフェードアウトが完了したので、完了フラグバッファにフラグをセットします
音源処理部はフェードアウトが完了したのを検出して、次の曲の読み込みを開始します…

ちなみに、フェードアウトするまでもなくループせずに終了する曲は、再生完了フラグを設定すると、音源処理部は直ちに次の曲に移行します。

のような動作をします。

音源ドライバ側に能力がない設定であれば、音源処理部は、指定された時間が経過すると、音源のI/O処理に対して、自動的にボリューム調整の
計算を行い音源チップへボリューム処理を行ったり、音源チップへのボリュームレジスタのI/Oに対して仲介を行い、フェードアウトします。

音源ドライバに能力があれば、なるべくその機能を使おうとする構成になっています。
なければ、または解析が面倒、I/F部を組みたくないなどの理由があれば、能力なしにすれば、音源処理部が代わりにやってくれます。
ただし、この場合は最低でも曲の処理時間を設定してください。ループ中断設定でも延々と同じ曲が流れ続ける事になります。


音源処理部は、処理しているx86のI/O命令のうち音源I/Oしか処理しません。割り込みコントローラ関連の処理は実装していません。
ポートからのIN命令には、音源以外はすべて0x00を返します。
98の割り込みコントローラや音源チップのBUSY周りは0が返って来るとOK扱いになっています。
なので、実質的に何も処理せずに抜けるので問題ありません。

音源からの読み込みの場合は、割り込みフラグがセットされています。
割り込みフラグである割り込みAまたは割り込みBへの処理は、マイコン側のタイマーにより処理されています。
どちらを使うかはヘッダ部にあるどちらの要求を使うかのフラグを設定してください。

両方を設定すると処理に実行時間がとられるので、通常はBだけでかまわないと思います。

#まれに音源ドライバのAで効果音を処理しており、曲の演奏でもドラムセットを割り込みAの効果音扱いで処理している
 ドライバがあったりします
 この場合は、Aも処理しないとなんとも間が抜けてしまいます。

音源チップへのOUTは、キューにバッファされます。
そして、x86のwait命令で一気にI/Oを処理する構成になっています。
x86エミュレータ側は、waitで指定したmsを待つだけですが、ボード側のファームウェアは
FM音源のタイマレジスタに指定した値がセットされるまで待つ動作になります。
1ループの処理終了時にwait命令を実行するようにしてください。

音源ドライバは通常、以下のような構成になっていると思います。

1.レジスタ退避
pusha
push ds
push es
...

2.割り込みの状態を確認
mov dx,188
in al,dx
test al,1
jnz xxx
...

3.割り込みの要因を判定し、割り込みAの場合を処理

終わったら、割り込みAフラグをクリアします

4.割り込みの要因を判定し、割り込みBの場合を処理

終わったら、割り込みBフラグをクリアします


5.割り込みコントローラに終了処理を必要に応じて実行します

※98の割り込みコントローラなどは、割り込みが完了したら再度割り込みを発生させるように割り込みをクリアします

6.レジスタを復帰して戻る

pop es
pop ds
popa
iret

これを以下の構成にします

1.レジスタ退避 →削除します
2、3、4はそのままでOKです
5は削除した方が、速度に余裕がでますが、そのままでもOKです
6.は、以下のようにします

wait
I/F処理を書く
jmp 2へ

I/F処理は、音源ドライバ側に処理能力がある場合に、処理能力があるフラグを設定した場合の処理を書く部分です。


詳細については、下のサンプルを見てください。


・x86ツールについて

どんなツールか?

YM2608を鳴らす事ができる音源ドライバのスタンダードが思いつかず、載せるシーケンサをどうしたものかと考えていました。
9801は、RA21の次は9821Xa13にいきなり移り、2608時代は指をくわえてみているだけでしたので、トレンドに疎かったのです。

結論が出ようはずもありません。知らないのですから。
ボードは既に完成しています。直ぐにでも鳴らしたいのです。
いつまでたっても完成しないので、妥協し、シーケンサは音色の設定と最低限キーOn/Off程度を実装し、適当なMMLを再生できるようにして、
聞きたい曲データをMML化することにしました。

当時聞いていたゲームの曲をまずはなんとかしようとしましたが、実際に鳴らしてみないとどうにもよくわかりません。

鳴らすために、ドライバのアセンブラリストを見ながら、C言語でドライバを組んでいったのですが・・・
サブルーチンの中から他のサブルーチンにjmpするばかりか、一部の命令を書き換えるなど、
古き時代のハイテクニックに満ち溢れたプログラムをC言語化するのは早々にあきらめました。
#SAN値が削れ過ぎて…

98エミュレータで鳴らすことができるのはわかっていたので、エミュレータで調べるようとしたのですが、
当時はまったく気にならなかったのですが、640x400サイズでシングル画面、SYMDEBでのデバッグにはもう戻れる事ができませんでした。

これではダメだということで、色々な機能がついていてトレース実行もできて、I/O処理をUSBで繋いだボード側に送信して実チップで鳴らす方式でデバッグすることにしました。

まずはx86を実行するコアを作らなければなりません。
DOS時代だったらシングルステップ割り込みを駆使すればそんな苦労はしなくてもいいのですが、もはやWindows時代です。そんな割り込みを使うとなると大事でしょう。
ましてや、I/O命令は除外しなければなりません。面倒です。
#SAN値がもっと削れます

久しぶりすぎて、もはやx86系の書籍は何処に言ったのか探すのも大変です。仕方ないのでネットでインストラクションを検索しながら組みました。
ついでに実行命令を逆アセンブルし表示するようにもしたので、逆アセンブル+エミュレーション可能で作成しました。
まさか2017年にもなって、8086をC言語で組むことになろうとは思いも寄りませんでしたが、便利に使えるようにするには、
全部自前で用意するしかありません。

結果、大幅に捗りました。
テンポだけは、WindowsAPIのSleep文なので、ミリ秒の単位&USB仮想COMポートの先にコマンドを送るラグがあるためおかしいのですが、
演奏はできるようになりました。

が、まだスタート地点なのです。
今度は調べた結果をMMLに変換し、さらにシーケンサも作らなければなりません。
非常に面倒です。
さらに当時聞きたかった曲&ドライバの回数だけ、同じ事を実行する必要があるのです。
非常に面倒です。

そんな時、ふと何かが私に囁いたのです。

…このままマイコンに入れてしまえばよくないか?と。

幸いにもフルスクラッチしたため、どうにでもできます。逆アセンブル表示部分を削り、押し込んでみました。
液晶にニーモニック出してもしょうがないですし。

心配なのは実行速度です。
PCでマイコンをエミュレーションするのはよくやられていますが、まったく逆の事をやらなければなりません。

というわけでやってみました。

…それなりに動きました。最近のマイコン凄いなぁ。

聴きたい曲が聴けたので、ひとまずこれでいいや。
ひよりました。

前置きが長くなりましたが、上記の事ができる2608サウンドボード用の支援ツールです。

・実装例 雪だるま式FM音源ドライバを乗せてみる

さて、実際の音源ドライバを例にとって、これをYM2608音源ボードで演奏できるようにしてみるまでをやってみようと思います。
サンプルに使うのは表題の音源ドライバなのですが、聞いたことないと思います。
ええ、大昔になんか作りかけて放置したものなのですから…。
昔のアーカイブから94-95年くらいに何かやっていたFM音源ドライバです。
雪だるま式。もはや記憶の彼方です。作りかけて途中で放置したと思います。再生したら微妙な曲が流れました。
何も覚えていません。作りかけのまま放置していたようなのですが、サンプルとしてだけはかろうじて使えます。
単純なのでちょうどいいでしょう。
#ドライバのネーミングとか何を持ってQ極と言っていたのやら突っ込みどころ多し

大抵の音源ドライバは大体2つの割り込みベクタを登録しています。
音源ボードからの割り込みを処理するベクタと、プログラムから呼び出して制御するベクタです。
これは、音源ドライバがBGM演奏を主に行っていたためで、何かをしながら曲を流すという目的の為、
メインプログラムとは別に、独立して動くように作られていたためです。

音源ドライバは、メインプログラムから呼び出されて使うので、インタフェース用のベクタを用意しています。
解析はまずこれを利用します。呼び出されて制御する部分を調べれば、曲を鳴らすのはそこまで難しくありません。
#たまに一体化して1つのベクタのドライバとかもいますけど

というわけで、サンプルを元に実装していく例を記述します。

エミュレータでも実行できたので、割と楽です。ソースもあるので、実際に解析した体で解説します。


まずは制御ベクタを調べます。

・ベクタから調べる場合


ドライバを登録する前と登録した後で、ベクタを比較して差分を調べる方法です。




上が常駐前、下が常駐した後です。
割り込みベクタのアドレス50hつまりint 14h(80/4=20 -> 0x14)と、アドレス348h(/4 -> 0xd2)が変っています。

結果:int 14hとint 0d2hでした。int 14hは音源ドライバからの割り込みでしょう。
ハードウェアからの割り込みは大体同じようなアドレスです。
int 0d2hがプログラム制御部でしょう。ここから解析すればよいわけです。

・ソースを解析する場合


常駐部分は大抵、メイン処理の後ろにあります。
常駐プログラムの性質上、メモリに居座る領域は少ないほうがよいので、初期化のみに必要な処理は切り離して常駐します。
DOSファンクション0x31は常駐量をパラグラフ単位(16バイト)で指定するので、必然的に後ろを切り捨てる事になります。

本当は逆アセンブルして確かめるのですが、ソースがあるので、解析した体で解説します。
stmain:			cld			;駐在管理部
			mov ax,cs
			mov ds,ax

			;タイトル表示
			mov dx,offset mes_tit
			mov ah,9
			int 21h

			;割り込みベクタ 14hを調べて、自分の制御部がいるか見る
			mov ax,3514h
			int 21h
			mov di,bx
			mov si,offset pmain
			mov cx,20
			rep cmpsb
			jnz stay

			;制御部の常駐解除を呼び出す
	remv:		mov ax,0ffffh
			int 0d2h
			
			;FM音源のキーを全部OFF
			call all_key_off

			;解除メッセージ表示
			push cs
			pop ds
			mov dx,offset mes_rmv
			mov ah,9
			int 21h

			;プログラム終了
			mov ax,4c00h
			int 21h

			;ベクタ14hの内容を保存して書き換える
	stay:		mov ds:vect14,bx
			mov ds:vect14+2,es
			mov ax,2514h
			mov dx,offset pmain
			int 21h
			
			;ベクタd2の内容を保存して書き換える
			mov ax,35d2h
			int 21h
			mov ds:vectd2,bx
			mov ds:vectd2+2,es
			mov ax,25d2h
			mov dx,offset cmain
			int 21h

			;常駐メッセージ表示
			mov dx,offset mes_sty
			mov ah,9
			int 21h

			;常駐を呼び出して終了
			mov ax,3100h
			mov dx,offset rb
			shr dx,4
			add dx,25600/16
			int 21h

int 21hはDOSファンクションコールです。

いくつかのDOSファンクションコールは解析の取っ掛かりの為に重要です。
0x35及び0x25は覚えて置いてください。
これは割り込みベクタを取得、保存するためのDOSファンクションコールです。
09hはメッセージの表示、4chはプログラムの終了、31hはメモリに残したまま終了(常駐)です。

さて、制御部が見つかったら制御部を調べます。
制御部は、経験的に以下のような機能が入っています。
・曲の再生
・曲の停止
・フェードアウト
・初期化
・データを転送して、演奏バッファに入れる処理
・常駐の解除

#曲データを内蔵しているドライバの場合、曲の再生などは番号を指定するだけで、転送などはなかったりします。

このドライバの場合、制御部は
			mov ax,25d2h
			mov dx,offset cmain
			int 21h
と、なっているので、cmainのアドレスに制御部があります。

cmainは以下のようになっていました。
cmain:			pusha
			push ds es cs
			pop ds
			cmp ax,0ffffh
			jz remvm
			cmp ax,14+1
			jnb cend
			shl ax,1
			mov si,ax
			call [ds:si+jptblcm]
		cend:	pop es ds
			popa
			iret
典型的なジャンプテーブルを使った機能呼び出し部です。
0xffffだけ特殊な処理をやっているようです。(ソースがあるのでわかりますが、常駐解除ですね)
大体14機能くらいあるみたいです。

次にジャンプテーブルを見てみましょう。
			;制御コマンド

jptblcm		dw	reset			;リセット
		dw	pam_set			;パラメータセット
		dw	fload			;ファイルロード+Pセット
		dw	sound_s			;再生
		dw	sound_t			;停止
		dw	fsound			;reset+pamset
		dw	all_key_off		;キーのオフ
		dw	fead_in			;フェードイン
		dw	fead_out		;フェードアウト
		dw	baf_in			;バッファにパラメータをセーブ
		dw	baf_out			;バッファからロード
		dw	reg_cnt			;レジスタコントロール
		dw	baf_cnt			;
		dw	baf_cnt2		;
		dw	mvolc			;Mボリューム設定

解析の場合は、テーブルの先を見ていく事になります。
#今回はソースがあるのでバレバレですが
reset:			call sound_t		;リセット
			mov ax,cs
			mov es,ax
			xor ax,ax
			mov di,offset ench
			mov cx,27
			rep stosw
			ret

コマンドの0番は、このようになっていました。
サブルーチンを呼んだ後に、バッファをクリアしています。
バッファクリアする=初期化のようです。

どんな感じのルーチンかな、と、あたりをつけたらサブルーチンを見てみます。
sound_t:		cli			;サウンドオフ
			mov ax,3027h
			call outdat
			in al,10
			or al,10h
			out 10,al
			sti
			call all_key_off
			ret
			
all_key_off:		mov ax,0028h		;音を止める
			call outdat
			mov ax,0128h
			call outdat
			mov ax,0228h
			call outdat
			mov ax,3f07h
			call outdat
			ret

outdat:			call nbusy		;2203へのデータ出力
			mov dx,188h
			out dx,al
			out 5fh,al
			out 5fh,al
			out 5fh,al
			out 5fh,al
			mov al,ah
			mov dx,18ah
			out dx,al
			ret
	nbusy:		push ax dx
			mov dx,188h
		nb2:	in al,dx
			shl al,1
			jb nb2
			pop dx ax
			ret

3027hを入れて、サブルーチンを呼んでいます。 サブルーチンでは、FM音源のBUSYレジスタを見て、al番のレジスタにahのデータを書き込んでいました。
これも典型的なFM音源操作の書き方です。
27h番はタイマーや音源リセットがあるレジスタです。リセットを叩いています。
I/O 10hは割り込み関連のI/Oですが、わからなければスルーしても大丈夫です。
その次のサブルーチンで、レジスタ0x28に値を0x00,0x01,0x02を入れています。
さらに0x07に0x3fを入れていました。

28はCh別の発声です。0,1,2なので、FM音源の発音をすべて停止しています。
07hはSSG音源のミキサーで、3fhを入れているので、SSGの発音ミキシングを全部OFFにしています。

初期化とあわせると、このサブルーチンは音を停止して、バッファをクリアする、つまりリセットコマンドであるという事がわかります。

ひとまず演奏前に必要かもしれませんが、次のコマンドを見てみます。
fload:			push cs			;データをバッファにロード
			pop es
			mov di,offset rb
			shr cx,1
			rep movsw
			rcl cx,1
			rep movsb

pam_set:		mov si,offset rb	;パラメータセット
			mov bx,offset pb00
			lodsw
			mov [ds:bx+2],ax
			lodsw
			mov [ds:bx+10],ax
			lodsw
			mov [ds:bx+18],ax
			lodsw
			mov [ds:bx+26],ax
			lodsw
			mov [ds:bx+34],ax
			lodsw
			mov [ds:bx+42],ax
			mov word ptr ds:ench,0
			mov word ptr ds:flg0,0
			ret

このサブルーチンは他のサブルーチンともくっついていました。
#まあよくあることです

上のサブルーチンは、いかにも曲データを内部バッファに転送してそうです。
下のサブルーチンは、転送先のバッファからデータを読み込んで内部制御バッファに値を設定しています。
しかも6箇所。これはFMx3音、SSGx3音の計6Ch分のバッファ設定ではないかと思われます。
ロード部分もあるので、これはデータのバッファ転送(ロード)及び、パラメータ設定のファンクションみたいですね。

これは曲データの再生の前に必要なのでメモです。
曲データは転送してもいいのですが、バッファであるrbにデータを最初から埋め込めば、転送処理を飛ばすことができそうです。
別ファイルで供給されている曲データと演奏ドライバを組み込んだ状態でセットにして、曲データを作り、
先頭でこのパラメータセットを呼び出せばよいでしょう。
#曲パラメータセットもスキップしてもよいように見えますが、このドライバは単純な作りの為です。
色々準備している場合もあるので、こういうのは呼んであげた方がいいです


バッファのセットとパラメータセットは見つかりました。
次は演奏の開始です。
sound_s:		cli			;サウンドスタート
			in al,10
			and al,0efh
			out 10,al
			mov ax,ds:tempo
			mov ah,al
			mov al,26h
			call outdat
			mov ax,3a27h
			call outdat
			sti
			ret

はい、もうコメントでバレバレですけど、割り込み禁止にしたうえに、割り込みコントローラーを操作しています。
そして、タイマレジスタをセットしています。終わった後割り込みを再開しています。
いかにも再生するぞ!っていう感じですね。

これはもう再生でしょうー間違いないですー(棒読み)

エミュレータで動かしてみて、演奏が開始されるかどうか確かめるのが手っ取り早かったりします。
#動く場合はこの方が早いですね

このドライバのようにテンポ設定などを、再生ファンクションで呼び出している場合は問題ありませんが、
ドライバ常駐時にやっているドライバもあります。
こういった場合は、常駐時にやっている音源チップの設定処理を入れる必要があります。

さて、ここまでわかったら曲データを作ります。
#時間があったら、曲の再生終了フラグやフェードアウト処理まで見つけると完璧です

音源ドライバと曲データを結合し、さらに呼び出し部分のコード演奏処理を入れます。
呼び出し部分は以下のようにしました。
			;演奏初期化
			mov ax,1
			int 15h
			mov ax,3
			int 15h
			
			;演奏処理
loop:			int 14h
			wait
			jmp loop

int 0d2hは、後ろ過ぎるので、15hを代わりに使うことにします。
タイマーはBだけで十分です。

曲データは以下のようにします。
割り込みベクタ + ヘッダ + 初期化/演奏処理 + 音源ドライバ本体 + 曲データ
このベースデータを作成します。
int main(int argc, char* argv[])
{
	char *x = new char [1048576];

	memset(x,0,1048576);

	//ドライバ読み込み
	FILE *fr = fopen("fmdrv.com","rb");
	if (!fr)
	{
		return 0;
	}
	fread(x + 0x600,1,32768,fr);
	fclose(fr);

	//このあたりにデータ埋め込みのコード入れる


	//かき出し
	FILE *fw = fopen("test.dat","wb");
	fwrite(x,1,1048576,fw);
	fclose(fw);

	delete[] x;

	return 0;
}

こんな単純なプログラムをつくり、ベースファイルを作成しました。
バイナリエディタをお持ちの場合は、そういったので作業したほうが良いでしょう。
x86エミュレータのmoveコマンドを駆使して作ることもできますが面倒です。

#曲データを読み込んでないじゃないかと、思った方もいるでしょうけど、
初期データとして、最初からバッファに埋め込んでありました。なので省略してます。


x86エミュレータに読み込みます。
>l test.dat
load file comp.[test.dat][1048576(00100000)]
>d 600
0000:0600 e9 73 09 90 00 00 00 00-00 00 00 00 00 00 00 00 駸.・...........
0000:0610 00 00 00 00 80 00 00 01-3f 00 00 00 00 00 00 00 .......?.......
0000:0620 00 00 00 00 00 00 00 00-00 00 00 00 87 db 87 db ............・・
0000:0630 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0640 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0650 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0660 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0670 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>d
0000:0680 60 1e 06 8c c8 8e d8 e8-88 00 ff 06 0c 01 83 3e `..己借闊....・
0000:0690 0c 01 03 73 02 eb 65 e8-b7 00 c7 06 0c 01 00 00 ...s.・霍.ヌ.....
0000:06a0 33 c9 f7 06 0e 01 01 00-75 06 bb 30 01 e8 84 01 3ノ・....u.サ0.閼.
0000:06b0 f7 06 0e 01 02 00 75 07-41 bb 38 01 e8 75 01 f7 ・....u.Aサ8.鑾.・
0000:06c0 06 0e 01 04 00 75 07 41-bb 40 01 e8 66 01 f7 06 .....u.Aサ@.鑁.・
0000:06d0 0e 01 08 00 75 08 33 c9-bb 48 01 e8 c9 01 f7 06 ....u.3ノサH.靄.・
0000:06e0 0e 01 10 00 75 07 41 bb-50 01 e8 ba 01 f7 06 0e ....u.AサP.霄.・.
0000:06f0 01 20 00 75 07 41 bb 58-01 e8 ab 01 b0 20 e6 08 . .u.AサX.隲.ー ・
アドレス600hから読み込んでいますので、元がCOMファイルということで、セグメント0050:0100から読み込まれた事になります。

先ほど作成した呼び出し部分を書き込みます。
>e 400 b8 01 00 cd 15 b8 03 00 cd 15 cd 14 9b eb fb

>d 400 0000:0400 b8 01 00 cd 15 b8 03 00-cd 15 cd 14 9b eb fb 00 ク.ヘ..ク.ヘ..ヘ.幎・ 0000:0410 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0420 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0430 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0440 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0450 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0460 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0000:0470 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ >u 400 0000:0400 b80100 mov ax,0001 0000:0403 cd15 int 15 0000:0405 b80300 mov ax,0003 0000:0408 cd15 int 15 0000:040a cd14 int 14 0000:040c 9b wait 0000:040d ebfb jmp 040a 0000:040f 0000 add [bx+si],al

#アセンブルはなんとかしてください

割り込みベクタに値をセットします。
割り込みベクタは上にある常駐時のオフセット値からわかります。
数値はキャプチャを見るとint 14hは180hで、int 0d2hは6e0hになっています。
>e 50 80 01 50 00 e0 06 50 00
>d 0
0000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 80 01 50 00 e0 06 50 00-00 00 00 00 00 00 00 00 .P.・P.........
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

値が設定できました。
一度保存しておきましょう。ついでに終了します。
>w
save file comp.[test.dat]
>q
exit!

再度立ち上げて確認してみましょう。
>l test.dat
load file comp.[test.dat][1048576(00100000)]
>d 0
0000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 80 01 50 00 e0 06 50 00-00 00 00 00 00 00 00 00 .P.・P.........
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>d 400
0000:0400 b8 01 00 cd 15 b8 03 00-cd 15 cd 14 9b eb fb 00 ク.ヘ..ク.ヘ..ヘ.幎・
0000:0410 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0420 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0430 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0440 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0450 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0460 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0470 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

OKです。

では、YM2608FM音源ボードを繋ぎ、再度x86を起動します。
reset:01
>l test.dat
load file comp.[test.dat][1048576(00100000)]
>rip 400
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:0400  NV UP EI PL NZ NA PO NC
0000:0400  b80100            mov        ax,0001
>

ボードを繋いだため、起動時にYM2608ボードに対して、リセットコマンドが送信されました。

ボード側もUSB制御モードに入っています。

#写真は編集の都合上、旧1.4版の基板を使用しています。

ちょっとトレースしてみましょう。
>t
ax:0001  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:0403  NV UP EI PL NZ NA PO NC
0000:0403  cd15              int        15
>t
ax:0001  bx:0000  cx:0000  dx:0000  sp:fff2  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0050  ip:06e0  NV UP EI PL NZ NA PO NC
0050:06e0  60                pusha
>u
0050:06e1  1e                push       ds
0050:06e2  06                push       es
0050:06e3  0e                push       cs
0050:06e4  1f                pop        ds
0050:06e5  3dffff            cmp        ax,ffff
0050:06e8  7411              jz 06fb
0050:06ea  3d0f00            cmp        ax,000f
0050:06ed  7308              jnc        06f7
>

AXレジスタに1が入ったあと、制御部にきちんと飛んでいます。

大丈夫そうなので、実行!(セーフティなし実行であるxコマンドを使っています)
>x
break!
ax:0003  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:040d  NV UP EI PL NZ NA PO NC
0000:040d  ebfb              jmp        040a
>

無事微妙な曲が演奏されて、止まりませんのでqキーを押し、ブレークしました。

PCのエミュレータ上では動作OKでしたので、ボードで演奏させる為のヘッダ情報を付け加えます。
今回のようにスタートアドレスが0000:0400であるなどを設定します。


ボード内のx86エミュレータの初期化処理は以下のようになっています。
                x86_init();
                switch(load_file_type)
                {
                    case 0:
                        x86_r.ip = 0x3360;
                        x86_r.cs = 0x0000;
                        x86_r.ds = 0x0000;
                        x86_r.es = 0x0000;
                        x86_r.ss = 0x0000;
                        x86_r.sp = 0x7ff8;
                        request_interrupt = 2;
                        break;
                    case 1:
                        x86_r.ip = 0x1960;
                        x86_r.cs = 0x0000;
                        x86_r.ds = 0x0000;
                        x86_r.es = 0x0000;
                        x86_r.ss = 0x0000;
                        x86_r.sp = 0x7ff8;
                        request_interrupt = 2;
                        break;
                    case 2:
                        x86_r.ip = x86_get_m16_(0x384);
                        x86_r.cs = x86_get_m16_(0x380);
                        x86_r.ds = x86_get_m16_(0x382);
                        x86_r.es = 0x0000;
                        x86_r.ss = 0x0000;
                        x86_r.sp = 0x7ff8;
                        request_interrupt = x86_m[0x389];
                        fade_looptimeout = x86_get_m16_(0x38a);
                        waitloop_cancel = x86_m[0x38d];
                        break;
                }

load_file_typeは2になります。一部拡張子の場合は0とか1になってしまうので、ファイル名は〜.datにするようにしてください。
ヘッダの0x380がcsレジスタの値、0x382がdsレジスタの値、0x384がipレジスタの値、0x389が割り込みタイプ(2はタイマーBです。1はタイマーAで、両方使う場合は3を指定します)
曲の長さは0x38aに0〜65535を入れます。
このサンプル曲の場合は、20秒くらいでしょうか。

cs,ds共に0でOKです。
ipは400hですね。
割り込みタイプは02hで、時間は0.1秒単位で指定するので、x10して200である0c8hにします。

>e 380
0000:0380 00-00 00-00 00-00 00-00 00-00 00-04 00-00 00-00
0000:0388 00-00 00-02 00-c8 00-
>d 380
0000:0380 00 00 00 00 00 04 00 00-00 02 c8 00 00 00 00 00 ................
0000:0390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03f0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

eコマンドの逐次指定モード(アドレスしか入れない)だと、インタラクティブに数値を聞いてくるので、
入力したり、スペースでスキップして次に飛んだりできます。

値を入れたので保存します。
>w
save file comp.[test.dat]

おっと、そろそろ実ファイルのサイズである32KBにしましょう。
ファイルをバックアップしておいてからファイルサイズコマンドで0x8000を指定し、再度書き込みます。
>fs 8000
set filesize -> [32768]
>w
save file comp.[test.dat]
>

これでファイルサイズが32KBになったと思います。確認してください。

再度読み込んでみます
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>d 400
0000:0400 b8 01 00 cd 15 b8 03 00-cd 15 cd 14 9b eb fb 00 ク..ヘ.ク..ヘ.ヘ.幎・
0000:0410 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0420 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0430 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0440 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0450 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0460 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0470 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>d 600
0000:0600 e9 73 09 90 00 00 00 00-00 00 00 00 00 00 00 00 駸.・...........
0000:0610 00 00 00 00 80 00 00 01-3f 00 00 00 00 00 00 00 .......?.......
0000:0620 00 00 00 00 00 00 00 00-00 00 00 00 87 db 87 db ............・・
0000:0630 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0640 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0650 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0660 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0670 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>d 0
0000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 80 01 50 00 e0 06 50 00-00 00 00 00 00 00 00 00 .P.・P.........
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>d 380
0000:0380 00 00 00 00 00 04 00 00-00 02 c8 00 00 00 00 00 ................
0000:0390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03f0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

読み込みサイズが32KBになっていて、内部のデータも大丈夫そうですね。

では、他にパラメータを設定するところがあったと思いますが、あんまり覚えてないので、設定ツールを使いましょう。

出来上がったtest.datをfmデータエディタに入れます。
>fm_dat_edit test.dat
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 200
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Disable
6.LimitEnd Flag      .. Disable
8.Save End
9.Exit

現在の状態が出ます。
フェードアウトは今回の曲はずっとループせずに普通に終わるので要りません。
また、2203のドライバなので、液晶のキー表示イコライザが2608用のままだと邪魔ですね。
2203用の6桁にしましょう。
5を押してエンターを押します。
cmd ..5
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 200
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Enable
6.LimitEnd Flag      .. Disable
8.Save End
9.Exit

5の状態が変りました。
曲はループしませんので、曲の終わりがそのまま終了です。
6番を設定します。
cmd ..6
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 200
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Enable
6.LimitEnd Flag      .. Enable
8.Save End
9.Exit

これでOKですね。
8番を押して、保存終了します。
cmd ..8
save end!

さて、データが出来上がりました。

と、その前に現在はPC上のx86エミュレータで動作しているわけですが、マイコンの制限された32KBのメモリで正しく動作するのか、
確認してみましょう。
#まあ実ボード上で演奏してみるのが早いのですけれども

カバレッジ機能でアクセス範囲を確認し、おかしなところにアクセスしていたりしないかを見てみます。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rip 400
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:0400  NV UP EI PL NZ NA PO NC
0000:0400  b80100            mov        ax,0001
>c
set coverage on.
>x
break!
ax:0003  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:040d  NV UP EI PL NZ NA PO NC
0000:040d  ebfb              jmp        040a
>cs
code coverage 426entry.
data coverage 55entry.
>co
writing..done.
>
途中でcコマンドを実行して、カバレッジ機能を有効にします。
そしてxコマンドで通常通り実行し、曲が終わるまで待ちました。
csコマンドで、カバレッジサイズを表示してみたところ、コードの実行範囲は426エントリで、
データにいたっては55エントリでした。曲がしょぼいです…

coコマンドで、coverage.txtが出力されていますので、中身を見てみます。
0180
0181
0182
0183
0185
.
.
.
略
.
.
.
078e
0790
0793
0796
0799
079a
0000060c
0000060e
00000610
00000616
00000618
.
.
.
略
.
.
.
00000d78
00000d7e
00000d88
00000d8a
00000d8e
00000d98
00000d9c
ぱっと見よくわからない表示なのですが、上の4桁がコードカバレッジです。
コードの範囲は180h〜79ahの範囲でアクセスされていました。
おかしなところにジャンプはしていなさそうです。
#本当はセグメントまで考慮して8桁なんでしょうけど、なぜかこれを組んだときは4桁でいいやと思ってしまったようです。

下の8桁の方はデータカバレッジです。
アクセスのあったメモリの情報が記録されています。
これを見る限り60ch〜0d9chの範囲のみメモリアクセスがあったようです。
32KBの壁は8000hですから、範囲内に収まっています。


余談ですが、プログラムが実際にどのように実行されているかは、ヒストリ機能を使って調べることができます。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rip 400
>h
history on
>x
break!
ax:0003  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0000  es:0000  ss:0000  cs:0000  ip:040d  NV UP EI PL NZ NA PO NC
0000:040d  ebfb              jmp        040a
>hw
write history..0
>
実はxコマンドはヒストリが有効な場合は常時追記書き込みしているので、最後にhwコマンドによる書き出しは必要ありません。
出来上がったヒストリは、history.txtに出力されています。
0000:0400  mov	ax,0001	
0050:0403  int	15	
0050:06e0  pusha	
0050:06e1  push	ds	
0050:06e2  push	es	
0050:06e3  push	cs	
0050:06e4  pop	ds	
0050:06e5  cmp	ax,ffff	
0050:06e8  jz	06fb	
0050:06ea  cmp	ax,000f	
0050:06ed  jnc	06f7	
0050:06ef  shl	ax,1	
0050:06f1  mov	si,ax	
0050:06f3  call	[si+0896]	(00d98:0750)

上記でint 15hを実行した直後から、int 15hの実行先であるpushaに移動しています。
#よく見るとint 15hは0000:403にあるのですが、実行後にヒストリテキストを書き出しているので変ってしまってました。後で直しときます ←しときました

0050:0750  mov	si,08c0	
0050:0753  mov	bx,0130	
0050:0756  lodsw	
0050:0757  mov	[bx+02],ax	(00632:0000)
0050:075a  lodsw	
0050:075b  mov	[bx+0a],ax	(0063a:0000)
0050:075e  lodsw	
0050:075f  mov	[bx+12],ax	(00642:0000)
0050:0762  lodsw	
0050:0763  mov	[bx+1a],ax	(0064a:0000)
0050:0766  lodsw	
0050:0767  mov	[bx+22],ax	(00652:0000)
0050:076a  lodsw	
0050:076b  mov	[bx+2a],ax	(0065a:0000)

書き込み先のメモリの内容が表示されています。
#lodswで読み込んだ値も表示されたら嬉しかったですね
 →追加しときました
0050:076e mov word ptr [010e],00 (0060e:0000) 0050:0774 mov word ptr [0110],00 (00610:0000) 0050:077a ret 0050:06f7 pop es 0050:06f8 pop ds 0050:06f9 popa 0000:06fa iret ここで元のアドレスに戻っていっています。 0000:0405 mov ax,0003 0050:0408 int 15 0050:06e0 pusha 0050:06e1 push ds 0050:06e2 push es 0050:06e3 push cs 0050:06e4 pop ds 0050:06e5 cmp ax,ffff 0050:06e8 jz 06fb 0050:06ea cmp ax,000f 0050:06ed jnc 06f7 0050:06ef shl ax,1 0050:06f1 mov si,ax 0050:06f3 call [si+0896] (00d9c:0782) 0050:0782 cli 0050:0783 in al,0a 0050:0785 and al,ef 0050:0787 out 0a,al 0050:0789 mov ax,[0114] ( 614:0080) 0050:078c mov ah,al 0050:078e mov al,26 0050:0790 call 021b 0050:021b call 0231 0050:0231 push ax 0050:0232 push dx 条件分岐命令は条件を満たしていないのでスルーされていることがわかります。 またcall命令を実行した直後にジャンプ先に移動しています。 0050:0233 mov dx,0188 0050:0236 in al,dx 0050:0237 shl al,1 0050:0239 jc 0236 0050:023b pop dx 0050:023c pop ax 0050:023d ret 0050:021e mov dx,0188 0050:0221 out dx,al 0050:0222 out 5f,al 0050:0224 out 5f,al 0050:0226 out 5f,al 0050:0228 out 5f,al 0050:022a mov al,ah 0050:022c mov dx,018a 0050:022f out dx,al 0050:0230 ret 0050:0793 mov ax,3a27 0050:0796 call 021b 0050:021b call 0231 0050:0231 push ax 0050:0232 push dx 0050:0233 mov dx,0188 0050:0236 in al,dx 0050:0237 shl al,1 0050:0239 jc 0236 0050:023b pop dx 0050:023c pop ax 0050:023d ret 0050:021e mov dx,0188 0050:0221 out dx,al 0050:0222 out 5f,al 0050:0224 out 5f,al 0050:0226 out 5f,al 0050:0228 out 5f,al 0050:022a mov al,ah 0050:022c mov dx,018a 0050:022f out dx,al 0050:0230 ret 0050:0799 sti 0050:079a ret 0050:06f7 pop es 0050:06f8 pop ds 0050:06f9 popa 0000:06fa iret 0050:040a int 14 0050:0180 pusha 0050:0181 push ds 0050:0182 push es 0050:0183 mov ax,cs 0050:0185 mov ds,ax 0050:0187 call 0212 0050:0212 mov ax,3827 0050:0215 call 021b 0050:021b call 0231 0050:0231 push ax 0050:0232 push dx 0050:0233 mov dx,0188 0050:0236 in al,dx 0050:0237 shl al,1 0050:0239 jc 0236 0050:023b pop dx 0050:023c pop ax 0050:023d ret 0050:021e mov dx,0188 0050:0221 out dx,al 0050:0222 out 5f,al 0050:0224 out 5f,al 0050:0226 out 5f,al 0050:0228 out 5f,al 0050:022a mov al,ah 0050:022c mov dx,018a 0050:022f out dx,al 0050:0230 ret 0050:0218 mov ax,3a27 0050:021b call 0231 0050:0231 push ax 0050:0232 push dx 0050:0233 mov dx,0188 0050:0236 in al,dx 0050:0237 shl al,1 0050:0239 jc 0236 0050:023b pop dx 0050:023c pop ax 0050:023d ret 0050:021e mov dx,0188 0050:0221 out dx,al 0050:0222 out 5f,al 0050:0224 out 5f,al 0050:0226 out 5f,al 0050:0228 out 5f,al 0050:022a mov al,ah 0050:022c mov dx,018a 0050:022f out dx,al 0050:0230 ret 0050:018a inc word ptr [010c] (0060c:0000) 0050:018e cmp byte ptr [010c],03 (0060c:0001) 0050:0193 jnc 0197 0050:0195 jmp 01fc 0050:01fc mov al,20 0050:01fe out 08,al 0050:0200 mov al,0b 0050:0202 out 08,al 0050:0204 in al,08 0050:0206 or al,al 0050:0208 jnz 020e 0050:020a mov al,20 0050:020c out 00,al 0050:020e pop es 0050:020f pop ds 0050:0210 popa 0000:0211 iret 0000:040c wait 0000:040d jmp 040a 0050:040a int 14 0050:0180 pusha 0050:0181 push ds 0050:0182 push es 0050:0183 mov ax,cs 0050:0185 mov ds,ax 0050:0187 call 0212 0050:0212 mov ax,3827 0050:0215 call 021b 0050:021b call 0231 0050:0231 push ax 0050:0232 push dx 0050:0233 mov dx,0188 0050:0236 in al,dx 0050:0237 shl al,1 0050:0239 jc 0236 0050:023b pop dx 0050:023c pop ax 0050:023d ret . . .
このようにヒストリ機能を有効にすると、プログラムがどのように実行されていったのかを履歴のように確認することができます。
メモリアクセスしていた場合、メモリの内容もある程度表示してくれますので、便利に解析してください。
#メモリの圧迫具合が凄いので、32000ヒストリでいったん中断します。xコマンドはディスクに書き込むので止まりませんがディスク空き容量に注意してください

閑話休題

さて、ファイルをUSBで転送して、ボード上でスタンドアロンで演奏するか見てみましょう。
2608play.exe test.dat

無事演奏されました!

あれ、イコライザ表示が2608用のままです。
そういえばUSB接続だと変化しなかったかも。
#後でSDカードに入れてみたらちゃんと2203表示になっていました

SDカードにファイルを入れて、演奏をテストし、20秒で次の曲に移ろうとするか確認してください。

不幸にも演奏されなかった人は、何かを間違えてしまったと思われます。
再度チャレンジしてみてください。ボードが暴走している場合は、ボード上のリセットボタンを押してください。
この場合、x86エミュレータも再起動しないと、COMポートを開いたままロックしている場合があります。

音源ドライバによっては処理がもたつくなども出てきますので、今回は省略してしまったのですが、 int 14hの先にある、pushaから始まるレジスタ保存処理などを全部取っ払ってしまうなどのチューニングが必要になります。


以上で解説を終わります。
大体曲データの作り方の雰囲気はつかめたでしょうか。
#曲データを作っているのかサウンドドライバを作っているのやら

・バッファの説明
 アドレス  サイズ  方向  意味 
0x380unsigned shortドライバ→制御初期状態のコードセグメントレジスタ(cs)の値
0x382unsigned shortドライバ→制御初期状態のデータセグメントレジスタ(ds)の値
0x384unsigned shortドライバ→制御初期状態のインストラクションポインタレジスタ(ip)の値
0x386unsigned charドライバ→制御演奏終了フラグ
0x01で制御側に終了が来た事を通知
0x387unsigned charドライバ→制御ループカウンタ
ループブレイカー設定が有効な時、ここが2以上であった場合ループを中断して次の曲へと進めます
0x388unsigned char制御→ドライバ0x01の時、制御部がフェードアウトを要求しています
0x389unsigned charドライバ->制御割り込みタイプ
b0:タイマーA有効 b1:タイマーB有効
0x38aunsigned shortドライバ→制御曲の長さ(0.1秒単位)
ex.200 = 20秒 省略する時は0秒で
0x38cunsigned charドライバ→制御制御フラグ
b0:フェードアウトを自前で実行 b1:2203用表示 b3:時間が来たら終了
0x38dunsigned charドライバ→制御ウェイトループキャンセラ。0x01で有効。
loop $+2をキャンセルします。ドライバによってはループでウェイトしているものがあるので、
キャンセルする場合に有効にします。
0x38eunsigned charドライバ->制御識別子:0x55
0x38funsigned charドライバ->制御識別子:0xaa

※方向が「ドライバ→制御」の場合は、制御部が読み取って処理を行います
 「制御→ドライバ」の場合は、制御部からドライバ側に通知を行っています


おまけ FMPを鳴らしてみる 技術実験


ここでは当時良く利用されていた(らしい)FMPを本ボードで演奏できるかやってみます。

#知り合いに話をしたところ、FMPが演奏できなきゃねーと言い放ち、むきーっとなったので、できるのかどうかを検証してみました。
 なお、FMPの利用規約を確認したところ、改竄しての商利用は禁止で、個人で楽しむ意外の組み込み禁止とあります。
 本PJは商利用ではないのですが、グレーゾーンは回避して改竄をしないように進めていきます。
 当然ながらここではツールの技術実験に終始するので、完成版のファイルは配布しません


説明文を見ると、I/Oポート自動判別、割り込み自動判別と書かれています。
自動判別はちょっとやっかいです。
というのも、I/Oエミュレーションは音源意外は実装していないので、
単に0x00を返す実装になっているからです。

#その音源にしても最低限の実装なのですが。 ちなみに0x00を返すと大抵のBUSYフラグはパスするのでそのまま動いたりします

ひとまず作業ファイルに配置して実行してみることにします。
常駐処理は多岐にわたる自動判別処理を行っているので、解析は最低限に抑えたいです。

プログラムサイズは31Kとかなり大きめです。かなり前方に配置しなければなりません。
曲データバッファがなくなってしまう気がしますが、説明文を読むと20K+バッファ8Kで最大でも28K程度の常駐サイズとあります。
これならば入りそうですが、最初から曲データはロードされた状態にしておく必要があるでしょう。

というわけで作業ファイルを作成します。

今回は2608x86だけで作業してみます。

2608x86を実行し、ファイルをロードします。
>l fmp.com
load file comp.[fmp.com][31073(00007961)]
>d 0
0000:0000 e9 5d 4d 00 00 00 00 00-00 00 00 00 00 00 00 00 饐M.............
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 23 6f 6f 00 00 00-00 00 00 00 00 00 00 00 ..#oo...........
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

次にセグメント0x40にロードされたCOMファイル扱いにします。
ということは、アドレスは500なので、転送コマンドMで転送します。
>m 0 500 7fff
>d 500
0000:0500 e9 5d 4d 00 00 00 00 00-00 00 00 00 00 00 00 00 饐M.............
0000:0510 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0520 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0530 00 00 23 6f 6f 00 00 00-00 00 00 00 00 00 00 00 ..#oo...........
0000:0540 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0550 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0560 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0570 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

一度保存しておきます。
ファイルサイズ及びファイル名を変更し、保存コマンドを実行します。
>fs 8000
set filesize -> [32768]
>n test.dat
set filename [test.dat]
>w
save file comp.[test.dat]
>

次は実行するために、レジスタを設定します。
配置アドレスは、0x500なので、セグメント0x40に配置されたCOMファイルになります。
>rcs 40
>rds 40
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0100  NV UP EI PL NZ NA PO NC
0040:0100  e95d4d            jmp        4e60
>

このドライバは引数を指定せずに実行した場合、常駐処理を実行しません。
なので、常駐用の引数[s]を指定します。

実行ファイルはCOMファイルなので、プログラムより128バイト前にコマンド引数部分があります。
ということで、コマンドラインは0x80から「文字数、スペース、常駐文字、改行文字」を記述します。
>e 80 02 20 73 0d
>d 80
0040:0080 02 20 73 0d 00 00 00 00-00 00 00 00 00 00 00 00 . s.............
0040:0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040:00f0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

実行前にもう一度セーブしておきます。
>w
save file comp.[test.dat]
>

実行してみます。
>x
change alloc memory block
dealloc memory block
change alloc memory block
Music driver 「FMP」    Ver 4.28u         Copyright (C)1990-98  by Guu

read interrupt vector
read interrupt vector
set interrupt vector
set interrupt vector
division by zero
ax:10a1  bx:0000  cx:0000  dx:0000  sp:8261  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:53a0  NV UP EI PL ZF NA PO NC
0040:53a0  40                inc        ax
>

0除算で止まりました。I/O情報などがあってないみたいですね。
まあ続行してみましょう。
>x
change alloc memory block
dealloc memory block
change alloc memory block
read interrupt vector
set interrupt vector
not dos-function implement
not dos-function implement
read interrupt vector
set interrupt vector
read interrupt vector
set interrupt vector
 - Theme of FMP -   Composed & Arranged by KID

Found YM2203, Access I/O = 0188h, Used INT0h, Hooked INT d2h, Loops = @2
メモリに常駐しました
stay resident
ax:3100  bx:0000  cx:0000  dx:08e7  sp:8261  bp:0000  si:4e7c  di:1404
ds:0040  es:0040  ss:0040  cs:0040  ip:5733  NV UP EI PL NZ NA PO NC
0040:5733  f606a85d01        test       byte ptr [5da8],01      (061a8:04)
>

ひとまずメモリに常駐するところまで実行されました。
#普通は0除算なんて出たらダメなんですけど、たまたまうまくいったようです。ラッキーでしたね
実機であれば、この後に初期に組み込まれているサンプルサウンドが演奏されます。

表示を見ていると、色々問題がありました。YM2203の判別になっています。
2608x86は、0xA460のI/Oエミュレーションは0x41を返すだけなので、なんかおかしいのでしょう。
割り込みベクタがINT0になっています。
しかもINT0の位置にも書いてないので、正常に登録動作もしていないようですが、ルーチンを呼び出せばOKですので、スルーします。
だいたい除算エラーが出たので、あちこち正常値なI/Oではないのでエラーが出ているみたいですね。
なのでここは実機(もしくはエミュレータ)で数値を見ておきましょう。
ベクタのアドレスは1774hでした。
#ベクタが登録されないのは、なんかおかしいなと思って見てみたら実装してなかったです。実装しときます
→しときました
read interrupt vector [0b][0000:0000]
set interrupt vector [0b][0040:1774]
のように表示されます。

よく見ればLoopsの値も文字化けしてます。相当数値が大きいようです。これ、なんかのウェイト値でしょうか。

2203の問題を調査するため、2203の文字が出るところまでトレースして調べました。
その前にある判定文のところでデータを変更すれば2608認識するようです。

というわけでもう一度。
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rcs 40
>rds 40
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0100  NV UP EI PL NZ NA PO NC
0040:0100  e95d4d            jmp        4e60

ここで実行前にブレークポイントを設定します。
>bp 6087
set break point -> 0040:6087

で、実行します。
>x
change alloc memory block
dealloc memory block
change alloc memory block
Music driver 「FMP」    Ver 4.28u         Copyright (C)1990-98  by Guu

read interrupt vector
ax:0000  bx:5df1  cx:0004  dx:038a  sp:825f  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:6087  NV UP EI PL NZ NA PO NC
0040:6087* 3b4702            cmp        ax,[bx+02]      (061f3:0041)    <--bp:e

止まりました。
この0x41が入っているところを0x43にすれば86ボードで認識されます。
データを変更します。
>e 5df3
0040:5df3 41-43 00-

アドレスは、bx+2なのでbxレジスタの値に+2を足したアドレスです。
逐次変更モードで変更しましたが、もちろん直接変更しても問題ありません。

というわけで再度実行。
>x
ax:0043  bx:5df5  cx:0003  dx:0188  sp:825f  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:6087  NV UP EI PL NZ NA PO NC
0040:6087* 3b4702            cmp        ax,[bx+02]      (061f7:0000)    <--bp:e

あ、また同じところで止まりました。
ブレークポイントを解除します。
>bp 6087
clear break point -> 0040:6087

また実行。
>x
read interrupt vector
set interrupt vector
set interrupt vector
division by zero
ax:0850  bx:0000  cx:0000  dx:0000  sp:8261  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:53a0  NV UP EI PL ZF NA PO NC
0040:53a0  40                inc        ax

例の0除算のところで止まりました。
再度実行。
>x
change alloc memory block
dealloc memory block
change alloc memory block
read interrupt vector
set interrupt vector
not dos-function implement
not dos-function implement
read interrupt vector
set interrupt vector
read interrupt vector
set interrupt vector
 - Theme of FMP -   Composed & Arranged by KID

Found YM2608, Access I/O = 0188h, Used INT0h, Hooked INT d2h, Loops = 81
「86ボード」を認識しました
メモリに常駐しました
stay resident
ax:3100  bx:0002  cx:0000  dx:08e7  sp:8261  bp:0000  si:4e7c  di:1404
ds:0040  es:0040  ss:0040  cs:0040  ip:5733  NV UP EI PL NZ NA PO NC
0040:5733  f606a85d01        test       byte ptr [5da8],01      (061a8:04)
>

86ボードで認識しました。
保存しておきます。
>w
save file comp.[test.dat]
>

ひとまずこの状態で実行できるように変更してみましょう。
INT5のアドレス(ベクタは0x14)に呼び出しベクタアドレスをセットします。
>rds 0
>d 0
0000:0000 e9 5d 4d 00 00 00 00 00-00 00 00 00 00 00 00 00 饐M.............
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 23 6f 6f 00 00 00-00 00 00 00 00 00 00 00 ..#oo...........
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

あ、先頭に移動前のゴミが残っていたのでフィルコマンドで消しておきます。
#気分の問題です
>f 0 37f 0
>d 0
0000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>

消えました。
ベクタを書きます。int 14hです。定番のINT5です。
#この紛らわしいの何とかならんのですかね
>e 50 74 17 40 00
>d 0
0000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0050 74 17 40 00 00 00 00 00-00 00 00 00 00 00 00 00 t.@.............
0000:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>rds 40
>

アドレス指定がいまいちなので、データを読み書きするときには、dsレジスタを変更するようにしてください。
フルアドレス指定にすると、それはそれで使いにくいのです。

呼び出し部分のストラップをコーディングします。
loop:
    int 14
    wait
    jmp loop
という単なるコードです。

書き込みます。
>e 0 cd 14 9b eb fb
>u 0
0040:0000  cd14              int        14
0040:0002  9b                wait
0040:0003  ebfb              jmp        0000
0040:0005  0000              add        [bx+si],al
0040:0007  0000              add        [bx+si],al
0040:0009  0000              add        [bx+si],al
0040:000b  0000              add        [bx+si],al
0040:000d  0000              add        [bx+si],al
>rip 0
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0000  NV UP EI PL NZ NA PO NC
0040:0000  cd14              int        14
>

そしてついでに保存
>w
save file comp.[test.dat]
>

あ、初期設定時に既にある程度のFM音源へのI/Oが行われているようです。
io出力を有効にしてからもう一度やり直して、何が行われたのかを見てください。
#もう一度やるのは面倒なので省略します
>io
io write enable.
>

iow.txtの内容抜粋
略
.
.
0188 <- 27
0188
0188
018a <- 30
0068 <- 0b
0068 <- 0a
0188
0188
0188 <- 26
0188
0188
018a <- 00
0188
0188
0188 <- 27
0188
0188
.
.
略

結構テキスト系のI/Oがありました。
オプション説明を見ると、外字登録をしているようです。ひとまずスルーします。
#5fhや0a1h〜0a9hは邪魔なので、iow.txtには出ないようにしときました

YM2608の27hや26hレジスタは、タイマーやモードレジスタ設定です。これは初期化時にやっておかないといけないですね。
後でやりましょう。

実行してみます。
あ、ボードを接続してなかった。接続して再起動します。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rcs 40
>rds 40
>rip 0
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0000  NV UP EI PL NZ NA PO NC
0040:0000  cd14              int        14
>

さて、実行してみます。
音は鳴りましたが・・・遅いです。qキーを押してブレークします。
>x
break!
ax:ffa5  bx:02f1  cx:0626  dx:018c  sp:1342  bp:0000  si:141e  di:029a
ds:0040  es:0040  ss:0040  cs:0040  ip:3234  NV UP DI PL NZ NA PO NC
0040:3234  e2fe              loop       3234
>fr
reset:01
fm reset!
>

ついでに音が出っぱなしなので、frコマンドでFM音源をリセットしておきます。
2608x86上では、タイマーではなくウェイト設定だけですのでウェイト値を0にして見ます。
>wait 0
set wait 0 msec.
>

再度実行してみても改善されていません。
ヒストリを有効にして、再度実行してみて、何をやっているのか見てみます。
>h
history on
>x
break!
ax:0609  bx:09e1  cx:03de  dx:0188  sp:1340  bp:0000  si:50d6  di:098a
ds:0040  es:0040  ss:0040  cs:0040  ip:323e  NV UP DI PL ZF NA PO NC
0040:323e  e2fe              loop       323e
>fr
reset:01
fm reset!
>h
history off
>

ヒストリを有効にしてほんのちょっと実行しただけなのに、巨大なファイルが出来上がっています。
ヒストリファイルを見てみると、同じアドレスで大量にループしています。
.
.
0040:323e  loop	323e	
0040:323e  loop	323e	
0040:323e  loop	323e	
0040:323e  loop	323e	
0040:323e  loop	323e	
.
.

そういえばさっきブレークしたときも、同じようにウェイトループで止まっていましたね。

ひとつ心当たりがあります。常駐時に表示されていたループ表示がおかしかったことです。
これ、ウェイト調整値でしょう。

ウェイトキャンセル機能を有効にして、ウェイトを無視するようにします。
>wc
wait loop cancel.
>

再度実行してみます。
速度は良い感じになりましたが、最初からやり直しましょう。
FM音源をリセットするコマンドを実行しているので、音色がダメです。

再起動して再読み込みします。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rcs 40
>rds 40
>rip 0
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0000  NV UP EI PL NZ NA PO NC
0040:0000  cd14              int        14
>

おっと、忘れてました。
キャンセル機能を有効にして実行します。
>wc
wait loop cancel.
>wait 0
set wait 0 msec.
>x

無事サンプル曲が再生されました!

後はカバレッジテストして、実機で動作するフォーマットに直せばよしです。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>rcs 40
>rds 40
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0100  NV UP EI PL NZ NA PO NC
0040:0100  e95d00            jmp        0160
>rip 0
>r
ax:0000  bx:0000  cx:0000  dx:0000  sp:fff8  bp:0000  si:0000  di:0000
ds:0040  es:0000  ss:0000  cs:0040  ip:0000  NV UP EI PL NZ NA PO NC
0040:0000  cd14              int        14
>c
set coverage on.
>wc
wait loop cancel.
>wait 0
set wait 0 msec.
>x
break!
ax:0080  bx:0000  cx:0008  dx:0188  sp:1348  bp:0000  si:0c26  di:0000
ds:0040  es:0040  ss:0040  cs:0040  ip:1b75  NV UP EI PL ZF NA PO NC
0040:1b75  740c              jz 1b83
>cs
code coverage 1161entry.
data coverage 705entry.
>

再生が終わったので中断してカバレッジ情報を出してみます。
やっぱちゃんとしたPGだとエントリ数が多いですね。
>co
writing..done.
>

出力して範囲を確認してみます。
0000
0002
0003
1774
1775
1778
1779
177e
17ad
.
.
.
3e7c
3e7d
3e81
3e84
3e87
3e8d
3eb7
00000502
00000503
0000050d
0000050f
00000511
00000512
.
.
.
000054fb
00005537
0000553a
0000554a
0000554d
00005590

コード、データ共に範囲内に収まっています。
意外と後ろのほうも使っていました。

次はヘッダを作成します。最初からデータエディタを使います。
fm_dat_edit.exe test.dat
1.TimerA             .. Disable
2.TimerB             .. Disable
3.LimitTime          .. 0
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Disable
6.LimitEnd Flag      .. Disable
8.Save End
9.Exit
cmd ..2
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 0
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Disable
6.LimitEnd Flag      .. Disable
8.Save End
9.Exit
cmd ..3
time ? 100
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 100
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Disable
6.LimitEnd Flag      .. Disable
8.Save End
9.Exit
cmd ..6
1.TimerA             .. Disable
2.TimerB             .. Enable
3.LimitTime          .. 100
4.Fadeout DriverMode .. Disable
5.2203 GraphicECMode .. Disable
6.LimitEnd Flag      .. Enable
8.Save End
9.Exit
cmd ..8
save end!

さて、今回はウェイトループキャンセラフラグも有効にしないといけません。
後でつけたので、データエディタにはついてませんでした。
reset:01
>l test.dat
load file comp.[test.dat][32768(00008000)]
>d 380
0000:0380 00 00 00 00 00 01 00 00-00 02 64 00 08 00 55 aa ..........d...Uェ
0000:0390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03f0 00 00 00 00 00 00 00 00-46 4d 50 20 34 2e 32 38 ........FMP 4.28
>e 38d 1
>d 380
0000:0380 00 00 00 00 00 01 00 00-00 02 64 00 08 01 55 aa ..........d...Uェ
0000:0390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03f0 00 00 00 00 00 00 00 00-46 4d 50 20 34 2e 32 38 ........FMP 4.28
>w
save file comp.[test.dat]
>

さて、次は初期設定部分と呼び出し部分を実装します。
先ほどのiow.txtに記録されていた初期化データを設定してから演奏ループに入るコードにします。
やらなくても大丈夫かもしれませんが。
コード部分はこれ。
	cld
	mov cx,9
	mov si,3a8h
lp:
	mov dx,188h
	lodsb
	out dx,al
	mov dl,8ah
	lodsb
	out dx,al
	loop lp

soundloop:
	int 14h
	wait
	jmp soundloop

	
	※以下のがよかったかも
	lodsw
	out dx,al
	mov dl,8a
	mov al,ah
	out dx,al
	loop lp
	

ちなみに設定する先ほどiow.txtで確認したデータ部分は以下の通り。
26,00
27,2a
22,00
b4,c0
b5,c0
b6,c0
07,38
26,ca
27,2a

ということで、入力開始。 ヘッダの直後からコードを書くので、アドレスは390hから入れる事にします。
ipアドレスのスタートアドレスを380hにして、390hにして、コードとデータを入れ込みます。
>e 380
0000:0380 00-  00-  00-  00-  00-90 01-03 00-
>e 390
0000:0390 00-fc 00-b9 00-09 00-00 00-be 00-a8 00-03 00-ba
0000:0398 00-88 00-01 00-ac 00-ee 00-b2 00-8a 00-ac 00-ee
0000:03a0 00-e2 00-f5 00-cd 00-14 00-9b 00-eb 00-fb 00-
>e 3a8
0000:03a8 00-26 00-00 00-27 00-2a 00-22 00-00 00-b4 00-c0
0000:03b0 00-b5 00-c0 00-b6 00-c0 00-07 00-38 00-26 00-ca
0000:03b8 00-27 00-2a 00-
>d 380
0000:0380 00 00 00 00 90 03 00 00-00 02 64 00 08 01 55 aa ....・....d...Uェ
0000:0390 fc b9 09 00 be a8 03 ba-88 01 ac ee b2 8a ac ee ・..セィ.コ・ャホ堪・
0000:03a0 e2 f5 cd 14 9b eb fb 00-26 00 27 2a 22 00 b4 c0 糢ヘ.幎・&.'*".エタ
0000:03b0 b5 c0 b6 c0 07 38 26 ca-27 2a 00 00 00 00 00 00 オタカタ.8&ハ'*......
0000:03c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:03f0 00 00 00 00 00 00 00 00-46 4d 50 20 34 2e 32 38 ........FMP 4.28
>w
save file comp.[test.dat]
>

入れ終わったらセーブしておきます。
これで演奏してみます。

おーオープニング曲が演奏されました!
後は、曲データと結合して1つのファイルにしなければなりません。

では、曲データを設定する方法を調べてみることにします。
データのロードは、画面メッセージを見ていると、Theme of FMPというメッセージを出しているので、ここで曲データを設定していると思われます。
このメッセージ出しているあたりで、きっと制御コマンドをint 0d2hで呼び出しているに違いありません。

wcコマンドでウェイトループをキャンセルし、もう一度ヒストリを出力してみます。
メッセージの表示タイミング的に、0除算エラーからヒストリを有効にしてみます。

・・・

何箇所かメッセージを出しているところがありました。
mov ah,09とint 21の部分をヒストリから探してみます。
見つけたうちの一番手前を見てみます。
0040:56af  test	byte ptr [5da8],02	(061a8:04)
0040:56b4  jnz	56d0	
0040:56b6  mov	si,65e0	
0040:56b9  mov	dx,57af	
0040:56bc  cmp	byte ptr [5263],00	(05663:00)
0040:56c1  jz	56c9	
0040:56c9  mov	ah,09	
0040:56cb  int	21	
0040:56cd  call	4b30	
ここでは、メッセージのアドレスとして、57afhを設定しています。

このメッセージが何かを確認してみます。
>d 57af
0040:57af 20 2d 20 54 68 65 6d 65-20 6f 66 20 46 4d 50 20  - Theme of FMP
0040:57bf 2d 20 20 20 43 6f 6d 70-6f 73 65 64 20 26 20 41 -   Composed & A
0040:57cf 72 72 61 6e 67 65 64 20-62 79 20 4b 49 44 0d 0a rranged by KID..
0040:57df 0a 24 20 2d 20 42 61 6c-61 6e 63 65 20 74 65 73 .$ - Balance tes
0040:57ef 74 20 2d 20 20 20 43 6f-6d 70 6f 73 65 64 20 26 t -   Composed &
0040:57ff 20 41 72 72 61 6e 67 65-64 20 62 79 20 4b 49 44  Arranged by KID
0040:580f 0d 0a 0a 24 20 2d 20 56-6f 6c 75 6d 65 20 63 68 ...$ - Volume ch
0040:581f 61 6e 67 65 20 2d 0d 0a-0a 24 41 63 63 65 73 73 ange -...$Access
を、これは曲のタイトルメッセージですね。

ということは、ここで曲データを設定しているようです。
直前に条件判定文がありますが、分岐しなかった場合は何が出るんでしょうか。
>u 56c1
0040:56c1  7406              jz 56c9
0040:56c3  bee268            mov        si,68e2
0040:56c6  bae157            mov        dx,57e1
0040:56c9  b409              mov        ah,09
0040:56cb  cd21              int        21
0040:56cd  e860f4            call       4b30
0040:56d0  33db              xor        bx,bx
0040:56d2  8a1e560b          mov        bl,[0b56]
dxレジスタに57e1hを設定しています。
このアドレスは、さっきのダンプにありましたが、バランステスト用の曲のようです。

ここで曲を切り替えできるという事は、これより前に曲データに関する処理はないみたいです。
そして、siレジスタに設定しているアドレスが、曲データの先頭でしょうね。
最後にcall 4b30hへジャンプしていますが、内部を確認してみたところ、曲データのロードのようです。
ヒストリでは、このサブルーチンを抜けると、もう後は画面表示をして常駐する処理しかありません。
ということは、siレジスタに値を設定して、このルーチンを呼び出せれば曲データを任意にロードできるようです。

呼び出すためにint 0d2hに設定されている制御コマンドを確認してみます。
ベクタに設定されていたアドレスは、32a0hでした。 この先を確認してみたところ、alレジスタにコマンド番号を入れてから呼び出すようです。
>u 32e5
0040:32e5  2ec6060201fe      mov        byte ptr cs:[0102],fe
0040:32eb  3c15              cmp        al,15
0040:32ed  7711              ja 3300
0040:32ef  2ec606020100      mov        byte ptr cs:[0102],00
0040:32f5  33db              xor        bx,bx
0040:32f7  8ad8              mov        bl,al
0040:32f9  d1e3              shl        bx,1
0040:32fb  2eff974633        call       cs:[bx+3346]

ジャンプテーブルが3346hにあります。テーブルを確認してみます。
>d 3346
0040:3346 72 3d fe 3e 3c 40 30 4b-72 33 fa 33 3c 3a ff 39 r=><@0Kr3・<:9
0040:3356 b8 3e c5 34 8d 39 bf 39-96 36 8c 39 c4 36 69 37 ク>ナ4・ソ9・・ト6i7
略
>
テーブルアドレスを見てみると… +6からありました。4b30hがあります。
という事は、alは3を設定すればOKです。

では、任意の曲データ(ここではdemo.ozi)を使って、その曲が再生されるか実験してみます。
#実際のコマンド表示にコメントを追記しています
reset:01
>l demo.ozi
load file comp.[demo.ozi][10552(00002938)]

#ここではdemo.oziファイルをロードしています

>m 0 a000 3000

#一度データを移動しておきます

>l fmp.com
load file comp.[fmp.com][31073(00007961)]

#fmpをロードします

>m 0 500 7fff

#現在の位置では割り込みベクタの上なので、セグメント40hに移動します

>rcs 40
>rds 40

#セグメントを更新します

>e 80 02 20 73 0d

#常駐コマンドラインを書き込みます

>bp 6087
set break point -> 0040:6087

#86ボード認識用にブレークポイントを設定します

>x
change alloc memory block
dealloc memory block
change alloc memory block
Music driver 「FMP」    Ver 4.28u         Copyright (C)1990-98  by Guu

read interrupt vector [d2][0000:0000]
ax:0000  bx:5df1  cx:0004  dx:038a  sp:825f  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:6087  NV UP EI PL NZ NA PO NC
0040:6087* 3b4702            cmp        ax,[bx+02]      (061f3:0041)    <--bp:e
>bp 6087
clear break point -> 0040:6087
>e 4df3
0040:4df3 06-
>e 5df3
0040:5df3 41-43 00-

#86ボード認識用設定にデータを変更し、ブレークポイントを解除します

>x
read interrupt vector [08][0000:0000]
set interrupt vector [08][0040:62d5]
set interrupt vector [08][0000:0000]
division by zero
ax:0850  bx:0000  cx:0000  dx:0000  sp:8261  bp:0000  si:0082  di:011a
ds:0040  es:0040  ss:0040  cs:0040  ip:53a0  NV UP EI PL ZF NA PO NC
0040:53a0  40                inc        ax

#0除算エラーでとまるので、再度実行します

>x
change alloc memory block
dealloc memory block
change alloc memory block
read interrupt vector [0b][0000:0000]
set interrupt vector [0b][0040:1774]
not dos-function implement
not dos-function implement
read interrupt vector [d2][0000:0000]
set interrupt vector [d2][0040:32a0]
read interrupt vector [1b][0000:0000]
set interrupt vector [1b][0040:327c]
 - Theme of FMP -   Composed & Arranged by KID

Found YM2608, Access I/O = 0188h, Used INT0h, Hooked INT d2h, Loops = 81
「86ボード」を認識しました
メモリに常駐しました
stay resident
ax:3100  bx:0002  cx:0000  dx:08e7  sp:8261  bp:0000  si:4e7c  di:1404
ds:0040  es:0040  ss:0040  cs:0040  ip:5733  NV UP EI PL NZ NA PO NC
0040:5733  f606a85d01        test       byte ptr [5da8],01      (061a8:04)

#メモリに常駐したところで自動で停止します

>e 0 be 00 9c b0 03 cd d2 9b cd 0b 9b eb fb
>u 0
0040:0000  be009c            mov        si,9c00
0040:0003  b003              mov        al,03
0040:0005  cdd2              int        d2
0040:0007  9b                wait
0040:0008  cd0b              int        0b
0040:000a  9b                wait
0040:000b  ebfb              jmp        0008
0040:000d  0000              add        [bx+si],al

#先ほど調べた曲データロードコマンドのコードを書き込みます。移動先は0a000hなのですが、セグメントが40hなので400hほど戻して、9c00hになっています
順序変えて、
	mov si,9c00
	mov al,3
	int d2
loop:
	wait
	int 0b
	jmp loop
のがよかったですね


>rip 0
>r
ax:3100  bx:0002  cx:0000  dx:08e7  sp:8261  bp:0000  si:4e7c  di:1404
ds:0040  es:0040  ss:0040  cs:0040  ip:0000  NV UP EI PL NZ NA PO NC
0040:0000  be009c            mov        si,9c00

#ipレジスタを0に設定します

>wc
wait loop cancel.
>wait 2
set wait 2 msec.

#ついでにデバッガの設定を変更します

>x

#いざ実行!

break!
ax:8181  bx:043e  cx:0000  dx:018a  sp:1342  bp:0c81  si:141e  di:002e
ds:0040  es:0040  ss:0040  cs:0040  ip:3249  NV UP DI PL NZ NA PO NC
0040:3249  58                pop        ax
>fr
reset:01
fm reset!
>

無事に再生することができました!

後は、FMPイメージに曲データをくっつけて、このブートストラップコードを埋め込めば曲データを作ることができますね。
しかし、メモリが32KBだと結構厳しいです。
バッファ8Kと聞いていましたが、曲データのサイズをみると平気で10Kとかあります。
プログラムの半分から後ろは、常駐処理などが書かれているので、つぶしても大丈夫でしょうか。
ここに曲データを入れるとか実験して試してみようかと思いますが、ひとまずデータは完成したので、よしとします。

#最悪ファームウェアを更新して、もうちょっとメモリを確保できるようにしようかと思います。
50KBくらいならいけるかしら・・・



その後…

漏れ:(^ω^)FMP演奏できたぞ!!

→奴:あ、ごめんPMDだったわ

 →漏れ:(#^ω^)





おまけのおまけ PMDを鳴らしてみる 技術実験2



1.試してみました。

2.2608x86のI/Oエミュレーションでは常駐まで行きませんでした。

3.というわけで、実機などで常駐まで実行します。

4.出来上がったら、メモリのイメージをファイルに落とします。

5.割り込みベクタ周りを見て、どこに実体があるか確認しておきます。

6.このドライバは常駐時に音源用のベクタや制御用のベクタを表示してくれますので、制御用のベクタにブレークポイントを設定します。
  音源はINT5(int 14h)、制御はint 60hでした。

7.再生プログラムで再生を実行します。制御用ベクタにどのコマンド送られてきたかを確認します。

8.メッセージの表示や内部のバッファへのデータ転送、再生の開始、停止をコマンドとあわせてメモします。
  コマンドの指定はahレジスタに番号でした。珍しい。

9.コマンド番号は、停止:01h、フェードアウト:02hで速度はal、再生開始:00h、バッファの位置を返す:06h(ds:dxにアドレス)でした。
  演奏を停止してから、バッファの位置にデータを埋め込み、再生開始を行えば再生される事がわかりました。

10.イメージを再配置します。500hに配置できるように、セグメントを設定(0040h)し、実体を転送します。

11.割り込みベクタを再設定します。セグメントを0040hにします。

12.380hにヘッダ情報を書き込みます。
   ひとあえず再生時間は120秒、タイマーB、WCキャンセル有効、時間で終了フラグで完了します。
   コード、データセグメントは0000hで、ipは390hにしておきます。

13.390hにコードを書きます。
	mov ah,0
	int 60h
loop:
	wait
	int 14h
	jmp loop
   ここまでで、ドライバイメージにしておきます。

14.実機上で、ah,06hにして、制御ベクタを呼び出しds:dxレジスタの値を確認しておきます。dsは常駐アドレスと同じ、dxは4e0chでした。
  symdeb.exeがない場合は、vectorからddeb等のsymdebライクなPGを用意して試しましょう。

15.データ作成PGを作ります。
  ドライバイメージをロードし、曲データを先ほどのdxレジスタの位置にロードします。

16.曲データをデータ作成PGで結合し、32KBで保存します。超えていた場合は、あきらめます。(ファームウェア改造まち)
  ※手動でがんばって作成する方法(おまけで解説済み)でもかまいません。

17.USB転送で再生するか確認します。

18.完成!


余裕があれば、演奏終了フラグを見つけたり、ループカウンタを見つけたりして制御部に通知してあげるようにコードを書きます。
面倒な場合は、1曲の時間を計測し、時間を設定、フラグなどを調整してください。

※あ、一点だけパッチが必要でした。
エミュレータのFM音源タイマ割り込みのフラグ設定ですが、一度読み出されるとクリアされるようになっています。
なので、2回連続で読んだりすると2回目はクリアされています。
	in al,dx
	in al,dx
	test al,2
	jc xxxx
のようにコードを組まれると、実チップでは2回目でも同じ値が返って来ますが、
ボードのエミュレーションでは2回目はフラグがクリアされた状態となります。
この為に動きませんので、どちらかのin al,dxをnopにつぶしてください。

・おまけ pmdドライバ+pmd曲から、2608ボードで再生できる形式のファイルを作成するプログラム


・rev.2018/12/30 17:36追加
pmd_song.zip

PMD86.comを用意し、プログラムと同じ場所に配置してください。
バージョンは4.8oが必要です。
#ベクターからPMDドライバをダウンロードしたところ、pmd48oを実行し、自動実行解凍でpmd86.comを出力する必要がありました。(README.1STより)
 9801で実行したので、コマンドプロンプトなどでは実行できないと思います。

使い方
pmd_song.exe sample.m

エラーがなければ、自動的にYM2608FM音源ボードで再生できる形式の.datファイルが出来上がります。
ただし、合計が32KB超えている場合は動作しません。10〜12KB程度のファイルまでなら再生可能だと思われます。

SDカードで聞く場合は、FMデータエディタでヘッダ情報を設定してください。(USBモードだと再生時間などは無視しています)
再生時間設定は2分固定になっています。(フェードアウトあり、1再生は1分で2ループ設定)
それより短い曲は無音が続くことになります。FMデータエディタで曲の再生時間を再設定してください。

■資料

・SDカードのデータ形式について

ファイルはルートディレクトリしかみません。
余計なファイルはサブディレクトリに入れれば再生されません。

SDHCしか使えません。
SDとの違いは、SPIモード初期化手順及び内部でアドレスを1/512にするかどうか等ですが、
ノーマルSD用のコードは実装しませんでした。

FAT32専用です。
16GBのカードを使っていますので、あまり大容量だと動かないかもしれません。
そのうち買ったら試してみます。

容量的にはSDでもいいかなと思ったのですが、既にSDカードは入手が困難なため、SDHC専用にしました。
SDXCは知りません。持っていないので・・・。
#SDHCがわからなければ、4GB〜32GBのマイクロSDカードを利用すればSDHCです。

・USBコマンド一覧

注意
USBバッファは64バイトしか確保していないので、コマンドは最大でも64バイト以内に収まるようにしてください。
USBからコマンドが送られてきた場合、ボードは演奏を中止し、USBモードで待機状態になります。
応答値は基本的に1バイトで、0x01が成功です。エラーはそれ以外です。
※手を抜いて全部応答値0x01とかもだったかも。(バッファクリア忘れている)

・携帯FM音源プレイヤー
コマンド名コマンドフォーマットバイト数説明
書き込みポインタリセット0x001バイト 内部メモリへの書き込みポインタをクリアします
データ書き込み0x01,データ...2〜64バイト 内部メモリへデータを書き込みます
再生開始0x021バイト 内部メモリのMDXデータを再生開始します
演奏停止0x031バイト MDXドライバの処理を停止し、待機状態に移行します
通常モードへ復帰0x041バイト USBモードを終了します
レジスタ読み込み0x06,開始レジスタ番号,個数3バイト 指定された番号から指定した個数レジスタを読み込みます
読み込みは指定されたバイト数だけ読み込んでください
レジスタ書き込み0x07,開始レジスタ番号,個数,データ...4バイト〜 指定された番号から指定した個数A0レジスタを書き込みます
レジスタ書き込み(fast)0x0b,レジスタ番号,データ3バイト 指定したレジスタにデータを書き込みます。
応答値はありません。読み込まないでください。
PGステータス値取得0x081バイト デバッグコマンド。内部シーケンス制御値を取得します
オプションバッファ取得0x091バイト デバッグコマンド。オプション値バッファ8バイトを取得します
オプションバッファ設定0x0a,オプションデータ(8バイト)9バイト デバッグコマンド。オプション値バッファ8バイトを設定します
YM2151リセット0x0c1バイト YM2151のみリセットします。内部シーケンサの状態は変更されません
存在確認0x101バイト '2151'の4バイトを返します
SDカード制御チップ初期化0x141バイト SDカードの制御チップをSPIモードで初期化します。
戻り値:
1 SPIモード初期化成功
3 SDカードが入っていない
4 SPIモード初期化失敗
SDセクタ読み込み0x15,アドレス(LL),アドレス(L),アドレス(H),アドレス(HH)5バイト SDカードのセクタをSD用内部バッファに読み込みます。アドレスは4バイトでリトルエンディアンで指定します。 戻り値:
1 成功
2 コマンドフォーマットエラー
3 SDカードが入っていない
4 失敗
内部バッファ読み込み0x16,アドレス(L),アドレス(H),個数4バイト SD用内部バッファを読み込みます。指定した個数だけデータが戻ります。
0x01,個数,データ...の形式で読み込んでください
SDセクタ書き込み0x17,アドレス(LL),アドレス(L),アドレス(H),アドレス(HH)5バイト SDカードのセクタをSD用内部バッファに読み込みます。アドレスは4バイトでリトルエンディアンで指定します。 戻り値:
1 成功
2 コマンドフォーマットエラー
3 SDカードが入っていない
4 失敗
内部バッファ書き込み0x18,アドレス(L),アドレス(H),個数,データ..5バイト〜 SD用内部バッファへデータを書き込みます。
キャッシュメモリ読み込み0x19,アドレス(L),アドレス(H),個数4バイト キャッシュメモリを読み込みます。
0x01,個数,データ...の形式で読み込んでください
キャッシュメモリ書き込み0x1a,アドレス(L),アドレス(H),個数,データ..5バイト〜 キャッシュメモリに書き込みます。
SDファイル読込み0x1b,ファイル番号(L),ファイル番号(H)3バイト 指定したファイルをキャッシュメモリに読み込みます。ファイル番号はFATアドレスの有効な番号なので、
数を数えるか、再生時に右上に表示される番号を確認してください。
戻り値:
1 成功
4 失敗
デバッグカウンタ読み込み0x1c,番号2バイト SDカード読み込み処理時の内部デバッグカウンタ値を読み込みます。
NGの時に、何かの役に立つかもしれません。
キャッシュメモリをSDバッファに転送0x1d,アドレス(L),アドレス(H)3バイト 指定したアドレスのメモリをSDバッファに転送します。
SPFMモードへ切り替え
(v1.2以上)
0xff1バイト 応答値OKの2バイトを返し、SPFMモードに切り替えます。
書き込みのみで、読み込みには対応していません。

・YM2608ボード
コマンド名コマンドフォーマットバイト数説明
リセット0x001バイト YM2608をリセットし、ボードを待機状態にします。
SDカードから演奏中だった場合、USB制御を開始する場合はまずこのコマンドでリセットしてください
書き込みポインタリセット0x011バイト 内部メモリへの書き込みポインタをクリアします
データ書き込み0x02,データ...2〜64バイト 内部メモリへデータを書き込みます
再生開始0x03,0x022バイト 内部メモリのデータを実行します。2バイト目は互換性の為に残してあります
2を指定してください
通常モードへ復帰0x041バイト USBモードを終了します
タイマーB強制変更0x05,tempo値2バイト タイマーB割り込み周期を強制変更します。(YM2608の割り込みは使っていないので、マイコンの、ですが)
演奏中のドライバが変更したら上書きされます
A0レジスタ読み込み0x06,開始レジスタ番号,個数3バイト 指定された番号から指定した個数レジスタを読み込みます
読み込みは指定されたバイト数だけ読み込んでください
A0レジスタ書き込み0x07,開始レジスタ番号,個数,データ...4バイト〜 指定された番号から指定した個数A0レジスタを書き込みます
A1レジスタ書き込み0x08,開始レジスタ番号,個数,データ...4バイト〜 指定された番号から指定した個数A1レジスタを書き込みます
A0レジスタ書き込み(fast)0x0d,レジスタ番号,データ3バイト 指定したA0レジスタにデータを書き込みます。
応答値はありません。読み込まないでください。
A1レジスタ書き込み(fast)0x0e,レジスタ番号,データ3バイト 指定したA1レジスタにデータを書き込みます。
応答値はありません。読み込まないでください。
A0レジスタ書き込み(multi fast)0x11,個数, レジスタ番号,データ x個数4バイト〜 指定したA0レジスタにデータを書き込むセットを複数指定します。
応答値はありません。読み込まないでください。
A1レジスタ書き込み(multi fast)0x12,個数, レジスタ番号,データ x個数4バイト〜 指定したA1レジスタにデータを書き込むセットを複数指定します。
応答値はありません。読み込まないでください。
メモリ書き込み0x09,サイズ,アドレス(下位),アドレス(上位),データ...5バイト〜 ADPCM用メモに書き込むため、まずマイコン内部のメモリにデータを書き込むためのコマンドです。
ある程度書き込んだからADPCMへ転送します。YM2608は32バイトアラインです。32バイト単位で書き込むようにしてください。
ADPCM用メモリ転送0x0a,サイズ(下位),サイズ(上位),アドレス(下位),アドレス(上位)6バイト メモリの内容を、ADPCM用メモリへ書き込みます。
32バイトアラインに足りない分は0で埋めます
信号線テスト用0x0b,テストデータ2バイト FM音源チップを接続しない状態で使うコマンドです。
テストデータによって以下の信号線が制御されます。
テスターなどで信号線がきちんと配線されているか確認する時に使う開発用コマンドです。
2バイト目のデータにより、信号線が制御されます。以下の実装を参考にしてください。
switch(usb_rd_buf[1])
{
    default:
        break;
        
    case 0: //初期化
        YM2608_IC = 1;		//IC	H   リセット動作
        YM2608_A0 = 1;		//A0	H   アドレス指定・データ指定の制御
        YM2608_A1 = 0;		//A1	L   (SSG+FM1-3)     H:(ADPCM + FM4-6)
        YM2608_WR = 1;		//WR	H   
        YM2608_RD = 1;		//RD	H   H固定 読み込みはしません   
        YM2608_CS = 0;		//CS	L   チップセレクト
        break;
    case 1: YM2608_IC = 0;  break;
    case 2: YM2608_IC = 1;  break;
    case 3: YM2608_A0 = 0;  break;
    case 4: YM2608_A0 = 1;  break;
    case 5: YM2608_A1 = 0;  break;
    case 6: YM2608_A1 = 1;  break;
    case 7: YM2608_WR = 0;  break;
    case 8: YM2608_WR = 1;  break;
    case 9: YM2608_CS = 0;  break;
    case 10: YM2608_CS = 1;  break;
        
    case 11: LATBbits.LATB0 = 1;    break;
    case 12: LATBbits.LATB0 = 0;    break;
    case 13: LATBbits.LATB1 = 1;    break;
    case 14: LATBbits.LATB1 = 0;    break;
    case 15: LATBbits.LATB2 = 1;    break;
    case 16: LATBbits.LATB2 = 0;    break;
    case 17: LATBbits.LATB3 = 1;    break;
    case 18: LATBbits.LATB3 = 0;    break;
    case 19: LATBbits.LATB4 = 1;    break;
    case 20: LATBbits.LATB4 = 0;    break;
    case 21: LATBbits.LATB5 = 1;    break;
    case 22: LATBbits.LATB5 = 0;    break;
    case 23: LATBbits.LATB7 = 1;    break;
    case 24: LATBbits.LATB7 = 0;    break;
    case 25: LATCbits.LATC0 = 1;    break;
    case 26: LATCbits.LATC0 = 0;    break;
}
ボリューム変更0x0c,ボリューム値2バイト 現リビジョンの基板ではチップ(MCP4018)が実装されていない為、動作しません
存在確認0x101バイト '2608'の4バイトを返します
A0レジスタ書き込み0x13,レジスタ番号,データ3バイト 内部I/O処理ロジックを通してA0レジスタの書き込みを行います。(LEDやLCDやフェードアウト処理などの計算ロジックを通過します)
応答値はありません。
A1レジスタ書き込み0x14,レジスタ番号,データ3バイト 内部I/O処理ロジックを通してA1レジスタの書き込みを行います。(LEDやLCDやフェードアウト処理などの計算ロジックを通過します)
応答値はありません。
バックライト制御0x15,制御値2バイト 制御値
0:現在の状態を反転します
1:強制点灯します
2:強制消灯します
ADPCMロード
(v1.1以上)
0x16,flag,ファイル名11バイト13バイト SDカードが初期化されていない場合、エラーになります。
ADPCMファイルをSDカードから読み込み、ADPCMメモリに書き込みます。
読み込むADPCMのアドレスはフラグにより、続けて読むか先頭から読むかを指定します。
フラグ
0x00:ADPCMファイル読込みアドレスを前回の続きから読み込みます
0x01:ADPCMファイル読込みアドレスを先頭から読み込みます
ファイル名はディレクトリにマッチングする11バイトをそのまま記述してください

応答値
0:失敗
1:成功
 成功の場合は、続けて4バイトのデータが返って来ます。
 ADPCM読込み開始アドレス 2バイト、下位・上位の順番 32バイト境界の数値
 ADPCM読込み終了アドレス+1 2バイト、下位・上位の順番 32バイト境界の数値
ADPCMの再生
(v1.1以上)
0x17,パン,TL,サンプリングレートL,サンプリングレートH,
開始アドレスL,開始アドレスH,終了アドレスL,終了アドレスH
9バイト パンは1がL、2がR、それ以外が両方です。
応答値
0:失敗
1:成功
次の曲へ進める0x181バイト 通常モード(SDカード)で演奏中に次のファイルへ進めます
応答値はありません。
SDカード制御チップ初期化
(v1.1以上)
0x191バイト SDカードの制御チップをSPIモードで初期化します。
戻り値:
1 SPIモード初期化成功
3 SDカードが入っていない
4 SPIモード初期化失敗
SDセクタ読み込み
(v1.1以上)
0x1a,アドレス(LL),アドレス(L),アドレス(H),アドレス(HH)5バイト SDカードのセクタをSD用内部バッファに読み込みます。アドレスは4バイトでリトルエンディアンで指定します。 戻り値:
1 成功
2 コマンドフォーマットエラー
3 SDカードが入っていない
4 失敗
内部バッファ読み込み
(v1.1以上)
0x1c,アドレス(L),アドレス(H),個数4バイト SD用内部バッファを読み込みます。指定した個数だけデータが戻ります。
0x01,個数,データ...の形式で読み込んでください
SDセクタ書き込み
(v1.1以上)
0x1b,アドレス(LL),アドレス(L),アドレス(H),アドレス(HH)5バイト SDカードのセクタをSD用内部バッファに読み込みます。アドレスは4バイトでリトルエンディアンで指定します。 戻り値:
1 成功
2 コマンドフォーマットエラー
3 SDカードが入っていない
4 失敗
内部バッファ書き込み
(v1.1以上)
0x1d,アドレス(L),アドレス(H),個数,データ..5バイト〜 SD用内部バッファへデータを書き込みます。
SPFMモードへ切り替え
(v1.2以上)
0xff1バイト 応答値OKの2バイトを返し、SPFMモードに切り替えます。
書き込みのみで、読み込みには対応していません。

・おまけ 携帯FM音源プレイヤー v1.2基板で再挑戦される方向け

・カバー基板


・メイン基板

抵抗配置及び液晶下の1uF積層セラミックコンデンサの配置が少し違っています。LEDの右側が電流制限抵抗680Ωです。
LED直下の2つの抵抗はI2C用の10kΩ抵抗です。
寝かせてつける抵抗のシルク印刷とパターンがありますが、v1.4用のファームウェアを使う場合、マイコン内蔵のプルアップ抵抗が有効になっているので不要です。
左上のボリュームボタン横の抵抗も同様に不要です。
液晶はバックライトなしのAQM0802A(http://akizukidenshi.com/catalog/g/gP-06669/)を購入してください。
かなり華奢なので、バックライト付よりも取り扱いには注意が必要です。
バックライト制御用のFET等の部品は不要です。
音源部分の構成は同じです。
書き込み端子の配置がv1.4と異なり、縦に並んでいます。裏面から見ると上から2つ目に太い線が接続されているので、こちらが2番ピンのようです。
一番上が1番ピンなので、PICKITの▲マークを合わせてください。

・2608用ファームウェアv1.1のADPCM読み込み仕様について

どう実装したものか迷ったので、ひとまずADPCMファイルの読み込みだけ実装してみました。
ADPCMの再生は通常通り、YM2608のADPCMレジスタに再生アドレスを指定してください。
ボードのメモリは8ビット接続ですので、32バイト境界に配置する必要があります。
再生しようとしているADPCMのファイルが32バイト境界で無い場合、最後は0x00などで埋められるので、
この場合最後の32バイトは再生しないほうが良いかもしれません。

0x38d:bit1:1でADPCMを読み込むため、0x370のヘッダ情報を読み込みます。
0x370:byte:ADPCMファイル数を設定します。
0x371〜0x37b:ファイル名(FATエントリのマッチング用に大文字で記述)

ファイル名の7文字目、8文字目に数字を埋め込み、指定したファイル数だけ読み込みます。ファイルが見つからない場合は、中断します。
ファイル名はそのままマッチングされます。大文字で記述した方が無難かもしれません。たしか大文字で書かれていると思うので、マッチングしない事が考えられます。

記述例
0000:0370 04 44 45 4d 4f 30 30 30-30 50 38 36 00 00 00 00 .DEMO0000P86....
0000:0380 00 00 00 00 00 04 00 00-00 02 50 00 08 03 55 aa ..........P...Uェ
この場合、
0x38dが0x03なので、ADPCM読み込み有効、ウェイトループキャンセル機能有効になります。
0x370が0x04なので、ADPCMファイル数は4ファイルになります。
0x371〜0x37bがファイル名なので、
DEMO0000.P86
DEMO0001.P86
DEMO0002.P86
DEMO0003.P86
の4ファイルが、演奏ファイル実行前にADPCMメモリへ読み込まれます。

なお、上の例では0000と4桁ありますが、仕様的に00〜99の100ファイルが限界です。

例であげたDEMO0000.P86ファイルはすべて15624バイトでした。
32バイト境界に合わせると、実際には15684バイト(0x1e9)になります。
ADPCM再生レジスタには、メモリの範囲を指定するので、0〜0x1e8を指定することになります。

読み込みに成功、失敗しても実行が開始アドレス(0x384〜0x385)の0x400から開始されます。

; 再生サンプル

;YM2608を拡張モードへ(たぶんいらない)
0000:0400  b88029            mov        ax,2980
0000:0403  e87a00            call       0480

;ADPCMの初期設定。メモリ指定、サンプリングレートや出力レベル、パンなどの設定
0000:0406  b80020            mov        ax,2000
0000:0409  e88000            call       048c
0000:040c  b80021            mov        ax,2100
0000:040f  e87a00            call       048c
0000:0412  b8490a            mov        ax,0a49	;あ、0x49cdをサンプリングレートに入れようとして、49だけしかいれてませんでした…
0000:0415  e87400            call       048c
0000:0418  b8ff0b            mov        ax,0bff	;ボリューム最大
0000:041b  e86e00            call       048c
0000:041e  b8c201            mov        ax,01c2	;パン設定(L+R)
0000:0421  e86800            call       048c

;4ファイルを再生する(再生アドレスは0x500のテーブルを使用)
0000:0424  b90400            mov        cx,0004
0000:0427  be0005            mov        si,0500
0000:042a  b82100            mov        ax,0021
0000:042d  e85c00            call       048c
0000:0430  ac                lodsb
0000:0431  b402              mov        ah,02
0000:0433  e85600            call       048c
0000:0436  ac                lodsb
0000:0437  b403              mov        ah,03
0000:0439  e85000            call       048c
0000:043c  ac                lodsb
0000:043d  b404              mov        ah,04
0000:043f  e84a00            call       048c
0000:0442  ac                lodsb
0000:0443  b405              mov        ah,05
0000:0445  e84400            call       048c
0000:0448  b8a000            mov        ax,00a0
0000:044b  e83e00            call       048c

;FM音源レジスタへの書き込みを反映
0000:044e  9b                wait

;2秒程度ウェイト
0000:044f  51                push       cx
0000:0450  b90900            mov        cx,0009	;大体2秒弱の時間のウェイトです
0000:0453  51                push       cx
0000:0454  b90080            mov        cx,8000
0000:0457  e65f              out        5f,al	;特に必要ないのですが、ウェイトポートを入れてウェイト時間を稼いで見ます(ウェイトキャンセル有効なので、なにか挟む必要があります)
0000:0459  e2fc              loop       0457
0000:045b  59                pop        cx
0000:045c  e2f5              loop       0453
0000:045e  59                pop        cx
0000:045f  e2c9              loop       042a

;終了用ウェイト
0000:0461  ebfe              jmp        0461

;通常側レジスタ書き込み
0000:0480  86e0              xchg       al,ah
0000:0482  ba8801            mov        dx,0188
0000:0485  ee                out        dx,al
0000:0486  b28a              mov        dl,8a
0000:0488  88e0              mov        al,ah
0000:048a  ee                out        dx,al
0000:048b  c3                ret

;拡張側レジスタ書き込み
0000:048c  86e0              xchg       al,ah
0000:048e  ba8c01            mov        dx,018c
0000:0491  ee                out        dx,al
0000:0492  b28e              mov        dl,8e
0000:0494  88e0              mov        al,ah
0000:0496  ee                out        dx,al
0000:0497  c3                ret

;再生アドレステーブル
0000:0500 00 00 e8 01 e9 01 d1 03-d2 03 ba 05 bb 05 a3 07 ..・・ム.メ.コ.サ.」.

adpcmtest.zip
上記のサンプルファイルです。ADPCMファイルはご準備ください。
ファイルサイズ15624バイトで、サンプリングレートは、0x49cdなのですがcdを設定するのが漏れていますが、
計算式から逆算すると 0x49cd = (samplingrate / 55500)x65536 なので、
サンプリングレートは15999.78、つまり16KHzのファイルだと思われます。(記憶が微妙)

#というかこんなマニアックな仕様で使えるのかしら・・・

・おまけ 携帯FM音源プレイヤー v1.3基板で挑戦される方向け

・メイン基板

ベースは1.4基板を参考に作成してください。抵抗の配置が異なっています。
I2C抵抗は液晶の右下にあります。
特に左下の液晶バックライト用抵抗(47Ω)と、マイコンのMCLR用抵抗(10kΩ)の位置が逆です。
シルク印刷が重なっており読めないワナ付です。注意してください。

書き込み端子の配置がv1.4と異なり、縦に並んでいます。裏面から見ると上から2つ目に太い線が接続されているので、こちらが2番ピンのようです。
一番上が1番ピンなので、PICKITの▲マークを合わせてください。
これはv1.2基板と同じです。
また、ファームウェアは基板バージョン1.2用を書き込んでください。基板バージョン1.4用を書き込んでもどうという事はありませんが、ボタン配置が逆です。

・おまけ YM2608FM音源ボード v1.4基板で挑戦される方向け

・旧1.4基板

ベースは1.5基板を参考に作成してください。液晶がバックライトなしで、バックライト制御部品がなく、またSSG音源のミキシング周りが異なっています。
OPAMP及びその受動部品は不要なので、この辺りのごちゃっとした回路の数値を細く記載しました。(v1.5と変らないものも一部数値が入っています)
OPAMPは搭載せず1-2番ピンをショートしてください。
ボタン及びSDカード検出スイッチ用の抵抗(主に左下にある)も不要です。v1.5用のファームを書き込めばマイコン内蔵プルアップ抵抗が有効になっています。

シリアルコンソールの使い方

TeraTermなどをご利用いただけます。
改行コードはLFのみなので、CRLFに変換するなどのオプションを指定してください。

!注意!
ピン制御コマンドは、基板作成時の動作確認用のコマンドです。音源チップを搭載した状態で使用しないでください。
最悪マイコンや音源チップが壊れます。

ピン制御コマンドは、使用前にセーフティスイッチ解除コマンドをまず実行しないと使えないようになっています。

シリアルコンソールを起動してEnterキーなどを押下することで、シリアルコンソールモードになります。
※SCCIを利用する場合は、SCCI対応ソフトを起動することで従来通り強制的にSCCIに切り替わります。


繋がった場合は、まずhキーを押してエンターキーを押してください。
コマンドヘルプが表示されます。

-h
Welcome to 2151Player Console Version 1.00
Copyright 2022 Ultrya All Rights Reserved.
Hardware type [2151PlayerNeo]
Firmware version [2022/11/23 2.05 ]

command
 reset cpu|fm                        ... reset cpu/fm chip
 out/o reg dat                       ... output fm register
 clock 3.57|4                        ... select fm frequency
 button                              ... button test
 led on|off                          ... led control
 lcd init|cls|light|string           ... lcd control
     light on|off
     string x y string
 oled init|on|off|cls|bright|string  ... oled control
      bright brightness(hex)
      string x y color(hex) string
 sd init|dir|read/r|write/w|set|dump ... sd control
    read readsector(hex)
    write writesector(hex)
    dump
    set address datas
 play [filename(8+3)]                ... playfile/information
 stop                                ... stop play
 cd directory                        ... change current directory
 fm                                  ... dump fm register
 fms                                 ... dump fm register (repeat 1sec)
 vol volume                          ... volume setting
 opt [address data]                  ... internal opt parameter setting
 mml init/play/ch                    ... mml initialize / play
    ch(A-H) mml                      ... set mml(music macro language)
 help/h/?                            ... this message

 unlock yes                          ... unlock safety switch
 pin/p pinname 0|1                   ... output pin level (safety unlock only)
    pinname:IC|WR|RD|D0..D7|A0|A1

-



コマンドの記述方法について

例1.
 reset cpu|fm                        ... reset cpu/fm chip

 コマンド+オプションを指定します

 reset cpu
 reset fm
 のように記述します。
 「cpu|fm」は、cpuまたはfmのどちらかを記述できるという意味です。


例2.
 out/o reg dat         ... output fm register

 コマンド+オプションを2つ指定します

 out 10 2a
 out 28 2a
 out 7 3f
  o 7 3f
 
 のように記述できます。
 「out/o」は、outまたはoで記述できるという意味です。


例3.
 oled init|on|off|cls|bright|string  ... oled control
      bright brightness(hex)
      string x y color(hex) string

 oled init
 oled bright ff
 oled off
 oled string 12 16 ff test!

 のように記述できます。
 一部オプションでは、追加引数があります。そのようなコマンドは下に追加が必要な場合のオプションが追記されています。
 (hex)となっている引数は16進数で指定してください


例4.
 play [filename(8+3)]                ... playfile/information

 play
 play testdat~1.vgm

 のように記述できます。「[]」は省略可能の意味です。


コマンドの簡易説明

reset
 CPU又はFM音源をリセットします。

clock
 FM音源に供給するクロックを指定できます。あらかじめ決められた組み合わせ以外は指定できません。

button
 ボタンの押下状態を16進数で表示します。負論理の為押下していない状態では1fとなります。
 押したボタンのビットが0になります。全部押すと0になります。
 この数値が意図した状態と違う場合、ボタンの半田がおかしい可能性があります。

led
 LEDの点灯・消灯を制御します

oled
 OLEDの初期化、表示・非表示、クリア、輝度(正確にはコントラスト00〜ffで、00が半分くらいの輝度です)、文字列表示を行います

sd
 SDの制御を行います。SDカードのSPIモード初期化、ディレクトリエントリの表示、セクタ読み込み、書き込み、データ設定、ダンプなどが行えます。
 
 SDカードはSPIモード初期化を行うことでデータの読み書きができるようになります。SDカードを初期化するわけではありません。

 sd init
 まずこのコマンドでSDカードを使えるようにしてください。(SDカードを挿入した状態でボードを起動していた場合、すでに初期化済みです)

 sd dir
 FAT32のディレクトリエントリを確認できます。8+3ファイル名のみです。
 →v1.02のコンソールバージョンからロングファイル名も表示するようになりました

 sd r 0
 リードコマンドで指定したセクタを読み込みます。SDバッファに読み込み、バッファをついでにダンプして表示します

 sd w 0
 SDバッファの内容を書き込みます

 sd set 10 01 02 03 04 ..
 バッファの内容を書き換えます。setの後に、アドレスを指定し、そのあとにデータを指定します。
 コマンドの有効最大長はそこまで長くありません。
 長いデータを書き換える場合は複数回指定してください。
 通常はsd readコマンドでバッファに読み込み、sd setコマンドで必要な場所だけを書き換え、sd writeコマンドでバッファの内容を書き込むという使い方をします。

play
 ファイルの再生を指定しています。8+3ファイル名のみです。
 ファイル名を省略した場合、再生中のファイル情報を表示します。

stop
 ファイルの再生を直ちに終了します。

cd
 現在のカレントディレクトリを、指定したディレクトリに変更します。
 ルートディレクトリに直接戻る場合はcd /のように指定してください。1つ上はcd ..を指定してください。

fm
 FM音源チップのレジスタバッファにある情報を出力します。
 内部的に保持しているレジスタ情報の為、実際のチップの情報ではありません。大体同じです。

help
 簡易ヘルプを表示します。


unlock yes
 ピン制御のロックを解除します。セーフティ解除は作成時のみに利用してください。
 音源チップをつけたままピンを制御しないでください。

pin
 ピンの出力を制御します。通常状態ではこのコマンドは実行できません。セーフティを解除する必要があります。
 ピン名としては IC WR RD D0 D1 D2 D3 D4 D5 D6 D7 A0を指定できます。
 pin WR 1
 pin IC 0
 のように指定できます。



なにかありましたらぶろぐにある基板頒布Projectのページのコメントまでお問い合わせください。
答えられるものは回答します。(わからないこと、答えにくい事は無理です)
既存音源ドライバの解析に関するものは答えられません。自分で何とかしてください。
https://asmpwx.at.webry.info/201907/article_2.html