//----------------------------------------------------------------------------
///
/// \file   platform.cpp
///
/// \brief  The whole SOC
///
/// \date   20121111
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


//---Documentation------------------------------------------------------------


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


//---General--------------------------

//---Own------------------------------

#include <HALWrapper/stm32_hal.h>       // HSI_VALUE
#include <HALWrapper/stm32_rcc.h>
#include <lepto/log.h>
#include <biwak/timer.hpp>

//---Declaration--------------------------------------------------------------


//---Implementation-----------------------------------------------------------

extern "C"
{
   //extern char heap_low;
   //extern char heap_high;
   extern char end asm("end");
   extern char heap_start asm("__heap_start");
   extern char heap_end asm("__heap_end");
   extern char _sdata ;
   extern char _edata ;
   extern char _sbss ;
   extern char _ebss ;
   extern char _stext ;
   extern char _etext ;
   extern char _sram ;
   extern char _eram ;
}

#define STRINGIFICATE_HELP(exp) "" #exp ""
#define STRINGIFICATE(exp) STRINGIFICATE_HELP(exp)

extern volatile hrtimer_t lrtPerMsec;
register char * stack_ptr asm ("sp");
//extern "C" char *heap_end;
#if ! defined(FLASH_SIZE)
//extern "C" int FLASH_SIZE;
#endif

extern char _eflash asm("_eflash") __attribute__((unused));
extern char _sflash asm("_sflash") __attribute__((unused));
extern char _start_user_flash asm("_start_user_flash") __attribute__((unused));
extern char __fini_array_end asm("__fini_array_end") __attribute__((unused));
extern char _end_data_flash asm("_end_data_flash") __attribute__((unused));

#if 0
void biwakPrintAppInfo( )
{
   printf(  "\n"
       "Firmware  : "  GIT_PROJECT " "
               GIT_SHORT " ID" BUILD_ID_STRING "\n"
   );
   return;
}
#endif

void biwakPrintBaseInfo( )
{
   fputs(  "\n\n", stdout) ;
   #if 1
   fputs(  "GCC  : "  STRINGIFICATE( __GNUC__ ) "."
                     STRINGIFICATE( __GNUC_MINOR__ ) "."
                     STRINGIFICATE( __GNUC_PATCHLEVEL__) "\n", stdout) ;
   #endif
   fputs(  "Board: "  STRINGIFICATE( ARENA_BOARD ) "\n", stdout) ;
   fputs(  "MCU  : "  STRINGIFICATE( MCU_REV_LONG ) "\n", stdout) ;
   #if defined(FLASH_SIZE)
      printf( "Flash: %dKB\n", (int)(FLASH_SIZE / 1024) );
      // printf( "RAM:   %dKB\n", (int)(RAM_SIZE / 1024) );
      // printf( "RAM:   %dKB\n", (int)( (uint32_t)&_eram - 0x20000000 ) );
   #elif defined(FLASHSIZE_BASE)
      printf( "Flash: %dKB\n",   *(uint16_t*)( FLASHSIZE_BASE ) );
   #else
      printf( "Flash: %dKB (LS)\n",   (int)( (&_eflash-&_sflash) / 1024) );
   #endif

   return;
}

void biwakPrintCompilerInfo( )
{
   fputs(  "GCC  : "  STRINGIFICATE( __GNUC__ ) "."
                     STRINGIFICATE( __GNUC_MINOR__ ) "."
                     STRINGIFICATE( __GNUC_PATCHLEVEL__) "\n", stdout) ;

   return;
}

void biwakPrintClockInfo( )
{
   printf( "SYSCLK    : %d Mhz\n", (int)HAL_RCC_GetSysClockFreq() / HZ_TO_MHZ );
   //lHint << eLogBaseDec << " H Clock  :  "  << (int)HAL_RCC_GetSysClockFreq();
   printf( "APB1/PCLK1: %d\n", (int)HAL_RCC_GetPCLK1Freq());
   #if defined( RCC_CLOCKTYPE_PCLK2 )
      printf( "APB2/PCLK2: %d\n", (int)HAL_RCC_GetPCLK2Freq());
   #endif
   printf( "HSE       : %d\n", (int)HSE_VALUE);
   printf( "HSI       : %d\n",  (int)HSI_VALUE);
   printf( "SysCrClk  : %d\n",  (int)SystemCoreClock);

   return;
}

extern char __heap_start[];
extern char __heap_end[];
extern char _Min_Heap_Size[];

void biwakPrintMemoryBaseInfo( )
{
   printf("BIN:   %ld\n", (uint32_t)&_end_data_flash - (uint32_t)&_sflash);
}

void biwakPrintMemoryInfo( )
{
   //lDebug << eLogBaseHex << "Flash End: " << (int)&_eflash;
   //lDebug << "Size Text:   " << eLogBaseDec << ((int)&_eram - (int)&_sram) / 1024 << " KB";
   printf("End       : 0x%lX\n", (uint32_t)&end);
   printf("End RAM   : 0x%lX\n", (uint32_t)&_eram);
   printf("Start BSS : 0x%lX\n", (uint32_t)&_sbss);
   printf("End BSS   : 0x%lX\n", (uint32_t)&_ebss);
   printf("Start Data: 0x%lX\n", (uint32_t)&_sdata);
   printf("End Data  : 0x%lX\n", (uint32_t)&_edata);
   printf("Heap start: 0x%lX\n", (uint32_t)&__heap_start);
   printf("Heap end  : 0x%lX\n", (uint32_t)&__heap_end);
   printf("Min heap  : 0x%lX\n", (uint32_t)&_Min_Heap_Size);
   //lDebug << "Start Code:  " << (int)&_stext ;
   //lHint << "End Text:    " << (int)&_etext ;
   //lDebug << "Size Text:   " << (int)&_etext - (int)&_stext
   //      << "/" << eLogBaseDec << ((int)&_etext - (int)&_stext) / 1024 << "K";

   printf("SP        : 0x%lX\n", (uint32_t)stack_ptr);

   return;
}


void biwakPrintDateInfo( )
{
   //printf("Date      : %s\n", __DATE__);
   //printf("Time      : %s\n", __TIME__);
   printf("Timestamp : %s\n", __TIMESTAMP__);
   return;
}


void biwakPrintFlashInfo( )
{
   printf("Start fl  : 0x%lX\n", (uint32_t)&_sflash );
   printf("End fl    : 0x%lX\n", (uint32_t)&_eflash );
}


void biwakPrintTimings( )
{
   printf("hrtPerUsec: %d\n", (int)usecToHrtValue(1) );
   printf("lrtPerMsec: %d\n", (int)msecToLrt(1) );
   printf("hrt Range : %d secs\n", (int)( ( ( ( 0x7FFFFFFF / 1000000 ) / 1 ) / 1 ) / usecToHrtValue(1) ) );
   printf("lrt Range : %d days\n", (int)( ( ( 0x7FFFFFFF / 1000 ) / SECS_PER_HOUR ) / HOUR_PER_DAY ) );
   
   return;
}


//---fin----------------------------------------------------------------------
