一つ前の記事「Raspberry PI でYMF825を鳴らす」はサンプルプログラムを使ったトライでした。こちらはNodeに置き換えて鳴らしてみます。物理的な接続は前の記事を参照してください。
SPI送信
SPIの通信モジュールとして、pi-spi を使いました。
npm install pi-spi
でインストールします。データの転送用として、以下のサブルーチンを作っておきます。
spisub.js
var SPI = require('pi-spi');
var spi = SPI.initialize("/dev/spidev0.0");
const HIGH=1;
const LOW=0;
function writeSingle( adrs, data )
{
buf = Buffer([adrs, data]);
ss(LOW); //信号ssをLOWにする
spi.transfer(buf,buf.length,function(e,d){
if (e) { //エラー処理
console.error(e);
process.exit(-1);
}
});
delayMs(1); //1msec waitします
ss(HIGH); //信号ssをHIGHにする
}
GPIO制御
GPIO の制御(SSをLOW/HIGHに設定)します。File System をダイレクトに使いました。
npm install fs
fsgpio = require('fs');
fsgpio.writeFileSync('/sys/class/gpio/export', 25); //SS
fsgpio.writeFileSync('/sys/class/gpio/gpio25/direction', 'out'); //SS
function ss(en)
{
fsgpio.writeFileSync('/sys/class/gpio/gpio25/value', en);
}
fsgpio.writeFileSync('/sys/class/gpio/export', 16); //RESET
fsgpio.writeFileSync('/sys/class/gpio/gpio16/direction', 'out'); //RESET
function reset(en)
{
fsgpio.writeFileSync('/sys/class/gpio/gpio16/value', en);
}
レジスタ・イニシャライズ
レジスター仕様書を参照しました。
initialize.js
function initialize()
{
ss(HIGH);
// 1. powerOnReset( void );
reset(LOW); //Reset を一旦Lowに設定
delayMs(1000); //wait 1sec
// 2. RST_N : high
reset(HIGH); //Reset をHighに戻す
// 3. DRV_SEL : low
// ←仕様書に説明がありません。多分LSB=0 が5.0V ではないかと**想像**されます。
writeSingle(29, 1); // 3.3v
// 4. AP0 : 0
// Analog Block Power-down control
writeSingle(2, 0x0e); // AP0 だけパワーダウンしない?
// 5. CLKE : "1"
// ←クロックをアクティブ
// ←この状態ではALRST=High になっているはず。
writeSingle(0, 0x01);
// 6. ALRST : low
// ←リセット状態を解除
writeSingle(1, 0x00);
// 7. SFTRST : 0xa3
// ←仕様書に説明がありません。SFTRST=0xa3 以外、たとえば0xff とか設定してみましたが、動作しませんでした。(意味わかりません。)
writeSingle(26, 0xa3);
delayMs(100); //待った方がよさそうなので
// 8. SFTRST : 0x00
// ←仕様書に説明がありません。おまじない。
writeSingle(26, 0x00);
delayMs(100); //待った方がよさそうなので
// 9. AP1 AP3: "0"
writeSingle(2, 0x04); //なぜ分けてパワーダウンするのだろう?
// 10. AP2: "0"
writeSingle(2, 0x00); //なぜ分けてパワーダウンするのだろう?
// 11.
writeSingle(25, 0x81); // -18[dB]
writeSingle(27, 0x3f); // set itp max
writeSingle(20, 0x00); // set itp on
writeSingle(3, 0x01); // amp gain(6.5[dB])
writeSingle(9, 0xcc); // 0[dB] Sequencer Volume
// 12. シーケンサー設定
// ←上位3bitは説明あり。AllKeyOff/AllMute/AllEGRstをリセット
// ←残りのビットは説明がありません。おまじない
writeSingle(8, 0xf6);
writeSingle(8, 0x00); // リセットから復帰
}
音のパラメータの初期化
Tone Parameterを以下のようにまとめて設定します。
function Tone_init()
{
mTone=Buffer([
0x07,0x90,0x00,0x43,0x00,0x67,0xff,0x9d,0x00,0x10,0x40,0x20,0x33,0xe2,0xa3,0x00,
0x50,0x00,0x10,0x41,0xd3,0x88,0x01,0x10,0x00,0x20,0x62,0xd4,0x02,0x01,0x10,0x00,
0x00,0x45,0x50,0xc4,0xfb,0x8c,0x44,0x70,0x95,0x10,0x82,0xff,0x12,0x45,0x10,0x00,
0x10,0xb0,0xf1,0x49,0x44,0x10,0x02,0x10,0x72,0xff,0x10,0x41,0x10,0x00,0x00,0x45,
0x00,0x03,0x70,0x16,0x44,0x10,0x0b,0x00,0x92,0x70,0x3c,0x43,0x10,0x40,0x00,0x03,
0x70,0x22,0x44,0x10,0x4b,0x00,0x92,0x70,0x36,0x43,0x10,0x00,0x00,0x43,0x20,0x37,
0xf1,0x4e,0x44,0x10,0x05,0x40,0x6b,0xc7,0x54,0x44,0x70,0x00,0x20,0x69,0xf2,0x5e,
0x44,0x20,0x00,0x60,0x82,0xb6,0x00,0x44,0x10,0x00,0x00,0x45,0x30,0x46,0xf5,0x41,
0x44,0xe0,0x03,0x70,0x66,0xce,0x2e,0x44,0x20,0x00,0x20,0x26,0xc5,0x78,0x44,0x77,
0x08,0x40,0x55,0xfd,0x04,0x54,0x60,0x00,0x00,0x45,0x30,0x3f,0xf0,0x98,0x44,0x70,
0x0d,0x40,0x47,0xf0,0x2e,0x44,0x50,0x00,0x00,0x11,0x60,0x62,0x03,0x17,0x0e,0x00,
0x51,0x81,0x02,0x03,0x10,0x00,0x00,0x45,0x58,0x50,0xf0,0x14,0x44,0xc0,0x17,0x78,
0x77,0xf7,0x00,0x44,0xb0,0x00,0x68,0x6a,0xf8,0x00,0x44,0xc0,0x00,0x78,0x77,0xf7,
0x00,0x44,0x70,0x10,0x00,0x45,0x58,0x97,0xff,0x08,0x44,0x70,0x0e,0x58,0xf8,0xaf,
0x00,0x44,0x50,0x30,0x68,0x55,0xf0,0x9c,0x44,0x20,0x28,0x98,0x9a,0xca,0x50,0x44,
0x50,0x00,0x00,0x43,0x00,0x67,0xff,0x9d,0x00,0x10,0x40,0x20,0x33,0xe2,0xa3,0x00,
0x50,0x00,0x10,0x41,0xd3,0x88,0x01,0x10,0x00,0x20,0x62,0xd4,0x02,0x01,0x10,0x00,
0x00,0x45,0x50,0xc4,0xfb,0x8c,0x44,0x70,0x95,0x10,0x82,0xff,0x12,0x45,0x10,0x00,
0x10,0xb0,0xf1,0x49,0x44,0x10,0x02,0x10,0x72,0xff,0x10,0x41,0x10,0x00,0x00,0x45,
0x00,0x03,0x70,0x16,0x44,0x10,0x0b,0x00,0x92,0x70,0x3c,0x43,0x10,0x40,0x00,0x03,
0x70,0x22,0x44,0x10,0x4b,0x00,0x92,0x70,0x36,0x43,0x10,0x00,0x00,0x43,0x20,0x37,
0xf1,0x4e,0x44,0x10,0x05,0x40,0x6b,0xc7,0x54,0x44,0x70,0x00,0x20,0x69,0xf2,0x5e,
0x44,0x20,0x00,0x60,0x82,0xb6,0x00,0x44,0x10,0x00,0x00,0x45,0x30,0x46,0xf5,0x41,
0x44,0xe0,0x03,0x70,0x66,0xce,0x2e,0x44,0x20,0x00,0x20,0x26,0xc5,0x78,0x44,0x77,
0x08,0x40,0x55,0xfd,0x04,0x54,0x60,0x00,0x00,0x45,0x30,0x3f,0xf0,0x98,0x44,0x70,
0x0d,0x40,0x47,0xf0,0x2e,0x44,0x50,0x00,0x00,0x11,0x60,0x62,0x03,0x17,0x0e,0x00,
0x51,0x81,0x02,0x03,0x10,0x00,0x00,0x45,0x58,0x50,0xf0,0x14,0x44,0xc0,0x17,0x78,
0x77,0xf7,0x00,0x44,0xb0,0x00,0x68,0x6a,0xf8,0x00,0x44,0xc0,0x00,0x78,0x77,0xf7,
0x00,0x44,0x70,0x10,0x00,0x45,0x58,0x97,0xff,0x08,0x44,0x70,0x0e,0x58,0xf8,0xaf,
0x00,0x44,0x50,0x30,0x68,0x55,0xf0,0x9c,0x44,0x20,0x28,0x98,0x9a,0xca,0x50,0x44,
0x50,0x00,0x80,0x03,0x81,0x80]);
ss(LOW);
spi.transfer(mTone,mTone.length,function(e,d){
if (e) {
console.error(e);
process.exit(-1);
}
});
delayMs(100);
ss(HIGH);
}
音を鳴らす
取りあえず、1音鳴らすには以下を実行します。音を鳴らしっぱなし(ずーっと鳴っている)にしたかったので、Tone Number=2 を鳴らしています。
main.js
initialize();
Tone_init();
writeSingle(11,0); // channel number
writeSingle(12,0x7C); // volume setting registers
writeSingle(16,0x71); // each voice volume
writeSingle(15,0x30); // KeyOn & Tone Numbber
writeSingle(13,0x14); // frequency information & octave
writeSingle(14,0x5B); // frequency information
writeSingle(15,0x42); // KeyOn & Tone Numbber