#ifndef __LOG_H
#define __LOG_H

#include "at32f403a_407.h"
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif
    

#define LOG_ENTRY_VERSION               1

#define ARCHIV_ENTRY_VERSION            1

#define LOG_FLASH_SECTOR_OFFSET         4

#define LOG_FLASH_SECTOR_COUNT          51

#define ARCHIVE_FLASH_SECTOR_OFFSET     60

#define ARCHIVE_FLASH_SECTOR_COUNT      30 //38

#define ARCHIVE_CHANNEL_OFFSET          (ARCHIVE_FLASH_SECTOR_COUNT + 4)
  
#define SECTOR_COUNT (spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET)  


  
  
#define MB_ARCHIVE_ENTRY                0x06
  
#define MB_LOG_ENTRY                    0x07

  
// -------------------------------------------------------------------------- //
  
  
// События архивов
typedef enum
{
    ARCH_CH_1 = 1 << 0,
    ARCH_CH_2 = 1 << 1,
    ARCH_CH_3 = 1 << 2,
    ARCH_CH_4 = 1 << 3,
    ARCH_CH_5 = 1 << 4,
    ARCH_CH_6 = 1 << 5,
    ARCH_CH_7 = 1 << 6,
    ARCH_CH_8 = 1 << 7,
    ARCH_CH_9 = 1 << 8,
    ARCH_CH_10 = 1 << 9,
    ARCH_CH_11 = 1 << 10,
    ARCH_CH_12 = 1 << 11,
    
} arch_event_t;

  
//
typedef enum 
{
    LOG_SYSTEM_BOOT = 1,    // включение питания/перезагрузка
    LOG_CLOCK_CHANGE,       // перевод времени
    LOG_UPDATE_FW,          // обновление FW
    LOG_SYSTEM_ERR,         // самодиагностика/системная ошибка
    LOG_CHANGE_CONFIG,      // изменение конфигурации
    LOG_OUPUTS,             // диагностика выходов
    LOG_SETPOINT,           // срабатывание уставок
    LOG_SAVE_MODE,          // переход в безопасный режим
    LOG_CLEAR,              // очистка журнала/архива
    
    LOG_NONE,

} log_event_type_t;


typedef enum
{
    LOG_EVENT_STATE_ERR = 0,
    LOG_EVENT_STATE_OK,
    
} log_event_state_t;


typedef enum
{
    LOG_ENTRY = 0,
    ARCHIVE_ENTRY,
    
} entry_type_t;


//
typedef __packed struct 
{
    uint64_t timestamp;
    
} common_entry_t;


// Структура записи журанала
typedef __packed struct 
{
	uint64_t timestamp;
    uint8_t code_type;  // код типа события
    uint8_t code_state; // код состояния
    uint8_t channel_number; // номер канала
    float value;        // значение
    uint8_t crc;
    
} log_entry_t;


// Структура архивной записи
typedef __packed struct
{
    uint64_t timestamp;
    uint8_t input_value;
    uint8_t crc;
    
} archive_entry_t;


//
void log_init(bool format);

//
void log_init_archive_tim(void);

//
int log_fetch(void *entry, entry_type_t entry_type, uint8_t ch, uint32_t timeout);

//
int log_discard(void *entry, entry_type_t entry_type, uint8_t ch, uint32_t timeout);

// 
int log_append(void *entry, entry_type_t entry_type, uint8_t ch);

//
uint16_t log_capacity(void);

//
uint16_t log_arch_capacity(uint8_t ch);

// -------------------------------------------------------------------------- //
// misc

uint8_t crc_8(uint8_t *data, int length);

// -------------------------------------------------------------------------- //
// Tests

//
void log_info(uint8_t val, uint8_t ch);

//
void log_format(uint8_t val, uint8_t ch);

//
int log_add_random_entry(uint8_t val, uint32_t cnt_entry, uint8_t ch);

//
int log_add_entry(log_event_type_t type, log_event_state_t state, 
                  uint8_t channel_number, float value);

//
void test_fetch(void);

//
void log_archive_state(bool state);

//
void log_log_state(bool state);

//
void test_archive_format(void);

//
void log_check_archive_cnt(void);

// -------------------------------------------------------------------------- //

extern uint16_t log_entries_capacity;
extern uint16_t archive_entries_capacity;



#ifdef __cplusplus
}
#endif


#endif /* __LOG_H */
