UART interrupt triggered by '0' byte from MIDI keyboard

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
simac_4074571
Level 1
Level 1

Hello everyone,

For A uni project I have to read MIDI uart output, but because the signal goes trough a optocoupler the interrupt is always triggerd by a '0' byte, and this poses an issue because I only need the data when its actually being sent. MIDI always sends 3 bytes, 1 for command, 1 for note and 1 for velocity.

This is the main, interrupt routine sets a flag when triggered:

int main()

{

   

    UART_1_Start();

   

    isr_1_StartEx(isr_1_Interrupt);

    UART_2_Start();

   

    IDAC_1_Start();

    IDAC_1_SetValue(0);

   

    CyGlobalIntEnable;

    while(1){

        //other code to be executed

    }

    if(rx_intr==1){          //the flag from the interrupt         

        rx_intr=0;

        count++;

    uint32 byte;

    uint8 byte1;

    uint8 byte2;

    uint8 byte3;

    uint8 byte4;

   

    if (count==1){

        byte1 = UART_1_UartGetChar();

        UART_2_UartPutChar(byte1);

        UART_2_UartPutChar(UART_1_SpiUartGetRxBufferSize());

    }

    else if (count==2){

        byte2 = UART_1_UartGetChar();

        UART_2_UartPutChar(byte2);

    }

    else if (count==3){

        byte3 = UART_1_UartGetChar();

        UART_2_UartPutChar(byte3);

        checkValue(byte1, byte2, byte3); //stuff to do with the read bytes

        tel =count;

    }

       

        UART_1_SpiUartClearRxBuffer();

       

        UART_1_ClearRxInterruptSource(UART_1_GetRxInterruptSourceMasked());

   

   // setvbuf(stdin, NULL,_IONBF, 0);   

   

   

   

   

}

}

0 Likes
1 Solution
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I'm also interested in MIDI, but have not studied it yet.

For the isr, may be you need to add isr_1_ClearPending() ;

Meantime, may be because I'm not too flexible,

but I don't feel comfortable having UART_2_UartPutChar()s in the isr routine.

Also calling UART_1_SpiUartClearRxBuffer() may discard 2nd, 3rd data when receiving the first data.

So if I were you I would modify the code  something like below.

in isr_1.c

===================================

CY_ISR(isr_1_Interrupt)

{

    #ifdef isr_1_INTERRUPT_INTERRUPT_CALLBACK

        isr_1_Interrupt_InterruptCallback();

    #endif /* isr_1_INTERRUPT_INTERRUPT_CALLBACK */

    /*  Place your Interrupt code here. */

    /* `#START isr_1_Interrupt` */

    extern int packet_index ;

    extern int packet_received ;

    extern uint8_t packet[] ;

    extern uint8_t packet_size ;

    if (UART_1_SpiUartGetRxBufferSize()) { /* if we have any data */

        packet[packet_index++] = UART_1_UartGetChar() ;

        if (packet_index >= PACKET_SIZE) {

            packet_index = 0 ;

            packet_received = 1 ;

        }

    }

    UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY) ;

    isr_1_ClearPending() ;

    /* `#END` */

}

===================================

in main.c

===================================

#include "common.h"

#include "bas.h"

#include "project.h"

#include "isr_1.h"

#include "stdio.h"

char str[32] ; /* print buffer */

int         packet_index = 0 ;

uint8_t  packet_size ;

int         packet_received = 0 ;

uint8_t  packet[3] ;

void checkValue(uint8_t command, uint8_t note, uint8_t speed)

{

    sprintf(str, "%02X %02X %02X\r\n", command, note, speed) ;

    UART_2_UartPutString(str) ;

    if (note == 60u){

        IDAC_1_SetValue(255);

    }

    else if (note == 61u){

        IDAC_1_SetValue(0);

    }

    else if (note == 62u){

        IDAC_1_SetValue(255);

    }

    else if (note == 63u){

        IDAC_1_SetValue(0);

    }

    else if (note == 64u){

        IDAC_1_SetValue(255);

    }

    else if (note == 65u){

        IDAC_1_SetValue(0);

    }

}

int main()

{

    CyGlobalIntEnable;

 

    UART_1_SpiUartClearRxBuffer() ;

    UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY) ;

    isr_1_ClearPending() ;

    isr_1_StartEx(isr_1_Interrupt);

    UART_1_Start();

    UART_2_Start();

 

    IDAC_1_Start();

    IDAC_1_SetValue(0);

 

    while(1){

        if (packet_received) {

            checkValue(packet[0], packet[1], packet[2]) ;

            packet_received = 0 ;

        }

    }

 

   // setvbuf(stdin, NULL,_IONBF, 0);     

}

===================================

Note: In case this does not work, I'm very sorry for that.

moto

View solution in original post

0 Likes
3 Replies
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hello

Could you please confirm the following for us?

1. An optocoupler is only for isolation. How is data mismatch occurring because of that?

2. Please confirm the data sent out by the MIDI device, if possible send the waveforms so that we can  confirm the data sent is correct.

3. The Rx code is present in main outside the infinite while loop. It wont be executed. Please clarify on this. It should be present inside the infinite while loop.

4. Please share the project so that we can debug faster and provide a resolution. What is the code inside the ISR? Is it checking for RxFIFO not empty condition?

5. The interrupt has to be cleared and the data has to be read within the ISR. Otherwise, it might result in the ISR getting triggered continuously. Please confirm that the interrupt is cleared inside the ISR. The last two lines of the code seems redundant.

Hoping to hear back from you.

Thanks and regards

Harigovind

0 Likes

Hi,

While I was typing my question I accidentally pressed enter so I didn't

check for any mistakes nor included the project, but this actually wasn't

the original working project.

In the project that you can download here <https://we.tl/t-HKasNcpjvu> the

code to be executed is written directly in the ISR and this worked when

tested. The signal from the keyboard has been measured and tested multiple

times. The PSoC can actually detect the right bytes but the issue is (I

think) that it's being triggered all the time, even when no key is pressed,

so it never stops executing the interrupt routine. The optocoupler doesn't

pose a problem, the data is read fine by the psoc.

And yes the ISR is checking for RX FIFO NOT EMPTY and interrupt is being

cleared inside the ISR.

I should have posted this code from the beginning, my apologies for this.

Kind regards and thanks in advance!

Simon

Here is the main followed by the ISR executed code:

int main()

{

CyGlobalIntEnable;

isr_1_StartEx(isr_1_Interrupt);

isr_1_Enable();

UART_1_Start();

UART_2_Start();

IDAC_1_Start();

IDAC_1_SetValue(0);

while(1){

}

// setvbuf(stdin, NULL,_IONBF, 0);

}

//ISR_1

int tel = 0;

void checkValue(uint8 command, uint8 note, uint8 speed);

CY_ISR(isr_1_Interrupt)

{

#ifdef isr_1_INTERRUPT_INTERRUPT_CALLBACK

isr_1_Interrupt_InterruptCallback();

#endif /* isr_1_INTERRUPT_INTERRUPT_CALLBACK */

/* Place your Interrupt code here. */

/* `#START isr_1_Interrupt` */

tel++;

uint32 byte;

uint8 byte1;

uint8 byte2;

uint8 byte3;

uint8 byte4;

if (tel==1){

byte1 = UART_1_UartGetChar();

UART_2_UartPutChar(byte1);

UART_2_UartPutChar(UART_1_SpiUartGetRxBufferSize());

}

else if (tel==2){

byte2 = UART_1_UartGetChar();

UART_2_UartPutChar(byte2);

}

else if (tel==3){

byte3 = UART_1_UartGetChar();

UART_2_UartPutChar(byte3);

checkValue(byte1, byte2, byte3);

tel =0;

}

UART_1_SpiUartClearRxBuffer();

UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY);

/* `#END` */

}

void checkValue(uint8 command, uint8 note, uint8 speed){

if (note == 60u){

IDAC_1_SetValue(255);

}

else if (note == 61u){

IDAC_1_SetValue(0);

}

else if (note == 62u){

IDAC_1_SetValue(255);

}

else if (note == 63u){

IDAC_1_SetValue(0);

}

else if (note == 64u){

IDAC_1_SetValue(255);

}

else if (note == 65u){

IDAC_1_SetValue(0);

}

}

Op wo 15 mei 2019 om 09:35 schreef AH_96 <community-manager@cypress.com>:

<http://www.cypress.com>

Cypress Developer Community

<https://community.cypress.com/?et=watches.email.thread>

UART interrupt triggered by '0' byte from MIDI keyboard

reply from AH_96

<https://community.cypress.com/people/AH_96?et=watches.email.thread> in *PSoC

4 MCU Community* - View the full discussion

<https://community.cypress.com/message/196029?et=watches.email.thread#196029>

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I'm also interested in MIDI, but have not studied it yet.

For the isr, may be you need to add isr_1_ClearPending() ;

Meantime, may be because I'm not too flexible,

but I don't feel comfortable having UART_2_UartPutChar()s in the isr routine.

Also calling UART_1_SpiUartClearRxBuffer() may discard 2nd, 3rd data when receiving the first data.

So if I were you I would modify the code  something like below.

in isr_1.c

===================================

CY_ISR(isr_1_Interrupt)

{

    #ifdef isr_1_INTERRUPT_INTERRUPT_CALLBACK

        isr_1_Interrupt_InterruptCallback();

    #endif /* isr_1_INTERRUPT_INTERRUPT_CALLBACK */

    /*  Place your Interrupt code here. */

    /* `#START isr_1_Interrupt` */

    extern int packet_index ;

    extern int packet_received ;

    extern uint8_t packet[] ;

    extern uint8_t packet_size ;

    if (UART_1_SpiUartGetRxBufferSize()) { /* if we have any data */

        packet[packet_index++] = UART_1_UartGetChar() ;

        if (packet_index >= PACKET_SIZE) {

            packet_index = 0 ;

            packet_received = 1 ;

        }

    }

    UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY) ;

    isr_1_ClearPending() ;

    /* `#END` */

}

===================================

in main.c

===================================

#include "common.h"

#include "bas.h"

#include "project.h"

#include "isr_1.h"

#include "stdio.h"

char str[32] ; /* print buffer */

int         packet_index = 0 ;

uint8_t  packet_size ;

int         packet_received = 0 ;

uint8_t  packet[3] ;

void checkValue(uint8_t command, uint8_t note, uint8_t speed)

{

    sprintf(str, "%02X %02X %02X\r\n", command, note, speed) ;

    UART_2_UartPutString(str) ;

    if (note == 60u){

        IDAC_1_SetValue(255);

    }

    else if (note == 61u){

        IDAC_1_SetValue(0);

    }

    else if (note == 62u){

        IDAC_1_SetValue(255);

    }

    else if (note == 63u){

        IDAC_1_SetValue(0);

    }

    else if (note == 64u){

        IDAC_1_SetValue(255);

    }

    else if (note == 65u){

        IDAC_1_SetValue(0);

    }

}

int main()

{

    CyGlobalIntEnable;

 

    UART_1_SpiUartClearRxBuffer() ;

    UART_1_ClearRxInterruptSource(UART_1_INTR_RX_NOT_EMPTY) ;

    isr_1_ClearPending() ;

    isr_1_StartEx(isr_1_Interrupt);

    UART_1_Start();

    UART_2_Start();

 

    IDAC_1_Start();

    IDAC_1_SetValue(0);

 

    while(1){

        if (packet_received) {

            checkValue(packet[0], packet[1], packet[2]) ;

            packet_received = 0 ;

        }

    }

 

   // setvbuf(stdin, NULL,_IONBF, 0);     

}

===================================

Note: In case this does not work, I'm very sorry for that.

moto

0 Likes