//----------------------------------------------------------------------------
///
/// \file   tests_systicks.cpp
///
/// \brief  Check calculated values
///
/// \date   20210922
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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


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

#if defined ( CATCH_V3 )
   #include <catch2/catch_test_macros.hpp>
#elif defined ( CATCH_V2 )
   #include <catch2/catch.hpp>
#elif defined ( CATCH_V1 )
   #include <catch/catch.hpp>
#else
   #error "Either 'catch' or 'catch2' has to be installed"
#endif

#include <QDebug>

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

#include <biwak/systick.h>
#include <biwak/flash_file.hpp>


//---Defines-------------------------------------------------------------------


#define TEST_ALL
#define STOP_ON_FAIL
#define FLASH_LAYOUT_MAJOR       1
#define FLASH_LAYOUT_MINOR       1

#define CLOCK_FREQUENCY          16000000    // 16Mhz


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


volatile hrtimer_t hrtPerUsec_fpf=-1;
volatile lrtimer_t lrtPerMsec=-1;
volatile int systickCounter=0;

// How much hr-ticks are in one lr-tick
hrtimer_t hrtMultiplikator=0x10000;
hrtimer_t hrtPerMsec = hrtMultiplikator;

// Fixed point float to increase precission
constexpr int fpf=1000;

// high-resulution ticks per one register tick
volatile hrtimer_t hrtPerRegTick_fpf=-1;


void initSystick()
{
   systickCounter=( CLOCK_FREQUENCY / MSECS_PER_SEC );
   /*
      Example: 16Mhz, that means we have 16000000 Ticks in one second.
               Thats 16 Ticks per usec (16Mhz/USECS_PER_SEC)
               Thats 16000 Ticks per msec
               We use 16000 as lrtDivider to have 1 lrt per msec.

               lrt has to be shifted in order to handle overflows.
               e.g. multiplied with 0x10000.
               An value of 0x10000 is equal to 1ms.
               hrtPerUsec=0x10000 (1ms) / usec_per_msec=65
               hrtPerRt=multiplikator/systickCounter=0x10000/16000=4,096

      real tick as timebase
               systickCounter=16000
               hrtPerSec=16000000;
               hrtPerUSec=16;
               hrtPerRegTick;
   */
   hrtMultiplikator = systickCounter;
   hrtPerRegTick_fpf = (hrtMultiplikator*fpf)/systickCounter;
   //regTickPeriodUsec =

   // It is defined that hrtMultiplikator/0x10000 hr-ticks are on lr-tick.
   hrtPerUsec_fpf= ( ( hrtMultiplikator * fpf ) / USECS_PER_MSEC );

   lrtPerMsec= 1;
}

TEST_CASE( "Systick", "[default]" ) {

   SECTION( "Standard" )
   {
      {
         /* The lrtimer has an resolution of 1ms
          * The hrtimer has an resolution of 1ms/0x10000
          */
         initSystick();

         float regtick=1.0/CLOCK_FREQUENCY;

         /* e.g. with 16Mhz, one tick is 62,5ns
          * There are 16000000 reg-ticks per second
          * The ammount of lr-ticks in one second is 1000
          * The ammount of hr-ticks in one second is
          *
          * hrtPerRt * 16000000 = 1000 * 0x1000;
          */

         REQUIRE( ( hrtPerRegTick_fpf * CLOCK_FREQUENCY ) / fpf
                                 == MSECS_PER_SEC * hrtMultiplikator );
         REQUIRE( ( hrtPerRegTick_fpf * CLOCK_FREQUENCY ) / fpf
                                 == ( hrtPerUsec_fpf * USECS_PER_SEC ) / fpf );

         // lrt should cover more than a week
         REQUIRE( ( 0x7FFFFFFF / lrtPerMsec ) / MSECS_PER_HOUR / HOUR_PER_DAY
                                 > 14 );
         // hrt should cover more than a 30 seconds
         REQUIRE( ( 0x7FFFFFFF / hrtPerMsec ) / MSECS_PER_SEC > 30 );
      }
   }
}


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