// rgb_controller
// Fab Academy Final Project
// Mio Kato
// 13/5/29

#include 
#include 

// I/O
#define output(directions,pin) (directions |= pin) // set port direction for output
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin

// Test
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 102 // bit delay for 9600 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define char_delay() _delay_ms(10) // char delay

// Serial
#define serial_port PORTA
#define serial_direction DDRA
#define serial_tx (1 << PA6) // TX(MOSI)
#define serial_rx (1 << PA5) // RX(MISO)

// reference voltage
#define vol_pin_out (1 << PA7)

// put sensing data
void put_char(volatile unsigned char *port, unsigned char pin, unsigned char txchar) {
    //
    // send character in txchar on port pin
    //    assumes line driver (inverts bits)
    //
    // start bit
    //
    clear(*port,pin);
    bit_delay();
    //
    // unrolled loop to write data bits
    //
    if bit_test(txchar,0)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,1)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,2)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,3)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,4)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,5)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,6)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    if bit_test(txchar,7)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
    //
    // stop bit
    //
    set(*port,pin);
    bit_delay();
    //
    // char delay
    //
    bit_delay();
    }

// main
int main(void) {

  // set clock divider
	CLKPR = (1 << CLKPCE);
  CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);

  // set serial port
	set(serial_port, serial_tx);
	output(serial_direction, serial_tx);

  // set voltage init
	set(serial_port, vol_pin_out);
	output(serial_direction, vol_pin_out);

  // use three ADC
	unsigned char color_value[3]; // array of RGB
	unsigned char AD[3] = {0b00000000, 0b00000001, 0b00000010}; //ADMAX array
  int i; // use for loop

	// init ADC
	ADCSRA = (1 << ADEN) // use ADC
    | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler 128
	ADCSRB = (1 << ADLAR); // only use 1 char

  while(1) {
    //send framing
    put_char(&serial_port, serial_tx, 1);
    char_delay();
    put_char(&serial_port, serial_tx, 2);
    char_delay();
    put_char(&serial_port, serial_tx, 3);
    char_delay();
    put_char(&serial_port, serial_tx, 4);
    char_delay();

		for (i = 0; i < 3; i++)
		{
		ADMUX = AD[i];

		// start AD Convert
		ADCSRA |= (1 << ADSC);
		// wait converting
		while (ADCSRA & (1 << ADSC))
        	;

		// After framing, start ADC and receive convert data
		// Then sending data using software serial
		color_value[i] = ADCH;
		put_char(&serial_port, serial_tx, color_value[i]);
		char_delay();

		}
    // For test making this
    put_char(&serial_port, serial_tx, '\n');
    char_delay();
    }
}