#include <stdlib.h>
#include <string.h>
#include <math.h>

#define F_CPU 8000000UL  // 1 MHz
    
#include <util/delay.h>


#include <avr/interrupt.h>

typedef uint8_t boolean;
typedef uint8_t byte;

#define REDPWM 0
#define WHTPWM 1
#define ONETWO 4
#define THREEFOUR 3

#define FALSE 0
#define TRUE 1


#define HIGH 0x1
#define LOW  0x0

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

void fadeInOut(boolean);
void setDuty(byte);
void releasePin(byte);
void attachPin(byte, byte);
void digitalWrite(byte, byte);
void delay(long);


int main() {

delay(10000);

//setup timer

sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
// set timer 0 prescale factor to 64
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);

//set pin directions
DDRB=0b00111111;


for(;;){

  releasePin(THREEFOUR);
  attachPin(ONETWO, LOW);
  //digitalWrite(ONETWO, LOW);
  delay(1000);
  fadeInOut(FALSE);
 
  digitalWrite(ONETWO, HIGH);
  delay(1000);
  fadeInOut(TRUE);
  
  
  releasePin(ONETWO);
  attachPin(THREEFOUR, LOW);
  //digitalWrite(THREEFOUR, LOW);
  delay(1000);
  fadeInOut(FALSE);
 
  digitalWrite(THREEFOUR, HIGH);
  delay(1000);
  fadeInOut(TRUE);


}

}

void fadeInOut(boolean inverted){
  
  if(inverted){
    //attachPin(REDPWM, HIGH);
    for(int i = 0; i<=254; i++){
      setDuty(255-i);
      setDuty(255-i);
      delay(10);
    }
  
    for(int i = 254; i>=0; i--){
      setDuty(255-i);
      setDuty(255-i);
      delay(10);
    }
  }
  
  else{
    //attachPin(REDPWM, LOW);
    for(int i = 0; i<=255; i++){
      setDuty(i);
      setDuty(i);
      delay(10);
    }
  
    for(int i = 255; i>=0; i--){
      setDuty(i);
      setDuty(i);
      delay(10);
    }
  }
  
  releasePin(REDPWM);
  releasePin(WHTPWM);
  cbi(TCCR0A, COM0A1); //stop the PWM
  OCR0A = 0;
  
}


void setDuty(byte val){

if(!bitRead(TCCR0A, COM0A1)){
	//cbi(DDRB, 0);
	//TIFR=0xff;
	sbi(GTCCR, TSM);
	sbi(GTCCR, PSR0);
	sbi(TCCR0A, COM0A1);
	OCR0A = val;
	cbi(GTCCR, TSM);
	//TCNT0 = 0;
	//delay(10);
	sbi(DDRB, 0);
	}
  // set pwm duty
 else OCR0A = val;


}

void releasePin(byte pin){

byte bit = _BV(pin);

  //pinMode(pin, INPUT);
  DDRB &= ~bit;
  //digitalWrite(pin, LOW); //disable pull-up
  PORTB &= ~bit;
  
}

void attachPin(byte pin, byte initval){

	byte bit = _BV(pin);

	//digitalWrite(pin, initval);
	if (initval == LOW) PORTB &= ~bit;
	else PORTB |= bit;
	//pinMode(pin, OUTPUT);
	DDRB |= bit;
}

void digitalWrite(byte pin, byte val){

	byte bit = _BV(pin);

	//digitalWrite(pin, initval);
	if (val == LOW) PORTB &= ~bit;
	else PORTB |= bit;
	
}

void delay(long time){

//long cycles = time * 8000;

//while(cycles-- > 0) {}

 _delay_ms(time); 

}
