Checkout: @tymkrs MIDI In Me + PIC18F14K22

I don’t want anyone thinking they’re going to see a bunch of music related items on the blog because I’m really no good at such things. My brother on the other hand is very talented and we recently decided he needed some more MIDI toys. A lot of his music is already created with the help of MIDI.

MIDI is “Musical Instrument Digital Interface“; a standard that defines hardware and protocol. If you want more information on it such as specifications Google is your friend.

My brother had some information on the specification but not really anything that helped me much. I did a lot of reading on the specifications on the MIDI Manufacturers Association webpage and then countless other sites describing the protocol in length. It even looks like there is a tutorial on the Arduino site, although I didn’t look at it because I don’t use them. Again, I’m not going to go into the protocol anymore than I discussed the specification. I’ll let you do that leg work. However, the *really* short version is there are a couple key commands followed (usually) by some extra bytes (generally 1 or 2). All the data is transmitted like normal 8N1 serial data at 31.25kbaud. Lucky for me 31.5k has a nice PIC SPBRG division value for low error rate (at 4MHz).

Hardware Interface: I decided I wasn’t going to build the 5mA loop interface and I remembered the Toymakers ( @tymkrs ) had a nice little interface board already built. One trip on over to their Tinde Store and I had it a few days later.

It’s a small kit, it came well packed, and it fit the bill just fine. I have nothing but praise this little kit with only one tiny little nit-picky mention. I wish they included a URL of the location of the instructions for building the kit. They had a couple resistors and I needed to know what was R1, R2, etc.. it was easy to find, a return trip to Tindie linked instructions, a construction video! and a lot of information on their website. So I know I’m picky.. If they wanted to make a 9.7 a 10.. that’d be it ๐Ÿ˜‰

The Toymakers Midi In Me Kit.
The Toymakers Midi In Me Kit.

After everything was plugged in, code was loaded on the PIC, a MIDI device plugged in.. etc.. I checked out the MIDI kit to see response and how noisy it might be… no complaints here.. it looked good…

MIDI In signal edge TEK0000

The Firmware: It’s just “sample” code. I haven’t written any real output yet because my brother is in charge of the “analog” bits which really means he is going to figure out what he wants in block diagrams and I will have to figure out how to make it happen in circuit. Right now I’m reading the MIDI signal in on UART by interrupt… and checking for my command signal. (I’m using a Control Change because of my MIDI device… you will most likely want to change this). The control change value is 0xB1 in my case, then… my device (Knob #1) which is 0x11 … and finally it gives me a value (knob position 0x00 to 0x7F). I’m taking that position value and transmitting it out the UART to my PC…

 

The output dropped onto my PC. Note: RealTerm allows me to enter in 31250 baud.. 8N1
The output dropped onto my PC. Note: RealTerm allows me to enter in 31250 baud.. 8N1
MIDI on the LA
MIDI on the LA

 

I used the TAUTIC 20 pin dev board (any groaning of “AGAIN??”??) … but a change-up! ๐Ÿ™‚ I used a PIC 18F14K22 … because I felt like getting crazy ๐Ÿ˜‰ and the 18 series is optimized for C so I will probably go back to the 18F series … I think the last time I used one was my ESR meter?  A few changes switching to the 18 series.. but nothing huge. Just getting used to slightly different registers.  Last warnings about the code; It’s simple… it’s just checking to see if your interface it working… (or if you’re sending MIDI and you don’t have a scope or LA). It has a lot of clutter because I was using it for some other non-MIDI related testing but it’s easy to spot and delete if you need to copy it as a starting point for whatever you’re working on. (Do share!)

/* 
 * File:   main.c
 * Author: Charles M Douvier
 * Contact at: http://iradan.com
 *
 * Created on February 8, 2014, 11:39 AM
 *
 * Target Device:
 * 18F14K22 on Tautic 20 pin dev board
 *
 * Project: MIDI Slave
 *
 *
 * Version:
 * 0.1  Configuration, 31.25Kbaud TX&RX
 * 0.2  Grab MIDI byte from 31.25K MIDI and turn around and TX the value of the
 *      MIDI command. <CMD: Control Change><Device><Value>
 *      <B1><11><value> //my example
 *
 */
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000 //4Mhz FRC internal osc
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#endif

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

//config bits
#pragma config FOSC=IRC, WDTEN=OFF, PWRTEN=OFF, MCLRE=ON, CP0=OFF, CP1=OFF, BOREN=ON
#pragma config STVREN=ON, LVP=OFF, HFOFST=OFF, IESO=OFF, FCMEN=OFF

#define _XTAL_FREQ 4000000 //defined for delay

/*
 * Variables
 */

    long int    decm;           //long temp
    int     tempi;              //temp
    int     i, ilevel;                  //temp
    int     itxdata;            //int RS232 tx data
    char    buf[10];            //buff for iota
    volatile unsigned int uart_data;    // use 'volatile' qualifer as this is changed in ISR

/*
 *  Functions
 */

    void interrupt ISR() {

    if (PIR1bits.RCIF)          // see if interrupt caused by incoming data
    {
        uart_data = RCREG;     // read the incoming data
        PIR1bits.RCIF = 0;      // clear interrupt flag
                                //
    }

}

void uart_xmit(unsigned int mydata_byte) {

    while(!TXSTAbits.TRMT);    // make sure buffer full bit is high before transmitting
    TXREG = mydata_byte;       // transmit data
}

void serial_init(void)
{

    // calculate values of SPBRGL and SPBRGH based on the desired baud rate
    //
    // For 8 bit Async mode with BRGH=0: Desired Baud rate = Fosc/64([SPBRGH:SPBRGL]+1)
    // For 8 bit Async mode with BRGH=1: Desired Baud rate = Fosc/16([SPBRGH:SPBRGL]+1)

    TXSTAbits.BRGH=1;       // select low speed Baud Rate (see baud rate calcs below)
    TXSTAbits.TX9=0;        // select 8 data bits
    TXSTAbits.TXEN = 1;     // enable transmit

    RCSTAbits.SPEN=1;       // serial port is enabled
    RCSTAbits.RX9=0;        // select 8 data bits
    RCSTAbits.CREN=1;       // receive enabled

    //BRGH=1        31.25KHz
    //SPBRG=7

    SPBRG=7;               //

    PIR1bits.RCIF=0;        // make sure receive interrupt flag is clear
    PIE1bits.RCIE=1;        // enable UART Receive interrupt
    INTCONbits.PEIE = 1;    // Enable peripheral interrupt
    INTCONbits.GIE = 1;     // enable global interrupt

         __delay_ms(50);        // give time for voltage levels on board to settle

    //  uart_xmit('S');         // transmit a character example

}

void init_io(void) {
    TRISAbits.TRISA0 = 0; // output
    TRISAbits.TRISA1 = 0; // output
    TRISAbits.TRISA2 = 0; // output
    TRISAbits.TRISA4 = 0; // output
    TRISAbits.TRISA5 = 0; // output

    ANSEL = 0x00;         // no A/D
    ANSELH = 0x00;

    TRISBbits.TRISB4 = 0; // RB4 = nc
    TRISBbits.TRISB5 = 1; // RB5 = nc
    TRISBbits.TRISB6 = 0; // RB6 = nc
    TRISBbits.TRISB7 = 0; // RB7 = nc

    TRISCbits.TRISC0 = 0; // output
    TRISCbits.TRISC1 = 0; // output
    TRISCbits.TRISC2 = 0; // output
    TRISCbits.TRISC3 = 0; // output
    TRISCbits.TRISC4 = 0; // output
    TRISCbits.TRISC5 = 0; // output
    TRISCbits.TRISC6 = 1; // input
    TRISCbits.TRISC7 = 1; // input

}

void set_cmd11(void)
{
    //set an AD output
                while(uart_data==0x11)
            {
                i++; //wait for next char
            }
            ilevel = uart_data;         //finally the value
            uart_xmit(ilevel);
}

void check0xb1(void)
{
    if (uart_data == 0xB1)
    {
            while(uart_data==0xB1)
            {
                i++; //wait for next char
            }
            if ( uart_data == 0x11)     //and the knob 1 is "device 11"... 
               set_cmd11();
    }
}

int main(void) {

    init_io();

    // set up oscillator control register, using internal OSC at 4MHz.
    OSCCONbits.IRCF = 0x05; //set OSCCON IRCF bits to select OSC frequency 4MHz
    OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block

    serial_init();

    decm=30;            //testing

    ltoa(buf,decm,10);  //long conversion to buffer
    tempi=strlen(buf);  //uh, adding leading zeros..
    uart_xmit('+');
    uart_xmit(itxdata);
    uart_xmit('.');
    LATAbits.LATA0=0;

    while (1) {

        i++;

        while (uart_data)
        {
            check0xb1();    //my midi device is sending a Control Change 0xB1
            uart_data=0;
        }

    }
    return (EXIT_SUCCESS);
}

 

Author: Chas

I don't know why I blog, because? I have no agenda, just love electronics and want to share. I love to follow other experimenters/hardware hackers just to see what other people are working on. Shoot me a message if you blog.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.