[sdiy] MIDI receiving interrupt function.. a promissing start..
Jean-Pierre Desrochers
jpdesroc at oricom.ca
Mon Apr 13 18:01:01 CEST 2020
Hi all,
Happy to see this list still alive in these dark moments of COVID19..
Anyway I wanted to share with you the actual coding I worked on
on the last weeks. This is the actual MIDI Rx interrupt c code I managed
to tweak and this gives very good results. Fast, efficient and reliable.
I tested my 6 voices poly M100 MIDIDAC
<http://www.arcenson.com/projects/Modular/M100_MIDI_Interface/Module_picture
s/M100_MIDI_interface_assembled_front.jpg> module's MIDI reception using an
external sequencer (Cakewalk SONAR X3)
through a MIDI cable, running at a rate of around 180bpm! with a polyphonic
Bach song MIDI file.
And this with 4 added continuously changing MIDI layers (velocities, after
touch, Breath, CC)
The result was great ! No losses at all. All the notes clearly received with
no stuck notes.
Please note this code IGNORES ALL THE INCOMING REAL TIME or SYSEX bytes.
Only MIDI voice messages commands are processed. This is what I only needed.
The complete MIDIDAC C code is available here
<http://www.arcenson.com/projects/Modular/M100_MIDI_Interface/Hitech_C_code_
files/MIDIDAC_MPLAB_X_code_files/> .
I wish I had these code lines many months ago and hope this will help new
MIDI developers like me..
Here is my interrupt lines:
//////////////////////////////////
// ---------------------------- //
// interrupt service routine //
// ---------------------------- //
//////////////////////////////////
void interrupt tmr0_USART_isr (void)
{
unsigned char x; // intermediate byte value
// RS232 receive interrupt
if (RCIF == TRUE && RCIE == TRUE)
{
if (OERR == TRUE) // overrun, reset UART
{
CREN = FALSE; // disable UART
CREN = TRUE; // re-enable UART
}
else
{ // Good Rx byte
x = RCREG;
//////////////////////////////////////////////////////
///////////////// Manage Status Byte /////////////////
//////////////////////////////////////////////////////
if(x & 0x80) // Bit 7 = 1 (Status byte)
{
if((x != 0xF6) & // Not a Real Time Message neither Tune
Request
(x != 0xF8) &
(x != 0xFA) &
(x != 0xFB) &
(x != 0xFC) &
(x != 0xFE) &
(x != 0xFF))
{
PendingMIDIStatusByteVal = x; // Here SYSEX Status (0xF0 & 0xF7)
can also be stored as PendingMIDIStatusByteVal
MIDIThirdByteFlag = FALSE; // to change the last active
'current' MIDI Status.
} // Doing so the SYSEX trailing data
bytes will be differentiated
// from other recognized data bytes
then ignored..
} // Bit 7 = 1 (Status byte)
//////////////////////////////////////////////////////
///////////////// Manage data Bytes //////////////////
//////////////////////////////////////////////////////
else // Bit 7 = 0 (data byte)
{
if(!MIDIThirdByteFlag) // MIDIThirdByteFlag = 0 ?
{
if(PendingMIDIStatusByteVal) // MIDI_Status greater than 0
{
// Checking for 0x8n, 0x9n, 0xAn, 0xBn, 0xEn channel messages
if ( (PendingMIDIStatusByteVal < 0xC0) ||
( (PendingMIDIStatusByteVal >= 0xE0) &&
(PendingMIDIStatusByteVal <= 0xEF)) ) // Messages that have 2 data bytes
after Status
{
MIDIThirdByteFlag = TRUE; // 2 data bytes Status here
PendingMIDISecondByteVal = x; // Store second byte..
}
// Checking Status byte range: 0xC0 to 0xDF (Status with only
one data byte)
else if (PendingMIDIStatusByteVal < 0xE0)
{
PendingMIDISecondByteVal = x; // Store second byte.. No third
byte
write_ring_buffer(PendingMIDIStatusByteVal);
write_ring_buffer(PendingMIDISecondByteVal);
PendingMIDISecondByteVal = 0; // Ready for next Status Message
or trailing Running Status 2 bytes chunk..
}
else if (PendingMIDIStatusByteVal == 0xF2) // Song Position
Pointer (followed by 2 data bytes..)
{ // Here we must
catch the Status, data1, data2 then throw them away
MIDIThirdByteFlag = TRUE; // after the
third byte is received
PendingMIDISecondByteVal = x;
}
}
}
else // MIDIThirdByteFlag = 1.. Third byte received here
{
MIDIThirdByteFlag = FALSE;
PendingMIDIThirdByteVal = x;
write_ring_buffer(PendingMIDIStatusByteVal);
write_ring_buffer(PendingMIDISecondByteVal);
write_ring_buffer(PendingMIDIThirdByteVal);
PendingMIDISecondByteVal = 0; // Ready for next Status Message or
trailing Running Status 2 bytes chunk..
PendingMIDIThirdByteVal = 0; // And keep the
PendingMIDIStatusByteVal in case it's a Runing Status not finished
}
} // Bit 7 = 0 (data byte)
MIDI_ACTIVITY_LED = ON; //RC0 = 0; // Set led MIDI ACTIVITY to ON
TMR0 = 0; // restart timer0
T0IE=1; // Activates overflow interrupt of TMR0 register
RCIF = 0; // Erase MIDI RX flag
} // Good Rx byte
}
I'm sure someone in the list will see something I did not see (maybe not)
so.. let me know if it's the case.
Cheers !
Jean-Pierre
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://synth-diy.org/pipermail/synth-diy/attachments/20200413/17d49c1c/attachment.htm>
More information about the Synth-diy
mailing list