BSM02でシーケンサー+D/A混在シンセを作りましたが、打ち込んだデーターを外に取り出す仕組みは作っていないので、
Nucleo_DCOに音階を与えるために流用するのは少しめんどうです。BSM02のハードウェア/ソフトウェアに手を入れる必要があるので、思いつきで崩してしまうのは抵抗があります。
ひとまずは、パソコン上のDAWを使ってMIDI信号を出力し、CV/GATE信号に変換する、MIDI-CVコンバーターを作ってみることにしました。
作戦
ArduinoとmbedのMIDI Libraryを簡単に試したことがありますが(
https://dad8893.blogspot.com/search/label/MIDI%20Library)、サイズの小さいNucleo F303K8を使ってmbedでやってみると、どうもMIDIメッセージを読みこぼすようです。
Nucleo-F303K8は12bit DACが3系統内蔵されていて、性能もCortex-M4でそこそこ高スペックなので使ってみたかったのですが、まずはArduinoでやってみることにしました。
Arduino NANOかArduino Pro Miniを使うつもりです。
想定している使用例
ArduinoにSPI/DACの
MCP4922を接続し、アナログ値を出力してCVとします。MCP4922は2ch DACなのでうまく行けば2ch分CVを出力できます。
Nucleo_DCOは3.3V系(5Vトレラント)なのでCVの信号レベルは0V~3.3Vとします。
「DASS01」(「ASS01」という名前にしようと思ってましたが、「DASS01」に変更します)はアナログ系でCV信号にもう少し振幅が欲しいので「DASS01」内の「Amp」で増幅します。増幅率は「Mod Level」POTで可変します。
GATE信号はGPIOから出力します。「
Arduino_EG」のプロセッサーは5V駆動のArduino Pro Miniなので入力するGATE信号レベルは5VでOKです。「
KIK01」はNucleo-F446RE、「
BSM02」はNucleo-F401REでSyncIn(GATEの立ち上がりで評価)は3.3V系ですが5Vトレラントなのでこれも5VでOKです。
開発環境
ArduinoでMIDI Libraryを使うとデフォルトではハードウェアUART(D0, D1)を使うので、デバッグ用にArduinoのSerialクラスが使えません。簡単なメッセージの表示しかできませんが、I2C接続のキャラクタLCD(秋月のAE-AQM1602A)を使うことにしました。
ブレッドボード配線図
※Arduinoで書き込むときは、RXの配線を抜く。
※MCP4922はまだ接続していません。
Arduinoのスケッチ
AE-AQM1602Aのライブラリは「I2CLiquidCrystal-1.5
https://n.mtng.org/ele/arduino/i2c.html」を使いました。
<MIDI_Display_Message_I2C_LCD_Gate.ino>
#include <Wire.h>
#include <I2CLiquidCrystal.h>
#include <MIDI.h>
#define LCD_TRACE (0)
#define PIN_CHECK (1)
#define TITLE_STR1 ("MIDI to GATE ")
#define TITLE_STR2 ("20181204 ")
// Pin assign
const int GateOutPin1 = 2;
const int GateOutPin2 = 3;
const int GateOutPin3 = 4;
const int GateOutPin4 = 5;
const int GateOutPin5 = 6;
const int GateOutPin6 = 7;
const int CheckPin1 = 8;
// MIDI
MIDI_CREATE_DEFAULT_INSTANCE();
// I2C LCD
#if (LCD_TRACE)
I2CLiquidCrystal lcd(32, (bool)true);
#endif
// MIDI -------------------------------------------------------------------------
#if (LCD_TRACE)
void printNoteOnOff(const char* type, byte inChannel, byte inNote, byte inVelocity)
{
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(type);
lcd.print(' ');
lcd.print(inChannel);
lcd.print(' ');
lcd.print(inNote);
lcd.print(' ');
lcd.print(inVelocity);
}
#endif
void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
{
digitalWrite(GateOutPin1, HIGH);
#if (LCD_TRACE)
printNoteOnOff("On", inChannel, inNote, inVelocity);
#endif
}
void handleNoteOff(byte inChannel, byte inNote, byte inVelocity)
{
digitalWrite(GateOutPin1, LOW);
#if (LCD_TRACE)
printNoteOnOff("Off", inChannel, inNote, inVelocity);
#endif
}
// -----------------------------------------------------------------------------
void setup()
{
pinMode(GateOutPin1, OUTPUT);
pinMode(GateOutPin2, OUTPUT);
pinMode(GateOutPin3, OUTPUT);
pinMode(GateOutPin4, OUTPUT);
pinMode(GateOutPin5, OUTPUT);
pinMode(GateOutPin6, OUTPUT);
pinMode(CheckPin1, OUTPUT);
MIDI.setHandleNoteOn(handleNoteOn);
MIDI.setHandleNoteOff(handleNoteOff);
MIDI.begin(MIDI_CHANNEL_OMNI);
#if (LCD_TRACE)
lcd.begin(16, 2);
lcd.print(TITLE_STR1);
lcd.setCursor(0, 1);
lcd.print(TITLE_STR2);
delay(2000);
#endif
}
void loop()
{
#if (PIN_CHECK)
digitalWrite(CheckPin1, HIGH);
#endif
if (MIDI.read()) {
// Display Raw Midi Message
byte type = MIDI.getType();
byte channel = MIDI.getChannel();
byte data1 = MIDI.getData1();
byte data2 = MIDI.getData2();
#if (LCD_TRACE)
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(type, HEX);
lcd.print(' ');
lcd.print(channel, HEX);
lcd.print(' ');
lcd.print(data1, HEX);
lcd.print(' ');
lcd.print(data2, HEX);
#endif
}
#if (PIN_CHECK)
digitalWrite(CheckPin1, LOW);
#endif
}
メモ:
LCD_TRACEを有効化(1)するとMIDIメッセージを読みこぼす。
中華製のArduino NANOはプロセッサでATMega328P(Old bootloder)を指定する必要がある場合がある。
メインループの処理時間は92kHzぐらいで変わらない?
DACからの出力にはLPFを入れる。Nucleo_DCOはADCにCV信号を入力するので注意。
厳密にするならDACやGPIOからの信号はデジタル回路でラッチをかけて同期させたいけど、そこまでは必要ないか・・・