/******************************************************************************
 Title:    Code for an IR reciever 
 
 0           1ms       8-9   counts
         Barrier at 17
 1           2.5ms     18-19 counts
         Barrier at 28 
 start bit   5ms       37-38 counts

 
 Author:   rue_mohr
 Date:     Jan 8 2006
 Software: AVR-GCC 3.3 
 Hardware: attiny26
 
    
*******************************************************************************/
#include<avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define Forward                  1
#define Reverse                  -1

#define OUTPUT                   1
#define INPUT                    0

// Bit positions
#define Strobe                   7
#define Data                     5
#define Clock                    4

#define IRDet                    6

#define NumLeds                  123

#define SetBit(BIT, PORT)        PORT |= (1<<BIT)
#define ClearBit(BIT, PORT)      PORT &= ~(1<<BIT)
#define DefBit(BIT, PORT, VALUE) PORT &= (~(1<<BIT))|((VALUE==0?0:1)<<BIT)
#define IsHigh(BIT, PORT)       (PORT & (1<<BIT)) != 0
#define IsLow(BIT, PORT)        (PORT & (1<<BIT)) == 0
#define NOP()                    asm volatile ("nop"::)

#define StrobeH()                SetBit(Strobe, PORTA)
#define StrobeL()                ClearBit(Strobe, PORTA)
#define DataH()                  SetBit(Data, PORTB)
#define DataL()                  ClearBit(Data, PORTB)
#define SetData(B)               DefBit(Data, PORTB, B)
#define ClockH()                 SetBit(Clock, PORTB)
#define ClockL()                 ClearBit(Clock, PORTB)
#define ClockPulse()             NOP(); ClockH(); NOP(); NOP(); ClockL(); NOP()
#define SendOne()                DataH(); ClockPulse()
#define SendZero()               DataL(); ClockPulse()

#define TimerReset()             TCNT0 = 0

#define IRH()                    IsHigh(IRDet, PINB)
#define IRL()                    IsLow(IRDet, PINB)

void Send (unsigned int bits);
void SetLights(unsigned int bits);
void Delay(unsigned int delay);
void OnEdge();
void TimerInit();
void Int0Init();

unsigned int count;

int main (void)  {
 
  DDRA = (INPUT << PA0 | INPUT << PA1 |OUTPUT << PA2 |INPUT << PA3 \
         |INPUT << PA4 | INPUT << PA5 |INPUT << PA6 |OUTPUT << PA7);
         
  DDRB = (INPUT << PB0 | INPUT << PB1 | INPUT << PB2 | INPUT << PB3\
        | OUTPUT << PB4 | OUTPUT << PB5 |INPUT << PB6 |INPUT << PB7);
      
  Int0Init();     
  sei();   
                  
  while(1) {      
     
  }
}
    
//------------------------| FUNCTIONS |------------------------

SIGNAL (SIG_INTERRUPT0) {  // fix this signal name!!! INT0
	//OnEdge();
	if (IRH()) {
	  SetBit(2, PORTA);
    } else {
      ClearBit(2, PORTA);
    }
}

void Int0Init() {
  MCUCR = (1<<ISC00);
  SetBit(INT0, GIMSK); 
}

void OnEdge() {

  if (0) {
  } else if (count > 28) {    
     // start bit
  } else if (count > 17) {
      SendOne();
  } else {
      SendZero();
  } 
  count = 0;
}

void TimerInit() { //set up 10Khz timer (15.625Khz)
  TCCR0 = ((1<<PSR0)|(3<<CS00));  
}

//------| Generic Functions |--------

void Delay(unsigned int delay) {
  unsigned int x;
  for (x = delay; x != 0; x--) {
    NOP();
  }
}

//------| Led array output functions |------

void SetLights(unsigned int bits) {
  StrobeH();
  Send(bits);
  StrobeL();
}

void Send (unsigned int bits) {
  unsigned int temp;  
  for( temp = 32768; temp != 0; temp = temp >> 1) {    
    if ( (bits & temp) == temp ) {
      SendOne();
    } else {
      SendZero();
    }    
  } 
}

