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:
Sat Jan 31 10:54:13 2015 +0000
Revision:
24:f93b49b4cd66
Parent:
23:deb76bdf6f03
NRPN 20h xxh???

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