/******************************************************************************
Title:    encoder -> PWM
Author:   rue_mohr
Date:     Aug 19 2005
Software: AVR-GCC 3.3 
Hardware: atmega32
  
                         ATmega32 - 40 PIN DIP LAYOUT FOR DECODER AND PWM - 
                                      _______________________
                                      [ 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] 
                       16 MHZ XTAL -> [13]XTAL2       PC6[28] 
                                A0 -> [14]PD0         PC5[27] -> D5
                                A1 -> [15]PD1         PC4[26] -> D4
                        PWM 1 ->      [16]PD2         PC3[25] -> D3  
                        PWM 2 ->      [17]PD3         PC2[24] -> D2 
                               /wr <- [18]PD4         PC1[23] -> D1 
                                      [19]PD5         PC0[22] -> D0        
                               D6 <-  [20]PD6         PD7[21] -> D7
                                      ______________________                         


    
*******************************************************************************/
 
/****************************| INCLUDGEABLES |********************************/
 
#include <avr/io.h>
#include <avr/signal.h>
#include "global.h"
#include "rprintf.h"
#include "timer.h"
#include "lcd.h"
#include "binary.h"



/*****************************| DEFINIATIONS |********************************/
  
#define OUTPUT             1
#define INPUT              0

#define IsHigh(BIT, PORT)    ((PORT & (1<<BIT)) != 0)
#define IsLow(BIT, PORT)     ((PORT & (1<<BIT)) == 0)
#define SetBit(BIT, PORT)     PORT |= (1<<BIT)
#define ClearBit(BIT, PORT)   PORT &= ~(1<<BIT)
// limit v to within low (l) and high (h) limits
#define limit(v, l, h)        ((v) > (h)) ? (h) : ((v) < (l)) ? (l) : (v)
#define NOP()                       asm volatile ("nop"::)

#define TimerReset()                 TCNT1 = 0
#define Ch0High()                    IsHigh(2, PIND)
#define Ch1High()                    IsHigh(3, PIND) 

#define WrLow()                      ClearBit(4, PORTD)
#define WrHigh()                     SetBit(4, PORTD)

 
/*****************************| VARIDIABLIES |********************************/
 volatile unsigned int value0;
 volatile unsigned int value1;
 volatile unsigned int start0;
 volatile unsigned int start1;
/************************| FUNKSHION DECLARATIONS |*************************/

void TimerInit(void);
void Int0Init(void);
void Int1Init(void);
void SetDAC(unsigned char channel, unsigned char value) ;
void SetAddress(unsigned char address) ;
void SetData(unsigned char data) ;

/****************************| MANE CODY... |***********************************/
 
int main (void)  {

  unsigned char ch0, ch1;

  lcdInit();                  // initialize LCD on PortC        
  rprintfInit(lcdDataWrite);  // direct printf output to LCD
  lcdClear();                 // Clear LCD

   	        
 // DDRA = (INPUT << PA0)|(INPUT << PA1)|(INPUT << PA2)|(INPUT << PA3)|(INPUT << PA4)|(INPUT << PA5)|(INPUT << PA6)|(INPUT << PA7);
  // port B for lcd  
  DDRC = (OUTPUT << PC0)|(OUTPUT << PC1)|(OUTPUT << PC2)|(OUTPUT << PC3)|(OUTPUT << PC4)|(OUTPUT << PC5)|(OUTPUT << PC6);
  DDRD = (OUTPUT << PD0)|(OUTPUT << PD1)|(INPUT << PD2)|(INPUT << PD3)|(OUTPUT << PD4)|(OUTPUT << PD5)|(OUTPUT << PD6)|(OUTPUT << PD7);        
  
  TimerInit(); // turn on timer
  Int0Init();  // set up interrupts for either edge of int0
  Int1Init();
  
  sei();

  
while(1) { 
    ch0 = (limit(value0, 1000, 2000)-1000)/4;
    ch1 = (limit(value1, 1000, 2000)-1000)/4;

    lcdGotoXY(0,0); // Char 1, LCD Line 2   
    rprintf(" >0 %d  V 5.4     ", ch0 );
    lcdGotoXY(0,1); // Char 1, LCD Line 2   
    rprintf(" >1 %d       ", ch1);
    
    SetDAC(0, ch0);
    SetDAC(1, ch1);
  }
  return 0;
}
    
//------------------------| FUNCTIONS |------------------------

void SetAddress(unsigned char address) {
  PORTD   &= ~b00000011;
  address &= b00000011;
  PORTD   |= address;
}

void SetData(unsigned char data) {
  unsigned char temp;
  
  temp = data & b11000000; // bits 6 and 7 to port D
  data &= b00111111;       // bits 0 thru 5 to port C
  
  PORTC   &= b11000000;  // clear our bits of port C
  PORTC   |= data;       // or in our data
  
  PORTD   &= b00111111;  // clear bits of port D
  PORTD   |= temp;       // or in our bits of port D

}

void SetDAC(unsigned char channel, unsigned char value) {
  WrHigh();
  SetAddress(channel);
  SetData(value);
  WrLow();
  NOP();
  WrHigh();
}

void TimerInit() { //set up 10Khz timer (15.625Khz)
  TCCR1B = (1<<CS10);  // 1Mhz / 1  !!!PROCESSOR!!!!
}

void Int0Init() {
  MCUCR |= (1<<ISC00);  // trigger interrupt on any edge !!!PROCESSOR!!!!
  SetBit(INT0, GICR); // enable the interrupt !!!PROCESSOR!!!!
}

void Int1Init() {
  MCUCR |= (1<<ISC10);  // trigger interrupt on any edge !!!PROCESSOR!!!!
  SetBit(INT1, GICR); // enable the interrupt !!!PROCESSOR!!!!
}


SIGNAL (SIG_INTERRUPT0) { 
	if (Ch0High()) {  // bit just went high, check value of time
	  start0 = TCNT1;
    } else {      // bit just went low, reset timer
      value0 = TCNT1 - start0;
    }
}

SIGNAL (SIG_INTERRUPT1) { 
	if (Ch1High()) {  // bit just went high, check value of time
	  start1 = TCNT1;
    } else {      // bit just went low, reset timer
      value1 = TCNT1 - start1;
    }
}


