Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
oleoleo2
PostPosted: Oct 20, 2011 - 08:45 PM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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
Code:
/* Name: main.c
 * Author: <insert your name here>
 * Copyright: <insert your copyright message here>
 * License: <insert your license reference here>
 */

#include <avr/io.h>
#include <util/delay.h>
#include <math.h>
#include "i2cDebug.h"
#include <avr/interrupt.h>

#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;
      }
         
   }                                 
}






 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Oct 20, 2011 - 08:50 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15127
Location: Vancouver, BC

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 <util/delay> also needs this value (though it needs it defined as F_CPU)?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Oct 20, 2011 - 08:51 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71915
Location: (using avr-gcc in) Finchingfield, Essex, England

Code:
#define CPU_CLOCK 8000000

Tell us more about this.

(IOW are you using an 8MHz crystal?)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 21, 2011 - 07:07 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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.
 
 View user's profile Send private message  
Reply with quote Back to top
skotti
PostPosted: Oct 21, 2011 - 07:32 AM
Hangaround


Joined: Sep 10, 2003
Posts: 352
Location: 51,25° / Germany

Hello oleoleo2,

where is your wrap around?
Code:

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
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 21, 2011 - 07:33 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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 <util/delay> 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.
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 21, 2011 - 07:40 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


skotti wrote:
Hello oleoleo2,

where is your wrap around?
Code:

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.
 
 View user's profile Send private message  
Reply with quote Back to top
mschoeldgen
PostPosted: Oct 21, 2011 - 07:46 AM
Hangaround


Joined: Sep 22, 2011
Posts: 240


Code:
#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 .
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 21, 2011 - 07:51 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


mschoeldgen wrote:
Code:
#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 Smile

hmm...that could be very obvious that the error could be somewhere around the optocoupler couldn't it?
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 21, 2011 - 08:49 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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.
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 23, 2011 - 07:26 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


I discovered the mistake! (a very stupid one indeed)
Code:
for(i = ringBufHead; i < ringBufTail; ++i)
                {
                   i2cWrite(ringBuf[ringBufHead]);
                }

I am using ringBufHead as index, but updating i, Jesus!
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 24, 2011 - 08:37 PM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Oct 24, 2011 - 09:21 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71915
Location: (using avr-gcc in) Finchingfield, Essex, England

Framing errors generally speak of un-synced clocks.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 25, 2011 - 06:51 PM
Hangaround


Joined: Mar 11, 2008
Posts: 155


Thanks for the clue Clawson! What I though..
 
 View user's profile Send private message  
Reply with quote Back to top
Jepael
PostPosted: Oct 25, 2011 - 08:04 PM
Raving lunatic


Joined: May 24, 2004
Posts: 6280
Location: Tampere, Finland

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.
 
 View user's profile Send private message  
Reply with quote Back to top
oleoleo2
PostPosted: Oct 26, 2011 - 10:33 AM
Hangaround


Joined: Mar 11, 2008
Posts: 155


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 Smile). Actually I have seen that 10K resistor in several places with similar projects eg. here http://www.embedds.com/wp-content/uploa ... ch_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(???).
 
 View user's profile Send private message  
Reply with quote Back to top
Jepael
PostPosted: Oct 26, 2011 - 02:36 PM
Raving lunatic


Joined: May 24, 2004
Posts: 6280
Location: Tampere, Finland

oleoleo2 wrote:
Actually I have seen that 10K resistor in several places with similar projects eg. here http://www.embedds.com/wp-content/uploa ... ch_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?
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits