curious4dev

中国旅行、Arduinoなどを使った電子工作、その他色々。

*

LPC810をSCC/PSGにする

 

お疲れ様です。高橋です。

出会い

ImpactDrillさんのサイトの「LPC810とArduino UNOでSCC互換音源を鳴らす(1)」という記事。

今まで1個500円もするPSG音源、YMZ294を何個か買って使ってるんですが、革命的に安価になります。しかもSCC音源にもなるという。

LPCに焼き込むPSG音源とSCC音源のhexファイルは、Qiitaで「I2Cで制御できる80円のPSG互換チップで遊ぼう」という記事を書いたtoyoshimさんという方が作られました。

toyoshimさんがhexを書き、それを操作しやすいようImpactDrillさんがArduino用ライブラリを書き。二人の神に支えられたら、あとはもう、使うしかありません。

とりあえず、鳴るところまで検証します。

焼き込み

生のLPC810がある状態から、音が鳴るまでの手順は下記の通り。

  1. LPC810を調達する(マルツで75円。秋月で300円!)
  2. USB-TTL変換機を調達する(aitendoとかで安い)
  3. FlashMagicをDLしとく
  4. ImpactDrillさんのサイト通りに書き込み用に配線する
  5. hexファイルを焼き込む
  6. ImpactDrillさんのサイト通りに演奏用に配線する

・・・ImpactDrillさんのサイト通りに試せばうまくいきます。

私の電子工作箱には、マルツで買い占めたLPC810が全部で6個あります。

img_9798

まずは1個試しに作ります。

img_9797

問題なくうまく行きましたので、一気に量産します。

img_9796

焼き込んだあとのLPC810。言うまでもなく見た目は変化がありません。

演奏

ImpactDrillさんが公開してくれているSCC810.zipを使って、LPC810の4番とGNDでSOUND OUTすることが出来ました。

exampleコードは和音に対応していませんが、sccオブジェクトを直接操作すれば和音も鳴ります。

こんな感じです。

#include <Wire.h>
#include <PSG810.h>
#include <SCC810.h>

SCC810* scc;

void setup() {
 scc = new SCC810();
 scc->SetMixer(0x11111);
 scc->SetVolume(SCC::SCC_A, 0x0f);
 scc->SetVolume(SCC::SCC_B, 0x0f);
 scc->SetVolume(SCC::SCC_C, 0x0f);
 scc->SetVolume(SCC::SCC_D, 0x0f);
 scc->SetVolume(SCC::SCC_E, 0x0f);
 char wave[] = "F0604010406020F0407050002030F0A0005010C0D0F0A080B000D090B0E0B090";
 char wt[SCC::WT_SIZE];
 strtowt(wave, sizeof(wave), wt);
 scc->SetWaveTable(SCC::SCC_A, wt, sizeof(wt));
 scc->SetWaveTable(SCC::SCC_B, wt, sizeof(wt));
 scc->SetWaveTable(SCC::SCC_C, wt, sizeof(wt));
 scc->SetWaveTable(SCC::SCC_D, wt, sizeof(wt));
 scc->SetWaveTable(SCC::SCC_E, wt, sizeof(wt));
}

void loop() {
 scc->SetFrequency(SCC::SCC_A, 340);
 scc->SetFrequency(SCC::SCC_B, 330);
 scc->SetFrequency(SCC::SCC_C, 320);
 scc->SetFrequency(SCC::SCC_D, 310);
 scc->SetFrequency(SCC::SCC_E, 300);
 delay(100);
 scc->SetFrequency(SCC::SCC_A, 440);
 scc->SetFrequency(SCC::SCC_B, 0);
 scc->SetFrequency(SCC::SCC_C, 0);
 scc->SetFrequency(SCC::SCC_D, 0);
 scc->SetFrequency(SCC::SCC_E, 0);
 delay(100);
 scc->SetFrequency(SCC::SCC_A, 540);
 delay(100);
 scc->SetFrequency(SCC::SCC_A, 640);
 delay(100);
}


void strtowt(char* str, int str_size, char* wt)
{
 for (int i = 0; i < str_size; i+=2){
 byte b = (ctob(str[i]) * 0x10) + (ctob(str[i+1]));
 wt[i/2] = b;
 }
}
byte ctob(char c)
{
 byte ret = 0;
 if (c >= '0' && c <= '9')
 ret = c - '0';
 else if(c >= 'a' && c <= 'f')
 ret = c - 'a' + 10;
 else if (c >= 'A' && c <= 'F')
 ret = c - 'A' + 10;
 return ret;
}

YMZの時に、チャネルに与える周波数を0にしても無音にならずノイズになった経験があるので、いずれきちんとしたドライバを書く予定。(mute時はmixerから外す、音量を0にする等)

課題1. SMFをArduinoコードに変換

MIDIシーケンサで作った楽曲を効率よくLPC810で鳴らすために考えました。

Arduino&YMZ294の頃は、

  1. kalshagarさんが作ったSMF→Arduino&YMZ用変換ツールでコード生成
  2. Arduinoにコード書き込み
  3. ArduinoからYMZに演奏させる

という流れで演奏してたのですが、時の流れは無情なもので、kalshagarさんのサイト自体が消失してしまっております。代替となる、SMFをシンプルなコードに変換するツールが必要です。

SMFを直接シリアル経由でArduinoに送り、そのまま演奏させるというのも手ですが、PCを介すと後の運用に悪影響を及ぼすので、やはりコード変換ツールが必要。

解決策: PSGの3和音 & SCCの5和音に対応したツールを作ろうと思います。

課題2. 配線が面倒

音を鳴らすときは、こんな感じに配線する必要があります。

img_9799

そんなに線は多くありませんが、地味に大変です。

解決策: Speaker OUT付きのArduinoシールドを作ろうと思います。

 

 

以上、よろしくお願い致します。

 - 電子工作

  関連記事

aitendoで買った375円のバックライト付きI2C LCDで文字を表示してみた。

お疲れ様です。高橋です。 ちょっと前にaitendoで買ったバックライト付きのL …

満員電車内でのオナラと検知 #5

お疲れ様です。高橋です。 マイコンと5V給電 先日実験に成功した硫化水素センサー …

マウスを入力I/Fとして使うのを断念してみた。

お疲れ様です。高橋です。 先日の「マウスを分解してみた」でマウスを分解し、ケーブ …

シフトレジスタLED付きのYMZ294回路をFritzingに起こしてみた。

お疲れ様です。高橋です。 ユニバーサル基板で作ったYMZボードと、音階LED及び …

音階LED実装 #4

お疲れ様です。高橋です。 今日は音階LEDのIC-IC間、GNDの敷設、そして1 …

遠隔でRaspberryPi+DCモーターを制御してaitendoの名刺をクルクルさせる。

お疲れ様です。高橋です。 「猫×おもちゃ×動画×アプリ」のための要素技術として必 …

Arduino nano互換機でオナラ検知デバイス

お疲れ様です。高橋です。 今日のお昼、会社の大先輩から、綺麗にケーシングした自作 …

PCとArduinoをJavaでシリアル通信

お疲れ様です。高橋です。 先日作ったコレ。 よくよく考えると、書き込む際にいちい …

マウスの位置座標を使った電子楽器を作ってみた。

お疲れ様です。高橋です。 先日分解したマウスを使って、位置座標の取り出しと、取り …

音階LED表示器の実体配線図を書いてみた。

お疲れ様です。高橋です。 前に「音階に合わせてLEDを光らせてみた。」で実験した …