/* ********************************************
   Modul : init_system.c

   Enthält kleine Module die die Peripherie und
   anderes einstellen, damit Main.c nicht so voll
   geladen ist

   Autor : Christian Julius
   ******************************************** */
#include "tools.h"
#include <stdint.h>
#include <ctype.h>

#include "tm_stm32f4_rtc.h"
#include "tm_stm32f4_bmp180.h"
#include "tm_stm32f4_disco.h"
#include "tm_stm32f4_ili9341.h"
#include "tm_stm32f4_ds18b20.h"

#include "config.h"
#include "init_system.h"
#include "graphik.h"
#include "tools.h"
#include "processing.h"

// LEDs aktivieren
void __attribute__((optimize(0))) Init_Ports() {

    static uint32_t foo;
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);     // Clock an Port C
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);     // Clock an Port D
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);     // Clock an Port E

    // PORT C
    GPIO_StructInit (&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin     = LCD_BACKLIGHT;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Low_Speed;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,LCD_BACKLIGHT);

    // Port D: LED Pins (Hoch, Neutral, Tief) und Relais auf Ausgang schalten
    GPIO_StructInit (&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin     = LED_ROT | LED_GLB| LED_GRN | RELAIS | LED_ALL;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Low_Speed;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    // Port E mit den Wetter Tendenz LED einstellen
    GPIO_StructInit (&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin     = WLED_ROT1 | WLED_ROT2| WLED_GLB | WLED_GRN | WLED_BLAU;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Low_Speed;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    // DIP Switches an Port E auf Input + Pull Up schalten
    GPIO_InitStructure.GPIO_Pin     = DIP_Switch_1 | DIP_Switch_2;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    // Port D: Pins auf 0 setzen, LED abschalten, Bildschirm LED ein
    GPIO_ResetBits(GPIOD,LED_ROT | LED_GRN | LED_GLB | RELAIS);
    GPIO_SetBits(GPIOD,RELAIS);

    // Alle LED ein, dann ausschalten
    GPIO_SetBits(GPIOE,WLED_ROT1 | WLED_ROT2 | WLED_GLB | WLED_GRN | WLED_BLAU);
    for (foo = 0; foo < 2000000; foo++);
    GPIO_ResetBits(GPIOE,WLED_ROT1 | WLED_ROT2 | WLED_GLB | WLED_GRN | WLED_BLAU);

    // Leds auf dem Board
    TM_DISCO_LedOff(LED_ALL);
}


// Backup Ram aktivieren
void Init_BackupRam()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);               // Power für RTC/Backup RAM
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);           // Backup RAM mit Clock versorgen

    // Prüfe, ob Spannungsregler eingeschaltet ist
    if (PWR_GetFlagStatus(PWR_FLAG_BRR) == RESET)
    {
        PWR_BackupAccessCmd(ENABLE);                                  // Schreibzugriff aufs Backup Ram
        PWR_MainRegulatorModeConfig(PWR_Regulator_Voltage_Scale1);    // Regulator auf Strom für 168 Mhz setzen
        PWR_BackupRegulatorCmd(ENABLE);                               // Backup Spannungsregler aktivieren
        while(PWR_GetFlagStatus(PWR_FLAG_BRR) != SET);                // Warte bis er stabil ist
    }

    PWR_BackupAccessCmd(ENABLE);                                      // Schreibzugriff aufs Backup Ram
}

// RTC einstellen
void Init_RTC()
{
    //Initialize RTC with internal 32768Hz clock
    if (!TM_RTC_Init(TM_RTC_ClockSource_External)) {
        //RTC was first time initialized
        TM_RTC_SetDateTimeString("01.01.00.0;00:00:00");
    }
    // Kalibrationswert: Uhr zu schnell, daher Pulse abziehen
    RTC_SmoothCalibConfig(RTC_SmoothCalibPeriod_32sec,RTC_SmoothCalibPlusPulses_Reset,20);
    TM_RTC_GetDateTime(&Time, TM_RTC_Format_BIN);

    // Zeit & Datum manuell setzen
    //TM_RTC_SetDateTimeString("30.12.15.4;09:56:45");

    // Interne Timer sync.
    timer.hour  = Time.hours;
    timer.min   = Time.minutes;
    timer.sec   = Time.seconds;
    timer.min15 = Time.minutes;
    timer.min30 = Time.minutes;
}

// LCD einstellen
void Init_LCD()
{
    TM_ILI9341_Init();
    TM_ILI9341_Rotate(TM_ILI9341_Orientation_Landscape_2);      //Rotate LCD 90 Grad
    TM_ILI9341_Fill(ILI9341_COLOR_BLACK);                       // Display schwarz
}

/* Init der Work Structs mit plausiblen Werten, damit
   Grafikroutinen keinen Uninn zeichnen */

void Init_WorkStructure(Work_t *W, size_t size)         // TODO!
{
    // Sind bereits Daten im batteriegepufferten Workspace vorhanden?
    if (W->id == 0x1234)  return;

    // Daten neu aufbauen
    memset(W,0,size);
    // Muss immer in dieser Reihenfolge aufgerufen werden
    W->T_Now = BMP180_ReadTemperature();
    W->P_Now = BMP180_ReadPressure();

    // Grenzen für Druck um aktuellen Druck legen
    W->P_MaxGraph  = W->P_Now + P_DELTA;
    W->P_MinGraph  = W->P_Now - P_DELTA;

    // Temperaturgrenzen
    W->T_MaxGraph = W->T_Now;
    W->T_MinGraph = W->T_Now;

    // Den ersten Historyeintrag bei Pos. 0 und 1 machen
    W->History[0].Pressure = W->P_Now;
    W->History[0].Temperature = W->T_Now;

    W->id = 0x1234;

}


////////////////////////////////////////////////////////
// Temperatursensor einstellen
// ROM Code: 0x10 0x12 0x08 0xd9 0x02 0x08 0x00 0x5b
////////////////////////////////////////////////////////

//uint8_t Init_DS18B20()
//{
//    float temps = 0.0;
//    uint8_t device[8];
//    uint8_t alarm_device[8];
//    TM_OneWire_t OneWire1;
//
//    /* Initialize OneWire on pin PC4 */
//    TM_OneWire_Init(&OneWire1, GPIOC, GPIO_Pin_4);
//    if (TM_OneWire_First(&OneWire1))
//        /* Get full ROM value, 8 bytes, give location of first byte where to save */
//        TM_OneWire_GetFullROM(&OneWire1, device);
//    else
//        return ERROR;
//
//    // 12 Bit Auflösung setzen
//    TM_DS18B20_SetResolution(&OneWire1,device,TM_DS18B20_Resolution_9bits);
//    TM_DS18B20_Start(&OneWire1,device);
//    TM_DS18B20_AllDone(&OneWire1);
//    uint8_t result = TM_DS18B20_Read(&OneWire1, device,&temps);
//    Delay(10);
//
//}

