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で。

FMOscillator/MIDIChannel.cpp

Committer:
kb10uy
Date:
2015-01-31
Revision:
24:f93b49b4cd66
Parent:
23:deb76bdf6f03

File content as of revision 24:f93b49b4cd66:

#include "MIDIChannel.h"

MIDIChannel::MIDIChannel()
{

}

MIDIChannel::MIDIChannel(AQM0802A *l, Timer *tm, AOTTrigon *tri)
{
    modulation = 0;
    portamentoTime = 0;
    portamento = false;
    volume = 127;
    panpot = 64;
    expression = 127;
    hold1 = false;
    dataEntryMSB = 0;
    dataEntryLSB = 0;
    nrpnMSB = 0;
    nrpnLSB = 0;
    rpnMSB = 0;
    rpnLSB = 0;
    algo = NULL;
    state = Undefined;
    lcd = l;
    nrpnStateSetter.attach(this, &MIDIChannel::setStateNRPNUndefined);
    nrpnStateProcessor.attach(this, &MIDIChannel::nrpnUndefined);
}

MIDIChannel::~MIDIChannel()
{
    if (algo != NULL) delete algo;
}

void MIDIChannel::noteOn(char key, char vel, double time) {
    prkey = key;
    algo->noteOn(getNoteNumberFrequency(prkey), time);
}

void MIDIChannel::noteOff(char key, double time) {
    if (prkey != key) return;
    algo->noteOff(time);
}

void MIDIChannel::setDataEntryMSB(char msb)
{
    dataEntryMSB = msb;
    if (state == NRPNSingleData || state == RPNSingleData) nrpnStateProcessor.call();
}

void MIDIChannel::setDataEntryLSB(char lsb)
{
    dataEntryLSB = lsb;
    if (state == NRPNDoubleData || state == RPNDoubleData) nrpnStateProcessor.call();
}

void MIDIChannel::setNRPNMSB(char msb)
{
    nrpnMSB = msb;
    setNRPNFunctions();
}

void MIDIChannel::setNRPNLSB(char lsb)
{
    nrpnLSB = lsb;
    nrpnStateSetter.call();
    if (state == NRPNNoData) nrpnStateProcessor.call();
}

void MIDIChannel::setRPNMSB(char msb)
{
    rpnMSB = msb;
    if (msb == 0x7f) {
        state = RPNNoData;
    } else {
        state = RPNSingleData;
    }
}

void MIDIChannel::setRPNLSB(char lsb)
{
    rpnLSB = lsb;
    if (state == RPNNoData) processRPNFunction();
}

void MIDIChannel::allSoundOff()
{
}

void MIDIChannel::allNoteOff()
{
}

void MIDIChannel::processRPNFunction()
{
    switch(rpnMSB) {
        case 0x00:
            //LSB 0~2全部実装できないですから
            break;
        case 0x7f:
            if (rpnLSB == 0x7f) {
                rpnMSB = 0;
                rpnLSB = 0;
                nrpnMSB = 0;
                nrpnLSB = 0;
            }
            lcd->cls();
            lcd->printf("RPN/NRPN\nNULL");
            break;
    }
    state = Undefined;
}