*注意*

近年、AIによるサイト内情報の要約や解説など便利な機能が増えています。 ですが、技術系のブログについてのAI要約はまだまだ不正確な記述をする場合が多いです。 AI要約や解説を鵜呑みにせず、元記事を参照して必ず自らの目で確かめて判断するようにしてください。 *Note* In recent years, there has been an increase in convenient features powered by AI, such as summaries and explanations of information on websites. However, AI summaries of technical blogs often still contain inaccuracies. Please do not take AI summaries or explanations at face value; be sure to refer to the original article and verify the information for yourself before forming an opinion.

2025年5月31日土曜日

HD43517 の使い方②

 

 音源ICの使い方一覧へ

HD43517 の使い方

注意:このサイトの内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。



の続きです。ページサイズが大きいので分割しました。





・使用例  - MMLで演奏 -

HD43517を1~4個使用し、MMLで演奏するプログラム(Arduino ATmega328p用)を紹介します。

・回路図(HD43517を3つ使用し、相互接続した場合)




・回路図(HD43517を3つ使用し、DACをそれぞれ用意した場合)



基本的に回路構成はCasioTone602のものと同じですが、アナログマルチプレクサを使用したりなどの変更点がいくつかあります。もちろんCasioTone602の回路例で紹介した回路でも音が出ます。



・プログラム(HD43517を1~4個使用、「I-4」と「MSO」端子でアドレス空間上の配置位置を決定)


// HD43517でMML演奏プログラム
//©oy
// https://oykenkyu.blogspot.com/2023/02/HD43517.html

#define XTAL 16000000 //水晶振動子の周波数(MML演奏速度に影響)

#include "avr/io.h"
#include "avr/interrupt.h"

//#define SERIALSPEED 31250 // UARTのボーレート
#define SERIALSPEED 38400 // UARTのボーレート(デバッグ用)

#define CH 16  // HD43517最大チャンネル数(HD43517は1つで4チャンネル分発音できます。)
#define MML_MAX_TR CH // MMLトラック数

//HD43517レジスタ
//bit6~bit4は実アドレス、bit3~bit0は内部レジスタ用アドレス
#define COMP_W_MODE 0x00 //波形合成モード
#define KEY_OFF 0x08 //キーオフ

#define KEY_ON 0x10 //キーオン
#define COMP_W_SW 0x18 //チャンネルごとの各正弦波合成ON/OFF

#define SV_W1_LV 0x20 //スタートレベル:基音音量
#define SV_W2_LV 0x21 //スタートレベル:2つ目の倍音音量
#define SV_W3_LV 0x22 //スタートレベル:3つ目の倍音音量
#define SV_W4_LV 0x23 //スタートレベル:4つ目の倍音音量
#define SV_W5_LV 0x24 //スタートレベル:5つ目の倍音音量
#define AR 0x25 //アタックレート
#define DR 0x26 //ディケイレート
#define SL 0x27 //サスティンレベル
#define AL_W1_LV 0x28 //アタックレベル:基音音量
#define AL_W2_LV 0x29 //アタックレベル:2つ目の倍音音量
#define AL_W3_LV 0x2A //アタックレベル:3つ目の倍音音量
#define AL_W4_LV 0x2B //アタックレベル:4つ目の倍音音量
#define AL_W5_LV 0x2C //アタックレベル:5つ目の倍音音量
#define RR 0x2D //リリースレート

#define W1_DLY 0x30 //基音発音ディレイ
#define W2_DLY 0x31 //2つ目の倍音発音ディレイ
#define W3_DLY 0x32 //3つ目の倍音発音ディレイ
#define W4_DLY 0x33 //4つ目の倍音発音ディレイ
#define W5_DLY 0x34 //5つ目の倍音発音ディレイ

#define PTC_CHG 0x40 //ピッチ変更値指定
#define PTC 0x50 //ピッチ指定
#define OCT_CHG 0x60 //オクターブ変更値セット
#define OCT 0x70 //オクターブセット

// HD43517_チップセレクト用テーブル(少し高速化できる?)
unsigned char hd43517_cs_conv[4] = {0x38,0x58,0x68,0x70};

// HD43517_保存用
unsigned char hd43517_main_vol[CH]; //音量保存用
unsigned char hd43517_main_pan[CH]; //パン保存用
unsigned char hd43517_main_ptc[CH]; //ピッチ保存用
unsigned char hd43517_main_cwm[CH]; //波形合成モード保存用(音程計算で使用)

//hd43517のノートデータへ変換(合成比率モード別)
//HD43517の入力クロック周波数が4.00MHzの時
unsigned int hd43517_note_conv[4][12] = {
  {0x157, 0x16C, 0x182, 0x199, 0x1B1, 0x1CB, 0x1E6, 0x203, 0x222, 0x242, 0x265, 0x289},
  {0x1C8, 0x1E4, 0x200, 0x21F, 0x23F, 0x261, 0x286, 0x2AC, 0x2D5, 0x300, 0x32E, 0x35E},
  {0x111, 0x122, 0x133, 0x145, 0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205},
  {0x157, 0x16C, 0x182, 0x199, 0x1B1, 0x1CB, 0x1E6, 0x203, 0x222, 0x242, 0x265, 0x289}
};
//hd43517のオクターブデータへ変換(合成比率モード別)
int hd43517_oct_conv[4]= {
  0, 1, -2, 0
};
//HD43517音色パラメータ
//CWM   :   波形合成モード、bit1~bit0の4通り
//CWSW  :   各正弦波合成ON/OFF、bit4~bit0がそれぞれ倍音5~基音に割り当て
//SV-W[N]-L  :  スタートレベル:[N]個目の倍音音量、bit3~bit0
//AL-W[N]-L  :  アタックレベル:[N]個目の倍音音量、bit3~bit0
//AR    :   アタックレート、bit3~bit0
//DR    :   ディケイレート、bit3~bit0
//SL    :   サスティンレベル、bit3~bit0
//RR    :   リリースレート、bit3~bit0
//W[N]-DLY    :  [N]目の倍音発音ディレイ、bit3~bit0
//TL    :   トータル発音レベル(未使用)
//PAN   :   パン(未使用)
//PTC   :   音程、7bit値 64が標準




//パラメータ構造
//CWM, CWSW, reserve, reserve, reserve,
//SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
//AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
//AR, DR, SL, RR, reserve,
//W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
//TL, PAN, PTC, reserve, reserve,
//reserve, reserve

const unsigned char hd43517_parameter[][32] PROGMEM = {

  //PIPE ORGAN
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0C, 0x0B, 0x09, 0x0B, 0x0B,
    0x08, 0x0B, 0x0E, 0x00, 0,
    0x01, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //D1A PASON
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x09, 0x0B, 0x00, 0x0B, 0x09,
    0x05, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //TIBIA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x00, 0x09, 0x0C,
    0x05, 0x0F, 0x0E, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //FLUTE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0B, 0x00, 0x00, 0x0D,
    0x07, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x02, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //JAZZ ORGAN1
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0B, 0x0B, 0x0B, 0x00, 0x00,
    0x05, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x00, 0x01, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //PIANO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0D, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x01, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x01, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //VIBRA PHONE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x00, 0x0C,
    0x00, 0x0B, 0x00, 0x00, 0x09,
    0x08, 0x01, 0x00, 0x01, 0,
    0x00, 0x01, 0x00, 0x00, 0x01,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //CELESTA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0C, 0x0D,
    0x00, 0x00, 0x00, 0x0C, 0x0B,
    0x08, 0x00, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x01, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //OBOE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0A, 0x0A, 0x0D, 0x00,
    0x07, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //FUNKY
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x0C, 0x0C,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x00, 0x00, 0x01, 0,
    0x00, 0x00, 0x00, 0x04, 0x05,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },

  //BRILLIANT OGAN
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0D, 0x00, 0x00, 0x00, 0x0E,
    0x05, 0x0B, 0x0D, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //WOOD WIND
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x0B, 0x00, 0x00,
    0x0B, 0x00, 0x00, 0x00, 0x0B,
    0x09, 0x03, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //FULL TIBAS
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x09, 0x00, 0x0D, 0x00, 0x0C,
    0x05, 0x0B, 0x0E, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //PICCOLO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x09, 0x00,
    0x00, 0x00, 0x00, 0x0E, 0x00,
    0x07, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //JAZZ ORGAN2
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0D, 0x00,
    0x0B, 0x0B, 0x0B, 0x00, 0x00,
    0x07, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //ELEC.PIANO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x00, 0x0D,
    0x00, 0x0C, 0x00, 0x00, 0x00,
    0x03, 0x02, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x01,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //MARIMBA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0E, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x09,
    0x03, 0x00, 0x00, 0x00, 0,
    0x00, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //CHIME
  {
    0x01, 0x1F, 0, 0, 0,
    0x0C, 0x0C, 0x0A, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x01, 0x00, 0x01, 0,
    0x01, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x2F, 0, 0,
    0, 0
  },
  //BASSOON
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x08, 0x0B, 0x0D, 0x08, 0x00,
    0x03, 0x02, 0x0E, 0x01, 0,
    0x01, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //WAH BRASS
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0C, 0x0E, 0x0C, 0x0A, 0x09,
    0x07, 0x0B, 0x0C, 0x00, 0,
    0x00, 0x04, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //@0_test
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0F, 0x0E, 0x0D, 0x0C, 0x0B,
    0x00, 0x0C, 0x00, 0x00, 0,
    0x00, 0x02, 0x04, 0x06, 0x08,
    0xFF, 0x40, 0x68, 0, 0,
    0, 0
  },
  //@1_test_bell
  {
    0x02, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0F, 0x00, 0x00, 0x0D, 0x00,
    0x00, 0x00, 0x00, 0x04, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x68, 0, 0,
    0, 0
  },
 

};


//---------------演奏したいSMFに合わせて要変更--------------------
//デフォルトオクターブ[ch0,ch1,ch2,…,]
//増やすとオクターブが高くなります。(出力オクターブ = def_oct + (mmlのオクターブ))
char def_oct[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//char def_oct[16] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};

//デフォルトキー
char def_key = 0;

//--------------------------------------------------------------

//ドラム発音用
unsigned char drum_note_num = 0; //ドラムチャンネルセット保存用(未使用)

// MML演奏用
// ATmega328だとdoubleでも精度はfloatと同様
volatile double mml_time = 0;      // MML演奏用時間カウンタ
volatile double mml_time_ms = 0;   // MML演奏用時間カウンタms
volatile char mml_time_cnt_en = 0; // MML演奏用時間カウント_有効無効(0で無効、1で有効)
volatile int tempo = 120;          //テンポ


//演奏のデータ
//簡易MML
unsigned int mml_data_len = 0xFFFF; //トラック終端「;」が入るため、適当な数値で良い

// mmlのトラック終端には必ず「;」を入れてください。
//使えるコマンド
//「;」             :トラック終端コマンド(トラック終端に必ず入れてください。)
//
//・全チャンネル(トラック)でパラメータを共有
//   「t」+ 数値:テンポを整数で指定
//
//・各チャンネル(トラック)でパラメータの独立指定が可能
//   「v」+ 数値      :ベロシティ(音量)を整数で指定
//   「p」+ 数値      :パン(音量)を整数で指定
//   「@」+ 数値      :音色を整数で指定
//   「o」+ 数値      :デフォルトオクターブを整数で指定
//   「l」+ 数値      :デフォルト音長を整数で指定
//   「<」または「>」  :オクターブを上げる、下げる(「<」で1オクターブ上げる)
//   「^」            :タイ(タイの次の音程コマンドでの発音は無視され、音長のみ取得します。音程の省略も可能です。)
//
//
//・音程コマンド
//   (音程)+(「+」または「-」)+(音長)+(「.」):音程はc,d,e,f,g,a,b,rで指定、+または-で半オクターブ移動、音長は整数で指定、ドットの数で(音調+(音調/2)+(音調/4)+(音調/8)+…)符点音長を追加指定
//   例:
//   「a4」    : 音階Aで4分音符
//   「c+16」  : 音階C#で16分音符
//   「g-1.」  : 音階G♭で符点1分音符(1分音符+2分音符の長さ)
//   「r.」    : 休符で符点デフォルト音長(デフォルト音長の初期値は4分音符です。変更したい場合は「l」コマンドで指定してください。)
//   「r2...」 : 休符で3符点2分音符(複符点2分音符)(2分音符+4分音符+8分音符+16分音符の長さ)
//
//・トラック10(ch9、0x09)のドラムパート場合のみ、和音(音長が0)が使えます。
//

//宵加減テトラゴン
const unsigned char PROGMEM mml_data[] =
"t150l8r1r1r1o4f.d+r16d+f16rdr16da+.a+2^a+.gg+.<c.>eg4..r16g.d+.rg4.d+d+4..r16d+rd+r<cr16>g+.g+c4..r16fr16fr16d+3r24<ee>g+r16d+r.c.c.>g+16r16<fr16d+r16efr16d+r16efr16d+r16efr16f+.f+fr16d+r16e16e16fr16d+r16efr16d+r16efr16c+.d<d+.r16d+.r2r16d+d+16r2.r16d4..r16d4rc+.r2...c.r4r16>g+.<cr.>f+r16f+r16f+f.r16f4a+2b2<c4.rc4.r4>e16f3r2r6>g.ra+r<d+d+rd+4r4f4r4f4r2rd+.g+.g+g.gr16g+>a+.<a+.a+g4rg>a+2g+2r1r1<g2..r<<b2.r4>>c2d2d+2d+2<d+.r16>a+2.g+r16g+r16g+g+4..r16dr16gr16gdr16f+r16f+r1d2g2e2d+2e2.d+4d2g4r16f.c+2c2>b2a+2a4..r16<e2d+.d+.dc+4>e4<<<<d4.>>e4.>c4<d+3r6>c2>b2<d+2>b2b2<e2.e4f+2f+2g4..r16b4e4g4a4a.gr16gb2b.<d.<<d>>>d+.a+.a+a+2d2d.d.de.<g.>e4.e>e<a.<cr16d+cd+>d+<<c>>a.<cr16>dd.<c16>ag+<f.>b.<dff>b<dg+.d+.>f<c.r16d+cf.>g.a+a+g4>g<d+.>g+.<g+g+f+d+4g+4d+d+>b4<g+4>a+.<d+.<d+>>a+4<a+4>a+.<<c16>g+g+a+4f4>b.<b16e>b<ee4.a1^a1r<e2..d+1e1>b2a+2>a1g+2g2f+1f+4r2.b2^b6r1r3br16<f+.ef+2cr16g.f<cr>g4d.d4^d16ar16dr16f+drdda.<d16>a<d16r16>d2g2e2d+2e2.d+4d2g4f4c+2c2>b2a+2a2<e2d+.d+.dc+4>e4<<<<d4.>>e4.>c4<d+3r6>c2>b2<d+2e4>b4b2<e2.e4f+2f+ef+4g4..r16b4e4g4a4a.d+r16gb2b.<d.<<d>>>d+.a+.a+a+2d2d.d.d<d.d2^d.>b<c.e.>g+b4..r16b.g.rb4.gg4..r16grgr<er16c.c>e4..r16ar16ar16g3r24<g+g+cr16>gr.e.e.c16r16ar16gr16g+ar16gr16g+ar16gr16g+ar16a+.a+ar16gr16g+16g+16ar16gr16g+ar16a+r16bbr16<c.c+>dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+d4.c16>b16a+16r32;l16r1r1r1r8.o5d+r8d+8>a+r8<dr8dr<a+2.r1r4>d+r4..d+4r1r1r1r1r2r8..a96a+96b96<c48c+48d12c+48c48>b96a+96a96r4...r3d+96f96g96a96a+96b96<c96c+96d96d+96e24r1r3r48>f+24f48e48d+48d48c+24c8c+24d12d+eff+24g24g+32a32a+32b32<c32c+32d48d+48e96f96f+96g96g+96r8r32>f32r32f8rd+rf6r48gr8>a+a+<f8d+8f8rg8r4r>b.r32a+4r8a+r<g+8rg8reeer8f8rg3r4r6crd+8crd+8rc8rf8f+8rf+8rf+.r32f6r3r8f32f32rfrd+rf6r48g.r.>a+a+<f8d+.r32f8rg.r3r96grf.r.>a+8ra+r<g+6r48g8rg+.r32g8..r8r32d+rd+8rd+8rf8g4r8grf4r8frf8ra+8rf.r32e6r48f6r48g8g+6r48c8rcrd+8.d8rd+rd+2.r4g4.r8g+4..ra+3r24a+.r32a+8rg+.r.g.r32f4..r8.d+8drd+8f3r6r8>a+4<a+8b8.rg8.rf6r48g8r8.c8r>b8r<c.r32d6r48c8rd+32r32d+d+6r48d8.d+8r8d+rd+ra+1^a+.r1r1r4r32d8.r<c6r48>b6r48<c8>b8rg8.a.r32g8.a8.gr<c6r48>b8.<cr>b6r6r24a.r32b8rd6r48arg8.a8rgr<c8.>b8r<cr>b8.r8.bbb6r48g8rera6r6r24d32d32rd6r48a8.f+8g8rg8.a8<c8.>b6r48g8a8.r8.br<c8r>b6r48g8a8.r<d.r32c.r32>b6r48g8rarg8.a8rgr<c8.>b6r48<c8>b8r8d+8..r32d8..r8r32<drd+6r48>b6r48b.r32a6r48g6r48a.r32g6r12b8r8<c4r8>ed+e.r8r32<c8.r>b4r8dd32r32d4r4e8r8<cr>e8r8<c8r8c32r32c32r32>b8..r32a4g8.f+8.f+rg2r4a.r32b.r32<c4..r4rd6r12>b8.ra8.rg6r48<d.r.d.r4.r32>g.r32a+6r48a+.r.a+32a+r32a6r48a+8r<c8r8>f4..r4ra+32r32a32r32<c6r48c8rc8c8r>b6r48<crd4r4>d+6r48d6r48d+8a+4r4f8re.r.f8<c4r4>f+8rg+8.a+8.rb6r12<c+4r8>d+4<c+8.>b8rb.r32a+8rg+8.a+1.r1r1r1r8g+6r48e6r48f+.r32e8.f+8rera6r48g+8ra8g+8..r8r32f+.r32g+6r48>b6r48<f+.r32e8.f+8rera8rg+6r48a.r32g+4r8g+32r32g+32r32g+8re8.c+8f+6r6r24>b32r32b32r32b8r<f+6r48d+.r32e6r48e.r.f+.r32a6r48g+8re8f+6r3a8.g+8.e8f+2r1r1<br4..>f+3r6<<cr4..c8.r4r>gr8gr8gr4ar8ar>d8r8<c8.rc8.>b6r48<c8>b8rg8.a.r32g8.a8rgr<c6r48>b6r48<cr>b8.r8.a8b6r48d6r48arg8.a8rgr<c8.>b8r<cr>b8.r8.bbb6r48g8rera6r6r24d32d32rd6r48a6r48f+8g8rg8.a8<c6r48>b6r48g8a8.r8.br<c8r>b6r48g8a6r12<d8c.r32>b6r48g8rarg8.a8rgr<c8.>b6r48<c8>b6r12d+8..r32d8..r8r32<drd+6r48>b6r48b.r32a6r48g6r48a.r32b6r12b8.r<c3r24>ed+e8r8<c8.r>b4r8dd32r32d4r4e8r8<cr>e8r8<c8r8c32r32c32r32>b8.ra8.rg6r48f+8.f+8g4..r4ra8b8<c2r4d6r12>b8.ra8.rg6r48<d.r.>f+8g2....r1r32gr4..g4r1r1r1r1r1r1r1r1r2.<c+r8cr8c+r2rc+r8cr8c+rc+r8cr8c+rc+r8cr8c+rg8.r4.r32;l8r1r1r1o2a+.a+.a+a+.a+.<fd+.d+.d+d+.d+16d+4d.d.d>b.b16b.r16<c.r16c.r16c.r16c.r16>a+.r16a+.r16<d+4..r16>f.r16f.r16f.r16f.r16g.gr16<c.r16c.r16c>g+g+g+g+a4a4a+.g+.aa+.g+.aa+.g+.aa+a+bba+.g+.aa+.g+.aa+.g+.aa+.<c+.dd+4d+.r16>a+.<d+r16d+3r24>d+d+<d+>b<g>g+g4.rgr16<g.c.r16<cr16>c.rd+e>gg+4..r16g+4..r16br16br16ba+4<cd>d+4<d+>a+g.g.<d+>g+4g+g+aaaaa+a+4a+bbbb<cg16>g.ed+.g.g+g+<g+>g+aa+a+a+g+g.r16gg<g16f+32f32e16d+16>g4g+r16g+r16ag+r16g+r16g+d+.d+.a+<d+4dc>a+<a+g+gd+>a+g+4g+1<g+4.d+4>g+a+g+g2^gg4.b2<f32f+64g32g+32g32f+64f64e64d+64d32c+32c32>b32a+32.a16^a64g+32.f.f.fg.g.gg+4g+<d+16>g+16<ad+16a.a16a16>a+.a+.a+<a+16a+16a16a16a+16a+16>a+16<c16c+r16c+r16c+c+.c16>b<c+d.d.g16f+16d16.c16.>a.f+<d16r2.r16>g16<g16>g.g.<g>g.g.gf+.f+.f+<d+<d+>d+d+e.>e.<e>e.<d+.dd>a<da>g24g24<f24gff16e16c+r16c+16c+.r16c.c.c>br16b4^b16a+a+a+a+ar16a16aaa4a4<d+r16d+r16dc+<c+>c+16<c+16c16>b16c.c16r16cr16c.c.cc.c.c>g<gcf>b.b.b<d+.d+.d+>e.e16<ef+g4dc+>a.r16aaa.r16aa+b.r16b<d+e.e.ec4ccc+4c+c+d.d.dd.d+4^d+16>e.e.<ed.d.dc.c.cc4c4d2^d.c+32.c32.>b32.a+32.r<e.e16eee.e16eed+.d+16d+d+d+<d+>d+<e>d.d16ddar16<d16>ag+g^g32f+32f16r>g<gg..f+32f16r16>f.r16fff.r16f<f>g.r16ggg<g>ggg+.r16g+g+<g+g>g+4g+.r16g+g+g+d+g+aa+.r16a+a+a+.r16a+ba+.r16a+a+a+.r16a+a+b.b.bb.r16bbb2^ba+ag+r1r1r1r1r1r1r1r1r1r1r1b.<e.e>b4bb<c.c.cc.c.cd.dr16ddr16da16f+16d+16da16f+16d16r16ada16<d16d16>a16<d16>a16>g.g.<g>g.g.gf+.f+.f+<d+<d+>d+<d+>e.>e.<e>e.<d+.dd>a<da>g24g24<f24gff16e16c+r16c+16c+.r16c.c.c>br16b4^b16a+a+a+a+ar16a16aaa4a4<d+r16d+r16dc+<c+>c+16<c+16c16>b16c.c16r16cr16c.c.cc.c.c>g<gcf>b.b.b<d+.d+.d+>e.e16<ef+gbdc+>a.r16aaa.r16aa+b.r16b<d+e.e.ec4ccc+4c+c+d.d.e32f+32a32<c32d.>d+4^d+16>e.e.<ed.d.dc.c.<c16.c+32d16.c+32c>gcd2^d.c+32.c32.>b32.a+32.r<g.g.gg.g16g4f+.f+.<f+>d+.d+16d+.r16e.e.ee.r16e.r16g.g.gg.g16g4>a.a.aa.r16a.r16b.br16<e.r16e.r16eccccc+4c+4d.c.c+d.c.c+d.c.c+ddd+d+d.c.c+d.c.c+d.d+.ee.f.f+>g.f.f+g.f.f+g.f.f+g.f.gg.f.f+g.f.f+g^g32f+32f32e32d+32d32r4r32;l16r1r1r1o3a+4.r8a+4.r4r<<<<<a+g+d+>a+gd+>a+gd+r>ga+<d+g8rg+8rg8>b<d+f8d+8f8r8.<<<c+r>d+c>gd+c>gd+c>g<d+8g8rg+8rg8>b<d+f8d+8<cdd+8.d+8.r8d+8.d8.c8>a+8.<f8.d+4r4.>d+4.d+rd+4r1r1r1r4.<<d+>a+g+gd+>a+g+gd+>a+g+gd+>a+r2..<<d+4d+r4..g+8g8f+8f4r4<d8>d8r8c+4r4c+4r4.d+4r4>g+8.gr8g+8b8.b8rb8a+4g+4<d+8.r4rd+8.r4rd+8.r4rd+8.r4r>a+8.r4rb8.r4ra+8.r2.r<d+8.r4rd+8.r4r>a+8.r4ra+8.r4r<d+8.r4rd+8.r4rd+4r8d+4r8d+4<g2g+2a+2r2g+2r1.b4..r2r>>d+6r48d+6^d+192g64g+.r32g6r48d+4rd+2<d+8.dd+.r32d+.r32>d+8.d+32r32>a+8.a+<d+4f4c+8rf+8.f+8f4r4>>d8r<<g8rg8r8.f+8rf+8r2<<<cr8>br8<cr>br1.rd+d+af+d+8r2.>>d+4r2.<<c8d8g8re8>eg8d+4r4<d8r>a8r<d8>g8r4<d32r32d32r8r32ere8g8a8r8b8.r<c8.>b8.g8<d48c32>b48a32g48f+32e48d32c48>b32a48g32f+48e48d48c48>b48a48g48f+48e48>>c8<c32r32cr1<<<f+8g8ad+8.d8c8>b8r4.>b4.<f+f+<a8.g8.g8g8.r4rer<aec>aec>gec>gec>ge<<<dr<d>bf+d>af+d>bf+d>bf+d>b<<<<cg<<c>gec>gec>ge>bge>bgr8<<<<agd>agd>dagd+f+d+>bf+<<<ere>bgd>egd>b<gd>bgd>b<<d+>gd+<g<d+8>g>g<d+4r4<d4r1..>f8rg8.a4a3r2r24a8.f8.r8a8.g8.a8b8.r4rd+2<<d+8.c4r>>d2<<d8.d4r>>d+3r24d+d+d+4..rd+8rd+r4d+4r4d+4r4d+4.<dd+f8rd+8.d8>d+3r6c+8.c+4^c+c+2<<c.r.>a6r48f+.r32d+6r48c6r48>a8f+6r48d+8.c8>a8rf+8.r2..<<a8r2r8d+8r8f+8r8e8r1r8e8r4rg+8.a8br2r8.f+8r2r8e8r8d+8r8e8r2..>f+4.r2r8>>>a1..r4>b8r<<<<<e8re8>>>>>b3r24<brc8r<c8.cr>c8r<c8.cr>d8r<<<g8.g8>>>d8r<<<a8.a8<d8r8>c4<d+8.<c.r.d32r32g32r32>b8.d8d8.r2>>>e2d+8<<<d+d+af+d+8>>>e4r4>e8.r<<d+4>d4r4>g4<<<<c8d8g8re8>eg8d+4r4<d8r>a8r<d8>g8r4<d32r32d32r8r32ere8g8a8r8b8.r<c8.>b8.g8<d48c32>b48a32g48f+32e48d32c48>b32a48g32f+48e48d48c48>b48a48g48f+48e48>>c8<c32r32cr8c8c2c4<<<f+8g8ad+8.d8c8>b8r4.>b4.<f+f+<a8.g8.a8b8.r4rer<aec>aec>gec>gec>ge<<<dr<d>bf+d>af+d>bf+d>bf+d>b<<<<cg<<c>gec>gec>ge>bge>bgr8<<<<agd>agd>dagd+f+d+>bf+<<<ere>bgd>egd>b<gd>bgd>b<<d+>gd+<g<d+8>g>g<<g8g8g8g8<d>g8.r2.d>b<dr<b32d32rd>bgd>bgd>bg<gb8r<c8r>b8d+ga8g8a8<br<dgbge>bge>bge>bge<b8r<c8r>b8d+ga8g8<ef+g8.g8.r8e192f+192g6^g96f+8.e8d8.a8.g4r4.>g4.grg4r1r1r1r1r2.>>g32r2....g32r2....g32r1r;l16r1r1r1.o4fa+<d+dd+f>a+a+a+8r<d+8rd+rd+3r24d+r<gc>g+f>g+g+bb<d>g<gb>bg<ffd+<c>gd+<d+c>gd+g>g<cd+gd+c>g+g<c+d+g>d+g<gabr48g24g<d+>g<d+>g+gcd+g+<cd+>>g+<c>g+<<c>cg+d+g+fcdd>bg<a+grd+>a+<grd+regegd+g+<d+>d+d+g+d+r<c>aec>a<cefr1r1r1r1ra+r1r1r1r1r1>br8br8.<fa+rg+rd+d+r1r1r1r1r1r1r1r1r1r4<<d+8.rd+8r8>b8d+8>b8r<<d+r8>g+8r4b8r4fra+rfrd8r4.<gr>>b<br8>br<<a+32g+32g32f32d32a+32g+32f+32f32a32g32f32d+d>d+>fg+>f<ag+<cd+>a+g+<d+gd+>a+>fg+g+<d+>>g+<<g+>>g+<d+g+<d+>a<d+>d+>a<a<d+>ad+<<d+8.>a+b8<d+d+d+4<f4>c+>g+r48<c+24c+8rc+8c+>g+<c+>g+<fc+>g+8edr<c8rc8>>br8<d8rcr<<d96g96<d32r6r32d4<c8.>b8.<c8>>>g>db<dgrd>d>b<b<dg>>b<dgdec>cre<ce>>b<<f+>bd+>b<b<d+a>b<eb<ed>>eb<e>ebe<ed+>a+d+>ba<fa<dfd>a<da>dg<dfbec>b<<e>b<gbgeggd+>b<f+d+>b>bdb<bgd>b<d>bf+d<d>a+<dg>>a+<e<eee24a24<c24e24a24b24a24e24c24>ecea>aea<eba<d+g<<<d+>>>d+>bb<gr>a<a>>c+ea<c+eg>g<cegec>egcg<e>c>g<cg<cd+c<c>d+c>gd+c>g<<<c>d+c>g<cd+>g<b>b<f+b<ba>>b<ef+b<d+f+>be>b<e>beb<e>e<ge>b<e>be>b<<g+bg+bce>>a<gega<c>>a<a<cegege>f+>b<bf+df+ab<e64f+32.d>bf+<<<d32r32d32r32<d32r32d32r32>>>ec>gc<c>ce<c>c+eb<ec+<e>>ec+<b<d>aed>ad<ged+ef+<f+d+>b<d+>>egb<e>eb<<ggg24e24>b24gd>d>b<eb<d+>cd+<d+cd+c>g<<gd+g32r32>>g<c>c<ba+<e>ad>ad>a<da<f+dada<df+<d>>gdg<d>gede>a+<e<dgd>ebe>a<cfd+a<f>d+>a<cacad+<fc>acfdcd<c>adg+c>g+<fg+f>bg+<dgfefd>bgbgb<f>gg<de>cf<cd+g+d+c>g+<d+g+<c>d+fd+c>g+<a+<a+d>c<c>dg<df>a+dagfe>g<d+>bg+<d+>b<d+bg+f+>bg+<d+g+d+>bg+<f+d+>g+b<f+bd+b<d+>d+<f+d+>>b<d+g+<d+>>d+<d+cd+>a+g+<ca+<c>g+d+c>a+g+<g+<d+c>g+c<c>g+>g+<d+>g+<<d+c>a+g+fd+>a+f<<c+>>e<eaef+ab<c+>aea<c+>ae>ar1r8<<d+r1r1r1r8.c+rg+r2.rer1r1r1.r<<a8.g+8.e8f+3r1r1r6>>>f+r>bar8f+rar8.brab<gr8.>cra<c>g<cea+raar>adra<grf+rdref+f+ef+edr8>f+a<cerf+re>a<de<c>g<g>db<dgrd>d>b<b<dg>>b<dgdec>cre<ce>>b<<f+>bd+>b<b<d+a>b<eb<ed>>eb<e>ebe<ed+>a+d+>ba<fa<dfd>a<da>dg<dfbec>b<<e>b<gbgeggd+>b<f+d+>b>bdb<bgd>b<d>bf+d<d>a+<dg>>a+<e<eee24a24<c24e24a24b24a24e24c24>ecea>aea<eba<d+g<<<d+>>>d+>bb<gr>a<a>>c+ea<c+eg>g<cegec>egcg<e>c>g<cg<cd+c<c>d+c>gd+c>g<<<c>d+c>g<cd+>g<b>b<f+b<ba>>b<ef+b<d+f+>be>b<e>beb<e>e<ge>b<e>be>b<<g+bg+bce>>a<gega<c>>a<a<cegec>af+>b<bf+df+ab<e64f+32.d>bf+<<<d32r32d32r32<d32r32d32r32>>>ec>gc<c>ce<c>c+eb<ec+<e>>ec+<b<d>aed>ad<ged+ef+<f+d+>b<d+>>egb<e>eb<<ggg24e24>b24gd>d>b<eb<d+>cd+<d+cd+c>g<<gd+g32r32>>g<c>c<ba+<e>ad>ad>a<da<f+dada<df+<d>>d8rg8rgrg3r24gr<bec>accd+d+f+>b<b<d+>d+>b<aag<e>bg<ge>bgb>b<egbgec>b<fgb>gb<b<c+d+r48>b24b<g>b<gc>beg<ceg>cec<e>e<c>g<c>aef+f+d+>b<<d>brgdbrgrg+bg+bg<cg>gg<c>gr<ec+>g+ec+eg+ar1r1r1r1g24d24g24<f24r24>f24<c24r24>f+24<c+24>f+24c+24>g24<d24g24r24f24<c24r24>f+24f24f24r12g24<d24g24f+24g24f24<c24>>f+24g24<c+c+<d24g24d24>c24>f24<c24r24>f+24r24f+24<c+24r24>g24<d24g24r24f24c24>g24c24r24c+24f+24c+24<g24d24g24r24f24c24>f24c24>f24f+24<c+24f+24<g32<d+32>g32r<b32>g32r4.;l8r1r1r1o6f.f.ff2>a+.<d+16>a+<d+d+2>g+.<c.>g+b4..r16g4.rd+4.gd+.g.d+d+4g4<d+.c.cc4>g+4f.fr16<d+2^d+>g+2a4rg16r16a+.r1..r16d.c.c+16c+16d.c.c+d.c.c+d.c+.dd+a+16r.d+16r.a+16r.b4b16r2.r16>a+4r4<d<fr>a+a+r4<e4r4.>g+4r4<d+4r4d+r16d+r16d+d+4r4>d+4r4d+4r4d+4r4d+4r4f4r4f4r4g4r4d+4r4g+4r4f4r4f4r4e4r4<c4r4>b4r4>a+3r24a+3r24<a+4<g4r4d+2r1r1r1r1d+.d+4^d+16g4..r16d+2>>a2<a+4r4<d+4f4f.f+r16f+f4r4d.g.d+16r4c.dr2d+4.r>g4.gg2f+4.>f+<f+4.f+g4.gg4f+4f4.ag4ffg.g.gg2g4.rf2e.e.ee4eegr16gr16ga4c+4e.e.ee.e.ed+.d+.d+16r16d+2f+2f+2g1a4a4a4>a4<f+2f+4f+4g2g4g4a.a4^a16a.b.bb.b16bbb.b.bg.g.gg2<d2d4dd>g<d>>a+4<a+4<d4c.>>a.<ac2a.<c.>ag+.<c16>g+4g.g.<d>b4<dgc4>g+4<d+.g+.r>>g4<ga+a+<ddd>g+4.g+f+.g+4^g+16g+.g+16rg+b2a+2<c2d+2c3r6e2e3r6>a4.r1.r<e4.r2rc2.r4>e2^e6r3b2<d4..r16<g+4r4>f+4..r16>b4.r2r<c+2^c+6r3e4r2.r192>c4.r16..r96<<c4.rr32>a4.rr32e4.r16>>b.b4^b16b4.b<cc32r32c.c16r16c.c>g16<cd.g.ga.a.a16a16<a16r.f+f+<<f+32r16.>>>>d16<<<<d32re32>f+32r32>>>d16<g4.gg2f+4.>f+<f+4.f+g4.gg4f+4f4.ag4ffg.g.gg2g4.rf2e.e.ee4eegr16gr16ga4c+4e.e.ee.e.ed+.d+.d+16r16d+2f+2f+2g1a4a4a4>a4<f+2f+4f+4g2g4g4a.a4^a16a.b.bb.b16bbb.b.bg.g.gg2<d2^d.d4^d16d.g16dgg2>f+.f+.<ed+4..r16>b4.rg4.bg.b.gg4b4<g.e.ee4c4>a.ar16<g4.d4>b2b4rb16r16<d.r1r1r1r1r1r1r2....r4..;l8r1r1r1o5a+.<d+r16d+>a+.r4r16g.g.ga+.a+.d+d4.cd2d+.d+4^d+16c4cd+c+.>a+4^a+16a+4<d+4d+.g+.g+d+4d+4d.dr16d+2^d+d+.d+.d+d+4rd+16r16d+.d+.ef.d+.ef.d+.efrf+r>a+.g+.aa+.g+.aa+.g+.aa+.<c+.d>a+4..r.<g16r.g3r2r24<d+c>>g4r4g4r<eer4a+4r4.d+4r4b4r4f+r16f+r16f+f2>a+4r4b4r4<c4r4c4r4d4r4d4r4d+4r4>a+4r4<d+4r4d+4r4c+4r4c+4r4g+4r4g+4r4g+3r24g3r24g4<c+2c+2r1r1r1r1c.r16c4dd+3r24>a+.b.b<c2>g+2<<d+4>>a+4<c+.>g+.g+g+3r6a.<c.>aa.a.ar2<c2>d.d.dd.d4^d16e4.ed+4.d+e.e.ee4d+d+d.d.dd4dde.e.ed+2d.d.dd2c.c.cc4.ccr16cr16>g<c+4>a4<c.c.>bb.<c.cc.c.c16r16c4c4d2d+4.d+e.e.ee4e4ee4ee4e4d4d4d4d4e2e4e4g.g.ge.f+.f+g.g.gg2d+.d+.d+d+2g2<a.r16<dd>>eg16g16g16r.d4g4f.fr<a16ar4f>f.f4^f16f4..r16d.>b.r<gg>b16<d16r16>g+16<d+.r16>g+4<c.<c4^c16>d4>a+4a+<d16<<d.>>ff+.fr16d+4r16d+4^d+16f+4.d+f+4d+4g+2a+4a+4<c4>g+4g+2>b.<e.>b<ee16e16>b4<<d+1^d+.r2.r16>g+2^g+6r3g+2^g+6r3g+2.r4f+4..r16g+2<c+4..r16>b4..r16g+2b2a2...r16a2..r>>b2r64<<<<e4^e32r4c4r4r32>a..r.r64>b16rf+.f+f+4.>f+16r16<<c16>f16r32<g32g.r.g16r16g.g>>ar16<d.d16d16>a.<f+.f+16f+16dr24e24d24<d+4<c.>d16rf+16f+16>d.d.dd.d4^d16e4.ed+4.d+e.e.ee4d+d+d.d.dd4dde.e.ed+2d.d.dd2c.c.cc4.ccr16cr16>g<c+4>a4<c.c.>bb.<c.cc.c.c16r16c4c4d2d+4.d+e.e.ee4e4ee4ee4e4d4d4d4d4e2e4e4g.g.ge.f+.f+g.g.gg2d+.d+.d+d+2g2<a.r4r16>b.>b.a<<d.d.>gc.c.ef+2g.g4^g16e4egf.f4^f16f4g4g.<c.c>g4g4f+.f+r16g4.b4g.g.gg4rg16r16g.g.g+a.g.g+a.g.g+ara+rd.c.c+d.c.c+d6r48d+6r48ee6r48f.f+r1r1gr16g16.r2...r4.;l8r1r1r1o4a+.<d+r16d+>a+.<dr16dd+.d+.d+d+.d+.>b<f.f.>g+b2<c.cr16>gg4g4g.<d+.>gg4g4<c.d+.cc4c4>a+.a+.<c4c3r24c2c.c16r>g+16r16a+.a+.aa+.g+.aa+.g+.aa+4b4>a+4.ra+4.ra+4.ra+.<g+4^g+16d+4..r.<d+16r.d+3r2r24>g+gd4r4d4ra+a+r4<c4r4.c4r4d+.c.r>b.br16b<d+2>g4r4g4r4g+4r4a4r4a+4r4b4r4<c4r4>g4r4g+4r4a+4r4a+4r4a+4r4<d+.r4r16d+4r4d+3r24d+3r6rg+2g+2r1r1r1<<g.b.r2r>>g+.r16g+ra+2g.g+.g+d+4d+4<d+.d+32r32>b.b16>a+4a+4<g+.c+.c+c+4r4>a<d16d.dd.c.dr4d2.>b.b.gb.b4^b16<c>f+16f+16r<c>b4.ab.b.bb4a+aa.a.ab4<c4c+2c.c4^c16>b.b.ba+2a.a.aa4a4<d+r16d+r16d>a4e4g.ar16gg.ar16gg.g.gg4g4b2b4.d+e.b.bb2<c.c.cc4c4>b4b4b4b4<c4c4c+4c+4d.dr16dd.<d+.d+>e.e.ed.d.>b<c.c.cc2d2.>a.r16<de4e4.e4c.c.d+16d+.d+d+4d.c.>aar16<c4r16f.f.dfffeg+.d+16d+d+g+.<<c.r>>f.f16dddg4b>b.<d+.>b4b4.<d+.d+.>b<d+4>b4<d+4d+4g+2f4f4f2a.a.aaaa4<c+3r1.r6>e2r2c4.r2rc+2r2d4.re2ee4c+d+4..r16d+2f2f+2.r4>a2.r4<e1..r4>>b.<<e.ed+4d+d+>c.<f.fe.e.e>d.a.gd.a.aa4r4<<f+.>a4r16>b.b.gb.b4^b16<c>f+16f+16r<c>b4.ab.b.bb4a+aa.a.ab4<c4c+2c.c4^c16>b.b.ba+2a.a.aa4a4<d+r16d+r16d>a4e4g.ar16gg.ar16gg.g.gg4g4b2b4.d+e.b.bb2<c.c.cc4c4>b4b4b4b4<c4c4c+4c+4d.dr16dd.<d+.d+>e.e.ed.d.>b<c.c.cc2d2.r4>g.<g.g>g.<g.d+e.e.cd+2e.er16>bb4b4b.g.bb4b4<e.g.ee4e4d.d.e4eg+4e2e.e16ec16r16d.c.c+d.c.c+d.c.c+d4d+4>d4.rd4.rd.d+.e16r16e.f.f+16r16<dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+dr16cr16c+d4..rr32;l16r1r1r1r1o5d+2.r8<a+<d+g8rg+8rg8>b<d+f8d+8ffr2>d+4r8a+<d+g8rg+8rg8>b<d+f8d+8cd>d+8.d+8r8.d+8rd8rcr>a+8r<f8rd+8.r4..c4r4c8c8r4a+8r1r1r1r1r1r1r1r1r1r1>g+32g+32rg+rgrg+6r48a+.r.d+d+g+8g.r32g+8ra+.r3r96a+rg.r.d8rdr<c6r48>b8r<c.r32>a+8..r8r32grg8rg8ra+8d+8.r8.d+rd4r8drd8rf8rd+rc+6r48d6r48e.r32d+6r48d+8rd+r>b8.b8rbra+2.r1r1r1r1r1r1r1r1r1r1r1r4<g8rd8.f+.r32e8.f+8.erg6r48f+8.grf+6r6r24f+.r32g8r>b6r48<f+re8.f+8rera8.f8rarg8.r8.<bbb6r48g8rera6r6r24d32d32rd6r48>d8.>b8a+8r<<g8.a8<c8.>b6r48g8a8.r8.>drd+.r.d+8rd.r32g8r8d8c8g6r48e8rf+re8.f+8rera6r48g6r48a.r32g8r8<d+8..r32d8..r8r32<drd+6r48>b6r48b.r32a6r48g6r48a.r32g6r12b8r8<c4r8>ed+e.r8r32<c8.r>b4r8dd32r32d4r4e8r8<cr>e8r8<c8r8c32r32c32r32>b8..r32a4g8.f+8.f+r4r<e4g4a8brc4..r1r>>d6r48d.r.d.r32<<<e8rd8r8.d8>>>g.r32a+.r32<<gr<f4c8c8f4r4>ar8<c8r8.g+8.r4rd4g+8g8f8.d8.r8c4r4>>>d+6r48d8rd+8<<<d4r4>>>f8re6r48fr<<<b4r4d+4r8>a+r<f+4r4f+4r4a+4r8>a+32r32a+32r32a+.r32a+.r32a+.r32a+32r32a+32r32<c4d+4r2>>>>b8.<e8.>b8<e8ee8.>b8r1r1r1r1r1r1r1r1r1r1r1r1b1<c1d2d2>a8r8<d8.rd8.d6r48d8g8rd8.f+.r32e8.f+8.erg6r48f+8.grf+8.r8.f+8g6r48>b6r48<f+re8.f+8rera8.f8rarg8.r8.ddg6r48e8r>br<d+6r6r24>b32b32rb6r48<d6r48>b8a+8r<d8.e8e6r48e6r48e8e8.r8.drd+8rd+6r48d8g6r12d8c.r32g6r48e8rf+re8.f+8rera8.g6r48a8g6r12c8..r32>b8..r8r32<erf+6r48f+6r48>b.r32<e6r48>b6r48<e.r32e6r12>b8.r<e3r24ccc8r8e8.rf+4r8>bb32r32b4r4<c8r8erc8r8e8r8e32r32e32r32e8.rd8.rd6r48d+8.d+8e4<<e4g4a8br>>d+2r2g8.r>a8.r<d6r48>a.r.<d8d2..<<dgb8r<c8r>b8d+ga8g8aar2>g4r8<dgb8r<c8r>b8d+ga8g8ef+>g8.g8r8.g8rf+8rerd8ra8rg8.r4..e4r4e8e8r4<d8r1r1r1r1r4.>gr8fr8gr2rgr8fr8grgr8fr8f+rgr8fr8gr>g8.r4.r32;;l16r1r1r1r8.o7d+8rd+8r>a+<cdd+fgg+r8>a+32r8..a+32r32a+32r8r32a+32r8..>a+<d+g8rg+8rg8>b<d+f8d+8ffd+r8d+r8d+32r32d+32r32d+4r8>a+<d+g8rg+8rg8>b<d+f8d+8cd<c32r8r32c32r8r32c32r32c32r32c32r8r32c32r1r4...cr8>d+r1r1r1r1r2r8.>a+32r32<d+32r32d+32r32>a+32r32<d+32r.<d96<d96r6r>>>a+32r32<d+32r32>b32r8..b32r32b32r32g32r32>b32r32<g32r32g+32r32<<g+96<c+96r6>>>b32r32<d+32r32>b32r32<d+32r8..>g32r32g32r32a+32r32d32r32a+32r.<<<c96d96r12r48>>f32r32d32r32>a+32r32<d+32r32>a+32r8..<c+32r32>a+32r32g32r32>a+32r32<<c+32r32>a+32r32<<g+96<c+96r12r48>>e32r32c+32r32g32r32f32r32d+32r32c+32r8r32>>g+32r32<<c32r32>g32r32d+32r32g32r.<g+32r.>d+32r32<g32r32>g32r32d+32r32g+32r.b32r32<b32r.>g+32r32<c+32r32d+32r32c+32r32d+32r32b32r32<a+48a48g+48g48f+48f48e48d+48d48c+32r8..<c48>>a+48<a+48>a+48<a+48>a+48>d+32r.a+32r32d+32r32a+192<g192>a+192<g64<g+32>g32<g32>d+32<d+32>>g32r32b32r32<d+32r32>b32r.d+192<d+192>d+192<d+192<d+48>d+48<d+48>d+48<d+32r96c48<c48>c48<c48>c48>c32r32d+32r32>g+32r32d+32r32d32r.<<g+192>>g192<<g+192>>g192<<g+192>>g192<<g+64r64g192>c192<g192>c192<g192>c192<g64r64d+192>d+192<d+192>d+192<d+192>d+192<d+64r64>c192<d192>c192<d192>c192<d192>d192<d192>d48g192<c192>g192<c192>g192<c192>d+192<c192>d+48f192a+192f192a+192f192a+64>b96<c96g192c+192g192c+192g192d192g192d+96e96f192c32r24r96a+48<a+48>f48<a+48d48>>a+192<a+192>a+192<a+192>a+192<f64r48>f192<d192>f192<d192>f192<d192r32>f192a+192f192a+192f192a+192r32d192>a+192<d192>a+192<d192>a+192r32<f32r.<<c32<cr32>>>f192b192f192b192f192b192r32f32r32b192<g192>b192<g192>b192<g192r32d32r32f192<d192>f192<d192>d48<d48>d48<d48>d48>g192<g192>g192<g192<g48>g48>a+192<<g192>>a+192<<g192>g48<a+48>c192a+192c192a+192<g+48>g+48<g+48>g+48<g48>>g192<g192>g192<g192<g48>g48>c192<<g192>>c192<<g192>g48<g48>>d+32r.a+48<a+48>a+48<a+48>a+48<a+48c+32r32>a+32r32<g32r32d+32r32c+32r32>a+32r32<d+48<d+48>d+48<d+32r32>>a+32r32d+32r32a+32r32d+32r32<d+192>g192<d+192>g192r24<d+48<d+32r96>f32<f32>f32<f32>>a+32r32g192<a+192>g192<a+192>g192<a+192r32d+32r32f32r32a+32r32.<c32r48r64>a+48<a+48>a+48<a+48>a+48>a+32r32<c+32r32>>a+192<<f192>>a+192<<f192>>a+192<<f192r32>c+32r32<<c+48<c+48>c+48<c+32>g64r64<g64r32c64r32>g64<g64r32.c64>>>a+32<<g64<g64>>a+32r64<<c64>>f32<g64<g64>>d32r32c+192<<c192>>c+192<<c192>>c+96r32<c48<c32rr96>>>d+32r32d+32r32<c32r32>d+32r32<d+32r24r96g48<g48>g+48<g+48>g+48<g+48>g+48<g+48>g+192>b192<g+192>b192r192b192r32<g+48<a48>a48<a192>>b192<<a192>>b192<a48<a48>a192>d+192<a192>d+192r24<a+192>g192<a+192>g192<<a+48>a+48<a+48>a+48<a+32r96>a+48<a+48>a+48<a+32r96>>a+192<g+192>a+192<g+192<g+48>g+48g+192<g+192>g+192<g+192>g+96r32>g+32r32d+32r32a+192<<a+192>>a+192<<a+192>>a+96r.<g48<g48>g48<g48>g32r96>a+192<<g192>>a+192<<g192>>a+96r32d+192<g192>d+192<g192>d+192r64<<g48>>g192<g192>g192<g192>g192<g192r32f32r32>g+32r32a+32r1r32>>dc+c>ba+ag+gf+fed+dc+r1r1r2r8<<<<d32r.>b32r32b<d32r32dgr<<<c>c4>>d+g+8<<d4g>>a+ra+<<d+8>>>bb<<ag+d+>g+<d+rcra+ad+c>a+32r32<f192<d192>f192<d192r8r96>>>a+32<a+.r32a+32r32a+32r32<ff+gg+aa+b<c>>g+<<c+32r.c+32r8r32c+32r.c192d192d+192e192f48e48d+48d32c+32c32>b32a+32a32g+32g32f+48f32e32d+48d48c+48c48>b32a+32a48g+32g32r24<d32r32>g32r32<d32r32d32r32d32r32>g32r32<e32f+32>g32r32a32r32<c32r32c32r32d32r32d32r1r32>g32r8r32<d32r32g48f+48f48<e48d+96d96c+96c96>b96a+96a96r.>e8<<e48d+96d96c+96c96>b48a+48a48g+48g48f+32f32r48>e32r32e32r8r32f+32r32f+32r8r32a32r32a32r8r32d+32r32d+32r8r32d+32r32d+32r8r32g32r32g32r8r32g32r32g32r32e32r32a32r32g32r32f+32r.f+32r32d+32r32f+32r32f32r.a32r32a32r8r32a32r32f32r32f32r32e32r32>b32<b32f32f32c32r.d32r.e32r8g32r8.<e32r32e32r32d+32r8r32d+32r.d+32r32f+32r.>>b32r.<g32r32f+32r8r32>b32r32b32r32a+32r.<<g32r32g32r8r32>d32r32d32r32>a32r.<e32r32e32r8r32g32r32a32r32<e32r.>a32r32a32r8r32a32r32<e32r32>g32r32a32r32g32r32a32r8r32<c32r.>a32r8..d32r32g32r32a32r32<c32r32e32r.e32r32e32r32g48f+48f48<e48d+96d96c+96c96>b96a+96a96r32e32r32e32r32e32r32<e48d+96d96c+96c96>b48a+48a48g+48g48f+32f32r48e32r.g32r.c32r32>b32r8r32<g32r32g32r8r32d+32r32d+32r8r32c32r.f+32r32>b32r32<f+32r32f+32r.>a32r32f+32r32f+32r8r32<d+32r32>b32r8r32>b32r32b32r32<a32r.a32r32<d32r8r32>a32r.b32r.e32r32e32r32e32r32g32r32a32r32b32r32e32r.<g32r32g32r8r32c32r32c32r32>e32r.<e32r32g32r8r32c32r32c32r32>a32r.<d32r32d32r32f+32r.>a32r32a32r32<<br>>>b32r32b32r8r32<d32r32d32r32e32r.<c32r32c32r8r32e32r32e32r32<<c8>>>e32r32e32r8r32<e32r32e32r32d32r32d32r32>b32r32<d32r8r32d32r32d32r32>d8rd+32r8r32d+32r32d+32r32e32r.<e32r32e32r32er>e32r32g32r32<g>e32r32g32r.g32r.<b32r.d+32r.g32r32g32r8r32g32r32g32r32g32r.ga+a+8g8d32r32a32r32<d32r32>g32r32<drd32r32d32r32>a32r32d32r32<d32r32>d32r32<d32r32>a32r32d32r32<d32r8r32>g32r32d32r32<d32r8..d32r32d32r32>d32r32d32r32<d32r.>g32r32g32r8..f32r32<c32r3r96>>a32r32a32r2.r32a32r4...a32r8r32g32r8r32a32r.b32r.g32r32g32r32<<d32r32>>g8rg+8rg+32r8r32g+32r32g+32r32g+8rg+r4a+8ra+r8a+32r32a+32r32a+8rgr4d+8r>br8b32r32<d+32r32d+.r32>b32r32<g+r4f+.r.d+r8b32r32b32r32<f+.r32f+32r32d+r4>>g+8.d+8d+d+32r32d+32r32g+8.d+32e32f8r8d+48e48f8r48d+32r32d+96e96f12^f48f.r32d+96e96f12^f48f.r32d+.r32f.r32<<<e4>c+32r32>b32r32>b32r32<e32r32d96d+96e12r48e32r32e32r32c+r32f+r1r1r1r1r1r1r1r1r1r1r1r1r32>>a<b64<f+64b32r32>b64<f+64b32r.b32r.b32r.b32r8b32rb32r8..cr8>a+32r.<f32r32c32r32>a+32r32<<c32r32>c32r32e32r32c32r8r32e32r.d32rf+32rd8rd32r32d32r8..a8ra32r.g+a32.a+32.b32.<c32.c+32.d32.d+32.eff+gg+^g+64a^a64a+^a+64b<c>>g8.d8r>g3r6<e32r32g32r8r32f+32r32f+32r8r32a32r32a32r8r32d+32r32d+32r8r32d+32r32d+32r8r32g32r32g32r8r32g32r32g32r32e32r32a32r32g32r32f+32r.f+32r32d+32r32f+32r32f32r.a32r32a32r8r32a32r32f32r32f32r32e32r32>b32<b32f32f32c32r.d32r.e32r8g32r8.<e32r32e32r32d+32r8r32d+32r.d+32r32f+32r.>>b32r.<g32r32f+32r8r32>b32r32b32r32a+32r.<g32r32g32r8r32d32r32d32r32>a32r.<e32r32e32r8r32g32r32a32r32<e32r.>a32r32a32r8r32a32r32<e32r32>g32r32a32r32g32r32a32r8r32<c32r.>a32r8..d32r32g32r32a32r32<c32r32e32r.e32r32e32r32g48f+48f48<e48d+96d96c+96c96>b96a+96a96r32e32r32e32r32e32r32<e48d+96d96c+96c96>b48a+48a48g+48g48f+32f32r48e32r.g32r.>d+32r32d+32r8r32d+32r32d+32r8r32d+32r32d+32r8r32<c32r32d+32r32f+32r32>b32r32<f+32r32f+32r.>a32r32f+32r32f+32r8r32<d+32r32>b32r8r32>b32r32b32r32<a32r.a32r32g32r8r32a32r.b32r.e32r32e32r32e32r32g32r32a32r32b32r32e32r.<g32r32g32r8r32c32r32c32r32>e32r.<e32r32g32r8r32c32r32c32r32>a32r.<d32r32d32r32f+32r.>d32r32a32r32<<br>>>b32r32b32r8r32<d32r32d32r32e32r.<c32r32c32r8r32e32r32e32r32<<c8>>>e32r32e32r8r32<e32r32e32r32d32r32d32r32>b32r32b32r8r32<d32r32d32r32>d8rd+32r8r32d+32r32d+32r32e32r.<e32r32e32r32er>e32r32g32r32<g>e32r32g32r.g32r.<b32r.>d+32r.g32r32g32r8r32<g32r32g32r32g32r.ga+a+8g8<d32r32>g32r32g32r32g32r32<drd32r32d32r32>a8.d8.g32r32g32r8r32d32r8..d32r32d32r8r32d32r8..>dgb8r<c8r>b8d+ga8g8aagr8gr8g32r32g32r32g4r8dgb8r<c8r>b8d+ga8g8ef+<e32r8r32e32r8r32e32r32e32r32e32r8r32e32r1r4...er8>gr1r1r1r1r4..<g32r32g32r32<f+32f32e32d+32c+32c32>b32a+32a32g+32g32f+32f32d+32d32c+32g32r8r32f32r8r32g32r32g32r32g32r8r32f32r8r32f+32r.g32r8r32f32r8r32g32r32g32r32>g32g+32a32a+32b<cc+dd+eff+gg+aa+b<cr2r;l16r1r1r1r8.o7d+8rd+8r8.d8rd8>a+2..a+<d+g8rg+8rg8>b<d+f8d+8f8a+r8a+2^a+8.>a+<d+g8rg+8rg8>b<d+f8d+8r8c2^c6r3d8rd8.d+2r8c4..rd+8r8f8g+aa+4.>e8dr8d+8rerf8rd+8re8f8d+c+8rc+8d8rc8rc+8d8rc8rc+8d8>a+<c8rd+rd8d+2^d+6r1r1r1r1r4.r3<f+.r.f+.r.f+8r2>>gr8a+>a+r<a+r<d+8rd+r4c8rd+r2.d8r4.c8r4.d+8c>a+r2.<c8d+4.d+2c+8rc+r8c+r2rc8rcr8cr>b8rbr4a+8a+g+r8a+3r1r1r2.r24<<a+8a8g+8g8f2d1^d4f8d8<c4c8.rd4>gr8.d+4^d+g+d+>g+<d+4>a+gd+8<f2.r4c+r8c+8.c+8c+8.r4rdr8d8.d8r8.c+8.c+8r1>g4.<a8g8.<g8a>c8c8.>b8.<c8>b4r8f+8<g4.arg8.r4ra8r8eeae>b4r4<e8rd8re8f+f+d+d+f+f+>a8<d4a8a8b8gg8g8>a<a8.e4rc4..rc8.c8r>g8a8r8<<d8c8>e8.e8.e4.e8e8g8ed+8rg8g4g8a8b4a8<d8d+8.>b8.f+8a8.g4^gb2a4e8e8<c8>c8e8<c8>d2b4<d4>g2.b8<c8>d2f+gr>f+3r12r48<d8e4g4a8brd+8g4.d+8g8a8g8>>>>a2<a4..r<<<d8g8d4g4d4f8f4.f2e8rc4^cc8.f8.f8f4.d2^d8>g+g8a+8.<c8>a+8.<c8.d8d8.c8.d8f8.e8.f8f+8.f8.d+8d+8.g+8.a+8a+4^a+g+8.f+4^f+f64e64d+8^d+32a+4g+8a+2^a+8<c8r>>g+8.g+8a+a+8r<f8.rc+1r8>>a8<c8.cc8.cc8cc2.r1r1r1r1r4..>>a4.b4..rb2g2r8<c+2..>b8r1r1r2..<<<<<cr8>>>f+4^f+>b3r24br<<<<cr8>>f8rf8<<cr8>>e8rerdr32<cr32>dradra<crf+r8f+rd.r8r32c.r8r32c.r.>b.r.<c.r32>>g4.<a8g8.<g8a>c8c8.>b8.<c8>b4r8f+8<g4.arg8.r4ra8r8eeae>b4<c8d8e8rd8re8f+f+d+d+f+f+>a8<d8f+8a8a8a+8gg8ga>a<a8.e4rec>arb4<c8.>b8rg8a8r8<<d8c8>e8.e8.e8ee8.e8e8g8ed+8rg8g4g8a8b4a8<d8d+8.>b8.f+8a8.g4^gb2a4e8e8<c8>c8e8<c8>d2b4<d4>g2.b8<c8>d2f+gr>f+4^f+er<d8e4g4a8brd+8g4.d+8g8g8g8>>>>a2...r<<<<d2..dgb8r<c8r>b8d+ga8g8a8<dr8d2^d8.>dgb8r<c8r>b8d+ga8g8r8e2^e6r3f+8rf+8.g2r8e4..rg8r8a8<cc+d4.>>g+8f+r8g8rg+ra8rg8rg+8a8gf8rf8d8rc8rc+8d8rc8rc+8d8rd+8re8e8rf8rf+8>g8rf8rf+8g8rf8rf+8g8rf8rf+8g8rf8rf+8g8rf8rf+8g8rf8rf+8<g4r3r96;";
//本来はテンポt166
/////////////////////////////関数

//HD43517へ書き込み
void hd43517_write(unsigned char cs, unsigned char adr, unsigned char data);

//HD43517のレジスタビットへ値をセット
void hd43517_dataset(unsigned char cs, unsigned char adr, unsigned char reg, unsigned char data);
//HD43517のレジスタビットへ値をセット(アドレスと内部アドレス統合)
void hd43517_regset(unsigned char cs, unsigned char reg, unsigned char data);
//hd43517パラメータセット
void hd43517_param_set_all(unsigned char ch, int inst);


//音程のセット
void ptc_set(unsigned char ch, unsigned int notenum);
//メインの音量とパンのセット
void main_vel_pan_set(unsigned char vel, unsigned char pan);
//チャンネルの音量とパンのセット
void vel_pan_set(unsigned char ch, unsigned char vel, unsigned char pan);
//チャンネルノートオン
void note_on(unsigned char ch);
//チャンネルノートオフ
void note_off(unsigned char ch);
//音色セット
void inst_set(unsigned char ch, unsigned char inst);

// MML演奏用関数/////////////////////////////////////
//簡易MMLデータより音を鳴らす
void mml_play(unsigned char *play_data, unsigned int len);
//簡易mmlデータ1バイト取得
int get_mml_data(unsigned char *mml_data, unsigned int len, unsigned int pos);
// mmlコマンド1つ取得
void get_mml_com(unsigned char *mml_data, unsigned int len, int *pos, int *ret_data);
// mmlデータから数値を返す
int get_mml_num(unsigned char *mml_data, unsigned int len, int *pos, int *dp_num);
// mmlデータ配列内のトラック数をカウントする。(「;」の数)
int get_mml_tr_num(unsigned char *mml_data, unsigned int len);
// mmlデータ配列内のトラック先頭位置配列に、トラック数分の先頭位置を入れる
int get_mml_tr_pos(unsigned char *mml_data, unsigned int len, unsigned int tr_max, int *pos_tr);


//タイマー割り込み~~~~~~~~~~~~~~~~~~~~~~~~~
ISR(TIMER1_COMPA_vect)
{
  // MML演奏用
  if (mml_time_cnt_en == 1)
  {
    // MML演奏用時間カウント有効の時、カウント
    mml_time_ms++; // 2msごとのカウント
    // mml_time = mml_time_ms * (9*2*8192.0 * tempo / (120.0 * 2000.0));//下式と等価
    mml_time = mml_time_ms * (3 * 128.0 * tempo / 625.0); // msをMMLカウンタ値に変換(トラックごとの演奏ずれをできるだけ抑制するため)
  }
}

//セットアップ
void setup()
{
  //デバッグメッセージ用
  Serial.begin(SERIALSPEED);
  //ポート設定
  // out_put
  DDRD = 0xFC;  // pin2~pin7_HD43517:D2~D7
  PORTD = 0xFF; // pin2~pin7_HD43517:D2~D7
 
  DDRB = 0x3B;  // pin8~pin9_HD43517:D0~D1   pin11~pin13_HD43517:~WE, A0, ~RST
  PORTB = 0x3B; // pin8~pin9_HD43517:D0~D1   pin11~pin13_HD43517:~WE, A0, ~RST

  DDRC = 0x0F;  // pin14~pin17_HD43517:CS0 ~ CS3
  PORTC = 0x0F; // pin14~pin17_HD43517:CS0 ~ CS3

  //リセット
  PORTB &= ~0x20; // pin13_HD43517: ~RST = L
  delay(100);
  PORTB |= 0x20; // pin13_HD43517: ~RST = H
  delay(100);
 
  // HD43517キーオフ
  for (int i = 0; i < CH; i++)
  {
    note_off(i);
  }
 

  //タイマー割り込み設定Timer1
 
  TCCR1A = 0b00000000;  //CTCモード
  TCCR1B = 0b00001001;  //CTCモード,分周なし,タイマー割り込み開始
  TIMSK1 = 0b00000010;  //コンペアマッチAの割り込みを設定
  OCR1A = (unsigned int)((float)((2000 * (XTAL / 1000000.0)) - 1));// 2000μs毎
  sei();//割り込みを許可
 
}

void loop()
{
  int inst_c=16;//音色
  for (int ch = 0; ch < CH; ch++)
  {
    hd43517_param_set_all(ch, inst_c);//パラメータセット
  }
  while (1)
  {
    // MML演奏
    mml_play(mml_data, mml_data_len);
    delay(20);

    for (int ch = 0; ch < CH; ch++)
    {
      note_off(ch);
    }
   
    inst_c++;
    if(inst_c >= 22){
      inst_c=0;
    }
    for (int ch = 0; ch < CH; ch++)
    {
      hd43517_param_set_all(ch, inst_c);
    }
  }
}
//HD43517へ書き込み
void hd43517_write(unsigned char cs, unsigned char adr, unsigned char data)
{
  PORTB |= 0x10; // pin13_HD43517: A0 = H
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
 
  //チップセレクト
  PORTC = (PORTC & 0xF0) | (0x0F & (1 << cs)); // pin14~pin17_HD43517:CS0 ~ CS3
 
  //アドレスのセット
  PORTB &= ~0x10; // pin13_HD43517: A0 = L
  delayMicroseconds(1);
  PORTB = (PORTB & 0xFC) | (0x03 & adr); // pin9,8_HD43517:D1,D0
  PORTD = (PORTD & 0x03) | (0xFC & adr); // pin7~2_HD43517:D7~D2
 
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H

  delayMicroseconds(7);
  //アドレスのセット2回目
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
  delayMicroseconds(1);
  PORTB |= 0x10; // pin13_HD43517: A0 = H

  //データのセット
  delayMicroseconds(20);

  PORTB = (PORTB & 0xFC) | (0x03 & data); // pin9,8_HD43517:D1,D0
  PORTD = (PORTD & 0x03) | (0xFC & data); // pin7~2_HD43517:D7~D2
 
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H

  //データのセット2回目
  delayMicroseconds(7);

  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
 
 
  delayMicroseconds(200);
}

//HD43517のレジスタビットへ値をセット
//csとアドレスチップセレクトを統合
//基本的にこの関数を介してHD43517を操作
void hd43517_dataset(unsigned char cs, unsigned char adr, unsigned char reg, unsigned char data)
{
  //csは4つを1ブロックとする
  //4つのHD43517のcsはアドレスbit6~bit3で指定
  //adrは0x0~0x7までを指定
  //regは0x0~0xFまでを指定
  //hd43517_cs_conv[0x03&cs]は(~(1<<(3+(0x03&cs))) & 0x78)の計算
  if(adr>=0x04)
  {
    //adr>=0x04の場合、データ幅は8bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & adr), data);
  }
  else if(adr>=0x02)
  {
    //0x04>adr>=0x02の場合、データ幅は4bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & adr), (reg<<4) | (0x0F&data));
  }
  else
  {
    //0x02>adr>=0x00の場合、データ幅は7bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x07&cs] | (0x07 & adr), (reg<<4) | (0x3F&data));
  }
}

//HD43517のレジスタビットへ値をセット(アドレスと内部アドレス統合)
//csとアドレスチップセレクトを統合
//defineで定義したレジスタ名で指定してレジスタを操作
//基本的にこの関数を介してHD43517を操作
void hd43517_regset(unsigned char cs, unsigned char reg, unsigned char data)
{
 
  //csは4つを1ブロックとする
  //4つのHD43517のcsはアドレスbit6~bit3で指定
  //reg上位4bitはアドレスで0x0~0x7までを指定
  //reg下位4bitは内部アドレスで0x0~0xFまでを指定
  //hd43517_cs_conv[0x03&cs]は(~(1<<(3+(0x03&cs))) & 0x78)の計算
  if(reg>=0x40)
  {
    //reg>=0x40の場合、データ幅は8bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), data);
  }
  else if(reg>=0x20)
  {
    //0x40>reg>=0x20の場合、データ幅は4bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), (reg<<4) | (0x0F&data));
  }
  else
  {
    //0x20>reg>=0x00の場合、データ幅は7bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), (reg<<4) | (0x7F&data));

  }
}




//hd43517パラメータセット
void hd43517_param_set_all(unsigned char ch, int inst)
{
  //入力データ構造////////////////////////////////
  //CWM, CWSW, reserve, reserve, reserve,
  //SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
  //AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
  //AR, DR, SL, RR, reserve,
  //W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
  //TL, PAN, PTC, reserve, reserve,
  //reserve, reserve
  ////////////////////////////////////////////////

  //CWM, CWSW, reserve, reserve, reserve,
  hd43517_regset(ch>>2, COMP_W_MODE, pgm_read_byte_near((int)(hd43517_parameter[inst] + 0)));
  hd43517_main_cwm[ch] = 0x03 & pgm_read_byte_near((int)(hd43517_parameter[inst] + 0));
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x00);//ch0
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x01);//ch1
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x02);//ch2
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x03);//ch3
  //SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
  hd43517_regset(ch>>2, SV_W1_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 5)));
  hd43517_regset(ch>>2, SV_W2_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 6)));
  hd43517_regset(ch>>2, SV_W3_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 7)));
  hd43517_regset(ch>>2, SV_W4_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 8)));
  hd43517_regset(ch>>2, SV_W5_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 9)));

  //AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
  hd43517_regset(ch>>2, AL_W1_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 10)));
  hd43517_regset(ch>>2, AL_W2_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 11)));
  hd43517_regset(ch>>2, AL_W3_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 12)));
  hd43517_regset(ch>>2, AL_W4_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 13)));
  hd43517_regset(ch>>2, AL_W5_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 14)));

  //AR, DR, SL, RR, reserve,
  hd43517_regset(ch>>2, AR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 15)));
  hd43517_regset(ch>>2, DR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 16)));
  hd43517_regset(ch>>2, SL, pgm_read_byte_near((int)(hd43517_parameter[inst] + 17)));
  hd43517_regset(ch>>2, RR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 18)));

  //W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
  hd43517_regset(ch>>2, W1_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 20)));
  hd43517_regset(ch>>2, W2_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 21)));
  hd43517_regset(ch>>2, W3_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 22)));
  hd43517_regset(ch>>2, W4_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 23)));
  hd43517_regset(ch>>2, W5_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 24)));

  //TL, PAN, PTC, reserve, reserve,
  hd43517_main_vol[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 25));
  hd43517_main_pan[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 26));
  hd43517_main_ptc[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 27));

}

//音程のセット
void ptc_set(unsigned char ch, unsigned int notenum)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  int ch_notenum = notenum + hd43517_main_ptc[ch]-76 + hd43517_oct_conv[hd43517_main_cwm[ch]]*12;
  while(ch_notenum<0){
    ch_notenum+=12;
  }
  while(ch_notenum>=128){
    ch_notenum-=12;
  }
  unsigned int tone = ch_notenum % 12;
  unsigned int oct = ch_notenum / 12;
  unsigned char inst =0;
 
  if (ch != 9)
  { //ドラムチャンネル以外
 
    hd43517_regset(cs_temp, PTC, (unsigned char)((unsigned int)0x00FF & hd43517_note_conv[hd43517_main_cwm[ch]][tone]));
    hd43517_regset(cs_temp, OCT, (((unsigned char)oct<<4) & 0x70) | (((unsigned int)hd43517_note_conv[hd43517_main_cwm[ch]][tone]>>6)&0x0C) | ch_temp);
 
  }
  else
  {
    //ドラムチャンネル
 
  }
}

//メインの音量とパンのセット
void main_vel_pan_set(unsigned char vel, unsigned char pan)
{
  //何もしません

}

//チャンネルの音量とパンのセット
void vel_pan_set(unsigned char ch, unsigned char vel, unsigned char pan)
{
  //HD43517はチャンネル音量設定ができません
 
}

//チャンネルノートオン
void note_on(unsigned char ch)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  if (ch != 9)
  {
    //ドラムチャンネル以外
    //hd43517_regset(cs_temp, KEY_ON, 0x08 | ch_temp);//リリース有効
    hd43517_regset(cs_temp, KEY_ON, 0x00 | ch_temp);//リリース無効
  }
  else
  {
    //ドラムチャンネルはなし
  }
}

//チャンネルノートオフ
void note_off(unsigned char ch)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  if (ch != 9)
  { //ドラムチャンネル以外
    hd43517_regset(cs_temp, KEY_OFF, 0x08 | ch_temp);
  }
  else
  {
    //ドラムチャンネルはなし
  }
}

//音色セット
void inst_set(unsigned char ch, unsigned char inst)
{
  hd43517_param_set_all(ch , inst);
}

// MML演奏用関数/////////////////////////////////////

//簡易MMLデータより音を鳴らす
void mml_play(unsigned char *play_data, unsigned int len)
{

  int mml_com[4] = {0, 0, 0, 0}; // mmlコマンド取得用[コード, 数値1, 時間, 数値2(音長表現のドットの数)]

  int mml_st[MML_MAX_TR];          // mml演奏状態(0でmml読み取り終了、1でmml読み取り中)、チャンネルごとに保存
  char mml_tie[MML_MAX_TR];        //タイ有効無効フラグ[^]
  char mml_oct[MML_MAX_TR];        //オクターブ[o]
  char mml_def_dly[MML_MAX_TR];    //デフォルト音調[l]
  char mml_pan[MML_MAX_TR];        //パン[p]
  char mml_vel[MML_MAX_TR];        //ベロシティ[v]
  double mml_next_tim[MML_MAX_TR]; //次のMMLコマンド実行時間(絶対時間)
  int mml_st_sum = 0;              //トラック演奏状態チェック用(フラグを加算して0になったらすべてのトラックの演奏が終了)

  ////////////////トラック数の取得と各トラック先頭位置の取得//////
  unsigned int tr_pos[MML_MAX_TR];                                         //トラック先頭位置保存用(先頭位置)
  int tr_num = get_mml_tr_pos(mml_data, mml_data_len, MML_MAX_TR, tr_pos); //各トラック先頭位置をtr_posに入れ、トラック数を返す

  //トラックごとの配列初期設定
  for (int mml_setup = 0; mml_setup < tr_num; mml_setup++)
  {
    mml_st[mml_setup] = 1;                                          // mml演奏状態フラグ(0でmml読み取り終了、1でmml読み取り中)
    mml_tie[mml_setup] = 0;                                         //タイ状態有効無効フラグ
    mml_oct[mml_setup] = 4;                                         //オクターブ
    mml_def_dly[mml_setup] = 4;                                     //デフォルト音調(四分音符)
    mml_next_tim[mml_setup] = 0;                                    //最初のMMLコマンドは無条件で読み取る。
    mml_pan[mml_setup] = 64;                                        //パン[p]
    mml_vel[mml_setup] = 60;                                        //ベロシティ[v]
    vel_pan_set(mml_setup, mml_vel[mml_setup], mml_pan[mml_setup]); //パンと音量の仮設定
  }
  // Serial.print("tr_num:");//デバッグ用
  // Serial.print(tr_num);//デバッグ用
  // Serial.print("\r\n");//デバッグ用

  mml_time_ms = 0;     // MML演奏用時間msカウンタ初期化
  mml_time_cnt_en = 1; // MML演奏用時間カウント_開始
  while (1)
  { //すべてのトラックが演奏終了のとき、mml演奏関数終了

    mml_st_sum = 0; //トラック演奏状態チェック用初期化
    //トラックごと処理

    for (int mml_st_tr = 0; mml_st_tr < tr_num; mml_st_tr++)
    {
      // Serial.print("mml_st[mml_st_tr]:");//デバッグ用
      // Serial.print(mml_st[mml_st_tr]);//デバッグ用
      // Serial.print("\r\n");//デバッグ用
      if (mml_st[mml_st_tr] == 0)
      { //演奏が終了したトラックは無視
        continue;
      }

      // Serial.print("mml_time:");//デバッグ用
      // Serial.print(mml_time);//デバッグ用
      // Serial.print("mml_next_tim[mml_st_tr]:");//デバッグ用
      // Serial.print(mml_next_tim[mml_st_tr]);//デバッグ用
      // Serial.print("\r\n");//デバッグ用

      if ((unsigned long)mml_next_tim[mml_st_tr] <= (unsigned long)mml_time)
      { //次回読み取り時間カウンタが時間カウンタの値以上になったらMMLコードを読み取る。
        ////////////////////////////

        // mmlコマンド取得(pos自動インクリメント)
        get_mml_com(play_data, len, (tr_pos + mml_st_tr), mml_com); //返しは、[コード, 数値1, 時間, 数値2(音長表現のドットの数)]の配列ポインタ
        if (mml_com[2] == -2)
        { // MMLの音調が省略されていたらデフォルト音長をセット
          mml_com[2] = mml_def_dly[mml_st_tr];
        }
        // MMLコマンド表示(多少不安定になります)//デバッグ用
        /*Serial.print("ch:");
        Serial.print(mml_st_tr);
        Serial.print("_pos:");
        Serial.print(tr_pos[mml_st_tr]);
        Serial.print("_");
        Serial.write(mml_com[0]);
        Serial.print(mml_com[1]);
        Serial.print("_dlytim:");
        Serial.print(mml_com[2]);
        Serial.print("_dot:");
        Serial.print(mml_com[3]);
        Serial.print("\r\n");*/

        switch (mml_com[0])
        {
        case 'n': //ノートオン
          if (mml_tie[mml_st_tr] == 0)
          {
            note_off(mml_st_tr);
            ptc_set(mml_st_tr, mml_com[1] +((mml_oct[mml_st_tr] + def_oct[mml_st_tr])*12) + def_key);//チャンネル, 音程
            note_on(mml_st_tr);//ノートオン
          }
          mml_tie[mml_st_tr] = 0; //タイ無効
          break;
        case 'r': //ノートオフ
          note_off(mml_st_tr);
          break;
        case 'o': //オクターブセット
          mml_oct[mml_st_tr] = mml_com[1];
          break;
        case '>': //オクターブ下げ
          mml_oct[mml_st_tr]--;
          break;
        case '<': //オクターブ上げ
          mml_oct[mml_st_tr]++;
          break;
        case '^':                 //タイ
          mml_tie[mml_st_tr] = 1; //タイ有効
          break;
        case 'l':                              //デフォルト音長
          mml_def_dly[mml_st_tr] = mml_com[1]; //音長
          break;
        case 'v': //ベロシティ
          mml_vel[mml_st_tr] = mml_com[1];
          vel_pan_set(mml_st_tr, mml_vel[mml_st_tr], mml_pan[mml_st_tr]); //チャンネル, 音量, パン
          break;
        case 'p': //パン
          mml_pan[mml_st_tr] = mml_com[1];
          vel_pan_set(mml_st_tr, mml_vel[mml_st_tr], mml_pan[mml_st_tr]); //チャンネル, 音量, パン
          break;
        case 't': //テンポ
          tempo = mml_com[1];
          break;
        case '@': //音色変更
          //inst_set(mml_st_tr, mml_com[1]);
          break;
        case '\n':                //無命令、数字のみの場合(タイ)
          mml_tie[mml_st_tr] = 0; //タイ無効
          break;
        case ';':                //トラック終端
          mml_st[mml_st_tr] = 0; //現在のトラックは演奏終了
          break;
        default:
          break;
        }

        //時間計算
        if (mml_com[2] == 0)
        {
          //待ち時間なし
        }
        else
        {
          // delay(500);
          //待ち時間計算(ms)
          double dly_tim_dot_sum = 0;
          for (int d_time = 0; d_time <= mml_com[3]; d_time++) // mmlのドットの数分ディレイを入れる
          {
            dly_tim_dot_sum += (double)(9.0 * 8192.0 / (mml_com[2] * pow(2, d_time)));
            // delay((int)((2000.0 / (mml_com[2]*pow(2, d_time))) * (120.0 / tempo)));
          }
          //次回のMMLコマンド実行時間を加算する
          mml_next_tim[mml_st_tr] += dly_tim_dot_sum;
        }
        ////////////////////////////
      }

      mml_st_sum += mml_st[mml_st_tr]; //トラック演奏状態チェック用(フラグを加算して0になったらすべてのトラックの演奏が終了)
     
      // Serial.print("mml_st_sum:");//デバッグ用
      // Serial.print(mml_st_sum);//デバッグ用
      // Serial.print("\r\n");//デバッグ用
    }
    //トラック演奏状態チェック
    if (mml_st_sum == 0)
    {
      //すべてのトラックが演奏終了のとき、mml演奏関数終了
      break; // mml演奏関数終了
    }
  }
  mml_time_cnt_en = 0; // MML演奏用時間カウント_停止
}
//簡易mmlデータ1バイト取得
int get_mml_data(unsigned char *mml_data, unsigned int len, unsigned int pos)
{
  // posは0~(len - 1)までを指定
  //データ範囲外で -1 を返す。

  if (pos >= len)
  {
    return -1;
  }
  // return mml_data[pos];    //MMLデータをSRAMに配置した時
  return pgm_read_byte_near(mml_data + pos); // MMLデータをPROGMEMに配置した時
}

// mmlコマンド1つ取得
//返しは、[コード, 数値1, 時間, 数値2(音長表現のドットの数)]の配列ポインタ
void get_mml_com(unsigned char *mml_data, unsigned int len, int *pos, int *ret_data)
{
  unsigned int pos_temp = *pos; //読み取り位置を記憶
  unsigned char temp_get_mml_byte;

  int ret_code = 0;
  int ret_num1 = 0;
  int ret_tim = 0;
  int ret_num2 = 0;

  switch (get_mml_data(mml_data, len, pos_temp))
  {
  case '0': //数字の場合、音長のみとして扱う
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
  case '7':
  case '8':
  case '9':
    ret_code = (int)'\n';
    ret_tim = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case 'b': //
    ret_num1 += 2;
  case 'a': //
    ret_num1 += 2;
  case 'g': //
    ret_num1 += 2;
  case 'f': //
    ret_num1 += 1;
  case 'e': //
    ret_num1 += 2;
  case 'd': //
    ret_num1 += 2;
  case 'c': //
    if (get_mml_data(mml_data, len, pos_temp + 1) == '+')
    {
      pos_temp++;
      ret_num1 += 1; //半音上げ
    }
    else if (get_mml_data(mml_data, len, pos_temp + 1) == '-')
    {
      pos_temp++;
      ret_num1 -= 1; //半音下げ
    }
    pos_temp++;
    ret_code = 'n';
    ret_tim = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    if (ret_tim == 0)
    { //音長が省略されていたら
      ret_tim = -2;
    }
    else if (ret_tim == -3)
    { //音長が0だった場合、和音(ドラムのみ)
      ret_tim = 0;
    }
    break;
  case 'r': //ノートオフ
    ret_code = 'r';
    pos_temp++;
    ret_tim = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    if (ret_tim == 0)
    { //音長が省略されていたら
      ret_tim = -2;
    }
    break;
  case '<': //
    ret_code = (int)'<';
    pos_temp++;
    break;
  case '>': //
    ret_code = (int)'>';
    pos_temp++;
    break;
  case '^': //タイ
    ret_code = (int)'^';
    pos_temp++;
    break;
  case 'o': //音程
    ret_code = (int)'o';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case 'v': //ベロシティ
    ret_code = (int)'v';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case 'p': //ベロシティ
    ret_code = (int)'p';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case 'l': //デフォルト音長
    ret_code = (int)'l';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case '[': //ループ開始(使用不可)
    pos_temp++;
    break;
  case ']': //ループ終了(使用不可)
    pos_temp++;
    break;
  case 't': //テンポ
    ret_code = (int)'t';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case '@': //音色
    ret_code = (int)'@';
    pos_temp++;
    ret_num1 = get_mml_num(mml_data, len, &pos_temp, &ret_num2); // mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
    break;
  case ';': //終端
    ret_code = ';';
    // pos_temp=len;
    break;
  default: //未定義コマンドが来るとストップ
    break;
  }

  *pos = pos_temp; //戻し用現在の読み取り位置更新
  ret_data[0] = ret_code;
  ret_data[1] = ret_num1;
  ret_data[2] = ret_tim;
  ret_data[3] = ret_num2;
}

// mmlデータから数値を返す
// mmlデータ配列, mmlデータ配列の長さ, 読み取り位置のポインタ, ドットの数戻り値用ポインタ
int get_mml_num(unsigned char *mml_data, unsigned int len, int *pos, int *dp_num)
{
  //※読み取り位置は配列外になっても加算されます。
  unsigned int pos_temp = *pos; //読み取り位置を記憶
  int keta = 0;                 //読み取る数値の桁数(0で数字以外,1で1桁,2で2桁)の読み取り位置インクリメント用
  int ret_num = 0;              //戻り値用数字
  int ret_dp_num = 0;           //ドットの数戻り値用
  int mml_data_byte = get_mml_data(mml_data, len, pos_temp);

  //数値読み取り
  while ((mml_data_byte >= '0') && (mml_data_byte <= '9'))
  {
    // ret_num += (mml_data_byte - '0')*pow(10, keta);//数字と桁数の乗算値を加算
    if ((keta == 0) && (mml_data_byte == '0'))
    { //音長が0(数値の最初が0)のとき、-3を返す
      ret_num = -3;
    }
    else
    {
      ret_num = ret_num * 10 + (mml_data_byte - '0');
    }

    keta++;
    mml_data_byte = get_mml_data(mml_data, len, pos_temp + keta);
  }

  //ドットの数を数える
  mml_data_byte = get_mml_data(mml_data, len, pos_temp + keta);
  while (mml_data_byte == '.')
  {
    ret_dp_num++;
    mml_data_byte = get_mml_data(mml_data, len, pos_temp + keta + ret_dp_num);
  }

  *pos += keta + ret_dp_num; //現在の読み取り位置に読み取った数分、加算
  *dp_num = ret_dp_num;      //ドットの数書き換え
  return ret_num;
}

// mmlデータ配列内のトラック数をカウントする。(「;」の数)
int get_mml_tr_num(unsigned char *mml_data, unsigned int len)
{
  int get_data_temp = 0;
  unsigned int tr_cnt = 0; //トラック数カウント

  for (int c_tr = 0; c_tr < len; c_tr++)
  {

    get_data_temp = get_mml_data(mml_data, len, c_tr);
    if (get_data_temp == ';')
    {
      tr_cnt++; //「;」の数カウント
    }
    else if ((get_data_temp == 0) || (get_data_temp == -1))
    {
      //終端判定
      //文字列配列終端(0x00)か配列サイズ外でデータ終了
      break;
    }
  }
  return tr_cnt;
}

// mmlデータ配列内のトラック先頭位置配列に、トラック数分の先頭位置を入れる
// mmlデータ配列, mmlデータ配列の長さ, 取得トラック数, トラック先頭位置配列の戻り値用ポインタ
//戻り値は、先頭位置取得トラック数
int get_mml_tr_pos(unsigned char *mml_data, unsigned int len, unsigned int tr_max, int *pos_tr)
{
  int get_data_temp = 0;
  unsigned int tr_cnt = 0;          //トラック数カウント
  unsigned int get_temp_tr_pos = 0; //トラック先頭アドレス一時保存

  for (int c_tr = 0; c_tr < len; c_tr++)
  {

    get_data_temp = get_mml_data(mml_data, len, c_tr);
    if (get_data_temp == ';')
    {
      pos_tr[tr_cnt] = get_temp_tr_pos; //前回の「;」の次のアドレスを入れる
      get_temp_tr_pos = c_tr + 1;
      tr_cnt++; //「;」の数カウント
    }
    if ((get_data_temp == 0) || (get_data_temp == -1) || (tr_max <= tr_cnt))
    {
      //終端判定
      //文字列配列終端(0x00)か配列サイズ外でデータ終了
      break;
    }
  }
  return tr_cnt;
}






演奏例の動画では、3つのHD43517を相互接続しているため、すべてのチャンネルが同じ音色かつ同じ音量となっており、あまり聞きやすくないです。
やはり、HD43517ごとにDACを用意した方がよいかもしれませんね。



・使用例  - MIDIの受信 -

HD43517を1~4個使用し、MIDIを受信する場合の回路とプログラム(Arduino ATmega328p用)を紹介します。

回路はArduinoのD0ピンにMIDI受信回路を追加するだけです。HD43517まわりはMMLでの使用例と同じなので、各自お好きな方で回路を組んでください。



・プログラム(HD43517を1~4個使用、「I-4」と「MSO」端子でアドレス空間上の配置位置を決定)


//HD43517でMIDI演奏プログラム
//©oy
//https://oykenkyu.blogspot.com/2023/02/hd43517.html


#include "avr/io.h"
#include "avr/interrupt.h"

#define SERIALSPEED 31250 // UARTのボーレート(MIDIのボーレートは31250bps)
//#define SERIALSPEED 38400 // UARTのボーレート(MIDIのボーレートは31250bps)

#define CH 16  // HD43517最大チャンネル数(HD43517は1つで8チャンネル分発音できます。)
#define MIDI_MAX_TR CH // MIDIトラック数

//HD43517レジスタ
//bit6~bit4は実アドレス、bit3~bit0は内部レジスタ用アドレス
#define COMP_W_MODE 0x00 //波形合成モード
#define KEY_OFF 0x08 //キーオフ

#define KEY_ON 0x10 //キーオン
#define COMP_W_SW 0x18 //チャンネルごとの各正弦波合成ON/OFF

#define SV_W1_LV 0x20 //スタートレベル:基音音量
#define SV_W2_LV 0x21 //スタートレベル:2つ目の倍音音量
#define SV_W3_LV 0x22 //スタートレベル:3つ目の倍音音量
#define SV_W4_LV 0x23 //スタートレベル:4つ目の倍音音量
#define SV_W5_LV 0x24 //スタートレベル:5つ目の倍音音量
#define AR 0x25 //アタックレート
#define DR 0x26 //ディケイレート
#define SL 0x27 //サスティンレベル
#define AL_W1_LV 0x28 //アタックレベル:基音音量
#define AL_W2_LV 0x29 //アタックレベル:2つ目の倍音音量
#define AL_W3_LV 0x2A //アタックレベル:3つ目の倍音音量
#define AL_W4_LV 0x2B //アタックレベル:4つ目の倍音音量
#define AL_W5_LV 0x2C //アタックレベル:5つ目の倍音音量
#define RR 0x2D //リリースレート

#define W1_DLY 0x30 //基音発音ディレイ
#define W2_DLY 0x31 //2つ目の倍音発音ディレイ
#define W3_DLY 0x32 //3つ目の倍音発音ディレイ
#define W4_DLY 0x33 //4つ目の倍音発音ディレイ
#define W5_DLY 0x34 //5つ目の倍音発音ディレイ

#define PTC_CHG 0x40 //ピッチ変更値指定
#define PTC 0x50 //ピッチ指定
#define OCT_CHG 0x60 //オクターブ変更値セット
#define OCT 0x70 //オクターブセット


// HD43517_チップセレクト用テーブル(少し高速化できる?)
unsigned char hd43517_cs_conv[4] = {0x38,0x58,0x68,0x70};

// HD43517_保存用
unsigned char hd43517_main_vol[CH]; //音量保存用
unsigned char hd43517_main_pan[CH]; //パン保存用
unsigned char hd43517_main_ptc[CH]; //ピッチ保存用
unsigned char hd43517_main_cwm[CH]; //波形合成モード保存用(音程計算で使用)

//HD43517のノートデータへ変換(合成比率モード別)
//HD43517の入力クロック周波数が4.00MHzの時
unsigned int hd43517_note_conv[4][12] = {
  {0x157, 0x16C, 0x182, 0x199, 0x1B1, 0x1CB, 0x1E6, 0x203, 0x222, 0x242, 0x265, 0x289},
  {0x1C8, 0x1E4, 0x200, 0x21F, 0x23F, 0x261, 0x286, 0x2AC, 0x2D5, 0x300, 0x32E, 0x35E},
  {0x111, 0x122, 0x133, 0x145, 0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205},
  {0x157, 0x16C, 0x182, 0x199, 0x1B1, 0x1CB, 0x1E6, 0x203, 0x222, 0x242, 0x265, 0x289}
};
//HD43517のオクターブデータへ変換(合成比率モード別)
int hd43517_oct_conv[4]= {
  0, 1, -2, 0
};

//スタートレベル保存(音量計算用)
unsigned char hd43517_sv_temp[16][5];
//アタックレベル保存(音量計算用)
unsigned char hd43517_al_temp[16][5];

//メイン音量一時保存
unsigned char main_vol_temp=0x7F;



//HD43517音色パラメータ
//CWM   :   波形合成モード、bit1~bit0の4通り
//CWSW  :   各正弦波合成ON/OFF、bit4~bit0がそれぞれ倍音5~基音に割り当て
//SV-W[N]-L  :  スタートレベル:[N]個目の倍音音量、bit3~bit0
//AL-W[N]-L  :  アタックレベル:[N]個目の倍音音量、bit3~bit0
//AR    :   アタックレート、bit3~bit0
//DR    :   ディケイレート、bit3~bit0
//SL    :   サスティンレベル、bit3~bit0
//RR    :   リリースレート、bit3~bit0
//W[N]-DLY    :  [N]目の倍音発音ディレイ、bit3~bit0
//TL    :   トータル発音レベル(未使用)
//PAN   :   パン(未使用)
//PTC   :   音程、7bit値 64が標準





//パラメータ構造
//CWM, CWSW, reserve, reserve, reserve,
//SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
//AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
//AR, DR, SL, RR, reserve,
//W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
//TL, PAN, PTC, reserve, reserve,
//reserve, reserve


const unsigned char hd43517_parameter_num = 22;//音色の数

const unsigned char hd43517_parameter[][32] PROGMEM = {
  //0 PIPE ORGAN
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0C, 0x0B, 0x09, 0x0B, 0x0B,
    0x08, 0x0B, 0x0E, 0x00, 0,
    0x01, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //1 D1A PASON
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x09, 0x0B, 0x00, 0x0B, 0x09,
    0x05, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //2 TIBIA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x00, 0x09, 0x0C,
    0x05, 0x0F, 0x0E, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //3 FLUTE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0B, 0x00, 0x00, 0x0D,
    0x07, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x02, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //4 JAZZ ORGAN1
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0B, 0x0B, 0x0B, 0x00, 0x00,
    0x05, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x00, 0x01, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //5 PIANO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0D, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x01, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x01, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //6 VIBRA PHONE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x00, 0x0C,
    0x00, 0x0B, 0x00, 0x00, 0x09,
    0x08, 0x01, 0x00, 0x01, 0,
    0x00, 0x01, 0x00, 0x00, 0x01,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //7 CELESTA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0C, 0x0D,
    0x00, 0x00, 0x00, 0x0C, 0x0B,
    0x08, 0x00, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x01, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //8 OBOE
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0A, 0x0A, 0x0D, 0x00,
    0x07, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //9 FUNKY
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x0C, 0x0C,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x00, 0x00, 0x01, 0,
    0x00, 0x00, 0x00, 0x04, 0x05,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //10 BRILLIANT OGAN
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0D, 0x00, 0x00, 0x00, 0x0E,
    0x05, 0x0B, 0x0D, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //11 WOOD WIND
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x0B, 0x00, 0x00,
    0x0B, 0x00, 0x00, 0x00, 0x0B,
    0x09, 0x03, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //12 FULL TIBAS
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x09, 0x00, 0x0D, 0x00, 0x0C,
    0x05, 0x0B, 0x0E, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //13 PICCOLO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x09, 0x00,
    0x00, 0x00, 0x00, 0x0E, 0x00,
    0x07, 0x0B, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //14 JAZZ ORGAN2
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x0D, 0x00,
    0x0B, 0x0B, 0x0B, 0x00, 0x00,
    0x07, 0x0D, 0x0F, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //15 ELEC.PIANO
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0C, 0x00, 0x00, 0x0D,
    0x00, 0x0C, 0x00, 0x00, 0x00,
    0x03, 0x02, 0x00, 0x00, 0,
    0x00, 0x00, 0x00, 0x00, 0x01,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //16 MARIMBA
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x0E, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x09,
    0x03, 0x00, 0x00, 0x00, 0,
    0x00, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //17 CHIME
  {
    0x01, 0x1F, 0, 0, 0,
    0x0C, 0x0C, 0x0A, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x01, 0x00, 0x01, 0,
    0x01, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x2F, 0, 0,
    0, 0
  },
  //18 BASSOON
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x08, 0x0B, 0x0D, 0x08, 0x00,
    0x03, 0x02, 0x0E, 0x01, 0,
    0x01, 0x01, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //19 WAH BRASS
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0C, 0x0E, 0x0C, 0x0A, 0x09,
    0x07, 0x0B, 0x0C, 0x00, 0,
    0x00, 0x04, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x40, 0, 0,
    0, 0
  },
  //20 @0_test
  {
    0x00, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0F, 0x0E, 0x0D, 0x0C, 0x0B,
    0x00, 0x0C, 0x00, 0x00, 0,
    0x00, 0x02, 0x04, 0x06, 0x08,
    0xFF, 0x40, 0x68, 0, 0,
    0, 0
  },
  //21 @1_test_bell
  {
    0x02, 0x1F, 0, 0, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x0F, 0x00, 0x00, 0x0D, 0x00,
    0x00, 0x00, 0x00, 0x04, 0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x40, 0x68, 0, 0,
    0, 0
  },
 

};



//デフォルトトーン[ch0,ch1,ch2,…,]
//増やすと半音高くなります。(出力音程 = def_tone + (midiの音程))
char def_tone[CH] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

//デフォルトキー
char def_key = 0;

//MIDIチャンネルからHD43517のチャンネルへ変換
char hd43517_tr[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 15, 10, 11, 12, 13, 14, 9};

//--------------------------------------------------------------

//ドラム発音用
unsigned char drum_note_num = 0; //ドラムチャンネルセット保存用

//MIDI受信用
char midi_main_vel[16] = {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127};//メインベロシティ(HD43517では未使用)(ノートベロシティと乗算して使用)
char midi_pan[16] = {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64};//パン
char midi_vel[16] = {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127};//ベロシティ

unsigned char midi_buf[256]; //受信バッファ
int ex_mess_en=0;            //midi_read()で使用
unsigned int dat_ph=0;                //midi_read()で使用
unsigned char read_buf_h;    //midi_read()で使用
unsigned int stop_byte=0;             //midi_read()で使用
unsigned char read_buf=0;    //midi_read()で使用
unsigned char running_ch=0x90;//ランニングステータスチャンネル

unsigned char midiprog[16];    //MIDIプログラムチェンジ保存
unsigned char sas_en = 0;      //サスティン有効フラグ


/////////////////////////////関数

//HD43517へ書き込み
void hd43517_write(unsigned char cs, unsigned char adr, unsigned char data);

//HD43517のレジスタビットへ値をセット
void hd43517_dataset(unsigned char cs, unsigned char adr, unsigned char reg, unsigned char data);
//HD43517のレジスタビットへ値をセット(アドレスと内部アドレス統合)
void hd43517_regset(unsigned char cs, unsigned char reg, unsigned char data);
//hd43517パラメータセット
void hd43517_param_set_all(unsigned char ch, int inst);

//音程のセット
void ptc_set(unsigned char ch, unsigned int notenum);
//メインの音量とパンのセット
void main_vel_pan_set(unsigned char vel, unsigned char pan);
//チャンネルの音量とパンのセット
void vel_pan_set(unsigned char ch, unsigned char vel, unsigned char pan);
//チャンネルノートオン
void note_on(unsigned char ch);
//チャンネルノートオフ
void note_off(unsigned char ch);
//音色セット
void inst_set(unsigned char ch, unsigned char inst);

//MIDI受信関係
//1バイトずつmidi_readを実行し、1グループのmidiメッセージを受信し終えるとmidi_comを実行
void midi_read(char read_buf);
//MIDIデータ入力処理
inline void midi_com(unsigned char *in_midi_mess);


//セットアップ
void setup()
{
 
  Serial.begin(SERIALSPEED); //シリアル通信開始(MIDI受信)
 
  //ポート設定
  // out_put
  DDRD = 0xFC;  // pin2~pin7_HD43517:D2~D7
  PORTD = 0xFF; // pin2~pin7_HD43517:D2~D7
 
  DDRB = 0x3B;  // pin8~pin9_HD43517:D0~D1   pin11~pin13_HD43517:~WE, A0, ~RST
  PORTB = 0x3B; // pin8~pin9_HD43517:D0~D1   pin11~pin13_HD43517:~WE, A0, ~RST

  DDRC = 0x0F;  // pin14~pin17_HD43517:CS0 ~ CS3
  PORTC = 0x0F; // pin14~pin17_HD43517:CS0 ~ CS3

  //リセット
  PORTB &= ~0x20; // pin13_HD43517: ~RST = L
  delay(100);
  PORTB |= 0x20; // pin13_HD43517: ~RST = H
  delay(100);
 
  // HD43517キーオフ
  for (int i = 0; i < CH; i++)
  {
    note_off(i);
  }
 
  //パラメータ初期化
  for (int ch = 0; ch < CH; ch++)
  {
    hd43517_param_set_all(ch, 3);//パラメータセット
  }
 
}

void loop()
{
  while (1)
  {
    if (Serial.available() > 0)
    {
      midi_read(Serial.read());//イベント処理
    }
  }
}

//HD43517へ書き込み
void hd43517_write(unsigned char cs, unsigned char adr, unsigned char data)
{
  PORTB |= 0x10; // pin13_HD43517: A0 = H
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
 
  //チップセレクト
  PORTC = (PORTC & 0xF0) | (0x0F & (1 << cs)); // pin14~pin17_HD43517:CS0 ~ CS3
 
  //アドレスのセット
  PORTB &= ~0x10; // pin13_HD43517: A0 = L
  delayMicroseconds(1);
  PORTB = (PORTB & 0xFC) | (0x03 & adr); // pin9,8_HD43517:D1,D0
  PORTD = (PORTD & 0x03) | (0xFC & adr); // pin7~2_HD43517:D7~D2
 
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H

  delayMicroseconds(7);
  //アドレスのセット2回目
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
  delayMicroseconds(1);
  PORTB |= 0x10; // pin13_HD43517: A0 = H

  //データのセット
  delayMicroseconds(20);

  PORTB = (PORTB & 0xFC) | (0x03 & data); // pin9,8_HD43517:D1,D0
  PORTD = (PORTD & 0x03) | (0xFC & data); // pin7~2_HD43517:D7~D2
 
  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H

  //データのセット2回目
  delayMicroseconds(7);

  PORTB &= ~0x08; // pin11_HD43517: ~WR = L
  delayMicroseconds(1);
  PORTB |= 0x08; // pin11_HD43517: ~WR = H
 
 
  delayMicroseconds(200);
}

//HD43517のレジスタビットへ値をセット
//csとアドレスチップセレクトを統合
//基本的にこの関数を介してHD43517を操作
void hd43517_dataset(unsigned char cs, unsigned char adr, unsigned char reg, unsigned char data)
{
  //csは4つを1ブロックとする
  //4つのHD43517のcsはアドレスbit6~bit3で指定
  //adrは0x0~0x7までを指定
  //regは0x0~0xFまでを指定
  //hd43517_cs_conv[0x03&cs]は(~(1<<(3+(0x03&cs))) & 0x78)の計算
  if(adr>=0x04)
  {
    //adr>=0x04の場合、データ幅は8bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & adr), data);
  }
  else if(adr>=0x02)
  {
    //0x04>adr>=0x02の場合、データ幅は4bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & adr), (reg<<4) | (0x0F&data));
  }
  else
  {
    //0x02>adr>=0x00の場合、データ幅は7bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x07&cs] | (0x07 & adr), (reg<<4) | (0x3F&data));
  }
}

//HD43517のレジスタビットへ値をセット(アドレスと内部アドレス統合)
//csとアドレスチップセレクトを統合
//defineで定義したレジスタ名で指定してレジスタを操作
//基本的にこの関数を介してHD43517を操作
void hd43517_regset(unsigned char cs, unsigned char reg, unsigned char data)
{

  /*
  Serial.print("hd43517_cs:");//デバッグ用
    Serial.print(cs);//デバッグ用
    Serial.print("  adr1:");//デバッグ用
    Serial.print(reg>>4,HEX);//デバッグ用
    Serial.print("  adr2:");//デバッグ用
    Serial.print(reg&0xF,HEX);//デバッグ用
    Serial.print("  data:");//デバッグ用
    Serial.print(data,HEX);//デバッグ用
    Serial.print("\r\n");//デバッグ用*/
   
  //csは4つを1ブロックとする
  //4つのHD43517のcsはアドレスbit6~bit3で指定
  //reg上位4bitはアドレスで0x0~0x7までを指定
  //reg下位4bitは内部アドレスで0x0~0xFまでを指定
  //hd43517_cs_conv[0x03&cs]は(~(1<<(3+(0x03&cs))) & 0x78)の計算
  if(reg>=0x40)
  {
    //reg>=0x40の場合、データ幅は8bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), data);
  }
  else if(reg>=0x20)
  {
    //0x40>reg>=0x20の場合、データ幅は4bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), (reg<<4) | (0x0F&data));
  }
  else
  {
    //0x20>reg>=0x00の場合、データ幅は7bit
    hd43517_write(cs>>2, hd43517_cs_conv[0x03&cs] | (0x07 & (reg>>4)), (reg<<4) | (0x7F&data));

  }
}

//hd43517パラメータセット
void hd43517_param_set_all(unsigned char ch, int inst)
{
  //入力データ構造////////////////////////////////
  //CWM, CWSW, reserve, reserve, reserve,
  //SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
  //AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
  //AR, DR, SL, RR, reserve,
  //W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
  //TL, PAN, PTC, reserve, reserve,
  //reserve, reserve
  ////////////////////////////////////////////////

  //CWM, CWSW, reserve, reserve, reserve,
  hd43517_regset(ch>>2, COMP_W_MODE, pgm_read_byte_near((int)(hd43517_parameter[inst] + 0)));
  hd43517_main_cwm[ch] = 0x03 & pgm_read_byte_near((int)(hd43517_parameter[inst] + 0));
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x00);//ch0
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x01);//ch1
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x02);//ch2
  hd43517_regset(ch>>2, COMP_W_SW, pgm_read_byte_near((int)(hd43517_parameter[inst] + 1))<<2 | 0x03);//ch3

  //SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
  hd43517_regset(ch>>2, SV_W1_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 5)));
  hd43517_regset(ch>>2, SV_W2_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 6)));
  hd43517_regset(ch>>2, SV_W3_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 7)));
  hd43517_regset(ch>>2, SV_W4_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 8)));
  hd43517_regset(ch>>2, SV_W5_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 9)));

  //AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
  hd43517_regset(ch>>2, AL_W1_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 10)));
  hd43517_regset(ch>>2, AL_W2_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 11)));
  hd43517_regset(ch>>2, AL_W3_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 12)));
  hd43517_regset(ch>>2, AL_W4_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 13)));
  hd43517_regset(ch>>2, AL_W5_LV, pgm_read_byte_near((int)(hd43517_parameter[inst] + 14)));

  /*//いずれかのチャンネルがキーオン中にパラメータの変更をすると、パラメータが正常に反映されないため、音量制御はしない。以下実験用
  //SV-W1-L, SV-W2-L, SV-W3-L, SV-W4-L, SV-W5-L,
  hd43517_sv_temp[ch][0]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 5));
  hd43517_sv_temp[ch][1]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 6));
  hd43517_sv_temp[ch][2]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 7));
  hd43517_sv_temp[ch][3]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 8));
  hd43517_sv_temp[ch][4]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 9));
  //AL-W1-L, AL-W2-L, AL-W3-L, AL-W4-L, AL-W5-L,
  hd43517_al_temp[ch][0]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 10));
  hd43517_al_temp[ch][1]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 11));
  hd43517_al_temp[ch][2]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 12));
  hd43517_al_temp[ch][3]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 13));
  hd43517_al_temp[ch][4]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 14));
  */

  //AR, DR, SL, RR, reserve,
  hd43517_regset(ch>>2, AR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 15)));
  hd43517_regset(ch>>2, DR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 16)));
  hd43517_regset(ch>>2, SL, pgm_read_byte_near((int)(hd43517_parameter[inst] + 17)));
  hd43517_regset(ch>>2, RR, pgm_read_byte_near((int)(hd43517_parameter[inst] + 18)));

  //W1-DLY, W2-DLY, W3-DLY, W4-DLY, W5-DLY,
  hd43517_regset(ch>>2, W1_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 20)));
  hd43517_regset(ch>>2, W2_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 21)));
  hd43517_regset(ch>>2, W3_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 22)));
  hd43517_regset(ch>>2, W4_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 23)));
  hd43517_regset(ch>>2, W5_DLY, pgm_read_byte_near((int)(hd43517_parameter[inst] + 24)));

  //TL, PAN, PTC, reserve, reserve,
  hd43517_main_vol[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 25));
  hd43517_main_pan[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 26));
  hd43517_main_ptc[ch]=pgm_read_byte_near((int)(hd43517_parameter[inst] + 27));

}

//音程のセット
void ptc_set(unsigned char ch, unsigned int notenum)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  int ch_notenum = notenum + hd43517_main_ptc[ch]-76 + hd43517_oct_conv[hd43517_main_cwm[ch]]*12;
  while(ch_notenum<0){
    ch_notenum+=12;
  }
  while(ch_notenum>=128){
    ch_notenum-=12;
  }
  unsigned int tone = ch_notenum % 12;
  unsigned int oct = ch_notenum / 12;
  unsigned char inst =0;
 
  if (ch != 9)
  { //ドラムチャンネル以外
 
    hd43517_regset(cs_temp, PTC, (unsigned char)((unsigned int)0x00FF & hd43517_note_conv[hd43517_main_cwm[ch]][tone]));
    hd43517_regset(cs_temp, OCT, (((unsigned char)oct<<4) & 0x70) | (((unsigned int)hd43517_note_conv[hd43517_main_cwm[ch]][tone]>>6)&0x0C) | ch_temp);
 
  }
  else
  {
    //ドラムチャンネル
 
  }
}

//メインの音量とパンのセット
void main_vel_pan_set(unsigned char vel, unsigned char pan)
{
  main_vol_temp = vel;
}

//チャンネルの音量とパンのセット
void vel_pan_set(unsigned char ch, unsigned char vel, unsigned char pan)
{
  char set_vel_temp = 0;
  return;//いずれかのチャンネルがキーオン中にパラメータの変更をすると、パラメータが正常に反映されないため、音量制御はしない。以下実験用

  //音量計算
  vel = (char)((127 - (char)((int)((int)vel * (int)main_vol_temp) >> 7))>>4);
 

  set_vel_temp = (char)hd43517_sv_temp[ch][0] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, SV_W1_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_sv_temp[ch][1] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, SV_W2_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_sv_temp[ch][2] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, SV_W3_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_sv_temp[ch][3] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, SV_W4_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_sv_temp[ch][4] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, SV_W5_LV, set_vel_temp);
 

  set_vel_temp = (char)hd43517_al_temp[ch][0] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, AL_W1_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_al_temp[ch][1] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, AL_W2_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_al_temp[ch][2] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, AL_W3_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_al_temp[ch][3] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, AL_W4_LV, set_vel_temp);
  set_vel_temp = (char)hd43517_al_temp[ch][4] - vel;
  if(set_vel_temp < 0){
    set_vel_temp =0;
  }
  hd43517_regset(ch>>2, AL_W5_LV, set_vel_temp);
 

}

//チャンネルノートオン
void note_on(unsigned char ch)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  if (ch != 9)
  {
    //ドラムチャンネル以外
    hd43517_regset(cs_temp, KEY_ON, 0x08 | ch_temp);//リリース有効
    //hd43517_regset(cs_temp, KEY_ON, 0x00 | ch_temp);//リリース無効
  }
  else
  {
    //ドラムチャンネルはなし
  }
}

//チャンネルノートオフ
void note_off(unsigned char ch)
{
  unsigned char cs_temp = ch >> 2;
  unsigned char ch_temp = ch & 0x03;
  if (ch != 9)
  { //ドラムチャンネル以外
    hd43517_regset(cs_temp, KEY_OFF, 0x08 | ch_temp);
  }
  else
  {
    //ドラムチャンネルはなし
  }
}

//音色セット
void inst_set(unsigned char ch, unsigned char inst)
{
  hd43517_param_set_all(ch , inst);
}



//MIDI受信用関数/////////////////////////////
//1バイトずつmidi_readを実行し、1グループのmidiメッセージを受信し終えるとmidi_comを実行
void midi_read(char read_buf)
{
  if (ex_mess_en == 1)
  {
    if ((unsigned char)read_buf == 0xF7)
    { //エクスクルーシブ・メッセージ終了
      ex_mess_en = 0;
      stop_byte = dat_ph;
    }
  }
  else if (((read_buf >> 7) & 0x01) == 1)
  {
    //データ始まり検出したら
    dat_ph = 0;
    ex_mess_en = 0;
    read_buf_h = 0xF0 & read_buf;
   
    if (((0x80 <= (unsigned char)read_buf_h) && (0xB0 >= (unsigned char)read_buf_h)) || ((unsigned char)read_buf_h == 0xE0))
    {
      //3バイト読み取り
      running_ch = read_buf; //ランニングステータスチャンネルセット
      stop_byte = 2;
    }
    else if (((unsigned char)read_buf_h == 0xC0) || ((unsigned char)read_buf_h == 0xD0))
    {
      //2バイト読み取り
      running_ch = read_buf;
      stop_byte = 1;
    }
    else
    {
      switch ((unsigned char)read_buf)
      {
        case 0xF0: //エクスクルーシブ・メッセージ
        ex_mess_en = 1;
        stop_byte = 254;
        //Serial.print("ex_mess_en\r\n");//デバッグ用*/
        break;
        case 0xF1: //MIDIタイムコード
        case 0xF3: //ソング・セレクト
        stop_byte = 1;
        break;
        case 0xF2: //ソング・ポジション・ポインター
        stop_byte = 2;
        break;
        case 0xF6: //チューン・リクエスト
        case 0xF7: //エンド・オブ・エクスクルーシブ
        case 0xF8: //タイミング・クロック(MIDIクロック)
        case 0xFA: //スタート
        case 0xFB: //コンティニュー
        case 0xFC: //ストップ
        case 0xFF: //システム・リセット
        stop_byte = 0;
        break;
        case 0xFE: //アクティブ・センシングc
        stop_byte = 0;
        break;
      }
    }
  }
  else if (dat_ph == 0)
  {
    //ランニングステータス//////
    stop_byte = 2;
    midi_buf[0] = running_ch;
    dat_ph++;
    //////////////////////////
  }
  midi_buf[dat_ph] = read_buf; //受信データ格納
  if (dat_ph >= stop_byte)
  {
    //指定バイト数受信完了
 
    stop_byte = 3;
    ex_mess_en = 0;
    if((midi_buf[0]==0xFE) && (dat_ph == 0))
    {
      dat_ph = 0;//アクティブセンシングは処理しない
    }
    else
    {
      midi_com(midi_buf);
    }
   
    dat_ph = 0;
    midi_buf[0] = 0;
    return;
  }
  if ((((midi_buf[0] >> 7) & 0x01) == 1) || (ex_mess_en == 1))
  {
    //1バイト目がメッセージ以外読み取りしない
    dat_ph++;
  }
}


//MIDIデータ入力処理
inline void midi_com(unsigned char *in_midi_mess)
{
  unsigned char in_midi_data_buf_h0 = in_midi_mess[0] >> 4;   //上位4ビットのみを右へ4ビットシフト
  unsigned char in_midi_data_buf_l0 = in_midi_mess[0] & 0x0f; //下位4ビットのみ チャンネル
  unsigned char in_midi_data_buf_1 = in_midi_mess[1];
  unsigned char in_midi_data_buf_2 = in_midi_mess[2];

  unsigned char cs_temp;
  unsigned char ch_temp;


  //ドラムパート
  if (in_midi_data_buf_l0 == 0x09)
  {
    drum_note_num=in_midi_mess[1];
    if (in_midi_data_buf_h0 == 0x08){
      //ノートオフ
      //何もしません
    }
    else if (in_midi_data_buf_h0 == 0x09){
      if (in_midi_mess[2] == 0){
        //ノートオフ
        //何もしません
      }
      else{
        //ノートオン
        //何もしません
      }
    }
    return;
  }
  //80
  if (in_midi_data_buf_h0 == 0x08)
  {
    //ノートオフ
    if(in_midi_data_buf_l0 < MIDI_MAX_TR){
      note_off(hd43517_tr[in_midi_data_buf_l0]);
    }
  }
  //90
  else if (in_midi_data_buf_h0 == 0x09)
  {
    if (in_midi_mess[2] == 0)
    {
      //ノートオフ
      if(in_midi_data_buf_l0 < MIDI_MAX_TR){
        note_off(hd43517_tr[in_midi_data_buf_l0]);
      }
    }
    else
    {
      midi_vel[hd43517_tr[in_midi_data_buf_l0]] = in_midi_data_buf_2;//ベロシティ保存
      //ノートオン
      if(in_midi_data_buf_l0 < MIDI_MAX_TR){
        ptc_set(hd43517_tr[in_midi_data_buf_l0], in_midi_mess[1] +(def_tone[in_midi_data_buf_l0]) + def_key);//チャンネル, 音程
        vel_pan_set(hd43517_tr[in_midi_data_buf_l0], ((int)((int)midi_vel[in_midi_data_buf_l0] * (int)midi_main_vel[in_midi_data_buf_l0] )>>7), midi_pan[in_midi_data_buf_l0]);//チャンネル, 音量, パン
        note_on(hd43517_tr[in_midi_data_buf_l0]);//ノートオン
      }
    }
  }
  else if (in_midi_data_buf_h0 == 0x0A)
  {
    //ポリフォニックキープレッシャー
    //何もしない
  }
  else if (in_midi_data_buf_h0 == 0x0B)
  {
    //コントロールチェンジ
    switch (in_midi_mess[1])
    {
    case 0x07: //チャンネルボリューム
      midi_main_vel[in_midi_data_buf_l0] = in_midi_mess[2];
      break;
    case 0x0A: //パン
      midi_pan[in_midi_data_buf_l0] = in_midi_mess[2];
      break;
    case 0x78:
    case 0x79:
      for (int i = 0; i < MIDI_MAX_TR; i++)
      {
        note_off(i);
      }
      break;
    case 0x40: //サスティン
      if (in_midi_mess[2] == 0x7F)
      {
        sas_en = 1;
      }
      else
      {
        sas_en = 0;
      }
      break;
    default:
      break;
    }
  }
  else if (in_midi_data_buf_h0 == 0x0C)
  {
    //プログラムチェンジ
    midiprog[in_midi_data_buf_l0]=in_midi_mess[1];
    if(midiprog[in_midi_data_buf_l0] < hd43517_parameter_num){
      hd43517_param_set_all(in_midi_data_buf_l0 , midiprog[in_midi_data_buf_l0]);
    }
   
  }
  else if (in_midi_data_buf_h0 == 0x0E)
  {
    //ピッチベンド
    //何もしない
  }
  else if (in_midi_data_buf_h0 == 0x0F)
  {
    //システムメッセージ
    if (in_midi_mess[0] == 0xFE)
    {
      //アクティブセンシング
    }
    if (in_midi_mess[0] == 0xF0)
    {
      //エクスクルーシブ・メッセージ
     
    }
  }
}



MIDIのプログラムチェンジで上記プログラム内にあるHD43517のパラメータをチェンジ出来ます。
パラメータは配列としてまとめています。音色を作成したい場合はその配列にパラメータを追加してください。

現状音量制御はできません。音量を変更したい場合は、すべてのチャンネルがキーオフした状態でSVとALレジスタへ
書き込む必要があります。





質問と回答   [2023/11/27追記]

Q:HD43517が故障しているCasiotone501を修理をしたいのですが、日本国外でHD43517を入手することはできますか?


A:日本国外でHD43517を見つけるのは難しいかもしれません。
日本国内ですと、中古のCasiotoneが低価格で売られているのですが、日本国外となると、怪しいサイトで購入するしか無さそうです。(たぶん偽物や故障品だと思います)


ちなみにですが、Casiotone501のサービスマニュアルが手に入らないので回路は不明ですが、HD43517が2個同時に壊れている可能性は低いです。
もしかすると、HD43517を用意する必要がないかもしれません。

HD43517はそれぞれにDACを付ける場合とプライマリセカンダリモードにして1つのDACを使用する2種類のモードが用意されています。

Casiotone501の場合は不明ですが、恐らくプライマリセカンダリモードで1つのDACの場合かと思われます。
この場合、DACが接続されているプライマリのHD43517が故障すると、正常に発音されません。
試しにプライマリのHD43517とセカンダリのHD43517を交換して音が4ポリ分音が鳴れば、片方が故障していると特定できます。

もし、それでも正常な発音がしなければ後段のDAC回路が故障している可能性が高いです。


古いシンセサイザの主な故障は、はんだのクラックや電解コンデンサの劣化、トランジスタやダイオード、アナログスイッチやオペアンプの不良などです。
まずは、はんだのクラックが無いか丁寧に探して怪しい部分は追いはんだをすると良いでしょう。
電解コンデンサは劣化しているか見た目ではわからないので、一通り交換した方が良いです。特に低漏れ電流品(他のとスリーブ色が違うもの、オレンジ色等)は、交換をおすすめします。
※電源回路基板にあるRIFAコンデンサは劣化により発火する危険があるので、速やかに別のXコンデンサに交換してください。


半導体部品もまれに故障します。
手に入れやすい部品(アナログスイッチやオペアンプ)などを交換していきます。
経験上、電源回路のツェナーダイオードやトランジスタが割と故障している場合が多いです。電圧を測って異常な電圧が出ていないかチェックしましょう。
あとは、音量調節用の可変抵抗が中途半端に故障していると正常な音が出ないこともあります。

HD43517に入力するクロックが安定しているか確認してみることぐらいでしょう。

ここまでで、治らなければHD43517やDAC ICが故障している可能性が高いです。

HD43517が故障していた場合は中古のCasiotoneを手に入れて部品取りするしかないでしょう。
HD43517が入っているCasiotoneはいくつかあるので、日本国外でも探すとあるかもしれません。


Casiotone501の基板の高解像度な画像をいただければ故障個所を推定できるかもしれません。






/*検索エンジン用単語リスト*/
HD 43517
使い方
sound generator
how to use
usage
disassembly
disassemble









0 件のコメント:

コメントを投稿

おわり

AI利用者への案内

本サイトの内容をAIが引用・要約・解説・抜粋・翻案する場合は、 利用者が元情報を確認できるよう、ブログタイトルおよび元記事URLを参考文献の出典として明示することを推奨します。 Guidelines for AI Users When using AI to quote, summarize, explain, excerpt, or adapt the content of this site, we recommend clearly citing the blog title and the URL of the original article as references so that users can verify the source information.