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がある状態から、音が鳴るまでの手順は下記の通り。
- LPC810を調達する(マルツで75円。秋月で300円!)
- USB-TTL変換機を調達する(aitendoとかで安い)
- FlashMagicをDLしとく
- ImpactDrillさんのサイト通りに書き込み用に配線する
- hexファイルを焼き込む
- ImpactDrillさんのサイト通りに演奏用に配線する
・・・ImpactDrillさんのサイト通りに試せばうまくいきます。
私の電子工作箱には、マルツで買い占めたLPC810が全部で6個あります。
まずは1個試しに作ります。
問題なくうまく行きましたので、一気に量産します。
焼き込んだあとのLPC810。言うまでもなく見た目は変化がありません。
演奏
ImpactDrillさんが公開してくれているSCC810.zipを使って、LPC810の4番とGNDでSOUND OUTすることが出来ました。
exampleコードは和音に対応していませんが、sccオブジェクトを直接操作すれば和音も鳴ります。
こんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#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の頃は、
- kalshagarさんが作ったSMF→Arduino&YMZ用変換ツールでコード生成
- Arduinoにコード書き込み
- ArduinoからYMZに演奏させる
という流れで演奏してたのですが、時の流れは無情なもので、kalshagarさんのサイト自体が消失してしまっております。代替となる、SMFをシンプルなコードに変換するツールが必要です。
SMFを直接シリアル経由でArduinoに送り、そのまま演奏させるというのも手ですが、PCを介すと後の運用に悪影響を及ぼすので、やはりコード変換ツールが必要。
解決策: PSGの3和音 & SCCの5和音に対応したツールを作ろうと思います。
課題2. 配線が面倒
音を鳴らすときは、こんな感じに配線する必要があります。
そんなに線は多くありませんが、地味に大変です。
解決策: Speaker OUT付きのArduinoシールドを作ろうと思います。
以上、よろしくお願い致します。
関連記事
-
-
ルンバにスピッツを演奏させてみた
お疲れ様です。高橋です。 家にあるルンバにArduinoを挿して、スピッツの「涙 …
-
-
YMZシールド 再作成
お疲れ様です。高橋です。 YMZのノイズが超気になる YMZ294用の音楽を聞く …
-
-
マウスを入力I/Fとして使うのを断念してみた。
お疲れ様です。高橋です。 先日の「マウスを分解してみた」でマウスを分解し、ケーブ …
-
-
満員電車内でのオナラと検知 #2
お疲れ様です。高橋です。 最近なんだか忙しかったので、なかなか物が作れませんでし …
-
-
bluetoothモジュールHC-06とAndroid
お疲れ様です。高橋です。 先日AliExpressで購入したbluetoothモ …
-
-
EEPROM書き込みシールドの作成
お疲れ様です。高橋です。 先日成功したPCからのEEPROM書き込みですが、ジャ …
-
-
音階に合わせてLEDを光らせてみた。
お疲れ様です。高橋です。 主旋律に合わせてLEDを光らせてみる実験を行いました。 …
-
-
満員電車内でのオナラと検知 #4
お疲れ様です。高橋です。 硫化水素センサーが到着しました。結構前に到着していたの …
-
-
遠隔でRaspberryPi+DCモーターを制御 #2
お疲れ様です。高橋です。 WiMAXが上限オーバー 私の家の自宅回線はWiMAX …
-
-
LEDドライバなる物の存在
お疲れ様です。高橋です。 本日、同僚とLED周りについて雑談していると、「LED …
- PREV
- 久々に耳コピ。FF4バトル2
- NEXT
- 満員電車内でのオナラと検知