12-polyphonic "chiptune" MIDI synthesizer for LPC1768 (Standalone version)
Dependencies: ClockControl PowerControl mbed
main.cpp
- Committer:
- kayekss
- Date:
- 2014-11-12
- Revision:
- 2:ca10e33bde0a
- Parent:
- 1:5f0c89bffec1
- Child:
- 3:cf57d7031c12
File content as of revision 2:ca10e33bde0a:
#include "mbed.h" #include "ClockControl.h" #include "EthernetPowerControl.h" #include "PowerControl.h" #include "defs.h" #include "Channels.h" #include "GeminiCore.h" #include "RingBuffer.h" #include "debug.h" #include "events.h" #include "note.h" #include "parser.h" Serial pc(/*Tx*/ USBTX, /*Rx*/ USBRX); Serial midiIn(/*Tx*/ p13, /*Rx*/ p14); Serial console(/*Tx*/ p28, /*Rx*/ p27); DigitalIn swSerialSelect(p12); DigitalIn swPanic(p15); BusOut led(/*Left*/ LED1, LED2, LED3, LED4 /*Right*/); BusOut ledBar(p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p29, p30); SPI spi(/*MOSI*/ p5, /*MISO*/ p6, /*SCK*/ p7); DigitalOut dacCs(p8); Ticker t1ms; Ticker tSample; volatile uint32_t __countMs; bool serSource; GeminiCore gemCore(NUM_INSTRUMENT_IN_PERFORMER); RingBuffer<char> buffer(BUFFER_LENGTH); Channels ch; note_t noteSent[NUM_INSTRUMENT]; uint32_t receivedBytes; dumpmode_t dumpMode; void sampleOut() { dacCs = 0; spi.write(0x3000 | gemCore.makeSample(noteSent) >> 4); dacCs = 1; } void count1ms() { __countMs++; } void readMidiIn() { char c; // Put a MIDI input byte into buffer if available if ((serSource ? midiIn : pc).readable()) { c = (serSource ? midiIn : pc).getc(); receivedBytes++; // Discard if input byte is an active sensing message if (c != 0xfe) { buffer.write(c); } } } void setup() { #ifdef POWER_SAVE // Power down Ethernet PHY chip PHY_PowerDown(); // Power down unused peripherals Peripheral_PowerDown(0x40067200); #endif #if defined(POWER_SAVE) && defined(CLOCKUP) // Change clock speed to 120 MHz setSystemFrequency(0x03, 0x01, 15, 1); #endif // Enable pull-up at switch inputs swSerialSelect.mode(PullDown); swPanic.mode(PullUp); wait(0.2); // Wait a moment for stability // Read serial selector switch serSource = swSerialSelect; // Open selected port if (serSource) { // Use MIDI port when high midiIn.baud(31250); midiIn.format(8, Serial::None, 1); midiIn.attach(readMidiIn, Serial::RxIrq); } else { // Use serial MIDI when low pc.baud(38400); pc.format(8, Serial::None, 1); pc.attach(readMidiIn, Serial::RxIrq); } receivedBytes = 0; // Setup console console.baud(115200); console.format(8, Serial::None, 1); dumpMode = DUMP_NOTHING; // Setup SPI spi.format(16, 0); spi.frequency(12000000); dacCs = 1; // Initialize channels ch.initializeAll(); // Initialize note status for (uint16_t i = 0; i < NUM_INSTRUMENT; i++) { noteSent[i].noteOnMs = 0; noteSent[i].channel = 0; noteSent[i].noteNumber = 0; noteSent[i].velocity = 0; } // Start Timer __countMs = 0; t1ms.attach_us(&count1ms, 1000); // Start playback & attach interrupt float clockUpRatio = SystemCoreClock / 96000000.0; tSample.attach_us(&sampleOut, 1000000 * clockUpRatio / GeminiCore::samplingRate); } void consoleOperations(uint8_t c) { switch (c) { case 'b': checkBuffer(); break; case 'e': if (dumpMode != DUMP_EVENTS) { dumpMode = DUMP_EVENTS; } else { dumpMode = DUMP_NOTHING; } break; case 'f': buffer.flush(); console.printf("* Buffer flushed.\r\n"); break; case 'i': if (dumpMode == DUMP_INST) { dumpMode = DUMP_INST_DETAIL; } else if (dumpMode == DUMP_INST_DETAIL) { dumpMode = DUMP_NOTHING; } else { dumpMode = DUMP_INST; } break; case 'p': // Panic for (uint8_t i = 0; i < NUM_INSTRUMENT_IN_PERFORMER; i++) { gemCore.noteOff(i); noteSent[i].noteOnMs = 0; noteSent[i].channel = 0; noteSent[i].noteNumber = 0; noteSent[i].velocity = 0; } break; case 'r': console.printf("* Received MIDI bytes: %u\r\n", receivedBytes); break; default: break; } } void loop() { static uint32_t lastPollSwitchMs = __countMs; static bool prevstatePanic = 0; bool statePanic; // Serial console if (console.readable()) { consoleOperations(console.getc()); } // Poll switches if (__countMs > lastPollSwitchMs + 20) { lastPollSwitchMs = __countMs; statePanic = swPanic; // Panic (all note off and flush buffer) if (!statePanic && prevstatePanic) { buffer.flush(); for (uint8_t i = 0; i < NUM_INSTRUMENT_IN_PERFORMER; i++) { gemCore.noteOff(i); noteSent[i].noteOnMs = 0; noteSent[i].channel = 0; noteSent[i].noteNumber = 0; noteSent[i].velocity = 0; } } // Preserve this time's switch states prevstatePanic = statePanic; } // Parse MIDI messages parseMessage(buffer); // LEDs uint8_t busyCount = 0; for (uint8_t i = 0; i < NUM_INSTRUMENT_IN_PERFORMER; i++) { if (noteSent[i].noteOnMs) { busyCount++; } } ledBar = (1 << busyCount) - 1; } int main() { setup(); while (1) { loop(); } }