//
//
// hello.RGB.45.c
//
// RGB LED software PWM hello-world
//
// Neil Gershenfeld
// 11/10/10
//
// (c) Massachusetts Institute of Technology 2010
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all 
// liability.
//

#include <avr/io.h>
#include <util/delay.h>
// My addition!!!!!!!!!!!!!!!!!
#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdbool.h>
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#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
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define PWM_delay() _delay_us(25) // PWM delay

//adition fron touchpad
#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 settle_delay() _delay_us(100) // settle delay
#define char_delay() _delay_ms(10) // char delay

////LED RGB
#define led_port PORTB
#define led_direction DDRB
#define red (1 << PB1)
#define green (1 << PB0)
#define blue (1 << PB2)

/////touchpad
#define serial_port PORTB
#define serial_direction DDRB
#define transmit_port PORTB
#define transmit_direction DDRB
#define transmit_pin (1 << PB4)
#define nloop 100 // loops to accumulate

// My Functions' Declarations!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void turn_on_red_led(void);
void turn_on_green_led(void);
void turn_on_yellow_led(void);
void turn_on_blue_led(void);
void turn_on_magenta_led(void);
void turn_off_led(void);
void semaforo(void);
uint16_t leer_value();
void put_char(volatile unsigned char *port, unsigned char pin, char txchar);
void send_info(int value);
// Variables
uint64_t _millis = 0;
uint16_t _1000us = 0;

// Interrupts routines 
// Every 0.256 ms
ISR(TIM0_OVF_vect) {
  _1000us += 256;
  while (_1000us > 1000) {
    _millis++;
    _1000us -= 1000;
  }
}

// safe access to millis counter
uint64_t millis(void) {
  uint64_t m;
  cli();
  m = _millis;
  sei();
  return m;
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

int main(void) {
	//
	// main
	//
	// Declaracion de variables
	static uint64_t start_time;
	static uint16_t quantity, contador, cont_act;
	//
	// set clock divider to /1
	//
	CLKPR = (1 << CLKPCE);
	CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// interrupt setup 
	// prescale timer0 to 1/8th the clock rate
	// overflow timer0 every 0.256 ms
	TCCR0B |= (1<<CS01);
	// enable timer overflow interrupt
	TIMSK  |= 1<<TOIE0;
	// Enable global interrupts
	sei();
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//
	// initialize LED pins
	//   
	output(led_direction, red);
	set(led_port, red);
	output(led_direction, green);
	set(led_port, green);
	output(led_direction, blue);
	set(led_port, blue);
	//
	// init touchpad
	//
	clear(transmit_port, transmit_pin);
	output(transmit_direction, transmit_pin);
	//
	// init A/D touchpad
	//
	ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref
	  | (0 << ADLAR) // right adjust
	  | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); // PB3
	ADCSRA = (1 << ADEN) // enable
	  | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128
	//
	// main loop
	//
	while (1) {	
		if(leer_value() > 12000){
			//Si estas aqui es xq estas tocando
			contador++;
			if(contador == 1){
				quantity++;
			}
		}else{
			contador = 0;
		}
		// Verificar si pasó 1 segundo:
		if(millis() - start_time > 1000){
			cont_act++;
			if (quantity == 1){
			   	turn_on_magenta_led();
				send_info(1);
				_delay_ms(1000);
				turn_off_led();
				_delay_ms(100);
			}
			if (quantity > 1){
			   	turn_on_blue_led();
				send_info(2);
				_delay_ms(1000);
				turn_off_led();
				_delay_ms(100);
			}
			//Inicia un nuevo juego, cada 5 seg:
			if (cont_act == 5){
				semaforo();
				cont_act = 0;
			}			
			// Reiniciar start_time y quantity:
			start_time = millis();	
			quantity = 0;					
		}
		//!!!!!!!!!!!!!!
	}
}

// My Functions' Definitions!
void turn_on_red_led(){
	clear(PORTB, red);
	set(PORTB, green);
	set(PORTB, blue);
}

void turn_on_green_led(){
	set(PORTB, red);
	clear(PORTB, green);
	set(PORTB, blue);
}

void turn_on_blue_led(){
	set(PORTB, red);
	set(PORTB, green);
	clear(PORTB, blue);
}

void turn_on_yellow_led(){
	clear(PORTB, red);
	clear(PORTB, green);
	set(PORTB, blue);
}

void turn_on_magenta_led(){
	clear(PORTB, red);
	clear(PORTB, blue);
	set(PORTB, green);
}

void turn_off_led(){
	set(PORTB, red);
	set(PORTB, green);
	set(PORTB, blue);
}

void semaforo(){
	turn_on_red_led();
	_delay_ms(500);
	turn_on_yellow_led();
	_delay_ms(500);
	turn_on_green_led();
	_delay_ms(500);
	turn_off_led();
}

uint16_t leer_value(){
	//
	// accumulate touchpad magnetic value
	//
	unsigned char count;
	uint16_t up,down,value;
	up = 0;
	down = 0;
	for (count = 0; count < nloop; ++count) {
		// settle, charge
		settle_delay();
		set(transmit_port, transmit_pin);
		// initiate conversion
		ADCSRA |= (1 << ADSC);
		// wait for completion
		while (ADCSRA & (1 << ADSC))
		;
		// save result
		up += ADC;
		// settle, discharge
		settle_delay();
		clear(transmit_port, transmit_pin);
		// initiate conversion
		ADCSRA |= (1 << ADSC);
		// wait for completion
		while (ADCSRA & (1 << ADSC))
		;
		// save result
		down += ADC;
	}
	value = up-down;
	return value;
}

void send_info(int value){
	//
	// send framing
	//
	put_char(&serial_port, transmit_pin, 1);
	char_delay();
	put_char(&serial_port, transmit_pin, 2);
	char_delay();
	put_char(&serial_port, transmit_pin, 3);
	char_delay();
	put_char(&serial_port, transmit_pin, 4);
	//
	// send result
	//
	put_char(&serial_port, transmit_pin, value);
	char_delay();
}

void put_char(volatile unsigned char *port, unsigned char pin, 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();
}	
//!!!!!!!!!!!!!!!!!!
