/**
 * @file        log.c
 */

/* Includes *******************************************************************/
#include "Timer.h"
#include "stm32f4xx_hal.h"
#include "encoder.h"
#include "log.h"
#include "gps.h"
#include "motor.h"

/* Defines ********************************************************************/
#define LOG_PERIOD 10

/* Public variables ***********************************************************/
/* Private variables **********************************************************/
volatile uint16_t encoderError = 0;
uint8_t log_active = 0;
static uint8_t log_flags = 0;

volatile uint8_t logOut_logSegment = 0;
volatile int logOut_logNumber = 0;
volatile gps_stamp_t logOut_tS;
volatile uint16_t logOut_subSecond;
volatile uint16_t logOut_tim1count;
volatile uint16_t logOut_tim2count;
volatile uint16_t logOut_rev;
volatile uint16_t logOut_freq;
volatile uint8_t logOut_source;
/* Exported variables *********************************************************/

extern volatile uint16_t uiLogTimer;
/* Constants ******************************************************************/
#define MSB16(a) ((uint8_t)(((a) & 0xFF00) >> 8))
#define LSB16(a) ((uint8_t)(((a) & 0x00FF) >> 0))

#define LASTB32(a) ((uint8_t)(((a) & 0xFF000000) >> 24))
#define THIRDB32(a) ((uint8_t)(((a) & 0xFF0000) >> 16))
#define SECONDB32(a) ((uint8_t)(((a) & 0xFF00) >> 8))
#define FIRSTB32(a) ((uint8_t)(((a) & 0x00FF) >> 0))
static uint8_t log_data[32];

/* Private functions **********************************************************/

/* Public functions ***********************************************************/
void LOG_Start(void) {
    log_active = 1;
}

void LOG_Stop(void) {
    log_active = 0;
}
void LOG_Reset(void) {
    logOut_logNumber = 0;
    logOut_logSegment = 0;
}

void LOG_NewSegment(void) {
    logOut_logSegment++;
}

void LOG_EncoderCount(uint16_t tim1count,uint16_t tim2count, uint16_t subSecond, uint8_t source)
{
    logOut_tS  = GPS_GetTimeStamp();
    logOut_rev    = Encoder_GetRevolutions();
    logOut_freq   = Motor_GetFreq();

    logOut_subSecond = subSecond;
    logOut_tim1count = tim1count;
    logOut_tim2count = tim2count;
    logOut_source = source;
    logOut_logNumber++;
    LOG_RaiseFlag(1);
}

void LOG_SendLog(void)
{
    /* LOG format:
     *  |     1      |  2 - 9                 |  10    |  11  |  12 | 13   |   14   |   15   |   16      |   17      |
     *  | log Number | UTC = Y,M,D,H,M,S,P1,P2| subsec | hall | rev | freq |segment | source | tim2count | enc error |
     */
    printf("%d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\r\n",
            logOut_logNumber,
            logOut_tS.Year,logOut_tS.Month,logOut_tS.Day,logOut_tS.Hour,logOut_tS.Minute,logOut_tS.Second,
            logOut_tS.ParamA,logOut_tS.ParamB,
            logOut_subSecond, logOut_tim1count, logOut_rev, logOut_freq, logOut_logSegment, logOut_source, logOut_tim2count,encoderError);
}

void LOG_SetPulseError(uint16_t pulse)
{
    encoderError = pulse;
}

/**
 * @brief   Log_Init()
 *
 */
void Log_Init(void)
{

}

/**
 * @brief   Log_Handler()
 *          This functions must be called from the super-loop.
 */
void Log_Handler(void)
{
    /* Check target rpm */
    if (0 == uiLogTimer) {
        uiLogTimer = LOG_PERIOD;
        uint16_t count = Encoder_GetCount();
        int16_t rev = Encoder_GetRevolutions();
        uint8_t timeData[24];
        GPS_GetStamp(timeData);
        uint32_t timCounter = TIM2->CNT;
        Log_SaveData(count, rev, timeData, timCounter);
    }
    if(1 == (log_flags & 1)) {
        log_flags &= ~1;
        if(1 == log_active) {
            LOG_SendLog();

        }
    }
}

void Log_GetData(uint8_t* timeData)
{
    for (int i = 0; i<32; i++) {
        *(timeData+i) = log_data[i];
    }
}

void Log_SaveData(uint16_t count, uint16_t rev, uint8_t* timeData, uint32_t timCounter)
{
    log_data[0] = MSB16(count);
    log_data[1] = LSB16(count);
    log_data[2] = MSB16(rev);
    log_data[3] = LSB16(rev);

    for (int i = 0; i<24;i++) {
        log_data[4+i] = *(timeData+i);
    }
    log_data[28] = LASTB32(timCounter);
    log_data[29] = THIRDB32(timCounter);
    log_data[30] = SECONDB32(timCounter);
    log_data[31] = FIRSTB32(timCounter);

}

void LOG_RaiseFlag(uint16_t flag)
{
    log_flags |= flag;
}
