Nucleo F401REでFM音源を実装するやつ 外部DACとオペアンプを利用 現在はMCP4922とNJM2737
Dependencies: AOTTrigon I2CEEPROM MCP4922 AQM0802A mbed
Fork of NuMidi401 by
NuFM401
Nucleo F401用の自作ソフトウェアMIDI音源
概要
だいたいそんなもんです。
特徴
- ブレッドボードの上で組める程度には簡単な回路構成
- 外部のDACにMCP4922を採用
- 念のためのボルテージフォロアとしてNJM2737Dを採用
- バンク用EEPROMに24FC1025を採用
- シリアル経由でMIDIデータを受信することで操作
補足
シリアル <=> MIDI のドライバにはHairless-MIDISerialをオススメします。 仮想MIDIケーブルはとりあえずMIDI Yokeで。
FMOscillator/FMOscillator.cpp@16:5cfa8b491882, 2015-01-26 (annotated)
- Committer:
- kb10uy
- Date:
- Mon Jan 26 13:26:34 2015 +0000
- Revision:
- 16:5cfa8b491882
- Parent:
- 15:b03677948732
- Child:
- 17:2e577c6000cf
LCD?????????????????????
Who changed what in which revision?
User | Revision | Line number | New 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 | 13:e11380ceb460 | 5 | FMOscillator::FMOscillator() { |
kb10uy | 13:e11380ceb460 | 6 | |
kb10uy | 13:e11380ceb460 | 7 | } |
kb10uy | 13:e11380ceb460 | 8 | |
kb10uy | 16:5cfa8b491882 | 9 | FMOscillator::FMOscillator(int opc, Timer *tim, Serial *ser, AOTTrigon *tri, I2C *i2clcd) { |
kb10uy | 16:5cfa8b491882 | 10 | master = tim; |
kb10uy | 16:5cfa8b491882 | 11 | serial = ser; |
kb10uy | 16:5cfa8b491882 | 12 | trigon = tri; |
kb10uy | 16:5cfa8b491882 | 13 | opcount = opc; |
kb10uy | 16:5cfa8b491882 | 14 | |
kb10uy | 16:5cfa8b491882 | 15 | operators = new FMOperator*[opcount]; |
kb10uy | 16:5cfa8b491882 | 16 | for(int i = 0; i < opcount; i++) { |
kb10uy | 16:5cfa8b491882 | 17 | operators[i] = new FMOperator(master, trigon); |
kb10uy | 16:5cfa8b491882 | 18 | } |
kb10uy | 16:5cfa8b491882 | 19 | lcd = new AQM0802A(*i2clcd); |
kb10uy | 16:5cfa8b491882 | 20 | |
kb10uy | 16:5cfa8b491882 | 21 | serial->baud(256000); |
kb10uy | 16:5cfa8b491882 | 22 | serial->format(); |
kb10uy | 16:5cfa8b491882 | 23 | serial->attach(this, &FMOscillator::midiReceived); |
kb10uy | 16:5cfa8b491882 | 24 | master->start(); |
kb10uy | 13:e11380ceb460 | 25 | |
kb10uy | 16:5cfa8b491882 | 26 | lcd->cls(); |
kb10uy | 16:5cfa8b491882 | 27 | lcd->printf("NuFM401\nFMDriver"); |
kb10uy | 16:5cfa8b491882 | 28 | } |
kb10uy | 16:5cfa8b491882 | 29 | |
kb10uy | 16:5cfa8b491882 | 30 | FMOscillator::~FMOscillator() { |
kb10uy | 16:5cfa8b491882 | 31 | for(int i = 0; i < opcount; i++) { |
kb10uy | 16:5cfa8b491882 | 32 | delete operators[i]; |
kb10uy | 16:5cfa8b491882 | 33 | } |
kb10uy | 16:5cfa8b491882 | 34 | delete operators; |
kb10uy | 16:5cfa8b491882 | 35 | delete lcd; |
kb10uy | 16:5cfa8b491882 | 36 | } |
kb10uy | 16:5cfa8b491882 | 37 | |
kb10uy | 16:5cfa8b491882 | 38 | void FMOscillator::midiReceived() |
kb10uy | 16:5cfa8b491882 | 39 | { |
kb10uy | 16:5cfa8b491882 | 40 | getMIDIMessage(); |
kb10uy | 16:5cfa8b491882 | 41 | while(serial->readable()) serial->getc(); |
kb10uy | 13:e11380ceb460 | 42 | } |
kb10uy | 13:e11380ceb460 | 43 | |
kb10uy | 13:e11380ceb460 | 44 | void FMOscillator::getMIDIMessage() |
kb10uy | 11:62da91a1eaf1 | 45 | { |
kb10uy | 13:e11380ceb460 | 46 | unsigned char st = serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 47 | switch(st >> 4) { |
kb10uy | 11:62da91a1eaf1 | 48 | case 0x8: |
kb10uy | 14:06785925915e | 49 | midiNoteOff(st & 0xf, serial->getc(), serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 50 | break; |
kb10uy | 11:62da91a1eaf1 | 51 | case 0x9: |
kb10uy | 14:06785925915e | 52 | midiNoteOn(st & 0xf, serial->getc(), serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 53 | break; |
kb10uy | 11:62da91a1eaf1 | 54 | case 0xa: |
kb10uy | 14:06785925915e | 55 | midiPolyphonicKeyPressure(st & 0xf, serial->getc(), serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 56 | break; |
kb10uy | 11:62da91a1eaf1 | 57 | case 0xb: |
kb10uy | 15:b03677948732 | 58 | char b2 = serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 59 | if (b2 >= 120) { |
kb10uy | 14:06785925915e | 60 | midiChannelMode(st & 0xf, b2, serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 61 | } else { |
kb10uy | 14:06785925915e | 62 | midiControlChange(st & 0xf, b2, serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 63 | } |
kb10uy | 11:62da91a1eaf1 | 64 | break; |
kb10uy | 11:62da91a1eaf1 | 65 | case 0xc: |
kb10uy | 14:06785925915e | 66 | midiProgramChange(st & 0xf, serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 67 | break; |
kb10uy | 11:62da91a1eaf1 | 68 | case 0xd: |
kb10uy | 14:06785925915e | 69 | midiChannelPressure(st & 0xf, serial->getc()); |
kb10uy | 11:62da91a1eaf1 | 70 | break; |
kb10uy | 11:62da91a1eaf1 | 71 | case 0xe: |
kb10uy | 14:06785925915e | 72 | char LSB = serial->getc(); |
kb10uy | 14:06785925915e | 73 | char MSB = serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 74 | midiPitchBend(st & 0xf, ((LSB << 7) | (MSB << 7)) + 8192); |
kb10uy | 11:62da91a1eaf1 | 75 | break; |
kb10uy | 11:62da91a1eaf1 | 76 | case 0xf: |
kb10uy | 11:62da91a1eaf1 | 77 | int t2 = st & 0xf; |
kb10uy | 11:62da91a1eaf1 | 78 | if (t2 <= 7) { |
kb10uy | 11:62da91a1eaf1 | 79 | getMIDISystemCommonMessage(t2); |
kb10uy | 11:62da91a1eaf1 | 80 | } else { |
kb10uy | 11:62da91a1eaf1 | 81 | midiSystemRealtimeMessage(st); |
kb10uy | 11:62da91a1eaf1 | 82 | } |
kb10uy | 11:62da91a1eaf1 | 83 | break; |
kb10uy | 11:62da91a1eaf1 | 84 | } |
kb10uy | 11:62da91a1eaf1 | 85 | } |
kb10uy | 11:62da91a1eaf1 | 86 | |
kb10uy | 13:e11380ceb460 | 87 | void FMOscillator::getMIDISystemCommonMessage(char t2) |
kb10uy | 11:62da91a1eaf1 | 88 | { |
kb10uy | 11:62da91a1eaf1 | 89 | switch(t2) { |
kb10uy | 11:62da91a1eaf1 | 90 | case 0: |
kb10uy | 11:62da91a1eaf1 | 91 | //もう面倒臭いから128byteのバッファに適当に放り込んでおこう |
kb10uy | 11:62da91a1eaf1 | 92 | sysexData[0] = 0xf0; |
kb10uy | 11:62da91a1eaf1 | 93 | int i = 1; |
kb10uy | 11:62da91a1eaf1 | 94 | char d = 0; |
kb10uy | 11:62da91a1eaf1 | 95 | do { |
kb10uy | 13:e11380ceb460 | 96 | d = serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 97 | sysexData[i]=d; |
kb10uy | 11:62da91a1eaf1 | 98 | i++; |
kb10uy | 11:62da91a1eaf1 | 99 | } while(d != 0xf7); |
kb10uy | 11:62da91a1eaf1 | 100 | |
kb10uy | 11:62da91a1eaf1 | 101 | break; |
kb10uy | 11:62da91a1eaf1 | 102 | case 1: |
kb10uy | 13:e11380ceb460 | 103 | serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 104 | break; |
kb10uy | 11:62da91a1eaf1 | 105 | case 2: |
kb10uy | 15:b03677948732 | 106 | serial->getc(); |
kb10uy | 15:b03677948732 | 107 | serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 108 | break; |
kb10uy | 11:62da91a1eaf1 | 109 | case 3: |
kb10uy | 15:b03677948732 | 110 | serial->getc(); |
kb10uy | 11:62da91a1eaf1 | 111 | break; |
kb10uy | 11:62da91a1eaf1 | 112 | case 4: |
kb10uy | 11:62da91a1eaf1 | 113 | break; |
kb10uy | 11:62da91a1eaf1 | 114 | case 5: |
kb10uy | 11:62da91a1eaf1 | 115 | break; |
kb10uy | 11:62da91a1eaf1 | 116 | case 6: |
kb10uy | 11:62da91a1eaf1 | 117 | break; |
kb10uy | 11:62da91a1eaf1 | 118 | case 7: |
kb10uy | 11:62da91a1eaf1 | 119 | //どうしろと |
kb10uy | 11:62da91a1eaf1 | 120 | break; |
kb10uy | 11:62da91a1eaf1 | 121 | } |
kb10uy | 11:62da91a1eaf1 | 122 | } |
kb10uy | 11:62da91a1eaf1 | 123 | |
kb10uy | 13:e11380ceb460 | 124 | void FMOscillator::midiSystemRealtimeMessage(char mes) |
kb10uy | 11:62da91a1eaf1 | 125 | { |
kb10uy | 11:62da91a1eaf1 | 126 | |
kb10uy | 11:62da91a1eaf1 | 127 | } |
kb10uy | 11:62da91a1eaf1 | 128 | |
kb10uy | 11:62da91a1eaf1 | 129 | |
kb10uy | 13:e11380ceb460 | 130 | void FMOscillator::midiNoteOn(char ch, char note, char vel) |
kb10uy | 11:62da91a1eaf1 | 131 | { |
kb10uy | 16:5cfa8b491882 | 132 | lcd->cls(); |
kb10uy | 16:5cfa8b491882 | 133 | lcd->printf("Note On\n"); |
kb10uy | 16:5cfa8b491882 | 134 | lcd->printf("%1x: %2x,%2x", ch, note, vel); |
kb10uy | 11:62da91a1eaf1 | 135 | if (vel==0) { |
kb10uy | 13:e11380ceb460 | 136 | //globalrelease((ch<<8)|note); |
kb10uy | 11:62da91a1eaf1 | 137 | } else { |
kb10uy | 13:e11380ceb460 | 138 | //globalattack((ch<<8)|note,vel); |
kb10uy | 11:62da91a1eaf1 | 139 | } |
kb10uy | 11:62da91a1eaf1 | 140 | } |
kb10uy | 11:62da91a1eaf1 | 141 | |
kb10uy | 13:e11380ceb460 | 142 | void FMOscillator::midiNoteOff(char ch, char note, char vel) |
kb10uy | 11:62da91a1eaf1 | 143 | { |
kb10uy | 16:5cfa8b491882 | 144 | lcd->cls(); |
kb10uy | 16:5cfa8b491882 | 145 | lcd->printf("Note Off\n"); |
kb10uy | 16:5cfa8b491882 | 146 | lcd->printf("%1x: %2x,%2x", ch, note, vel); |
kb10uy | 13:e11380ceb460 | 147 | //globalrelease((ch<<8)|note); |
kb10uy | 11:62da91a1eaf1 | 148 | } |
kb10uy | 11:62da91a1eaf1 | 149 | |
kb10uy | 13:e11380ceb460 | 150 | void FMOscillator::midiPolyphonicKeyPressure(char ch, char note, char vel) |
kb10uy | 11:62da91a1eaf1 | 151 | { |
kb10uy | 11:62da91a1eaf1 | 152 | |
kb10uy | 11:62da91a1eaf1 | 153 | } |
kb10uy | 11:62da91a1eaf1 | 154 | |
kb10uy | 13:e11380ceb460 | 155 | void FMOscillator::midiControlChange(char ch, char ctrl, char data) |
kb10uy | 11:62da91a1eaf1 | 156 | { |
kb10uy | 11:62da91a1eaf1 | 157 | |
kb10uy | 11:62da91a1eaf1 | 158 | } |
kb10uy | 11:62da91a1eaf1 | 159 | |
kb10uy | 13:e11380ceb460 | 160 | void FMOscillator::midiChannelMode(char ch, char ctrl, char data) |
kb10uy | 11:62da91a1eaf1 | 161 | { |
kb10uy | 11:62da91a1eaf1 | 162 | |
kb10uy | 11:62da91a1eaf1 | 163 | } |
kb10uy | 11:62da91a1eaf1 | 164 | |
kb10uy | 13:e11380ceb460 | 165 | void FMOscillator::midiProgramChange(char ch, char prg) |
kb10uy | 11:62da91a1eaf1 | 166 | { |
kb10uy | 11:62da91a1eaf1 | 167 | |
kb10uy | 11:62da91a1eaf1 | 168 | } |
kb10uy | 11:62da91a1eaf1 | 169 | |
kb10uy | 13:e11380ceb460 | 170 | void FMOscillator::midiChannelPressure(char ch, char pres) |
kb10uy | 11:62da91a1eaf1 | 171 | { |
kb10uy | 11:62da91a1eaf1 | 172 | |
kb10uy | 11:62da91a1eaf1 | 173 | } |
kb10uy | 11:62da91a1eaf1 | 174 | |
kb10uy | 13:e11380ceb460 | 175 | void FMOscillator::midiPitchBend(char ch, short pb) |
kb10uy | 11:62da91a1eaf1 | 176 | { |
kb10uy | 11:62da91a1eaf1 | 177 | |
kb10uy | 11:62da91a1eaf1 | 178 | } |
kb10uy | 11:62da91a1eaf1 | 179 | |
kb10uy | 13:e11380ceb460 | 180 | void FMOscillator::midiSystemExclusiveMessage() |
kb10uy | 11:62da91a1eaf1 | 181 | { |
kb10uy | 11:62da91a1eaf1 | 182 | |
kb10uy | 11:62da91a1eaf1 | 183 | } |