/*C**************************************************************************
* NAME:         usb_task.c
*----------------------------------------------------------------------------
* Copyright (c) 2003 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      c5131-usb-kbd-light-1_0_2      
* REVISION:     1.7.2.3     
*----------------------------------------------------------------------------
* PURPOSE: 
* This file controls the USB protocol.
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/

#include "config.h"
#include "usb_task.h"
#include "lib_mcu\usb\usb_drv.h"
#include "modules\usb_kbd_enum\usb_kbd_enum.h"
#include "modules\timer_soft\timer_soft.h"
//#include "lib_board\lcd_twi\lcd_twi.h"
//#include "lib_board\kbd_4_4\kbd_4_4.h"

/*_____ M A C R O S ________________________________________________________*/

/*_____ D E F I N I T I O N ________________________________________________*/

bit   usb_connected;
bit   usb_connected_stored;
bit   usb_configured_stored;
Uchar usb_sof_counter;

Uchar usb_kbd_state;

Uchar  transmit_no_key;
Union16 idata  scan_key;
        Uchar  key_hit;
        Uchar  shift_key;

extern         Uchar  usb_configuration_nb;
Uchar  code    usb_keys[]= {HID_ENTER, \
                            HID_SB, HID_SB, HID_SB, HID_SB, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_ENTER, \
                            HID_SB, HID_SB, HID_SB, HID_SL, HID_L , HID_SB, HID_L , HID_SB, HID_L , HID_SB, HID_SB, HID_L , HID_SB, HID_L , HID_MN, HID_MN, HID_SB, HID_L , HID_SB, HID_SB, HID_ENTER, \
                            HID_SB, HID_SB, HID_SL, HID_MN, HID_L , HID_SB, HID_L , HID_SB, HID_L , HID_BS, HID_SL, HID_L , HID_SB, HID_L , HID_MN, HID_SB, HID_SB, HID_L , HID_SB, HID_SB, HID_ENTER, \
                            HID_SB, HID_SL, HID_SB, HID_SB, HID_L , HID_SB, HID_L , HID_SB, HID_L , HID_SB, HID_SB, HID_L , HID_SB, HID_L , HID_MN, HID_MN, HID_SB, HID_L , HID_MN, HID_MN, HID_ENTER, \           
                            HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_MN, HID_ENTER, \
                            HID_ENTER, \
                            HID_W, HID_E, HID_L, HID_C, HID_O, HID_M, HID_E, \
                            HID_SPACEBAR, HID_T, HID_O, HID_SPACEBAR, \
                            HID_A, HID_T, HID_8, HID_9, HID_C, HID_5, HID_1, \
                            HID_3, HID_1, HID_SPACEBAR, HID_H, HID_I, HID_D, \
                            HID_SPACEBAR, HID_D, HID_E, HID_M, \
                            HID_O, HID_ENTER, HID_ENTER, \
                            HID_T, HID_H, HID_E, HID_SPACEBAR, \
                            HID_A, HID_T, HID_8, HID_9, HID_C, HID_5, HID_1, HID_SPACEBAR,\
                            HID_P, HID_R, HID_O, HID_D, HID_U, HID_C, HID_T, HID_SPACEBAR, \
                            HID_I, HID_S, HID_SPACEBAR, HID_A, HID_SPACEBAR, HID_C, HID_5, HID_1, HID_SPACEBAR, \
                            HID_B, HID_A, HID_S, HID_E, HID_D, HID_SPACEBAR, \
                            HID_C, HID_O, HID_N, HID_T, HID_R, HID_O, HID_L, HID_L, HID_E, HID_R, HID_ENTER, \
                            HID_W, HID_I, HID_T, HID_H, HID_SPACEBAR, HID_T, HID_H, HID_E, HID_SPACEBAR, \
                            HID_F, HID_O, HID_L, HID_L, HID_O, HID_W, HID_I, HID_N, HID_G, HID_SPACEBAR, \
                            HID_F, HID_E, HID_A, HID_T, HID_U, HID_R, HID_E, HID_S, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_X, HID_2, HID_SPACEBAR, HID_C, HID_5, HID_1, HID_SPACEBAR, HID_C, HID_O, HID_R, HID_E, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_3, HID_2, HID_SPACEBAR, HID_K, HID_B, HID_Y, HID_T, HID_E, HID_SPACEBAR, HID_F, HID_L, HID_A, HID_S, HID_H, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_U, HID_S, HID_B, HID_SPACEBAR, HID_B, HID_O, HID_O, HID_T, HID_L, HID_O, HID_A, HID_D, HID_E, HID_R, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_U, HID_S, HID_B, HID_SPACEBAR, HID_F, HID_U, HID_L, HID_L, HID_SPACEBAR, HID_S, HID_P, HID_E, HID_E, HID_D, HID_SPACEBAR, HID_C, HID_O, HID_N, HID_T, HID_R, HID_O, HID_L, HID_L, HID_E, HID_R, HID_SPACEBAR, \
                            HID_W, HID_I, HID_T, HID_H, HID_SPACEBAR, HID_7, HID_SPACEBAR, HID_E, HID_N, HID_D, HID_P, HID_O, HID_I, HID_N, HID_T, HID_S, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_U, HID_S, HID_B, HID_SPACEBAR, HID_S, HID_O, HID_F, HID_T, HID_W, HID_A, HID_R, HID_E, HID_SPACEBAR, HID_D, HID_E, HID_T, HID_A, HID_C, HID_H, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_K, HID_E, HID_Y, HID_B, HID_O, HID_A, HID_R, HID_D, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_T, HID_W, HID_I, HID_ENTER, \
                            HID_MINUS, HID_SPACEBAR, HID_S, HID_P, HID_I, HID_ENTER, HID_ENTER, \
                            HID_SPACEBAR, HID_SPACEBAR, HID_E, HID_N, HID_J, HID_O, HID_Y, HID_DOT, HID_DOT, HID_DOT,HID_ENTER \
};
#define SIZEOF_USB_KEYS     (Uint16)sizeof(usb_keys)

Uchar          usb_key;
Uint16         usb_data_to_send;
Uchar *        usb_key_pointer;

/*_____ D E C L A R A T I O N ______________________________________________*/



/*F**************************************************************************
* NAME: usb_task_init
*----------------------------------------------------------------------------
* PARAMS:
* delay:    none
* return:   none
*----------------------------------------------------------------------------
* PURPOSE: 
* This function initializes the USB controller and the associated variables.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_task_init(void)
{ 
  Usb_enable();			// #define Usb_enable()        (USBCON |= MSK_USBE) 
						// look at usb_drv.h(180)
						// #define MSK_USBE      0x80
  Usb_detach();			// #define Usb_detach()        (USBCON |= MSK_DETACH)
						// look at usb_drv.h
  tempo(TIMER_5_MS);	// stay in "timer_soft.c"
						// #define TIMER_5_MS      5
  Usb_attach();			// #define Usb_attach()    (USBCON &= ~MSK_DETACH)
						// look at usb_drv.h
  configure_usb_clock();  // "usb_drv.c" (339)Body.
						  // #if FOSC == 24000
						  //	 Pll_set_div(PLL_24MHz);
						  //     Pll_enable();
						  // #endif

  usb_configure_endpoint(EP_CONTROL, CONTROL);	// "usb_drv.c"(70)
			//void usb_configure_endpoint (Uchar ep_num, Uchar ep_type)
			//{
			//   Usb_select_ep(ep_num);	// #define Usb_select_ep(e)  (UEPNUM = e)
			//   Usb_configure_ep_type(ep_type); 
			//}

  usb_reset_endpoint(EP_CONTROL);   // "usb_drv.c"(302)
									// void usb_reset_endpoint (Uchar ep_num)
									//{
									//  UEPRST = 0x01 << ep_num ;
									//  UEPRST = 0x00;
									//}
  usb_connected = FALSE;  // bit   usb_connected;(26) in this file.
  usb_connected_stored = TRUE;      // above
  usb_configured_stored = FALSE;	// above	
  transmit_no_key = FALSE;			// above //Uchar  transmit_no_key;
  key_hit = FALSE;					// above
  usb_kbd_state = 0;				// above
  shift_key = 0;					// above
  usb_var_init();					// Body in "usb_kbd_enum.c"(131)

  Configure_led(0,LED_PORT_2MA);	// "5131_drv.h"(131)
  Configure_led(1,LED_PORT_2MA);
  Configure_led(2,LED_PORT_2MA);
  Configure_led(3,LED_PORT_2MA);

  Led_all_off();					// "5131_drv.h"(118)
}


/*F**************************************************************************
* NAME: usb_task
*----------------------------------------------------------------------------
* PARAMS:
* delay:    none
* return:   none
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the USB communication
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_task(void)
{

  if (Usb_suspend())
  {
    if (usb_connected == TRUE)
    { 
      usb_connected = FALSE;
      Led_all_off();
      Led_3_on();
    }

    if (Usb_resume())
    {
      usb_connected = TRUE;
      Usb_clear_suspend();
      Usb_clear_resume();
      Usb_clear_sof();
      Led_3_off();
    }
  }
  else
  {
    usb_connected = TRUE;
    if (Usb_reset()) { usb_var_init();   Usb_clear_reset(); }

    if (Usb_sof())
    {
      usb_sof_counter ++;
      if (usb_sof_counter == 0xFF)
      {
        Led_0_toggle();
      }
      Usb_clear_sof();
    }

    if (Usb_endpoint_interrupt())
    {
      Usb_select_ep(EP_CONTROL);
      if (Usb_setup_received()) { usb_enumeration_process(); }
      Usb_select_ep(EP_KBD_IN);
      if (Usb_tx_complete())    { Usb_clear_tx_complete();
                                  key_hit = FALSE;
                                  Led_1_off(); }
    }
  }
}

/*F**************************************************************************
* NAME: usb_kbd
*----------------------------------------------------------------------------
* PARAMS:
* delay:    none
* return:   none
*----------------------------------------------------------------------------
* PURPOSE: 
* This function links the keyboard and the USB bus.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_kbd_task (void)
{
  // if USB ready to transmit new data :
  //        - if last time = 0, nothing
  //        - if key pressed -> transmit key
  //        - if !key pressed -> transmit 0
  if ((!key_hit) && (usb_configuration_nb != 0) && !(Usb_suspend()))
  {
    kbd_test_hit();
    if (key_hit == TRUE)
    {
      Led_1_on();
      transmit_no_key = TRUE;
      Usb_select_ep(EP_KBD_IN);
      Usb_write_byte(0);
      Usb_write_byte(shift_key);
      Usb_write_byte(usb_key);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_set_tx_ready();
      return;
    }

    if (transmit_no_key)
    {
      key_hit = TRUE;
      transmit_no_key = FALSE;
      Usb_select_ep(EP_KBD_IN);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_write_byte(0);
      Usb_set_tx_ready();
    }
  }
}

/*F**************************************************************************
* NAME:     kbd_test_hit
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   This function scans the keyboard keys and update the scan_key word.
*   if a key is pressed, the key_hit bit is set to TRUE.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void kbd_test_hit(void)
{
  switch (usb_kbd_state)
  {
    case 0: if (P3_2 == 0)
              { 
                usb_kbd_state = 1; 
                usb_key_pointer = usb_keys;
                usb_data_to_send = SIZEOF_USB_KEYS;
                Led_2_off();
              }
              else
              {
                Led_2_on();
              };
            break;
    case 1: if (usb_data_to_send != 0)
            {
              if ((key_hit == FALSE) && (transmit_no_key == FALSE))
              {
                usb_key = *usb_key_pointer;
                usb_key_pointer ++;
                usb_data_to_send --;
                key_hit = TRUE;
              }
            }
            else
            {
              usb_kbd_state = 0;
            }
            break;
  }
}

