X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

main.cpp

Committer:
okini3939
Date:
2019-06-05
Revision:
1:0dac72ab5910
Parent:
0:0fd787d62a99

File content as of revision 1:0dac72ab5910:

/*
 * BEHRINGER X-TOUCH to DJAY bridge
 *   for mbed LPC1768
 *
 * X-TOUCH (MC/USB) <---USB---> LPC1768 <---UART MIDI---> MD-BT01 (YAMAHA, BLE MIDI)
 */

#include "mbed.h"
#include "USBHostHub.h"
#include "USBHostMIDI.h"
#include "MIDI.h"
#include "CBuffer.h"

Serial pc(USBTX, USBRX);
DigitalOut led1(LED1);
PwmOut led2(LED2), led3(LED3), led4(LED4);
USBHostHub hub;
USBHostMIDI midi;
MIDI midi2(p28, p27);

CircBuffer <uint32_t>midi_out(20);


void systemExclusive (uint8_t *buffer, uint16_t length, bool flag) {
    midi2.sendSysEx(length, buffer, flag);
}
void noteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
    midi_out.queue(((uint32_t)NoteOn << 24) | ((uint32_t)channel << 16) | (note << 8) | velocity);
}
void noteOff(uint8_t channel, uint8_t note, uint8_t velocity) {
    midi_out.queue(((uint32_t)NoteOff << 24) | ((uint32_t)channel << 16) | (note << 8) | velocity);
}
void controlChange(uint8_t channel, uint8_t key, uint8_t value) {
    midi_out.queue(((uint32_t)ControlChange << 24) | ((uint32_t)channel << 16) | (key << 8) | value);
}
void programChange (uint8_t channel, uint8_t progra) {
    midi_out.queue(((uint32_t)ProgramChange << 24) | ((uint32_t)channel << 16) | (progra << 8));
}
void pitchBend (uint8_t channel, uint16_t value) {
    midi_out.queue(((uint32_t)PitchBend << 24) | ((uint32_t)channel << 16) | value);
}


void printLcd (int x, int y, char *buf) {
    int i, len;
    uint8_t msg[40] = {0xf0, 0x00, 0x00, 0x66, 0x14,  0x12, 0x00};

    msg[6] = (7 * x) + (0x38 * y);
    len = 7;
    for (i = 0; i < strlen(buf); i ++) {
        msg[len ++] = buf[i];
    }
    msg[len ++] = 0xf7;
    midi.sendSystemExclusive(msg, len);
}

void midi_task(void const*) {
    int i;

//    hub = new USBHostHub;
//    midi = new USBHostMIDI;

    // attach midi event callbacks
    midi.attachSystemExclusive(systemExclusive);
    midi.attachNoteOn(noteOn);
    midi.attachNoteOff(noteOff);
    midi.attachControlChange(controlChange);
    midi.attachProgramChange(programChange);
    midi.attachPitchBend(pitchBend);
    
    pc.printf("begin\r\n");

    uint32_t m;
    int channel, data1, data2;
    for (;;) {
        // try to connect a midi device
        while(!midi.connect()) {
            Thread::wait(500);
            led1 = !led1;
        }
        Thread::wait(500);

        pc.printf("detected\r\n");
        for (i = 0; i < 9; i ++) {
            midi.sendPitchBend(i, 0); // fader 0
        }
        for (i = 0; i < 0x7f; i ++) {
            midi.sendNoteOn(0, i, 0); // led off
        }

        // LCD
        printLcd(0, 0, " High");
        printLcd(1, 0, "  Mid");
        printLcd(2, 0, "  Low");
        printLcd(3, 0, " Gain");
        printLcd(4, 0, " Gain");
        printLcd(5, 0, "  Low");
        printLcd(6, 0, "  Mid");
        printLcd(7, 0, " High");
        printLcd(2, 1, " Speed");
        printLcd(3, 1, "   1  <");
        printLcd(4, 1, ">  2   ");
        printLcd(5, 1, " Speed");
        // 7segment LED
        midi.sendControlChange(0, 0x43, 'D' & 0x1f);
        midi.sendControlChange(0, 0x42, 'J' & 0x1f);
        midi.sendControlChange(0, 0x41, 'A' & 0x1f);
        midi.sendControlChange(0, 0x40, 'Y' & 0x1f);

        led1 = 1;
        for (;;) {
            if (!midi.connected()) {
                pc.printf("disconnected\r\n");
                break;
            }

            if (!midi_out.isEmpty()) {
                // USB -> uart
                midi_out.dequeue(&m);
                channel = (m >> 16) & 0x7f;
                data1 = (m >> 8) & 0x7f;
                data2 = m & 0x7f;
                
                switch (m >> 24) {
                case NoteOn:
                    midi2.sendNoteOn(data1, data2, channel);
//                    pc.printf("noteOn %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case NoteOff:
                    midi2.sendNoteOff(data1, data2, channel);
//                    pc.printf("noteOff %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case ControlChange:
                    if ((data1 >= 0x10 && data1 <= 0x17) || data1 == 0x3c) {
                        midi2.sendControlChange(data1, data2 < 0x40 ? data2 : 0x80 - (data2 - 0x40), channel);
                    } else {
                        midi2.sendControlChange(data1, data2, channel);
                    }
//                    pc.printf("controlChange %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case ProgramChange:
                    midi2.sendProgramChange(data1, channel);
//                    pc.printf("programChange %02x %02x\r\n", channel, data1);
                    break;
                case PitchBend:
                    data1 = m & 0x3fff;
                    midi.sendPitchBend(channel, data1);
                    midi2.sendControlChange(channel, data1 >> 7, 0);
//                    pc.printf("pitchBend %02x %04x\r\n", channel, data1);
                    break;
                }
            }

            if (midi2.read()) {
                // uart -> USB
                channel = midi2.getChannel();
                data1 = midi2.getData1();
                data2 = midi2.getData2();

                switch (midi2.getType()) {
                case NoteOn:
                    midi.sendNoteOn(channel, data1, data2);
//                    pc.printf(" noteOn %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case NoteOff:
                    midi.sendNoteOff(channel, data1, data2);
//                    pc.printf(" noteOff %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case ControlChange:
                    if (data1 < 0x10) {
                        midi.sendPitchBend(data1, (data2 << 7) | data2);
                    } else
                    if (data1 >= 0x10 && data1 <= 0x17) {
                        midi.sendControlChange(channel, 0x30 | (data1 & 0x0f), (data2 * 0x0c) / 0x7f);
                    } else {
                        midi.sendControlChange(channel, data1, data2);
                    }
//                    pc.printf(" controlChange %02x %02x %02x\r\n", channel, data1, data2);
                    break;
                case ProgramChange:
                    midi.sendProgramChange(channel, data1);
//                    pc.printf(" programChange %02x %02x\r\n", channel, data1);
                    break;
                case PitchBend:
//                    pc.printf(" pitchBend %02x %04x\r\n", channel, data1);
                    break;
                case SystemExclusive:
                    midi.sendSystemExclusive((uint8_t *)midi2.getSysExArray(), midi2.getSysExArrayLength());
//                    pc.printf(" SystemExclusive\r\n");
                    break;
                }
            }
        }
    }
}

int main() {
    pc.baud(115200);
    pc.printf("*** USB Host MIDI\r\n");

    midi2.begin(MIDI_CHANNEL_OMNI);
    midi2.turnThruOff();

//    Thread midiTask(midi_task, NULL, osPriorityNormal, 5120);
    for (;;) {
        midi_task(NULL);
//        Thread::wait(100);
    }
}