/**
  ******************************************************************************
  * @file joystick_button.c
  * @brief This file contains basic functions to control the joystick button.
  * @author STMicroelectronics - MCD Application Team
  * @version V1.1.0
  * @date    09/14/2009
  ******************************************************************************
  *
  */

// Includes ------------------------------------------------------------------

#include "joystick_button.h"
#include "functions.h"


// Private typedef -----------------------------------------------------------
// Private define ------------------------------------------------------------

#define JOYSTICK_DEBOUNCE_NB   3 /* Number of samples to validate a joystick event */
#define BUTTON_DEBOUNCE_NB     3 /* Number of samples to validate a button event */

// Following timings are based on TimerTick 
#define JOYSTICK_PERIOD        2 /* Defines the period to read the joystick */
#define BUTTON_PERIOD          2 /*  Defines the period to read the button */

// Private macro -------------------------------------------------------------
// Private variables ---------------------------------------------------------
uint8_t ButtonStatus;

// Private function prototypes -----------------------------------------------
// Private functions ---------------------------------------------------------

/** Read the joystick.
  * @param[in] None
  * @return the new joystick state
  **/
JOYSTICK_ID_T ReadJoystick(void)
{
    uint16_t TimeStamp;
    uint16_t PeriodStamp;
    uint8_t CurrentJoystickState;
    static uint16_t JoystickPeriodStart;
    static uint8_t PreviousJoystickState;
    static uint8_t JoystickDebounceNb;

    sim();
    TimeStamp = (uint16_t)(GetTimeStamp());
    rim();

    PeriodStamp = TimeStamp - JoystickPeriodStart;

    if (PeriodStamp >= JOYSTICK_PERIOD)
    {

        // Adjust TimeStamp in a Period range. 
        while (PeriodStamp >= JOYSTICK_PERIOD)
        {
            PeriodStamp -= JOYSTICK_PERIOD;
            JoystickPeriodStart += JOYSTICK_PERIOD;
        }

        /* Read PB[3..1], PA4 and PD7:
           PB1 = LEFT
           PB2 = RIGHT
           PB3 = UP
           PA4 = DOWN
           PD7 = SEL
           CurrentJoystickState:
           bit5 = SEL
           bit4 = DOWN
           bit3 = UP
           bit2 = RIGHT
           bit1 = LEFT
         */
        CurrentJoystickState = (uint8_t)((GPIO_ReadInputData(GPIOD) & (uint8_t)0x80) >> 2);
        CurrentJoystickState |= (uint8_t)(GPIO_ReadInputData(GPIOA) & (uint8_t)0x10);
        CurrentJoystickState |= (uint8_t)(GPIO_ReadInputData(GPIOB) & (uint8_t)0x0E);
        if (CurrentJoystickState != PreviousJoystickState)
        {
            PreviousJoystickState = CurrentJoystickState;
            JoystickDebounceNb = 0;
            SetBit(ButtonStatus, BUTTON_STATUS_JOYSTICK_DEBOUNCE_ENABLE);
        }
        else
        {
            if (ValBit(ButtonStatus, BUTTON_STATUS_JOYSTICK_DEBOUNCE_ENABLE))
            {

                JoystickDebounceNb++;

                if (JoystickDebounceNb >= (JOYSTICK_DEBOUNCE_NB - 1))
                {
                    switch (CurrentJoystickState)
                    {
                    case 0x1E:
                        // Select button 
                        CurrentJoystickState = SEL;
                        break;
                    case 0x2E:
                        // Down button 
                        CurrentJoystickState = DOWN;
                        break;
                    case 0x3C:
                        // Left button 
                        CurrentJoystickState = LEFT;
                        break;
                    case 0x3A:
                        // Right button 
                        CurrentJoystickState = RIGHT;
                        break;
                    case 0x36:
                        // Up Button 
                        CurrentJoystickState = UP;
                        break;
                    default:
                        // Release Button 
                        CurrentJoystickState = J_RELEASED;
                        break;
                    }
                    ClrBit(ButtonStatus, BUTTON_STATUS_JOYSTICK_DEBOUNCE_ENABLE);
                    return((JOYSTICK_ID_T)CurrentJoystickState);
                }
            }
        }
    }
    return(J_NONE);
}

/** Read the joystick.
  * @param[in] None
  * @return the new joystick state
  **/
BUTTON_ID_T ReadButton(void)
{
    static uint16_t ReadButtonPeriodStart;
    uint16_t TimeStamp;
    uint16_t PeriodStamp;
    uint8_t CurrentButtonState;
    static uint8_t PreviousButtonState;
    static uint8_t ButtonDebounceNb;

    sim();
    TimeStamp = (unsigned int)( GetTimeStamp() );
    rim();

    PeriodStamp = TimeStamp - ReadButtonPeriodStart;

    if ( PeriodStamp >= BUTTON_PERIOD )
    {

        while ( PeriodStamp >= BUTTON_PERIOD )
        { /* Adjust TimeStamp in a Period range */
            PeriodStamp -= BUTTON_PERIOD;
            ReadButtonPeriodStart += BUTTON_PERIOD;
        }

        // Read PA5 
        CurrentButtonState = (uint8_t)(GPIO_ReadInputData(GPIOA) & 0x20);

        if (CurrentButtonState != PreviousButtonState)
        {
            PreviousButtonState = CurrentButtonState;
            ButtonDebounceNb = 0;
            SetBit(ButtonStatus, BUTTON_STATUS_BUTTON_DEBOUNCE_ENABLE);
        }
        else
        {
            if (ValBit(ButtonStatus, BUTTON_STATUS_BUTTON_DEBOUNCE_ENABLE))
            {
                ButtonDebounceNb++;
                if (ButtonDebounceNb >= (BUTTON_DEBOUNCE_NB - 1))
                {
                    switch (CurrentButtonState)
                    {
                    case 0x20:
                        // Button released
                        CurrentButtonState = B_RELEASED;
                        break;
                    default:
                        // Button pressed
                        CurrentButtonState = B_PRESSED;
                        break;
                    }
                    ClrBit(ButtonStatus, BUTTON_STATUS_BUTTON_DEBOUNCE_ENABLE);
                    return(CurrentButtonState);
                }
            }
        }
    }
    return(B_NONE);
}

