/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support
 * ----------------------------------------------------------------------------
 * Copyright (c) 2012, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: 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
 * 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.
 * ----------------------------------------------------------------------------
 */

/**
 *  \page pyrosensor_motion_detect Pyro Sensor Motion Detection Example
 *
 *  \section Purpose
 *
 *  This example utilizes the ACC peripheral to capture the pulse generated by
 *  the Pyro Sensor with an external amplifier.
 *
 *  \section Requirements
 *
 *  This package can be used with SAM4S-WPIRD-RD.
 *
 *  \section Description
 *
 *  A Passive InfraRed sensor (PIR sensor) is an electronic device that measures
 *  infrared  (IR) light radiating from objects in its field of view. PIR sensors
 *  are often used in the construction of PIR-based motion detectors.
 *
 *  The PIR sensor could sense a human motion and output a signal in combination
 *  with some external circuit, such as an amplifier in SAM4S-WPIR-RD. The output
 *  stays at a stable level called offset with no mition detection. And it will
 *  generate significant change while a motion causes a big change of the infared
 *  energy in the field of the sensor's view. The change varies on the distance
 *  of the source. Further distance less change.
 *
 *  The Analog Comparator is in use to finish the work. The controller could
 *  generate an interrupt while the two inputs applied to the comparator are
 *  different since the last read of the comparison flag. In SAM4S-WPIR-RD, one
 *  input to the ACC is the output of the amplifer dedicated to the PIR sensor and
 *  the other input is the reference voltage corresponding to the least energy
 *  change which could be monitored by the system. Less difference between
 *  the reference and the offset makes the motion detector more sensitive
 *  but more vulnerable to noise.
 *
 *  \section Usage
 *
 *  -# Build the program and download it inside the evaluation board. Please
 *     refer to the
 *     <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6224.pdf">
 *     SAM-BA User Guide</a>, the
 *     application note or to the
 *     <a href="ftp://ftp.iar.se/WWWfiles/arm/Guides/EWARM_UserGuide.ENU.pdf">
 *     IAR EWARM User Guide</a>,
 *     depending on your chosen solution.
 *  -# After downloading with SAM-BA or IAR flash loader, run the application.
 *  -# If a LCD is mounted, some message will be displayed on the screen if
 *     motion is detected by the sensor.
 *
 */

/** \file
 *
 *  This file contains all the specific code for the pyrosensor_motion_detect
 */

/*----------------------------------------------------------------------------
 *        Headers
 *----------------------------------------------------------------------------*/

#include "board.h"
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "motion_detector.h"

/*----------------------------------------------------------------------------
 *        Local definitions
 *----------------------------------------------------------------------------*/

/** lcd debug output support, comment to remove */
#define LCD_DEBUG_OUT

/** for power on or off*/
#define ON  true
#define OFF false

/*----------------------------------------------------------------------------
 *        Local variables
 *----------------------------------------------------------------------------*/
/** indicate if there's any event triggered*/
static volatile bool bCmpEventFlag = false;

/*----------------------------------------------------------------------------
 *        Local functions
 *----------------------------------------------------------------------------*/

/**
 * \brief Enter Sleep Mode.
 * Enter condition:  WFI + (SLEEPDEEP bit = 0) + (LPM bit = 0)
 *
 */
static void _EnterSleepMode( void )
{
    PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM ;
    SCB->SCR &= (uint32_t)~SCB_SCR_SLEEPDEEP_Msk ;

    __WFI() ;
}

#ifdef LCD_DEBUG_OUT
/** intialize LCD for debugging output*/
static void _Init_LCD(void)
{
    /* Initialize LCD */
    LCDD_Initialize();
    LCD_On();
    LCDD_Fill(COLOR_TURQUOISE);
}
#endif
/*----------------------------------------------------------------------------
 *        Exported functions
 *----------------------------------------------------------------------------*/

/** system systick handler*/
void SysTick_Handler( void )
{
    TimeTick_Increment() ;
}
/**
 *  \brief pyrosensor_motion_detect Application entry point.
 *
 *  Initialize ACC with channel 4 and 0 as inputs,enable comparison interrupt
 *  output messages if a motion is detected and then wait for another motion.
 *
 *  \return Unused (ANSI-C compatibility).
 *  \callgraph
 */
extern int main(void)
{
    bool bIsMotionDetected = false;
    /* Disable watchdog */
    WDT_Disable( WDT ) ;

    LED_Configure(0);

#ifdef LCD_DEBUG_OUT
    /* reinitialize with mck*/
    TimeTick_Configure( (BOARD_MCK) );
    Wait(1000); // wait for 1s to be sure LCD is ready for initialization
    _Init_LCD();
    /*disable systick counter*/
    SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
#endif
    while(1)
    {
     MD_Init();
     ACC->ACC_ISR;
     MD_Enabled();

     _EnterSleepMode();
     if((bIsMotionDetected = MD_IsDetected()))
        {
          /* disable motion detector and alarm*/
          MD_Disabled();

#ifdef LCD_DEBUG_OUT
            static int i = 0;
            char str[30];
#endif

                LED_Toggle(0);

#ifdef LCD_DEBUG_OUT
                if(i * 20 <BOARD_LCD_HEIGHT)
                {
                    sprintf(str,"Motion Detected:%d",i);
                    LCDD_DrawString(0,i*20,str,COLOR_BLACK);
                    i++;
                }
                else
                {
                    i = 0;
                    sprintf(str,"Motion Detected:%d",i);
                    LCDD_ClearWindow(0,0,BOARD_LCD_WIDTH,BOARD_LCD_HEIGHT,COLOR_TURQUOISE);
                    LCDD_DrawString(0,0,str,COLOR_BLACK);
                }
#endif
        }

    }
    return 0;
}



