#include <avr/io.h>
#include <avr/interrupt.h>

#define M1 0
#define M2 1
#define MOTOR_PORT PORTB
#define ENAB(i) ((i) ? PB2 : PB0)
#define DIR_A(i) ((i) ? PB3 : PB1)
#define DIR_B(i) ((i) ? PB5 : PB4)

unsigned char velocity[2];
unsigned char cycleCounter = 0;

int main(void)
{
	// Set USART, enable "databyte received" interrupt
	UBRRH=0;
	UBRRL=51;
	UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
	UCSRC=(1<<URSEL)|(1<<USBS)|(3<<UCSZ0);

	// Set IO
	DDRB=DDRC=0xFF;

	// Set motor direction
	MOTOR_PORT=(1<<DIR_A(M1)|(1<<DIR_A(M2));

	// Set initial velocity
	velocity[M1] = 0;
	velocity[M2] = 0;

	// Enable interrupt system	
	sei();

	// PWM generation loop
	while(1) 
	{
		// rotate from 0 to 255
		cycleCounter++;
		
		if(cycleCounter < velocity[M1])
			MOTOR_PORT |= (1<<ENAB(M1));
		else	
			MOTOR_PORT &= ~(1<<ENAB(M1));	

		if(cycleCounter < velocity[M2])
			MOTOR_PORT |= (1<<ENAB(M2));
		else	
			MOTOR_PORT &= ~(1<<ENAB(M2));			
	}

	return 0;
}

// Interrupt handler - databyte received
SIGNAL(SIG_UART_RECV)
{
	// Wait for receive completion
	while ( !(UCSRA & (1<<RXC)) );
	unsigned char data = UDR;
	
	// Set velocity
	velocity[M1] = ((data &0x07) << 5);
	velocity[M2] = ((data &0x70) << 1);
	
	// wipe previous configuration of driving direction
	MOTOR_PORT &= ~((1<<DIR_B(M1) | (1<<DIR_A(M1) |
		 (1<<DIR_B(M2)) | (1<<DIR_A(M2));
	
	// Set driving direction	
	MOTOR_PORT |= ((data & 0x08) > 0) ? 
		(1 << DIR_A(M1)) : (1 << DIR_B(M1));
	MOTOR_PORT |= ((data & 0x80) > 0) ? 
		(1 << DIR_A(M2)) : (1 << DIR_B(M2));	
} 
