/*
 * HallEffectSensor.c
 *
 * Created: 4/10/2018 4:39:42 PM
 * Author : Marta Cortés
 *
 * Used code from
 // hello.HC-SR04.c
 //
 // HC-SR04 sonar hello-world
 //    9600 baud FTDI interface
 //
 // Neil Gershenfeld 11/15/15
 // (c) Massachusetts Institute of Technology 2015
 //
 // 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.
 //
 */ 

#define F_CPU 20000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin

#define output(directions,pin) (directions |= pin) // set port direction for output
#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


#define serial_port_out PORTA
#define serial_direction_out DDRA
#define serial_pins_in PINA
#define serial_pin_out (1 << PA1)
#define serial_pin_in (1 << PA0)
#define serial_interrupt (1 << PCIE0)
#define serial_interrupt_pin (1 << PCINT0)


#define timeout 255


/**
* CODe for Calculating int output
*/
void calculate (unsigned int measure, unsigned int hall_on){
	static float measured_value;
	measured_value = 5.0*measure/1023.0;
	//Check sensor value in PINA
	if(measured_value>3){ //if 0, check schematics
		//Put value in PORTB
		if(hall_on==7)
			clear(PORTB,1<<PB2);
		else
			clear(PORTA,1<<PA3);
	}else {
		//Clear value in PORTB
		if(hall_on==7)
			set(PORTB,1<<PB2);
		else
			set(PORTA,1<<PA3);
	}
}

/***
* Code for serial communication from Neil
*
*******/
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();
}

void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) {
	//
	// read character into rxbyte on pins pin
	//    assumes line driver (inverts bits)
	//
	*rxbyte = 0;
	while (pin_test(*pins,pin))
	//
	// wait for start bit
	//
	;
	//
	// delay to middle of first data bit
	//
	half_bit_delay();
	bit_delay();
	//
	// unrolled loop to read data bits
	//
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 0);
	else
	*rxbyte |= (0 << 0);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 1);
	else
	*rxbyte |= (0 << 1);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 2);
	else
	*rxbyte |= (0 << 2);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 3);
	else
	*rxbyte |= (0 << 3);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 4);
	else
	*rxbyte |= (0 << 4);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 5);
	else
	*rxbyte |= (0 << 5);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 6);
	else
	*rxbyte |= (0 << 6);
	bit_delay();
	if pin_test(*pins,pin)
	*rxbyte |= (1 << 7);
	else
	*rxbyte |= (0 << 7);
	//
	// wait for stop bit
	//
	bit_delay();
	half_bit_delay();
}

	/*ISR(PCINT0_vect) {
		;
		//
		// pin change interrupt handler
		//
		static char chr;
		//static char buffer[max_buffer] = {0};
		//static int index;
		get_char(&serial_pins_in, serial_pin_in, &chr);
		//put_string(&serial_port, serial_pin_out, "hello.ftdi.44.echo.interrupt.c: you typed \"");
		//buffer[index++] = chr;
		//if (index == (max_buffer-1))
		//index = 0;
		//put_string(&serial_port, serial_pin_out, buffer);
		//put_char(&serial_port_out, serial_pin_out, '\"');
		//put_char(&serial_port, serial_pin_out, 10); // new line
		//clear(PORTA,1<<PA3);
		if bit_test(chr,0)
			//set(*port,pin);
			set(PORTA,1<<PA3);
			
		else
			clear(PORTA,1<<PA3);
		

	}*/



int main(void)
{
/*	//DIGITAL VERSION //
	//Sensor is connected to PA7: define DDRA as in in PA7 and in PA5
	DDRA = DDRA & ~(1 << PA7);
	DDRA = DDRA & ~(1 << PA5);
	//Led is connected to PB2: define DDRB as out in PB2
	DDRB = DDRB | (1<<PB2);
	DDRA = DDRA | (1<<PA3);
	while (1)
	{
		//Check sensor value in PINA
		if(!(PINA &(1<<PA7))){ //if 0, check schematics
			//Put value in PORTB
			PORTB = PORTB |(1<<PB2);
			}else {
			//Clear value in PORTB
			PORTB = PORTB &~(1<<PB2);
		}
		_delay_ms(20);
		
		//Check switch value in PINA
		if(!(PINA &(1<<PA5))){ //if 0, check schematics
			//Put value in PORTB
			PORTA = PORTA |(1<<PA3);
			}else {
			//Clear value in PORTB
			PORTA = PORTA &~(1<<PA3);
		}
		_delay_ms(20);
		
	}*/

	
	/*ANALOG VERSION*/
	static unsigned int measure;
	static unsigned char high,low;
	unsigned int hall_on = 0; //Stores which is the read hall
	//
	// set clock divider to /1
	//
	CLKPR = (1 << CLKPCE);
	CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
	
	   //
	   // initialize output pins
	   //
	   set(serial_port_out, serial_pin_out);
	   output(serial_direction_out, serial_pin_out);
	
	//Sensor is connected to PA7  and in PA5
	//INITIALIZING ADC
	ADMUX = (0 << REFS1) | (0 << REFS0) | // Vcc ref (Table 16.3)
	(0 << MUX5)  | (0 << MUX4)  | (0 << MUX3)  | (1 << MUX2)  | (1 << MUX1)  | (1 << MUX0);  //Activate PA7/ADC7 (Table 16.4)
	hall_on=7;//PA7 activated
	ADCSRA = 0x00;
	ADCSRA = (1 << ADEN) | // enable ADC (16.13.2)
	(0 << ADATE) | // Disable autotriggering. Using single conversion mode.
	(1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128
	ADCSRB = 0x00; // (16.13.4)
	ADCSRB = (0 << ADLAR); // Be sure that you have right adjusted mode
	//Digital input to PA5
	DDRA = DDRA & ~(1 << PA5);
	
	//Led is connected to PB2, PA3
	
	DDRB = DDRB | (1<<PB2);
	DDRA = DDRA | (1<<PA3);
	
	
	
	clear(PORTA,1<<PA3);
	clear(PORTB,1<<PB2);
	
			/*put_char(&serial_port_out,serial_pin_out,1);
			put_char(&serial_port_out,serial_pin_out,2);
			put_char(&serial_port_out,serial_pin_out,3);
			put_char(&serial_port_out,serial_pin_out,4);*/
	   //
	   // set up pin change interrupt on input pin
	   //
	   /*set(GIMSK, serial_interrupt);
	   set (PCMSK0, serial_interrupt_pin);
	   sei();
	   */
	   
	
	while (1)
	{
		// initiate conversion
		//
		ADCSRA |= (1 << ADSC);
		//
		// wait for completion
		//
		while (ADCSRA & (1 << ADSC)) // while there is no 1 in ADCS no continue
		{
						//Check switch value in PINA
						
						if(!(PINA &(1<<PA5))){ //if 0, check schematics
							//Put value in PORTA3
							set(PORTA,1<<PA3);
							}else {
							//Clear value in PORTA3
							clear(PORTA,1<<PA3);
						}
		}
		//Read the value
		low=ADCL;
		high =ADCH;
			
		//INT cli();	
		//
		put_char(&serial_port_out,serial_pin_out,1);
		put_char(&serial_port_out,serial_pin_out,2);
		put_char(&serial_port_out,serial_pin_out,3);
		put_char(&serial_port_out,serial_pin_out,4);
		put_char(&serial_port_out,serial_pin_out,low);
		put_char(&serial_port_out,serial_pin_out,high);
		//
		// delay before next cycle
		//
		_delay_ms(10);
		measure = low + 256*high; // Read first ADCL and then ADCH
		calculate(measure,hall_on);
		
		//INT sei();	
			
			
		//TODO		
		//calculate
		_delay_ms(10);
		//Change MULTIPLEX
		//if(hall_on == 7)
		_delay_ms(10);
		//calculate
		_delay_ms(10);

		
	}
	

	
	
}

