/**
 * \file
 *
 * \brief main source file.
 *
 * Copyright (c) 2015 Atmel Corporation. All rights reserved.
 *
 * \asf_license_start
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel microcontroller product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \asf_license_stop
 *
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */

/* == include files ==========================================================*/
#include <avr/sleep.h>
#include "touch_api_ptc.h"

/* == #defines ================================================================ */

#define JOIN( x, y )				x ## y
#define REG( REGISTER, SIDE )		JOIN( REGISTER, SIDE )

#define SET_GPIO_PIN(port , pin)	REG(PORT, port) |= (1 << pin)
#define RESET_GPIO_PIN(port, pin)	REG(PORT, port) &= ~(1 << pin)

/* == types ==================================================================== */

/* == constants ================================================================= */
#define DEF_MCU_CLOCK_PRESCALER		1u
#define DEF_TIME_PERIOD_1MSEC       8u

#define LED_0_PORT					B
#define LED_0_PIN					5u

/* == global constants ========================================================== */

/* == global variables ========================================================== */
volatile uint16_t touch_time_counter = 0u;

/* == file-scope (static) variables ============================================= */

/* == file-scope (static) function prototypes =================================== */

/*! \brief MCU clock prescaler configuration routine
 *
 */
static void configure_prescaler(const uint8_t MCU_Clock_Prescaler);

/*! \brief Timer initialization routine
 *
 */
static void timer_init(void);

/*! \brief Timer initialization routine
 *
 */
static void configure_port_pins(void);

/* == file-scope (static) functions defines =================================== */

/*! \brief Set the system prescaler to 1 to ensure main clock is running at 8Mhz
 *
 * \param Sys_Clock_Prescaler	MCU clock prescaler value
 * \param MCU_Clock_Prescaler   MCU main clock prescaler.
 *
 * \return void
 */
static void configure_prescaler(const uint8_t MCU_Clock_Prescaler)
{
    /* set the prescaler of SYS Clock to 1 - 8 MHz */
    /* all these have 4 cycles*/
    __asm__ __volatile__  (
        "ldi r16, 0x80; \n\t"
        "sts 0x61, r16; \n\t"
        "sts 0x61, %0; \n\t "
        : /* no output registers */
        : "r"(MCU_Clock_Prescaler) /* Input register List */
        : "r17" /* Clobber List */
    );

}/*configure_prescaler*/


/*! \brief Timer0 overflow ISR
 *
 * \param void
 * \return void
 */
ISR(TIMER0_OVF_vect)
{
	SET_GPIO_PIN(LED_0_PORT,LED_0_PIN) ;
}

/*! \brief Timer0 compareA ISR
 *
 * \param void
 * \return void
 */
ISR(TIMER0_COMPA_vect)
{
	RESET_GPIO_PIN(LED_0_PORT,LED_0_PIN) ;
}

/*! \brief Configures the timer 2 for Output compare A interrupt at every 1 ms
 *
 * \param void
 * \return void
 */
static void timer_init(void)
{
    /* Setup Timer 2 for Clear Timer on Compare (CTC) mode of operation */
    TCCR2A = 0x00u | (1u << WGM21) ;

    /* Clear the Timer2 to zero */
    TCNT2 = 0x00u;

    /* Set the Output compare match A to Measurement period */
    OCR2A = DEF_TIME_PERIOD_1MSEC ;

    /* Clear the timer 2 compare Match A flag*/
    TIFR2 = 0x00 | (1u << OCF2A);

    /*Enable the Interrupt for Timer 2 Output compare match A */
    TIMSK2 = 0x00 | ( 1u << OCIE2A);

    /* Start timer.Set the prescaler to 7 */
    TCCR2B = ((1 << CS20) | (1 << CS21) | (1<< CS22)) ;

	/* setup timer0 for soft PWM*/
	TCCR0A = 0x00u;

	/* Start timer with 32 prescaling */
	TCCR0B = ((1 << CS01) | (1<< CS00)) ;

	/* Enable compare A and over flow interrupt enable*/
	TIMSK0 = ((1 << OCIE0A) | (1<< TOIE0)) ;

	/* Set the initial compare value or the soft PWM duty cycle*/
	OCR0A = 0x01u;	
}/*timer_init*/



/*! \brief Configures the port pins to output push - pull to drive LED
 *
 * \param void
 * \return void
 */
static void configure_port_pins(void)
{
    REG(DDR , LED_0_PORT)  |= (1 << LED_0_PIN);
}/*configure_port_pins*/



/* == public function(global function) defines =================================== */

/*! \brief Main function
 *
 */
int main(void)
{
	uint8_t timer_running  =  0u;
	uint8_t slider_position;

	/* Configure the sys_clock prescaler */
	configure_prescaler(DEF_MCU_CLOCK_PRESCALER);

	/* Configure the Timer 2 */
	timer_init();
	timer_running = 1u;
	
	/* Enable global interrupts */
	cpu_irq_enable();

	/* Initialize QTouch library and configure touch sensors. */
	touch_sensors_init();

	configure_port_pins();


	while(1){
		
		touch_sensors_measure();

		if ((p_selfcap_measure_data->measurement_done_touch == 1u)) {
			p_selfcap_measure_data->measurement_done_touch = 0u;

			slider_position= GET_SELFCAP_ROTOR_SLIDER_POSITION(0);
			
			if(slider_position < 3 ) {
				timer_running =0u;
				/* disable timer 0 interrupts */
				TIMSK0 = 0x0u; 
				
				/* clear pending flags */
				TIFR0 = ((1 << OCF0A) | (1<< TOV0)) ; 
				
				RESET_GPIO_PIN(LED_0_PORT,LED_0_PIN) ;
			}else if(slider_position > 252 ) {
				timer_running =0u;
				
				/* disable timer 0 interrupts */
				TIMSK0 = 0x0u; 
				
				/* clear pending flags */
				TIFR0 = ((1 << OCF0A) | (1<< TOV0)) ;
				
				SET_GPIO_PIN(LED_0_PORT,LED_0_PIN) ;

			/* 
				# if slider position is less than 3 LED is switched OFF
				# if slider position is greater than 252 LED is permanently switched 
				# ON slider position is duty cycle of soft PWM when slider position 
				# is between 5 and 252 slider position between 2 and 5 is no change 
				# zone, if this small hysteresis is not given then LED will flicker 
				# when slider position value oscillates between values 
				# < than 3  and > than 3 Ex:- say 2 and 4 value 2 will make 
				# first if to execute causing LED to OFF and 4 will cause the 
				# LED to ON executing the else part. 
			*/
				
			}else if((slider_position <= 252) && (slider_position >= 5))	{
				if(!timer_running) {
					timer_running = 1u;
					/* clear pending flags */
					TIFR0 = ((1 << OCF0A) | (1<< TOV0)) ;
					
					/* Restart the timer */
					TIMSK0 = ((1 << OCIE0A) | (1<< TOIE0)) ;					
				}
				OCR0A = slider_position;				
			}



        }/*if*/

    }/*while*/
}/*main*/



/* == Interrupt =================================== */

/*! \brief ISR routine for Timer 2 output compare match A
 *
 */
ISR(TIMER2_COMPA_vect)
{
    /* Clear the timer flag */
    TIFR2 |= OCF2A;

    /* Do something on RTC overflow here */
    if (touch_time_counter == touch_time.measurement_period_ms){
        touch_time.time_to_measure_touch = 1u;
        touch_time.current_time_ms = touch_time.current_time_ms + 
									touch_time.measurement_period_ms;
        touch_time_counter = 0u;
    }else {
        touch_time_counter++;
    }
}/*ISR(TIMER2_COMPA_vect)*/
