[sdiy] MIDI I/O c code..

Mikko Helin maohelin at gmail.com
Fri Mar 20 19:40:31 CET 2020


Hi,
I would keep the ISR very simple like this and handle rest in main loop.

#define RCVBUFSIZEMASK 0x3F // for 64 bytes, 0x1F for 32 bytes
unsigned char rcvbuf[RCVBUFSIZEMASK+1];
unsigned int rcvoffset = 0;

void interrupt USART_isr (void) {
  unsigned char x;
  if (RCIF == 1) {
    x = RCREG;
    rcvbuf[rcvoffset++ & RCVBUFSIZEMASK] = x;

  }
}

void main() {
  // TODO setup UART & ISR
  unsigned int readoffset = 0;
  unsigned char running_status = 0;
  unsigned char databyte_cnt = 0; // keep count of data bytes
  unsigned char data;
  RCIE = 1 // enable interrupts
  // other initialisations
  while (1) {
    unsigned char x;
    while (rcvoffset != readoffset) {
        MIDI_ACTIVITY_LED = ON;
        x = rcvbuf[readoffset++ & RCVBUFSIZEMASK];
        if (x & 0x80 == 0x80) { // handle status
            running_status = x;
            continue;
        }
        switch (running_status) {
        case NOTE_ON:
            if (databyte_cnt == 0) {
                data = x;
                databyte_cnt++;
                continue;
            }
            if (databyte_cnt == 1) {
                handle_midi_note_on_off(data, x); // key, velocity,
velocity = 0 => note off
                databyte_cnt = 0;
            }
            break;
        }
    }
    MIDI_ACTIVITY_LED = OFF;
    }
}

or something like that. If you have to send something from MIDI out I would
just use polling like
TXREG = midi_data_to_send;
while (!TRMT);

--Mikko

On Fri, Mar 20, 2020 at 4:11 PM Jean-Pierre Desrochers <jpdesroc at oricom.ca>
wrote:

> Hi Mikko,
>
>
>
> Here is my USART Rx  interrupt routine :
> Maybe you’ll spot any errors or things I forgot.. ??
>
>
>
> *void interrupt tmr0_USART_isr (void) *
>
> * {*
>
> *  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 *
>
> *     { *
>
> *      x = RCREG;*
>
> *      if((x & 0xF0) != 0xF0)             // Ignore all 1 byte commands*
>
> *       {                                                    // data
> without errors*
>
> *        rcvbuf[rcvoffset] = x;         // move byte to rcv
> buffer
>
> *
>
> *        rcvoffset++;                          // offset next byte*
>
>
>
> *        if (rcvoffset == RCVBUFSIZE)    // beyond buffer boundary*
>
> *          rcvoffset = 0;                                 // wrap to begin*
>
> *       }  *
>
>
>
> *      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*
>
> *      }*
>
>     *}*
>
>
>
> *De :* Synth-diy [mailto:synth-diy-bounces at synth-diy.org] *De la part de*
> Mikko Helin
> *Envoyé :* 20 mars 2020 01:39
> *À :* synth-diy at synth-diy.org List
> *Objet :* Re: [sdiy] MIDI I/O c code..
>
>
>
> >Running status are ignored here
>
> So you are ignoring the data bytes that belong to next note on which is
> using running status, meaning the sender does not send the same status byte
> again but just skips it and just sends the key and velocity bytes?
>
>
>
>
>
> pe 20. maalisk. 2020 klo 3.29 Jean-Pierre Desrochers <jpdesroc at oricom.ca>
> kirjoitti:
>
> > Are you handling running status and note off sent as zero velocity note
> on?
>
> Yes I handle both.
>
> Running status are ignored here,
>
> And I consider both NOTE OFF and NOTE ON with zero velocity
>
> As the end of a note.
>
>
>
>
>
> *De :* dougall [mailto:dougalli at gmail.com]
> *Envoyé :* 19 mars 2020 21:06
> *À :* eidorian at aladan.net
> *Cc :* Jean-Pierre Desrochers; Synth-diy at synth-diy.org
> *Objet :* Re: [sdiy] MIDI I/O c code..
>
>
>
> Are you handling running status and note off sent as zero velocity note on?
>
>
>
> -d
>
>
>
> On Fri, 20 Mar 2020 at 11:55, <eidorian at aladan.net> wrote:
>
> Sorry, I don't have example code for you, but here is some analysis that I
> hope might help point you in the right direction:
>
> 20MHz / 31,250Hz => ~640 instructions per MIDI data bit, or 6,400
> instructions per MIDI data byte.  That's quite a lot of instruction
> execution time between notes, so I'd be checking the
> efficiency/optimisation of the code.
>
> How long is it taking to update the analog outputs and do other
> processing?  If it's updating all 8 CVs via a "slow" protocol like I2C
> every time it loops then that might be taking a while, and maybe you need a
> different approach (i.e. only update a CV output when it changes).
>
> How have you implemented the FIFO?  Do you have locking to ensure the
> interrupt isn't writing to it while the main loop is updating it?
>
> Create a debug version that has checks on the FIFO size in the interrupt,
> and sets an LED on if it overflows, so you can confirm for certainly
> whether or not that's the problem.
>
> What I do (with 30+ years of programming experience) is pretend I'm the
> CPU, and "execute" the code in my head (or on paper if complex) in order to
> try to work out what unplanned or unexpected things might be happening to
> cause the problematic behaviour.
>
> Cheers,
> A.
>
> ---
>
>
>
>
>
> On 20-03-2020 11:14, Jean-Pierre Desrochers wrote:
>
>
>
> I’m working on a new polyphonic MIDI to CV module (8 voices).
>
> So far I did my tests with an old PIC16F887 @ 20Mhz micro I had on hand.
>
> I use a USART interrupt driven c function to ‘catch’ all the incoming MIDI
> bytes.
>
> My code is pretty fast, but still, since I only read one MIDI channel
> (1-16) at the time
> when I play very fast chords on an external keyboard
>
> all the notes are read in the incoming queue but sometimes
>
> I get stuck notes or unread ones..
>
> Same thing happens when playing MIDI files on Cakewalk SONAR
> feeding my prototype with  a MIDI cable.
> The interrupt function grabs each incoming byte and put them
>
> In a receive buffer of 32 bytes and the main () reads and treats them in a
> FIFO manner
>
> Later in the main loop.
>
>
>
> *-Would a 32Mhz micro do a difference in the USART interrupt reading speed
> ?*
>
> *-And is 32 bytes long enough for the RxBuffer to handle a 6 voices chords
> ?*
>
> *-And finaly I checked the web for a ‘decent’ C code examples*
>
> *  for MIDI reception (MIDI Tx is much easier to implement) with no
> success..*
> *  ‘Obscure’ Arduino libraries all around with no explainations of its
> inner code.*
>
>
>
> Did anybody use good C code available ?
>
> JP
>
>
>
> Synth-diy at synth-diy.org
>
>
>
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at synth-diy.org
> http://synth-diy.org/mailman/listinfo/synth-diy
>
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at synth-diy.org
> http://synth-diy.org/mailman/listinfo/synth-diy
>
> _______________________________________________
> Synth-diy mailing list
> Synth-diy at synth-diy.org
> http://synth-diy.org/mailman/listinfo/synth-diy
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://synth-diy.org/pipermail/synth-diy/attachments/20200320/f9758728/attachment.htm>


More information about the Synth-diy mailing list