/******************************************************************************
 Title:    ADC -> PWM
 Author:   dan williams
 Date:     Apr 17 2005
 Software: AVR-GCC 3.3 
 Hardware: Any AVR with built-in ADC, tested with ATmega8 at 1Mhz
  
*******************************************************************************/
#include<avr/io.h>

#define Forward 1
#define Reverse 0

#define Threashold 3

#define abs(A) ((A)>0)?(A):(-A)

void pwm_init( );
void adc_init( );
int  Analog  ( uint8_t n);
void SetPWM  ( uint8_t channel, uint8_t value) ;
void SetDir  ( uint8_t side, uint8_t dir );
void dostuff ( ) ;

int main (void)  {
  DDRB = 0xFF;      // port B output
  DDRD = 0xFF;      // port D output
      
  adc_init();          
  pwm_init();
  
  dostuff();
}
  

//------------------------| FUNCTIONS |------------------------

void SetDir  ( uint8_t side, uint8_t dir ) {
  PORTB |= 0x20;
}


void SetPWM( uint8_t channel, uint8_t value) {
   if (channel == 0)   
      OCR0 = value;
   if (channel == 1)   
      OCR2 = value;
}

void adc_init() {
  // Activate ADC with Prescaler 
  ADCSRA =  1 << ADEN  |
            0 << ADSC  |
            0 << ADATE |
            0 << ADIF  |
            0 << ADIE  |
            1 << ADPS2 |
            0 << ADPS1 |
            0 << ADPS0 ;
}

void pwm_init() {
  // clear pwm levels
  OCR0 = 0; 
  OCR2 = 0;
  
  // set up WGM, clock, and mode for timer 0
  TCCR0 = 0 << FOC0  | 
          1 << WGM00 | /* fast pwm */
          1 << COM01 | /* not inverted */
          0 << COM00 |
          1 << WGM01 | /* fast pwm */
          0 << CS02  | /* no prescale */
          0 << CS01  |
          1 << CS00  ;
  
  // set up WGM, clock, and mode for timer 2
  TCCR2 = 0 << FOC2  | 
          1 << WGM20 |
          1 << COM21 |
          0 << COM20 |
          1 << WGM21 |
          0 << CS22  |
          0 << CS21  |
          1 << CS20  ;
  
 }


int Analog ( uint8_t n ) {

    // Select pin ADC0 using MUX
    ADMUX = n & 7;
    
    //Start conversion
    ADCSRA |= _BV(ADSC);
    
    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}
    
    // get converted value
    return ADC;  
}


void dostuff ( ) {
      int X, Y;
      int SpeedR;
      
      while (1) {
   
        Y = Analog(0);
        
        // Offset correction
        SpeedR = Y - 127;
  
        if (SpeedR < 0) {
           SetDir(1, Reverse );
           SpeedR = -SpeedR;
        } else {
           SetDir(1, Forward );
        }
       
      }

}

