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:
Thu Jan 29 11:05:37 2015 +0000
Revision:
19:f0dcf591c5dd
Parent:
18:b20fdf1da8f8
Child:
20:8278e607a687
delete?????; FMAlgorithm?????

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