/* 	Code for reading pulses from a quadrature encoder.
	Output is directed to an LCD on PORTC of an ATMEGA32
	Code uses AvrLib for the LCD so this must be installed to compile
	19/08/2005 By rue_mohr            */

/*                       ATmega32 - 40 PIN DIP LAYOUT FOR LCD AND DECODER- 
                                      _______________________
                                      [ 1]PB0         PA0[40] 
                                      [ 2]PB1         PA1[39]
                                      [ 3]PB2         PA2[38] 
                                      [ 4]PB3         PA3[37] 
                                      [ 5]PB4         PA4[36] 
                                      [ 6]PB5         PA5[35] 
                                      [ 7]PB6         PA6[34] 
                                      [ 8]PB7         PA7[33] 
                             RESET -> [ 9]RST        AREF[32] <- +5V VCC
                            5V VCC -> [10]VCC         GND[31] <- GROUND
                            GROUND -> [11]GND        AVCC[30] <- +5V VCC
                       16 MHZ XTAL -> [12]XTAL1       PC7[29] -> LCD DATA 7
                       16 MHZ XTAL -> [13]XTAL2       PC6[28] -> LCD DATA 6
                                      [14]PD0         PC5[27] -> LCD DATA 5
                                      [15]PD1         PC4[26] -> LCD DATA 4
                          Encoder 1   [16]PD2         PC3[25] -> LCD E  
                          Encoder 2   [17]PD3         PC2[24] -> LCD RS 
                                      [18]PD4         PC1[23] -> LCD RW 
                                      [19]PD5         PC0[22]                  
                                      [20]PD6         PD7[21]  
                                      ______________________                         */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "global.h"
#include "rprintf.h"
#include "lcd.h"
#include "timer.h"
 
void setupEncoder(void);
void updatePos(void);
int position;           // note that this is signed
int revs;		//motor revolutions
unsigned char oldstate; // for quadrature decoding

int main(void)  {
        // initialize the timer system
        timerInit();
	// initialize LCD on PortC
	lcdInit();
	// direct printf output to LCD
	rprintfInit(lcdDataWrite);
 	lcdClear(); //Clear LCD
	setupEncoder(); 
	sei();
 
	while (1) {
	lcdGotoXY(1,0);	// LCD Line 1 , Character 1
	// print motor position to LCD
	rprintf("Position %d  ",position); 
        lcdGotoXY(1,1); // LCD Line 2 , Character 1
        // print motor revolutionss to LCD
        rprintf("Mot/Revs %d  ",revs);
}
}
 
void setupEncoder() {
	// clear position
	position = 0; 
 
	// we need to set up int0 and int1 to 
	// trigger interrupts on both edges
	MCUCR = (1<<ISC10) | (1<<ISC00);
 
	// then enable them.
	GICR  = (1<<INT0) | (1<<INT1);
}
 
#define ERROR 0
	signed char offsets[] = {
	/* 0000 */   0,
	/* 0001 */  +1,
	/* 0010 */  -1,
	/* 0011 */   ERROR,
	/* 0100 */  -1,
	/* 0101 */   0,
	/* 0110 */   ERROR,
	/* 0111 */  +1,
	/* 1000 */  +1,
	/* 1001 */   ERROR,
	/* 1010 */   0,
	/* 1011 */  -1,
	/* 1100 */   ERROR,
	/* 1101 */  -1,
	/* 1110 */  +1,
	/* 1111 */   0
};
 
SIGNAL (SIG_INTERRUPT0) {  // fix this signal name!!! INT0
	updatePos();
}
 
SIGNAL (SIG_INTERRUPT1) { // fix this signal name!!! INT1
	updatePos();
}
 
void updatePos() {
unsigned char temp;
/*	get the bits        PIND     = XXXXiiXX
  	clear space       & 0x0C     = 0000ii00
  	or in old status  | oldstate = XX00iijj
 	clean up          & 0x0F     = 0000iijj  */  
	oldstate = oldstate | (PIND & 0x0C); // Update Oldstate 
	position += offsets[oldstate]; 	     // Update Position
	oldstate = oldstate >> 2; 
	// This example uses a HP deskjet 500 DC motor Quadrature encoder
	// The encoder has 504 slots on the wheel giving a total of 2016 quadrature
	// pulses per revolution. revs keeps track of the total amount of turns in either
	// direction from the starting position
	if (position == 2016) {position = 0; revs++;} // 2016 == Encoder slots * 4
	if (position == -1) {position = 2015; revs--;}// adjust for different encoders
}
