MIDI (Musical Instrument Digital Interface) is a technology born in the early 80s, and still widely used today. Part of its attraction is its simplicity - there are very few concepts to understand, and it is easy to implement both the hardware and software at the hobbyist level, which is basically where I'm coming from.
At the physical layer, MIDI operates as a 5mA current loop, using 5 pin DIN male-male cables. On the receive side an optoisolator is used to extract the signal which is then typically input to a UART (whether standalone or in a microcontroller). The use of an optoisolator on the input side places some restrictions on the transmit voltage - the optoisolator's LED needs at least its forward voltage to do anything at all, and
That MIDI is a serial protocol is implied by the physical spec - with only a two wire connection between the source and sink, it couldn't be anything else! The format of the signal is asynchronous (8-bit) byte-oriented messages sent at a signalling rate of 31250 baud, with single start/stop bits and no parity. Standard UARTs typically default to the correct link settings (8-N-1) and only need the baud rate configured to work correctly.
There are two main types of messges in MIDI - Channel Messages and System Messages. For sending simple messages MIDI uses a byte oriented stream protocol, where the top bit in each byte is used to indicate whether this is a status byte or a data byte. Messages always start with
If the above were all there was to it, it would be very simple sending and receiving MIDI. Unfortunately, there is more to it than that, complicating things. On the plus side, these additions aren't too difficult to cope with, and provide some useful features.
Often in MIDI streams, For a sender, using running status is optional, but every receiver should handle this. Various intermediate devices will automatically strip unnecessary status bytes from incoming midi streams. Since it is not difficult when sending midi to compare any new channel message status byte with the previous one and omit it if the same, it makes sense to always use and assume running status will be present.
Sysex (System Exclusive) messages allow arbitrary data to be sent using the MIDI protocol. This is typically used for uploading or downloading configuration to a MIDI device.
Back in 1983, 31250 baud was a high-speed protocol. The same couldn't be said today, but even then it was recognised that having to wait until any current message had finished (compounded by arbitrarily long sysex messages) before sending new status messages was not a great idea. For this reason, a number of system messages are designated real-time messages, and these may be sent at any time. They are all single byte messages, so the receiver can simply check for these messages and filter them out of the incoming stream, either ignoring them altogether or processing them as required.
For the extended-range (18F) and 16bit PICs, writing MIDI processing code in assembly is probably not worth the effort, unless cost reduction is such a priority that the absolute lowest code-size is a benefit. But for the mid-range (16F) PICs, assembly might make sense - here minimum code-size is a barrier every program will come up against.