//
// Encoder module common operations library
//
// Department of Mechatronics
// Tallinn University of Technology
// © Copyrights 2010
//

//
// Take use of pin and timer operations
//
#include "pin.h"
#if defined (__AVR_ATmega128__)
#include "timer128.h"
#elif defined (__AVR_ATmega2561__)
#include "timer2561.h"
#endif

//
// Use interrupts
//
#include <avr/interrupt.h>

//
// Encoders count
//
#define NUM_ENCODERS 2

//
// Encoder counter ticks per second
//
#define ENCODER_TICKS (F_CPU / 8 / 256)

//
// Pin configuration
//
static pin encoder_pins[NUM_ENCODERS] =
{
	PIN(E, 6),
	PIN(E, 7)
};

//
// Data types
//
typedef struct
{	
	unsigned short num_pulses;
}
encoder_data;

//
// Local variables
//
//static unsigned short encoder_ticks = 0;
static encoder_data encoder[NUM_ENCODERS];

//
// Encoder pulse interrupt handler.
//
void encoder_pulse(unsigned char index)
{
	encoder[index].num_pulses++;
}

//
// External interrupt.
//
ISR(INT6_vect)
{
	encoder_pulse(0);
}

//
// External interrupt.
//
ISR(INT7_vect)
{
	encoder_pulse(1);
}

//
// Specific encoder initialization
//
void encoder_init(unsigned char index)
{
	// Set pin as input
	pin_setup_input_with_pullup(encoder_pins[index]);
	
	// Enable external interrupts on falling edge.
	switch (index)
	{
		case 0:
			bit_set(EICRB, ISC61);
			bit_clear(EICRB, ISC60);
			bit_set(EIMSK, INT6);
			break;
			
		case 1:
			bit_set(EICRB, ISC71);
			bit_clear(EICRB, ISC70);
			bit_set(EIMSK, INT7);
			break;
	}
	
	// Reset data
	encoder[index].num_pulses = 0;
}

//
// Reset specific encoder number of pulses
//
void encoder_reset_pulses(unsigned char index)
{	
	// Interrupt-safe resetting
	cli();
	encoder[index].num_pulses = 0;
	sei();
}

//
// Get specific encoder number of pulses
//
unsigned short encoder_get_pulses(unsigned char index)
{
	// Return number of pulses without disabling interrupts.
	return encoder[index].num_pulses;	
}
