MIDIoIP test This test program controls blinking of Four LEDs by Knob#1/slider#1/key of KORG nano Kontrol/Key, and needs midi_bridge.c on linux to transfer MIDI data to mbed (over PC-serial or IP packet)

Dependencies:   EthernetNetIf mbed

main.cpp

Committer:
xshige
Date:
2010-09-20
Revision:
0:189db48772ae

File content as of revision 0:189db48772ae:


// MIDI over IP/serial test (MIDIoIP_test)

// This test program controls blinking of Four LEDs 
// by Knob#1/slider#1/key of KORG nano Kontrol/Key,
// and needs midi_bridge.c on linux to trasfer MIDI data 
// to mbed (over PC-serial or IP packet)
//
// Note:
//  midi_bridge.c is included in this file as comment.
//

// written by: xshige
// 2010/9/20


//#define SERIAL_MIDI // get MIDI data from PC serial
#define UDP_MIDI // get MIDI data from IP packet(UDP) 

#include "mbed.h"
#include "EthernetNetIf.h"
#include "UDPSocket.h"

EthernetNetIf eth;
#if 0
EthernetNetIf eth(
  IpAddr(192,168,0,25), //IP Address
  IpAddr(255,255,255,0), //Network Mask
  IpAddr(192,168,0,1), //Gateway
  IpAddr(192,168,0,1)  //DNS
);
#endif

UDPSocket udp;


//-------------------------------------------------

class RingBuffer
{
    protected:
        unsigned char *buffer;
        int buffersize;
        int rp; // read index
        int wp; // write index
        int num; // how many bytes you have in buffer
    
    public:
        RingBuffer(int bufsiz)
        {
            buffersize = bufsiz;
     
            buffer = new unsigned char[buffersize];
        //    memset(buffer, 0, sizeof(char) * buffersize);
 
            // reset pointer to make empty
            rp = 0;
            wp = 0;
            // zero byte in buffer
            num = 0;
        };
 
        ~RingBuffer(void)
        {
            delete[] buffer;
        };
 
        int GetByte(unsigned char *cp);
        int PutByte(unsigned char c);
        int IsEmpty(void);
        int IsNumBytes(void); 
};


int RingBuffer::GetByte(unsigned char *cp )
{
   if( rp != wp ) {    // not empty
      *cp = buffer[rp];
      rp = (rp + 1) % buffersize;
      num--;
      return 0;
   } else {            // empty
      num = 0;
      return -1;
   }
}


int RingBuffer::PutByte(unsigned char c )
{
   int next = (wp + 1) % buffersize;
   if( next == rp ) {
      printf("*** Buffer Full ***\r\n" );
//        printf("*");//debug
        return -1;
   }
   buffer[wp] = c;
   wp = next;
   num++;
   return 0;
}


int RingBuffer::IsEmpty(void)
{
   return  (rp==wp)?(true):(false);
}

int RingBuffer::IsNumBytes(void)
{
    return num;
}

//-----------------

// create RingBuffer
RingBuffer  UDPbuf(64);

void onUDPSocketEvent(UDPSocketEvent e)
{
  switch(e)
  {
  case UDPSOCKET_READABLE: //The only event for now
    char buf[64] = {0};
    Host host;
    while( int len = udp.recvfrom( buf, 63, &host ) )
    {
      if( len <= 0 ) break;
      for(int i=0;i<len;i++) {
        UDPbuf.PutByte(buf[i]);
      }
//        printf("\r\nFrom %d.%d.%d.%d\r\n", 
//      host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]); //debug
//     printf("len:%d\r\n",len); // debug
    }
    break;
  }
}

DigitalOut led1(LED1, "led1");
DigitalOut led2(LED2, "led2");
DigitalOut led3(LED3, "led3");
DigitalOut led4(LED4, "led4");

BusOut myleds(LED1, LED2, LED3, LED4);

int main() {

    // make debug port Fast
  Serial pc(USBTX, USBRX);
//    pc.baud(9600);
    pc.baud(115200);
//  pc.baud(230400);


  printf("Setting up...\r\n");
  EthernetErr ethErr = eth.setup();
  if(ethErr)
  {
    printf("Error %d in setup.\r\n", ethErr);
    return -1;
  }
  printf("Setup OK\r\n");
  
//Host broadcast(IpAddr(192, 168, 0,255), 12345, NULL); // local broadcast over router
//Host multicast(IpAddr(239, 192, 1, 100), 50000, NULL); // Join multicast group on port 50000 
Host broadcast(IpAddr(255, 255, 255,255), 8888, NULL); // broadcast in a router

  udp.setOnEvent(&onUDPSocketEvent);
  
  udp.bind(broadcast);
  
  Timer tmr;
  tmr.start();
  
#ifdef SERIAL_MIDI
  printf("Serial MIDI enable\r\n");
#else
  printf("Serial MIDI disable\r\n");
#endif

  
#ifdef UDP_MIDI
  printf("IP MIDI enable\r\n");
#else
  printf("IP MIDI disable\r\n");
#endif
 
  
  while(true)
  {
    Net::poll();
    int velocity,MIDIch,pitch;
    //
#ifdef SERIAL_MIDI
    if(pc.readable()) {
        int c;
        c=pc.getc(); // get 1st byte
        printf("Received:%02X\r\n",c);
        MIDIch=c&0x0F;
        c=c&0xF0;
        if (0xB0==c) { 
            c=pc.getc();
            printf("Received:%02X\r\n",c);
            if (0x0E==c) { // Knob#1 on KORG Kontrol (SCENE#1)
                c=pc.getc(); // get volume
                printf("Received:%02X\r\n",c);
                // MIDI controls LEDs
                myleds=(15*c)/127;
             }
            if (0x02==c) { // Slider#1 on KORG Kontrol (SCENE#1)
                c=pc.getc(); // get volume
                printf("Received:%02X\r\n",c);
                // MIDI controls LEDs
                myleds=(15*c)/127;
            }   
        } // if (0xB0==c)
        if (0x90==c) {  // Note On
            c=pc.getc(); // get Note#
            printf("Received:%02X\r\n",c);
            // Note# controls LEDs
            myleds=(c%0x10);
            c=pc.getc(); // get Velocity
            printf("Received:%02X\r\n",c);
            velocity=c;
        }
        if (0x80==c) {  // Note Off
            c=pc.getc(); // get Note#
            printf("Received:%02X\r\n",c);
            // Note# controls LEDs
            myleds=(c%0x10);
            c=pc.getc(); // get Velocity
            printf("Received:%02X\r\n",c);
             // Velocity(at Note On) controls LEDs
             myleds=(15*velocity)/127;
        }
        if (0xE0==c) {  // Pich Bend
            c=pc.getc(); // get LSB
            printf("Received:%02X\r\n",c);
            if (0xE0==c) c=pc.getc(); // re-get for error recover
            pitch=(c&0x7F);
            c=pc.getc(); // get MSB
            printf("Received:%02X\r\n",c);
            pitch+=((c&0x7F)<<7);pitch-=8192;
            printf("Pitch Bend:%d\r\n",pitch);
            
        }     
    } // pc.readable
#endif // ifdef SERIAL_MIDI
#ifdef UDP_MIDI
    // get MIDI data in UDP packet
     if(UDPbuf.IsNumBytes()>3) {
        unsigned char uc;
        UDPbuf.GetByte(&uc); // get 1st byte
        printf("\r\nFrom Net:%02X\r\n",uc);
        MIDIch=uc&0x0F;
        uc=uc&0xF0;
        if (0xB0==uc) { 
            UDPbuf.GetByte(&uc);
            if (0xB0==uc) UDPbuf.GetByte(&uc); // re-get for error recover
            printf("From Net:%02X\r\n",uc);
            if (0x0E==uc) { // Knob#1 on KORG Kontrol (SCENE#1)
                UDPbuf.GetByte(&uc); // get volume
                printf("From Net:%02X\r\n",uc);
                // MIDI controls LEDs
                myleds=(15*uc)/127;
             }
            if (0x02==uc) { // Slider#1 on KORG Kontrol (SCENE#1)
                UDPbuf.GetByte(&uc); // get volume
                printf("From Net:%02X\r\n",uc);
                // MIDI controls LEDs
                myleds=(15*uc)/127;
            }   
        } // if (0xB0==uc)
        if (0x90==uc) {  // Note On
            UDPbuf.GetByte(&uc); // get Note#
            printf("From Net:%02X\r\n",uc);
            // Note# controls LEDs
            myleds=(uc%0x10);
            UDPbuf.GetByte(&uc); // get Velocity
            printf("From Net:%02X\r\n",uc);
            velocity=uc;
        }
        if (0x80==uc) {  // Note Off
            UDPbuf.GetByte(&uc); // get Note#
            printf("From Net:%02X\r\n",uc);
            // Note# controls LEDs
            myleds=(uc%0x10);
            UDPbuf.GetByte(&uc); // get Velocity
            printf("From Net:%02X\r\n",uc);
             // Velocity(at Note On) controls LEDs
             myleds=(15*velocity)/127;
        }
        if (0xE0==uc) {  // Pich Bend
            UDPbuf.GetByte(&uc); // get LSB
            if (0xE0==uc) UDPbuf.GetByte(&uc); // re-get for error recover
            printf("From Net:%02X\r\n",uc);
            pitch=(uc&0x7F);
            UDPbuf.GetByte(&uc); // get MSB
            printf("From Net:%02X\r\n",uc);
            pitch+=((uc&0x7F)<<7);pitch-=8192;
            printf("Pitch Bend From Net:%d\r\n",pitch);   
        }     
    } // if !UDPbuf.IsNumBytes()
#endif // ifdef UDP_MIDI
//    
    if(tmr.read() > 0.5) {
        tmr.reset();

        // blink to indicate alive
        led1=!led1;          
    }
  } // while(true)
}

//---------------------------------------------------------------------------
#if 0
/*
midi_bridge.c

How to Compile:
gcc midi_bridge.c -o midi_bridge

How to execute(on linux):
<connet USB-MIDI devices and mbed USB to PC>
midi_bridge[Enter]
init serial between mbed and PC
init serial for USB-MIDI
Connected on /dev/mid2
Connected on /dev/mid3
Setting up...
[..\fwk\if\eth\EthernetNetIf.cpp:setup@86] HW Addr is : 00:02:f7:f0:4f:9d.
[..\fwk\if\eth\EthernetNetIf.cpp:setup@99] DHCP Started, waiting for IP...
[..\fwk\if\eth\EthernetNetIf.cpp:setup@142] Connected, IP : 192.168.0.2
Setup OK
Serial MIDI disable
IP MIDI enable
<move knob#1>
B0
0E
35

From Net:B0
From Net:0E
From Net:36
B0
0E
34

From Net:B0
From Net:0E
From Net:35
....

*/


//----

// MIDI bridge among USB-MIDI, PC-serial, and IP-packet
//
// written by:xshige

// v0.5 2010/9/18 
// (implemented path: USB-MIDI to PC-serial, USB-MIDI to IP-packet)

#include <stdio.h>
#include <stdlib.h>

//#include <io.h>
#include <fcntl.h>

#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <errno.h>

// socket
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>


#define max(a,b) ((a) > (b) ? (a) : (b))

int main(void)
{
    // init socket
    int sock;
    struct sockaddr_in addr;
    int yes = 1;
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    addr.sin_family = AF_INET;
// ******* IP setup *******
    addr.sin_port = htons(8888); // port#
//addr.sin_port = htons(50000); // port#
//addr.sin_addr.s_addr = inet_addr("239.192.1.100"); //Join multicast group on port 50000
    addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // broadcast in a router
//addr.sin_addr.s_addr = inet_addr("192.168.0.255"); // local broadcast over routers
//memo: multicast IP 224.0.0.1 hosts in the subnet
// *************************
    //
    setsockopt(sock,
            SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof(yes));

    // *** serial for mbed ***
    printf("init serial between mbed and PC\n");
    struct termios options;
    int fdt=open("/dev/ttyACM0",O_RDWR|O_NOCTTY|O_NONBLOCK);
    if (fdt == -1) {
        perror("open_port: Unable to open port between mbed and PC - ");
          }
    // Get the current options for the port...
        tcgetattr(fdt, &options);
    // Set the baud rates to 1115200 bps for mbed
     cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    // No parity (8N1)
          options.c_cflag &= ~PARENB;
          options.c_cflag &= ~CSTOPB;
          options.c_cflag &= ~CSIZE;
          options.c_cflag |= CS8;
    // Set the new options for the port...
    tcsetattr(fdt, TCSANOW, &options);

    // *** serial for MIDI ***
    printf("init serial for USB-MIDI\n");
    int fdm2=open("/dev/midi2", O_RDONLY|O_NONBLOCK);
    int fdm3=open("/dev/midi3", O_RDONLY|O_NONBLOCK);
    int fdm4=open("/dev/midi4", O_RDONLY|O_NONBLOCK);
    if (fdm2 != -1) printf("Connected on /dev/mid2\n");
    if (fdm3 != -1) printf("Connected on /dev/mid3\n");
    if (fdm4 != -1) printf("Connected on /dev/mid4\n");

    // Init FDs for Select
    int maxfd=-1;
        fd_set fds,readfds;
        struct timeval timeout;
        // Init the read FD set
        FD_ZERO(&readfds);
        FD_SET(fdt, &readfds);
    if (fdm2 != -1) FD_SET(fdm2, &readfds);
    if (fdm3 != -1) FD_SET(fdm3, &readfds);
    if (fdm4 != -1) FD_SET(fdm4, &readfds);
    // get max fd
    maxfd=max(maxfd,fdt);
    if (fdm2 != -1) maxfd=max(maxfd,fdm2);
    if (fdm3 != -1) maxfd=max(maxfd,fdm3);
    if (fdm4 != -1) maxfd=max(maxfd,fdm4);
    maxfd=maxfd+1;
// printf("FDs:%d %d %d %d\n",fdt,fdm2,fdm3,fdm4); // debug
// printf("maxfd:%d\n",maxfd); // debug

    unsigned char cs,cm;
    while(1) {
        // init FDs for the select at everytime
        memcpy(&fds, &readfds, sizeof(fd_set));
         // Init the timeout structure
            timeout.tv_sec  = 3600; // set one hour for timeout
            timeout.tv_usec = 0;
            // Do the select
            int n = select(maxfd, &fds, NULL, NULL, &timeout);
        if (n == 0) {
            puts("*** TIMEOUT *** ");
            } else {
        //
        // for /dev/midi2
        if (fdm2 != -1) 
            if (FD_ISSET(fdm2,&fds)) if (read(fdm2,&cm,1) == 1) {
            // readable
            printf("%02X\n",cm); // display MIDI in HEX on console
            write(fdt,&cm,1); // USB-MIDI to mbed
            sendto(sock,&cm,1, // USB-MIDI to IP network
                0, (struct sockaddr *)&addr, sizeof(addr));
        }
        // for /dev/midi3
        if (fdm3 != -1)
             if (FD_ISSET(fdm3,&fds)) if (read(fdm3,&cm,1) == 1) {
            // readable
            printf("%02X\n",cm); // display MIDI in HEX on console
            write(fdt,&cm,1); // USB-MIDI to mbed
            sendto(sock,&cm,1, // USB-MIDI to IP network
                0, (struct sockaddr *)&addr, sizeof(addr));


        }
        // for /dev/midi4
        if (fdm4 != -1)
            if (FD_ISSET(fdm4,&fds)) if (read(fdm4,&cm,1) == 1) {
            // readable
            printf("%02X\n",cm); // display MIDI in HEX on console
            write(fdt,&cm,1); // USB-MIDI to mbed
            sendto(sock,&cm,1, // USB-MIDI to IP network
                0, (struct sockaddr *)&addr, sizeof(addr));


        }
        // for /dev/ttyACM0
        if (FD_ISSET(fdt,&fds)) if (read(fdt,&cs,1) == 1) {
            // readable on mbed
            putchar(cs); // display to console
            //write(fdm2,&cs,1); // mbed to USB-MIDI
        }
        }// if else

    } // while
}
#endif