/*
 * Decode_Encoder___2_Detents_Per_Pulse.c
 *
 * Created: 20/12/2014 18:43:42
 *  Author: Mike
 */ 

#include <avr/io.h>
#include "Decode Encoder - 2 Detents Per Pulse.h"

#define PORT(x) (*(&x))			/* address of output register of port x */
#define DDR(x) (*(&x - 1))      /* address of data direction register of port x */
#define PIN(x) (*(&x - 2))      /* address of input register of port x */

uint8_t enc_A_old = 0;
uint8_t enc_A = 0;
uint8_t enc_B = 0;

void EncoderInit_2DetentsPerPulse(void)
{	//Set inputs A and B as inputs with pull-up
	DDR(DECODE_INPUT_PORT) &= ~(1 << DECODE_INPUT_PIN_A) & ~(1 << DECODE_INPUT_PIN_B);
	PORT(DECODE_INPUT_PORT) |= (1 << DECODE_INPUT_PIN_A) | (1 << DECODE_INPUT_PIN_B);
}

/*	
Reads encoder outputs and determines if it has been turned. Returns integer 'result' where:
		-1 -> CCW
		1  -> CW
		0  -> none
Must be called frequently enough that the encoder output is read between detents, i.e. as the dial is turned from one position to another. 
This is because the function must read the value of output B immediately after output A is toggled, else the direction of turn cannot be determined. */
int ReadEncoder_2DetentsPerPulse(void)
{	int result = 0;
	
	enc_A = PIN(DECODE_INPUT_PORT) & (1 << DECODE_INPUT_PIN_A);
	enc_B = PIN(DECODE_INPUT_PORT) & (1 << DECODE_INPUT_PIN_B);
	
	if (enc_A == enc_A_old)			// If output A has not changed since the last measurement, the dial has not been turned.
	{	return result;	}
		
	if (enc_A != enc_A_old)			// If output A has toggled since the last measurement, the dial has been turned.
	{	if (enc_A > 0)				
		{	if (enc_B > 0)			
			{	result = -1;}
			if (enc_B == 0)			
			{	result = 1;	}
		}
		if (enc_A == 0)
		{	if (enc_B > 0)			
			{	result = 1;	}
			if (enc_B == 0)	
			{	result = -1;}
		}
	}
	enc_A_old = enc_A;
	return result;
}