Frame error on MIDI reception

17 posts / 0 new
Last post
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!

Pages