/*
 * supply.c
 *
 *  Created on: 28.4.2014
 *      Author: Stefan
 */


/* Includes ------------------------------------------------------------------*/
#include "supply.h"
#include <stm32f4xx_gpio.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SUPPLY_TIMEOUT 500

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static SemaphoreHandle_t supply_mutex;

static float supply_battery_volatge;

/* Public variables ----------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
bool_t supply_init(
    void
)
{
    GPIO_InitTypeDef gpio;
    bool_t response = FALSE;

    /* Enable GPIOs */
    RCC->AHB1ENR |= (RCC_AHB1ENR_GPIOFEN | RCC_AHB1ENR_GPIOHEN);
    __DSB();

    /* Configure GPIO pins */
    GPIO_StructInit(&gpio);
    gpio.GPIO_OType = GPIO_OType_PP;    /* < Push-Pull mode */
    gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;  /* < No pull Up/Down */
    gpio.GPIO_Speed = GPIO_Speed_2MHz;  /* < Lowest speed is enough */

    /* OUTPUT pins */
    gpio.GPIO_Mode = GPIO_Mode_OUT;
    /* POWER_ON */
    gpio.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init(GPIOH, &gpio);
    /* CHRG_EN */
    gpio.GPIO_Pin = GPIO_Pin_9;
    GPIO_Init(GPIOF, &gpio);

    /* INPUT pins */
    gpio.GPIO_Mode = GPIO_Mode_IN;
    /* CHRG_STAT, PWR_STAT */
    gpio.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
    GPIO_Init(GPIOF, &gpio);


    supply_mutex = xSemaphoreCreateMutex();
    if(NULL != supply_mutex)
    {
        response = TRUE;
    }
    return response;
}

void supply_power(
    bool_t value
)
{
    /* Set value of PH3 pin */
    if(TRUE == value)
    {
        GPIOH->ODR |= GPIO_ODR_ODR_3;
    }
    else
    {
        GPIOH->ODR &= ~GPIO_ODR_ODR_3;
    }
}

void supply_charge(
    bool_t value
)
{
    /* Set value of PF9 pin */
    if(TRUE == value)
    {
        GPIOF->ODR |= GPIO_ODR_ODR_9;
    }
    else
    {
        GPIOF->ODR &= ~GPIO_ODR_ODR_9;
    }
}

bool_t supply_ext_pwr_state(
    void
)
{
    /* Get value of PF8 pin */
    return (0 == (GPIOF->IDR & (1 << 8)));
}

bool_t supply_charge_state(
    void
)
{
    /* Get value of PF7 pin */
    return (0 != (GPIOF->IDR & (1 << 7))) &&  supply_ext_pwr_state();
}

bool_t supply_battery_status(
    float* percentage
)
{
    register float tmp;
    bool_t result = FALSE;

    /* try to obtain Mutex */
    if(pdTRUE == xSemaphoreTake(supply_mutex, SUPPLY_TIMEOUT))
    {
        tmp = supply_battery_volatge;

        /* release mutex */
        xSemaphoreGive(supply_mutex);

        result = TRUE;
        /* Calculate percentage */
        tmp = (tmp - 2.9f) * 76.9231f;

        if(tmp > 100)
        {
            tmp = 100.0f;
        }
        if(tmp < 0)
        {
            tmp = 0.0f;
        }

        *percentage = tmp;
    }

    return result;
}

void supply_update_info(
    float voltage,
    float temp
)
{
    /* If battery voltage is too low and is used as power source,
    turn off the device */
    if(voltage < 2.8 && voltage > 0.5 && FALSE == supply_ext_pwr_state())
    {
        supply_power(FALSE);
    }

    /* If ouside temperature is below zero,
    turn off battery charging */
    if(temp < 0)
    {
        supply_charge(FALSE);
    }
    else
    {
        supply_charge(TRUE);
    }

    /* try to obtain Mutex */
    if(pdTRUE == xSemaphoreTake(supply_mutex, SUPPLY_TIMEOUT))
    {
        supply_battery_volatge = voltage;
        /* release mutex */
        xSemaphoreGive(supply_mutex);

    }
}

