Frame error on MIDI reception

Last post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Avrfreaks!

I am trying to get an Atmega8 to receive MIDI data at the USART (Yes I have read Midi and the avr and several other very nice tutorials and I know how the protocol is too).

The problem is that if I send a control code from my external MIDI transmitter (right now a foot controller) I only get 0x80 at all places in the receive buffer in the avr. Also no matter what channel I send it on (the least significant nibble should tell the MIDI channel). If I check the USCRA register before I read out the UDR reg. I get 0xB0, which tells me:

7. USART Receive complete
5. USART data register empty (??)
4. Frame error

It should be simple to get this up and running so I hope someone has some suggestions! Here is the code

/* Name: main.c
 * Author: 
 * Copyright: 
 * License: 
 */

#include 
#include 
#include 
#include "i2cDebug.h"
#include  

#define CPU_CLOCK 8000000
#define BIT(x) (1 << (x)) 
#define SETBITS(x,y) ((x) |= (y)) 
#define CLEARBITS(x,y) ((x) &= (~(y))) 
#define SETBIT(x,y) SETBITS((x), (BIT((y)))) 
#define CLEARBIT(x,y) CLEARBITS((x), (BIT((y)))) 
#define BITSET(x,y) ((x) & (BIT(y))) 
#define BITCLEAR(x,y) !BITSET((x), (y)) 
#define BITSSET(x,y) (((x) & (y)) == (y)) 
#define BITSCLEAR(x,y) (((x) & (y)) == 0) 
#define BITVAL(x,y) (((x)>>(y)) & 1)
#define HERTZ(x) ((CPU_CLOCK/400)/2) 
#define SWITCH_PIN PIND
#define SW1 PD7
#define SW2 PD6
#define SW3 PD5
#define V_SWITCH_PIN PINC
#define V_SWITCH1 PC4
#define V_SWITCH2 PC5
#define LED_DISP PORTD
#define LD1 PD3
#define LD2 PD2
#define LD3 PD1
#define LD4 PD4
#define LED1 8
#define LED2 4
#define LED3 2
#define LED4 0x10
#define LED_MASK 0x0F
#define OSC_INIT 0x80
#define UP 1
#define DOWN 0
#define DUTY_STEP 2
#define FREQ_STEP 1
#define SWEEP_MIN 0xFF
#define SWEEP_MAX 0xFFF
#define BIG_DELAY 100
#define SM_DELAY 10
#define SYSTEM_CLOCK 8000000
#define MIDI_BAUD 31250
#define MIDI_CTRL_MASK 0x80
//#define UBRR_VAL 15 //v 8000000
//test

//global variables
volatile unsigned char ringBufHead = 0;
volatile unsigned char ringBufTail = 0;
volatile unsigned char ringBuf[64];
volatile unsigned char error = 0;



ISR(USART_RXC_vect){
	
	unsigned char midiRX;
	error = UCSRA;
	midiRX = UDR;
	ringBuf[ringBufTail] = midiRX;
	ringBufTail++;
		
}

void ini(void){
	
	//pins and ports
	
	
	DDRD = 0b00001110; //mixed
	i2c_init();
	//debug --- 
	LED_DISP = LED1;
	// ----

	// Set PB1 and PB2 as outputs
	DDRB |= 0xFF; //all out
	
	//UART:
	//set BAUD rate
	unsigned char ubrr_val = 31;
	//ubrr_val = ((SYSTEM_CLOCK/(MIDI_BAUD*16)) - 1); //= 31, (gives overflow)
	UBRRH = (unsigned char) (ubrr_val>>8);
	UBRRL = (unsigned char)  ubrr_val;
	UCSRB = (1<<RXEN) | (1<<RXCIE); 	//enable reciever, interrupt on recieve
	UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 	// 8 bit data, asynchonous, 1 stop bit, no parity
	sei(); //global interrupt enable
	
}



int main(void)
{

	ini();
	int i = 0;
		
	for(;;){
		
		if (bit_is_clear(SWITCH_PIN, SW1)){ //big blue button
			//debug LED:
			LED_DISP = LED2;
			
			_delay_ms(SM_DELAY); //prell delay
			i2cStart();
			for(i = ringBufHead; i < ringBufTail; ++i)
			 		{
			 			i2cWrite(ringBuf[ringBufHead]);
			 		}
			ringBufTail = 0;
			ringBufHead = 0; 		
			
					
			while(bit_is_clear(SWITCH_PIN, SW1)); //until button is released
			i2cStop();
			LED_DISP = LED1;
		
		} else if (bit_is_clear(SWITCH_PIN, SW2)){
			
			_delay_ms(SM_DELAY); //prell delay
			i2cStart();
			LED_DISP = LED3;
			//test:
			i2cWrite(0x01);
			i2cWrite(0x02);
			i2cWrite(0x03);
			i2cWrite(0x04);
			
			while(bit_is_clear(SWITCH_PIN, SW2)); //until button is released
			i2cStop();
			LED_DISP = LED1;
		} else if (bit_is_clear(SWITCH_PIN, SW3)){
			_delay_ms(SM_DELAY); //prell delay
			i2cStart();
			LED_DISP = LED4;
			i2cSendBytes(0x00, error); 
		
			while(bit_is_clear(SWITCH_PIN, SW3)); //until button is released
			i2cStop();
			LED_DISP = LED1;
		} 
		    
	}                                 
}






  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
#define CPU_CLOCK 8000000
First, how sure are you that the AVR is really running at this rate. And second do you realize that the functions in also needs this value (though it needs it defined as F_CPU)?

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define CPU_CLOCK 8000000 

Tell us more about this.

(IOW are you using an 8MHz crystal?)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Tell us more about this.

(IOW are you using an 8MHz crystal?)

Ah, I forgot to update that #define (but I'm not using it anyway). I use a 16MHz crystal now.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello oleoleo2,

where is your wrap around?

volatile unsigned char ringBuf[64]; 
volatile unsigned char ringBufTail = 0; 


   ringBuf[ringBufTail] = midiRX; 
   ringBufTail++; 

This would only work, if your buffer's size were 256.

Regards,
michaeL

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
#define CPU_CLOCK 8000000
First, how sure are you that the AVR is really running at this rate. And second do you realize that the functions in also needs this value (though it needs it defined as F_CPU)?

1. I'm sure it's not! (sorry for that one forgot to change/remove it).
I am using a 16MHz crystal. I cant' check that it is actually running 16MHz cause my oscilloscope can't measure a frequency that high, but if I pick it up the Atmega8 stops.

2. No, but thanks for the info! I don't think that could be the problem though, as it is only my "Debug system" (http://www.saleae.com/logic/) that uses the delay and it works apparently.

I am using AVR-gcc on Mac (avrdude) and AVR-fuse 1.0.1 to program it with.
I have attached the makefile where the frequency is defined.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skotti wrote:
Hello oleoleo2,

where is your wrap around?

volatile unsigned char ringBuf[64]; 
volatile unsigned char ringBufTail = 0; 


   ringBuf[ringBufTail] = midiRX; 
   ringBufTail++; 

This would only work, if your buffer's size were 256.

Regards,
michaeL

Well, it's not implemented as a ringbuffer yet. I just test small amount of data and then set head and tail to location zero again.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define SYSTEM_CLOCK 8000000

Did you update that define, too ? 'Cause its used for calculating the Midi baudrate.
And perhaps let us know which optocoupler you use. An e.g. CNY17 will not work - a PC900 will .

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mschoeldgen wrote:

#define SYSTEM_CLOCK 8000000

Did you update that define, too ? 'Cause its used for calculating the Midi baudrate.

I have updated it. Actually if I use it to calculate the Midi baud I get a integer overflow compile error, so that's why that Midi baud calculation is done manually and the line that calculates the baud is uncommended (should give UBRR = '31').

I use a 6N138 optocoupler with '5' to GND, VCC on '8'. RXD on '6' with 10K pull up the MIDI signal from pin '4' at the Midi connector through a series 220R to pin '2' on the opto. Pin '5' on the midi connector to pin '3' on the opto...(I'm gonna make a drawing soon :)

hmm...that could be very obvious that the error could be somewhere around the optocoupler couldn't it?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have double checked the optocoupler setup now. I even tried to couple an old working optocoupler setup (programmed with a different processor and in assembly, so I can't just copy the code). It gives the same results so I think it is unlikely that the optocoupler setup is the problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I discovered the mistake! (a very stupid one indeed)

for(i = ringBufHead; i < ringBufTail; ++i) 
                { 
                   i2cWrite(ringBuf[ringBufHead]); 
                } 

I am using ringBufHead as index, but updating i, Jesus!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, that was apparently only part of the problem. I still got framing errors. If someone have good ideas please speak up! I have checked with a working optocoupler setup so I guess that's not where it is burried. The processor is an Atmega8A-PU, it should be able to run at 16MHz.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Framing errors generally speak of un-synced clocks.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the clue Clawson! What I though..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

10k on a 6N138? Please use your logic analyzer to determine the reception is sane. Too high resistance value will cause the line to rise slowly. Most people have something like 270 ohms there.

You know you could use the USART to transmit a know character like 'U' and measure the bit lengths, so that you know you have configured it on 31250 bps and you are running on 16MHz.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
10k on a 6N138? Please use your logic analyzer to determine the reception is sane. Too high resistance value will cause the line to rise slowly. Most people have something like 270 ohms there.

You know you could use the USART to transmit a know character like 'U' and measure the bit lengths, so that you know you have configured it on 31250 bps and you are running on 16MHz.

Thanks! I have lowered the resistor to 300 Ohm (I copied the setup from a projekt that was posted in this forum, I have learnt a lesson here: always check datasheet :)). Actually I have seen that 10K resistor in several places with similar projects eg. here http://www.embedds.com/wp-content/uploads/2007i/0709/midi_sch_big.png (not saying that i makes it more right)

When I measure with the logic analyzer at the optocoupler at 31250 BAUD, I get the right values. I tried to set the logic analyzer at the USART TX. I couldn't get a value out of it. The funny thing is apparently when I set the TXCIE in the UCSRB reg. I started to get the right values at the receiver and no frame error! how weird is that(???).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oleoleo2 wrote:
Actually I have seen that 10K resistor in several places with similar projects eg. here http://www.embedds.com/wp-content/uploads/2007i/0709/midi_sch_big.png (not saying that i makes it more right)

Well beats me, it may have been a mixup between other optocouplers with different kind of outputs that can work with such a value.

In fact the previous time I saw that schematic, I kept thinking why have USB-UART to AVR and then from AVR UART to MIDI port, while the FTDI USB chip is perfectly capable of 31250 bps operation. Most likely just in case that PC software uses UART but the software sets the UART to more standard frequency like 38400 bps. I have one MIDI synth module with RS232 to PC, selectable between 31250 and 38400. The PC must obey with the 38400 that it does not send more than 3150 bytes averaged over some smallish time period.

oleoleo2 wrote:

When I measure with the logic analyzer at the optocoupler at 31250 BAUD, I get the right values. I tried to set the logic analyzer at the USART TX. I couldn't get a value out of it. The funny thing is apparently when I set the TXCIE in the UCSRB reg. I started to get the right values at the receiver and no frame error! how weird is that(???).

Very weird. Do a double-check?