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 13:25:14 2015 +0000
Revision:
18:b20fdf1da8f8
Parent:
17:2e577c6000cf
Child:
19:f0dcf591c5dd
?????????????

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