/**
  ******************************************************************************
  * @file function.c
  * @brief This file contains some functions that can be used in the demo.
  * @author STMicroelectronics - MCD Application Team
  * @version V1.1.0
  * @date    09/14/2009
  ******************************************************************************
  *
  */

// Includes ------------------------------------------------------------------
#include "functions.h"

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

// Private macro -------------------------------------------------------------
// Private variables ---------------------------------------------------------
uint32_t GTimeStamp;
uint16_t TimeOutStartTime;
uint8_t EEPBuffer[16];
uint8_t GUseEeprom;

// Private function prototypes -----------------------------------------------
// Private functions ---------------------------------------------------------
void Init_SPISimplex(void)
{
		SPI_DeInit();
		
    SPI_Init(SPI_FirstBit_MSB, SPI_BaudRatePrescaler_64, 
		         SPI_Mode_Master, SPI_CPOL_High, 
             SPI_CPHA_2Edge, SPI_Direction_1Line_Tx,
						 SPI_NSS_Soft);
    SPI_Cmd(ENABLE);
    // Otherwise the LCD display doesn't work when the board is powered-up ... 
    WaitDelay(50);
}

void Init_SPIFullDuplex(void)
{
	  // Set the MOSI,MISO and SCK at high level
    GPIO_ExternalPullUpConfig(GPIOB,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7, ENABLE);
    SPI_DeInit();
    SPI_Init(SPI_FirstBit_MSB, SPI_BaudRatePrescaler_4, SPI_Mode_Master, SPI_CPOL_High, 
             SPI_CPHA_2Edge, SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft);

    SPI_Cmd(ENABLE);
		
    // Otherwise the LCD display doesn't work when the board is powered-up ... 
    WaitDelay(50);
}

// PWM for buzzer: TIM3_CC4 
void Init_TIM3(void)
{
    TIM3_PrescalerConfig((uint16_t)3, TIM3_PSCReloadMode_Immediate);

    TIM3_OC2Init(TIM3_OCMode_PWM1,  TIM3_OutputState_Enable, 0xFFFF,  TIM3_OCPolarity_Low,  TIM3_OCIdleState_Reset);

    TIM3_CtrlPWMOutputs(ENABLE);

    TIM3_Cmd(ENABLE);
}

// General Purpose 5ms Time base 
void Init_TIM4(void)
{
    /* TimerTick = 1 ms
       Warning: fcpu must be equal to 16MHz
       fck_cnt = fck_psc/presc = fcpu/128 = 125kHz --> 1 tick every 8 µs
       ==> 1 ms / 8 µs = 125 ticks
     */
    TIM4_TimeBaseInit(TIM4_Prescaler_128, 125);

    TIM4_UpdateRequestConfig(TIM4_UpdateSource_Global);

    TIM4_ITConfig(TIM4_IT_Update, ENABLE);
    TIM4_Cmd(ENABLE);

}

void Init_GPIO(void)
{
    // ** Initialize I/Os in Output Mode Push-Pull **
    GPIO_Init(LEDS_PORT, (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6),
          		GPIO_Mode_Out_PP_High_Fast);
		
		GPIO_Init(LEDBICOLOR_PORT, LEDBICOLOR_PIN, 
		          GPIO_Mode_Out_PP_High_Fast);
		
    // PWM pin (TIM2_CH2) 
    GPIO_Init(GPIOD,GPIO_Pin_0 ,GPIO_Mode_Out_PP_High_Fast);
}

void Init_Clock(void)
{
   	CLK_PeripheralClockConfig((CLK_Peripheral_TIM2 | CLK_Peripheral_TIM3 | \
		                           CLK_Peripheral_TIM4 |CLK_Peripheral_AWU | \
															 CLK_Peripheral_SPI), ENABLE);
	  // Select fCPU = 16MHz 
    CLK_MasterPrescalerConfig(CLK_MasterPrescaler_HSIDiv1);
    // For test purpose output Fcpu on MCO pin 
		CLK_CCOConfig(CLK_Output_ClockMaster);
}

/** Initialize the application.
  * @param[in] None
  * @return None
  **/
void Init_Application(void)
{
    // Variables initialization 
    ButtonStatus = 0;

    // Clock initialization 
    Init_Clock();

    // I/O Port initialization 
    Init_GPIO();

    // TIMER4 initialization for generic timebase 
    Init_TIM4();

    // SPI initialization for LCD 
    Init_SPISimplex();

    // LCD initialization: Init_SPISimplex must be executed before 
    LCD_Init();

    // Menu initialization 
    MenuInit();

    // TIMER3 initialization for buzzer (PWM mode)  
    Init_TIM3();

    // Enable interrupts 
    enableInterrupts();

}

/** Get the Timer time stamp.
  * @param[in] None
  * @return the timer time stamp
  **/
uint32_t GetTimeStamp(void)
{
    return GTimeStamp;
}

/** Initialize the start time for generating a time-out.
  * @param[in] Delay before time-out generation
  * @return None
  **/
void GetTimeOutStartTime(void)
{
    sim();
    TimeOutStartTime = (unsigned int)( GetTimeStamp() );
    rim();
}

/** Generate a time out after Delay.
  * @note Before calling this function, the function GetTimeOutStartTime()
 *       must be called.
  * @param[in] Delay before time-out generation based on timer tick
  * @return None
  **/
bool TimeOut(uint16_t Delay)
{
    uint16_t TimeStamp;
    uint16_t PeriodStamp;

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

    PeriodStamp = TimeStamp - TimeOutStartTime;

    if (PeriodStamp >= Delay)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }

}

/** Wait a delay
  * @param[in] Delay based on timer Tick
  * @return None
  **/
void WaitDelay(uint16_t Delay)
{

    uint16_t DelayPeriodStart;
    uint16_t TimeStamp;
    uint16_t PeriodStamp;

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

    while (1)
    {
        sim();
        TimeStamp = (uint16_t)(GetTimeStamp());
        rim();
        PeriodStamp = TimeStamp - DelayPeriodStart;
        if (PeriodStamp >= Delay)
        {
            return;
        }
    }

}

