- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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);
}
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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