/*This file is prepared for Doxygen automatic documentation generation.*/
//! \file *********************************************************************
//!
//! \brief This file manages the generic HID IN/OUT task.
//!
//! - Compiler:           IAR EWAVR and GNU GCC for AVR
//! - Supported devices:  AT90USB1287, AT90USB1286, AT90USB647, AT90USB646
//!
//! \author               Atmel Corporation: http://www.atmel.com \n
//!                       Support and FAQ: http://support.atmel.no/
//!
//! ***************************************************************************

/* Copyright (c) 2009 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:
 *
 * 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
 * AVR 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.
 */


//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "conf_usb.h"
#include "hid_task.h"
#include "lib_mcu/usb/usb_drv.h"
#include "usb_descriptors.h"
#include "modules/usb/device_chap9/usb_standard_request.h"
#include "usb_specific_request.h"
#include "lib_mcu/util/start_boot.h"
#include "lib_mcu/adc/adc_drv.h"


//_____ M A C R O S ________________________________________________________


//_____ D E F I N I T I O N S ______________________________________________


//_____ D E C L A R A T I O N S ____________________________________________

extern   volatile U16   g_u16_cpt2_sof;
extern            U8    jump_bootloader;
#if( HID_GENERIC_DEMO_FULL == ENABLE )         
                  U8    g_temperature    =0;
                  U8    g_potentiometer  =0;
#else
                  U8    g_last_joy       =0;
#endif

void hid_report_out  (void);
void hid_report_in   (void);

//! @brief This function initializes the target board ressources.
//!
void hid_task_init(void)
{
#if( HID_GENERIC_DEMO_FULL == ENABLE )         
   init_adc();
#endif
   Leds_init();
   Joy_init();
}

//! @brief Entry point of the HID generic communication task
//! This function manages IN/OUT repport management.
//!
void hid_task(void)
{
   if(!Is_device_enumerated())               // Check USB HID is enumerated
      return;

   hid_report_out();
   hid_report_in();
}


//! @brief Get data report from Host
//!
void hid_report_out(void)
{
   Usb_select_endpoint(EP_HID_OUT);
   if(Is_usb_receive_out())
   {
#if( HID_GENERIC_DEMO_FULL == ENABLE )         
      //* Read report from HID Generic Demo Full
      U8 report_byte_4;
      U8 report_byte_5;
      Leds_set_val(    Usb_read_byte());     // RepportOUT[0] is LEDS value
      GPIOR1         = Usb_read_byte();      // not used
      GPIOR1         = Usb_read_byte();      // not used
      report_byte_4  = Usb_read_byte();
      report_byte_5  = Usb_read_byte();
      // Check if we received DFU mode command from host
      if( (report_byte_4==0x55) && (report_byte_5==0xAA) )
         jump_bootloader = TRUE;
#else
      //* Read report from HID Generic Demo
      U8 led_state;
      U8 led_number;
      led_state      = Usb_read_byte()&0x0F; // RepportOUT[0] is LEDS value
      led_number     = Usb_read_byte()&0x0F;
      switch (led_number)
      {
         case 1:
            if(led_state)
            {  Led0_on();   }
            else {Led0_off();}
            break;
         case 2:
            if(led_state)
            {  Led1_on();   }
            else {Led1_off();}
            break;
         case 3:
            if(led_state)
            {  Led2_on();   }
            else {Led2_off();}
            break;
         case 4:
            if(led_state)
            {  Led3_on();   }
            else {Led3_off();}
            break;
      }         
#endif
      Usb_ack_receive_out();
   }

   //** Check if we received DFU mode command from host
   if(jump_bootloader)
   {
      U32 volatile tempo;
      Leds_off();
      Usb_detach();                          // Detach actual generic HID application
      for(tempo=0;tempo<70000;tempo++);      // Wait some time before
      start_boot();                          // Jumping to booltoader
   }
}


//! @brief Send data report to Host
//!
void hid_report_in(void)
{
   U8 joy   =0;

   Usb_select_endpoint(EP_HID_IN);
   if(!Is_usb_write_enabled())
      return;                                // Not ready to send report

#if( HID_GENERIC_DEMO_FULL == ENABLE )         
   #if (TARGET_BOARD!=USBKEY)
   if (g_u16_cpt2_sof%100==0)
   {
      g_potentiometer=Get_adc_pot_val()>>2;
   }
   #endif
   if (g_u16_cpt2_sof>=600)
   {
      g_temperature=(S8)Read_temperature();
      g_temperature=(S8)Read_temperature();
      g_u16_cpt2_sof=0;
   }
   // Build the Joytick report
   if(Is_joy_up())                           // Check for UP event
   {
      joy+=0x01;
   }
   if(Is_joy_down())                         // Check for DOWN event
   {
      joy+=0x02;
   }
   if(Is_joy_right())                        // Check for RIGHT event
   {
      joy+=0x04;
   }
   if(Is_joy_left())                         // Check for LEFT event
   {
      joy+=0x08;
   }
#else
   // Build the Joytick report
   if(Is_joy_up()|| Is_joy_down() || Is_joy_right() || Is_joy_left() )                     //! Check for UP event
   {
     joy=0x01;
   }
   if(joy==g_last_joy)
      return;                                // Same report then no send report
   g_last_joy=joy;
#endif

   // Send report
#if( HID_GENERIC_DEMO_FULL == ENABLE )         
   Usb_write_byte(Leds_get_val());           // Leds
   Usb_write_byte(joy);                      // Joystick
   Usb_write_byte(g_potentiometer);          // Potentiometer
   Usb_write_byte(g_temperature);            // temperature
#else
   Usb_write_byte(g_last_joy);               // Joystick
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
#endif
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_write_byte(GPIOR1);                   // Dummy (not used)
   Usb_ack_in_ready();                       // Send data over the USB
}

