/*******************************************************************************
 Rue's "is it alive" program for avr processors
  also makes a good skel to build your programs form.
*******************************************************************************/
 
/*



1     PB0 <- led
2	  PB1 
3	  PB2 
4	  PB3 
5	  PB4 
6     PB5
7     PB6 
8     PB7 
9     PA0 
10    PA1  	 
11    PA2 
12    PA3  
13    PA4   
14    PA5  
15    PA6	
16    PA7
17    PC7
18	  PC6
19	  PC5
20	  PC4
21	  PC3
22	  PC2
23	  PC1
24	  PC0
25	  PD7
26	  PD2
27	  PD3  data line
28	  PD4  
29	  PD5
30	  PD6  clock for greyscale pwm chip


*/


// manual port D bits 2 to 7


#include <avr/io.h>
#include <avr/interrupt.h>


// misc
#define SETBIT(BIT, PORT)  PORT |= (1<<BIT)
#define CLRBIT(BIT, PORT)  PORT &= ~(1<<BIT)

#define IsHigh(BIT, PORT)    (PORT & (1<<BIT)) != 0
#define IsLow(BIT, PORT)     (PORT & (1<<BIT)) == 0

#define OUTPUT             1
#define INPUT              0



  #define SetBit(BIT, PORT)     PORT |= (1<<BIT)
  #define ClearBit(BIT, PORT)   PORT &= ~(1<<BIT)
  #define IsHigh(BIT, PORT)    (PORT & (1<<BIT)) != 0
  #define IsLow(BIT, PORT)     (PORT & (1<<BIT)) == 0
  #define NOP()                 asm volatile ("nop"::)

  // Bit positions, PORTD 
  #define BLANKIN          2
  #define SIN              3
  #define SCLK             4
  #define XLAT             5
  #define BLANKOUT         6


  #define SINlow()              ClearBit(SIN, PORTD)
  #define SCLKlow()             ClearBit(SCLK, PORTD)
  #define XLATlow()             ClearBit(XLAT, PORTD)
  #define BLANKlow()            ClearBit(BLANKOUT, PORTD)
  
  #define SINhigh()             SetBit(SIN, PORTD)
  #define SCLKhigh()            SetBit(SCLK, PORTD)
  #define XLAThigh()            SetBit(XLAT, PORTD)
  #define BLANKhigh()           SetBit(BLANKOUT, PORTD)

  #define pulseSCK()            SCLKhigh(); NOP(); NOP(); SCLKlow()
  #define pulseXLAT()           XLAThigh(); NOP(); NOP(); XLATlow()
  
  #define SendOne()            SINhigh(); pulseSCK()
  #define SendZero()           SINlow();  pulseSCK()
  
  void send12 (unsigned int bits);
  void Delay(unsigned int delay) ;
  void Delay2(unsigned int delay) ;
  void setupInterrupt(void);
  
  volatile unsigned int value;

int main (void) {

  unsigned int i;
  

  // set up directions 
  DDRB = (INPUT << PB0 | INPUT << PB1 |INPUT << PB2 |INPUT << PB3 |INPUT << PB4 |INPUT << PB5 |INPUT << PB6 |INPUT << PB7);
  DDRC = (INPUT << PC0 | INPUT << PC1 |INPUT << PC2 |INPUT << PC3 |INPUT << PC4 |INPUT << PC5 |INPUT << PC6 );
  DDRD = (INPUT << PD0 | INPUT << PD1 |INPUT << PD2 |OUTPUT << PD3 |OUTPUT << PD4 |OUTPUT << PD5 |OUTPUT << PD6 |INPUT << PD7);        
     
  // this is stupid and I could make my own pwm eaiser.   
   
   XLATlow();
   SCLKlow();
   setupInterrupt();
   sei();
            
  while(1) {
    value++;
    if (value == 4095) value = 0;      
   Delay(500);       
  }
  

}


void setupInterrupt() {
 
        // we need to set up int0 
        // trigger interrupts on rising edges
        EICRA = (1<<ISC00) | (1<<ISC01);
 
        // then enable them.
        EIMSK  = (1<<INT0) ;
}

// there was just a BLANK, so update the pwm values.
ISR( INT0_vect ) {
   unsigned int i;

   BLANKhigh();
   pulseXLAT();
   BLANKlow();
  // for( i = 0; i < 16; i++) {  send12(1024);   }
  /*
  send12(256);
  send12(512);
  send12(768);
  send12(1024);
  send12(1280);
  send12(1536);
  send12(1792);
  send12(2048);
  send12(2304);
  send12(2560);
  send12(2816);
  send12(3072);
  send12(3328);
  send12(3584);
  send12(3840);
  send12(4095);
  */
  
  send12(0);  // channel 15
  send12(0);
  send12(0);
  send12(0);
  send12(0);
  send12(0);
  send12(0); //
  send12(1000); // channel 7ish
  send12(0); //channel 6
  send12(0); // channel 6
  send12(0); // mauled channel 5
  send12(0); // mauled channel 4
  send12(0); // mauled channel 3
  send12(0); // channel 2, but mauled
  send12(0); // channel 1
  send12(0); //channel 0
}


// send a 12 bit word, msb first
void send12 (unsigned int bits) {
  unsigned int temp;  
  for( temp = (1<<11); temp != 0; temp >>= 1) {    
    if ( (bits & temp) != 0 ) {    SendOne();
    } else {                       SendZero();
    }    
  } 
}

void Delay(unsigned int delay) {
  unsigned int x;
  for (x = delay; x != 0; x--) {
    asm volatile ("nop"::); 
  }
}

void Delay2(unsigned int delay) {
  unsigned int x;
  for (x = delay; x != 0; x--) {
    Delay(65000);
  }
}

