Nucleo F401REでFM音源を実装するやつ 外部DACとオペアンプを利用 現在はMCP4922とNJM2737

Dependencies:   AOTTrigon I2CEEPROM MCP4922 AQM0802A mbed

Fork of NuMidi401 by Yuu Kobayashi

NuFM401

Nucleo F401用の自作ソフトウェアMIDI音源

概要

だいたいそんなもんです。

特徴

  • ブレッドボードの上で組める程度には簡単な回路構成
  • 外部のDACにMCP4922を採用
  • 念のためのボルテージフォロアとしてNJM2737Dを採用
  • バンク用EEPROMに24FC1025を採用
  • シリアル経由でMIDIデータを受信することで操作

補足

シリアル <=> MIDI のドライバにはHairless-MIDISerialをオススメします。 仮想MIDIケーブルはとりあえずMIDI Yokeで。

Committer:
kb10uy
Date:
Tue Jan 27 12:56:33 2015 +0000
Revision:
17:2e577c6000cf
Parent:
16:5cfa8b491882
Child:
18:b20fdf1da8f8
MIDIChannel????ControlChange?????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kb10uy 13:e11380ceb460 1 #include "FMOscillator.h"
kb10uy 11:62da91a1eaf1 2
kb10uy 11:62da91a1eaf1 3 char sysexData[128];
kb10uy 11:62da91a1eaf1 4
kb10uy 17:2e577c6000cf 5 FMOscillator::FMOscillator()
kb10uy 17:2e577c6000cf 6 {
kb10uy 17:2e577c6000cf 7
kb10uy 13:e11380ceb460 8 }
kb10uy 13:e11380ceb460 9
kb10uy 17:2e577c6000cf 10 FMOscillator::FMOscillator(int opc, Timer *tim, Serial *ser, AOTTrigon *tri, I2C *i2clcd)
kb10uy 17:2e577c6000cf 11 {
kb10uy 16:5cfa8b491882 12 master = tim;
kb10uy 16:5cfa8b491882 13 serial = ser;
kb10uy 16:5cfa8b491882 14 trigon = tri;
kb10uy 16:5cfa8b491882 15 opcount = opc;
kb10uy 17:2e577c6000cf 16
kb10uy 16:5cfa8b491882 17 operators = new FMOperator*[opcount];
kb10uy 16:5cfa8b491882 18 for(int i = 0; i < opcount; i++) {
kb10uy 16:5cfa8b491882 19 operators[i] = new FMOperator(master, trigon);
kb10uy 16:5cfa8b491882 20 }
kb10uy 17:2e577c6000cf 21
kb10uy 17:2e577c6000cf 22 channels = new MIDIChannel*[16];
kb10uy 17:2e577c6000cf 23 for(int i = 0; i < 16; i++) {
kb10uy 17:2e577c6000cf 24 channels[i] = new MIDIChannel();
kb10uy 17:2e577c6000cf 25 }
kb10uy 17:2e577c6000cf 26
kb10uy 16:5cfa8b491882 27 lcd = new AQM0802A(*i2clcd);
kb10uy 17:2e577c6000cf 28
kb10uy 16:5cfa8b491882 29 serial->baud(256000);
kb10uy 16:5cfa8b491882 30 serial->format();
kb10uy 16:5cfa8b491882 31 serial->attach(this, &FMOscillator::midiReceived);
kb10uy 16:5cfa8b491882 32 master->start();
kb10uy 17:2e577c6000cf 33
kb10uy 16:5cfa8b491882 34 lcd->cls();
kb10uy 16:5cfa8b491882 35 lcd->printf("NuFM401\nFMDriver");
kb10uy 16:5cfa8b491882 36 }
kb10uy 16:5cfa8b491882 37
kb10uy 17:2e577c6000cf 38 FMOscillator::~FMOscillator()
kb10uy 17:2e577c6000cf 39 {
kb10uy 16:5cfa8b491882 40 for(int i = 0; i < opcount; i++) {
kb10uy 16:5cfa8b491882 41 delete operators[i];
kb10uy 16:5cfa8b491882 42 }
kb10uy 16:5cfa8b491882 43 delete operators;
kb10uy 16:5cfa8b491882 44 delete lcd;
kb10uy 16:5cfa8b491882 45 }
kb10uy 16:5cfa8b491882 46
kb10uy 16:5cfa8b491882 47 void FMOscillator::midiReceived()
kb10uy 16:5cfa8b491882 48 {
kb10uy 16:5cfa8b491882 49 getMIDIMessage();
kb10uy 16:5cfa8b491882 50 while(serial->readable()) serial->getc();
kb10uy 13:e11380ceb460 51 }
kb10uy 13:e11380ceb460 52
kb10uy 13:e11380ceb460 53 void FMOscillator::getMIDIMessage()
kb10uy 11:62da91a1eaf1 54 {
kb10uy 13:e11380ceb460 55 unsigned char st = serial->getc();
kb10uy 11:62da91a1eaf1 56 switch(st >> 4) {
kb10uy 11:62da91a1eaf1 57 case 0x8:
kb10uy 14:06785925915e 58 midiNoteOff(st & 0xf, serial->getc(), serial->getc());
kb10uy 11:62da91a1eaf1 59 break;
kb10uy 11:62da91a1eaf1 60 case 0x9:
kb10uy 14:06785925915e 61 midiNoteOn(st & 0xf, serial->getc(), serial->getc());
kb10uy 11:62da91a1eaf1 62 break;
kb10uy 11:62da91a1eaf1 63 case 0xa:
kb10uy 14:06785925915e 64 midiPolyphonicKeyPressure(st & 0xf, serial->getc(), serial->getc());
kb10uy 11:62da91a1eaf1 65 break;
kb10uy 11:62da91a1eaf1 66 case 0xb:
kb10uy 15:b03677948732 67 char b2 = serial->getc();
kb10uy 11:62da91a1eaf1 68 if (b2 >= 120) {
kb10uy 14:06785925915e 69 midiChannelMode(st & 0xf, b2, serial->getc());
kb10uy 11:62da91a1eaf1 70 } else {
kb10uy 14:06785925915e 71 midiControlChange(st & 0xf, b2, serial->getc());
kb10uy 11:62da91a1eaf1 72 }
kb10uy 11:62da91a1eaf1 73 break;
kb10uy 11:62da91a1eaf1 74 case 0xc:
kb10uy 14:06785925915e 75 midiProgramChange(st & 0xf, serial->getc());
kb10uy 11:62da91a1eaf1 76 break;
kb10uy 11:62da91a1eaf1 77 case 0xd:
kb10uy 14:06785925915e 78 midiChannelPressure(st & 0xf, serial->getc());
kb10uy 11:62da91a1eaf1 79 break;
kb10uy 11:62da91a1eaf1 80 case 0xe:
kb10uy 14:06785925915e 81 char LSB = serial->getc();
kb10uy 14:06785925915e 82 char MSB = serial->getc();
kb10uy 11:62da91a1eaf1 83 midiPitchBend(st & 0xf, ((LSB << 7) | (MSB << 7)) + 8192);
kb10uy 11:62da91a1eaf1 84 break;
kb10uy 11:62da91a1eaf1 85 case 0xf:
kb10uy 11:62da91a1eaf1 86 int t2 = st & 0xf;
kb10uy 11:62da91a1eaf1 87 if (t2 <= 7) {
kb10uy 11:62da91a1eaf1 88 getMIDISystemCommonMessage(t2);
kb10uy 11:62da91a1eaf1 89 } else {
kb10uy 11:62da91a1eaf1 90 midiSystemRealtimeMessage(st);
kb10uy 11:62da91a1eaf1 91 }
kb10uy 11:62da91a1eaf1 92 break;
kb10uy 11:62da91a1eaf1 93 }
kb10uy 11:62da91a1eaf1 94 }
kb10uy 11:62da91a1eaf1 95
kb10uy 13:e11380ceb460 96 void FMOscillator::getMIDISystemCommonMessage(char t2)
kb10uy 11:62da91a1eaf1 97 {
kb10uy 11:62da91a1eaf1 98 switch(t2) {
kb10uy 11:62da91a1eaf1 99 case 0:
kb10uy 11:62da91a1eaf1 100 //もう面倒臭いから128byteのバッファに適当に放り込んでおこう
kb10uy 11:62da91a1eaf1 101 sysexData[0] = 0xf0;
kb10uy 11:62da91a1eaf1 102 int i = 1;
kb10uy 11:62da91a1eaf1 103 char d = 0;
kb10uy 11:62da91a1eaf1 104 do {
kb10uy 13:e11380ceb460 105 d = serial->getc();
kb10uy 11:62da91a1eaf1 106 sysexData[i]=d;
kb10uy 11:62da91a1eaf1 107 i++;
kb10uy 11:62da91a1eaf1 108 } while(d != 0xf7);
kb10uy 11:62da91a1eaf1 109
kb10uy 11:62da91a1eaf1 110 break;
kb10uy 11:62da91a1eaf1 111 case 1:
kb10uy 13:e11380ceb460 112 serial->getc();
kb10uy 11:62da91a1eaf1 113 break;
kb10uy 11:62da91a1eaf1 114 case 2:
kb10uy 15:b03677948732 115 serial->getc();
kb10uy 15:b03677948732 116 serial->getc();
kb10uy 11:62da91a1eaf1 117 break;
kb10uy 11:62da91a1eaf1 118 case 3:
kb10uy 15:b03677948732 119 serial->getc();
kb10uy 11:62da91a1eaf1 120 break;
kb10uy 11:62da91a1eaf1 121 case 4:
kb10uy 11:62da91a1eaf1 122 break;
kb10uy 11:62da91a1eaf1 123 case 5:
kb10uy 11:62da91a1eaf1 124 break;
kb10uy 11:62da91a1eaf1 125 case 6:
kb10uy 11:62da91a1eaf1 126 break;
kb10uy 11:62da91a1eaf1 127 case 7:
kb10uy 11:62da91a1eaf1 128 //どうしろと
kb10uy 11:62da91a1eaf1 129 break;
kb10uy 11:62da91a1eaf1 130 }
kb10uy 11:62da91a1eaf1 131 }
kb10uy 11:62da91a1eaf1 132
kb10uy 13:e11380ceb460 133 void FMOscillator::midiSystemRealtimeMessage(char mes)
kb10uy 11:62da91a1eaf1 134 {
kb10uy 11:62da91a1eaf1 135
kb10uy 11:62da91a1eaf1 136 }
kb10uy 11:62da91a1eaf1 137
kb10uy 11:62da91a1eaf1 138
kb10uy 13:e11380ceb460 139 void FMOscillator::midiNoteOn(char ch, char note, char vel)
kb10uy 11:62da91a1eaf1 140 {
kb10uy 16:5cfa8b491882 141 lcd->cls();
kb10uy 16:5cfa8b491882 142 lcd->printf("Note On\n");
kb10uy 16:5cfa8b491882 143 lcd->printf("%1x: %2x,%2x", ch, note, vel);
kb10uy 11:62da91a1eaf1 144 if (vel==0) {
kb10uy 13:e11380ceb460 145 //globalrelease((ch<<8)|note);
kb10uy 11:62da91a1eaf1 146 } else {
kb10uy 13:e11380ceb460 147 //globalattack((ch<<8)|note,vel);
kb10uy 11:62da91a1eaf1 148 }
kb10uy 11:62da91a1eaf1 149 }
kb10uy 11:62da91a1eaf1 150
kb10uy 13:e11380ceb460 151 void FMOscillator::midiNoteOff(char ch, char note, char vel)
kb10uy 11:62da91a1eaf1 152 {
kb10uy 16:5cfa8b491882 153 lcd->cls();
kb10uy 16:5cfa8b491882 154 lcd->printf("Note Off\n");
kb10uy 16:5cfa8b491882 155 lcd->printf("%1x: %2x,%2x", ch, note, vel);
kb10uy 13:e11380ceb460 156 //globalrelease((ch<<8)|note);
kb10uy 11:62da91a1eaf1 157 }
kb10uy 11:62da91a1eaf1 158
kb10uy 13:e11380ceb460 159 void FMOscillator::midiPolyphonicKeyPressure(char ch, char note, char vel)
kb10uy 11:62da91a1eaf1 160 {
kb10uy 11:62da91a1eaf1 161
kb10uy 11:62da91a1eaf1 162 }
kb10uy 11:62da91a1eaf1 163
kb10uy 13:e11380ceb460 164 void FMOscillator::midiControlChange(char ch, char ctrl, char data)
kb10uy 11:62da91a1eaf1 165 {
kb10uy 17:2e577c6000cf 166 switch(ctrl) {
kb10uy 17:2e577c6000cf 167 //bank select
kb10uy 17:2e577c6000cf 168 case 0x00:
kb10uy 17:2e577c6000cf 169 break;
kb10uy 17:2e577c6000cf 170 case 0x20:
kb10uy 17:2e577c6000cf 171 break;
kb10uy 11:62da91a1eaf1 172
kb10uy 17:2e577c6000cf 173 //modulation
kb10uy 17:2e577c6000cf 174 case 0x01:
kb10uy 17:2e577c6000cf 175 channels[ch]->setModulationMSB(data);
kb10uy 17:2e577c6000cf 176 break;
kb10uy 17:2e577c6000cf 177 case 0x21:
kb10uy 17:2e577c6000cf 178 //channels[ch]->setModulationLSB(data);
kb10uy 17:2e577c6000cf 179 break;
kb10uy 17:2e577c6000cf 180
kb10uy 17:2e577c6000cf 181 //portamento time
kb10uy 17:2e577c6000cf 182 case 0x05:
kb10uy 17:2e577c6000cf 183 channels[ch]->setPortamentoTime(data);
kb10uy 17:2e577c6000cf 184 break;
kb10uy 17:2e577c6000cf 185 case 0x25:
kb10uy 17:2e577c6000cf 186 break;
kb10uy 17:2e577c6000cf 187
kb10uy 17:2e577c6000cf 188 //Volume
kb10uy 17:2e577c6000cf 189 case 0x07:
kb10uy 17:2e577c6000cf 190 channels[ch]->setVolume(data);
kb10uy 17:2e577c6000cf 191 break;
kb10uy 17:2e577c6000cf 192 case 0x37:
kb10uy 17:2e577c6000cf 193 break;
kb10uy 17:2e577c6000cf 194
kb10uy 17:2e577c6000cf 195 //balance
kb10uy 17:2e577c6000cf 196 case 0x08:
kb10uy 17:2e577c6000cf 197 break;
kb10uy 17:2e577c6000cf 198 case 0x28:
kb10uy 17:2e577c6000cf 199 break;
kb10uy 17:2e577c6000cf 200
kb10uy 17:2e577c6000cf 201 //panpot
kb10uy 17:2e577c6000cf 202 case 0x0a:
kb10uy 17:2e577c6000cf 203 channels[ch]->setPanpot(data);
kb10uy 17:2e577c6000cf 204 break;
kb10uy 17:2e577c6000cf 205 case 0x2a:
kb10uy 17:2e577c6000cf 206 break;
kb10uy 17:2e577c6000cf 207
kb10uy 17:2e577c6000cf 208 //expression
kb10uy 17:2e577c6000cf 209 case 0x0b:
kb10uy 17:2e577c6000cf 210 channels[ch]->setExpression(data);
kb10uy 17:2e577c6000cf 211 break;
kb10uy 17:2e577c6000cf 212 case 0x2b:
kb10uy 17:2e577c6000cf 213 break;
kb10uy 17:2e577c6000cf 214
kb10uy 17:2e577c6000cf 215 //hold1
kb10uy 17:2e577c6000cf 216 case 0x40:
kb10uy 17:2e577c6000cf 217 if (data > 0x40) {
kb10uy 17:2e577c6000cf 218 channels[ch]->startHold1();
kb10uy 17:2e577c6000cf 219 } else {
kb10uy 17:2e577c6000cf 220 channels[ch]->endHold1();
kb10uy 17:2e577c6000cf 221 }
kb10uy 17:2e577c6000cf 222 break;
kb10uy 17:2e577c6000cf 223
kb10uy 17:2e577c6000cf 224 //portamento
kb10uy 17:2e577c6000cf 225 case 0x41:
kb10uy 17:2e577c6000cf 226 channels[ch]->setPortamentoSwitch(data > 0x40);
kb10uy 17:2e577c6000cf 227 break;
kb10uy 17:2e577c6000cf 228
kb10uy 17:2e577c6000cf 229 //data entry
kb10uy 17:2e577c6000cf 230 case 0x06:
kb10uy 17:2e577c6000cf 231 channels[ch]->setDataEntryMSB(data);
kb10uy 17:2e577c6000cf 232 break;
kb10uy 17:2e577c6000cf 233 case 0x26:
kb10uy 17:2e577c6000cf 234 channels[ch]->setDataEntryLSB(data);
kb10uy 17:2e577c6000cf 235 break;
kb10uy 17:2e577c6000cf 236
kb10uy 17:2e577c6000cf 237 //nrpn
kb10uy 17:2e577c6000cf 238 case 0x63:
kb10uy 17:2e577c6000cf 239 channels[ch]->setNRPNMSB(data);
kb10uy 17:2e577c6000cf 240 break;
kb10uy 17:2e577c6000cf 241 case 0x62:
kb10uy 17:2e577c6000cf 242 channels[ch]->setNRPNLSB(data);
kb10uy 17:2e577c6000cf 243 break;
kb10uy 17:2e577c6000cf 244
kb10uy 17:2e577c6000cf 245 //rpn
kb10uy 17:2e577c6000cf 246 case 0x65:
kb10uy 17:2e577c6000cf 247 channels[ch]->setRPNMSB(data);
kb10uy 17:2e577c6000cf 248 break;
kb10uy 17:2e577c6000cf 249 case 0x64:
kb10uy 17:2e577c6000cf 250 channels[ch]->setRPNLSB(data);
kb10uy 17:2e577c6000cf 251 break;
kb10uy 17:2e577c6000cf 252 }
kb10uy 11:62da91a1eaf1 253 }
kb10uy 11:62da91a1eaf1 254
kb10uy 13:e11380ceb460 255 void FMOscillator::midiChannelMode(char ch, char ctrl, char data)
kb10uy 11:62da91a1eaf1 256 {
kb10uy 17:2e577c6000cf 257 switch(ctrl) {
kb10uy 17:2e577c6000cf 258 case 0x78:
kb10uy 17:2e577c6000cf 259 channels[ch]->allSoundOff();
kb10uy 17:2e577c6000cf 260 break;
kb10uy 17:2e577c6000cf 261
kb10uy 17:2e577c6000cf 262 case 0x7b:
kb10uy 17:2e577c6000cf 263 case 0x7c:
kb10uy 17:2e577c6000cf 264 case 0x7d:
kb10uy 17:2e577c6000cf 265 channels[ch]->allNoteOff();
kb10uy 17:2e577c6000cf 266 break;
kb10uy 17:2e577c6000cf 267 }
kb10uy 11:62da91a1eaf1 268 }
kb10uy 11:62da91a1eaf1 269
kb10uy 13:e11380ceb460 270 void FMOscillator::midiProgramChange(char ch, char prg)
kb10uy 11:62da91a1eaf1 271 {
kb10uy 11:62da91a1eaf1 272
kb10uy 11:62da91a1eaf1 273 }
kb10uy 11:62da91a1eaf1 274
kb10uy 13:e11380ceb460 275 void FMOscillator::midiChannelPressure(char ch, char pres)
kb10uy 11:62da91a1eaf1 276 {
kb10uy 11:62da91a1eaf1 277
kb10uy 11:62da91a1eaf1 278 }
kb10uy 11:62da91a1eaf1 279
kb10uy 13:e11380ceb460 280 void FMOscillator::midiPitchBend(char ch, short pb)
kb10uy 11:62da91a1eaf1 281 {
kb10uy 11:62da91a1eaf1 282
kb10uy 11:62da91a1eaf1 283 }
kb10uy 11:62da91a1eaf1 284
kb10uy 13:e11380ceb460 285 void FMOscillator::midiSystemExclusiveMessage()
kb10uy 11:62da91a1eaf1 286 {
kb10uy 11:62da91a1eaf1 287
kb10uy 11:62da91a1eaf1 288 }