//
// Copyright (C) 2015-2023  Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// This file is part of Open Source Scan Converter project.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef AV_CONTROLLER_H_
#define AV_CONTROLLER_H_

#include "avconfig.h"
#include "sysconfig.h"
#include "sc_config_regs.h"
#include "osd_generator_regs.h"
#include "pll_reconfig_regs.h"

// sys_ctrl bits
#define LT_ACTIVE                   (1<<15)
#define LT_ARMED                    (1<<14)
#define LT_MODE_OFFS                12
#define VSYNC_I_TYPE                (1<<10)
#define PLL_BYPASS                  (1<<9)
#define REMOTE_EVENT                (1<<8)
#define SD_SPI_SS_N                 (1<<7)
#define LCD_CS_N                    (1<<6)
#define LCD_RS                      (1<<5)
#define LCD_BL                      (1<<4)
#define LCD_BL_TIMEOUT_OFFS         2
#define VIDGEN_OFF                  (1<<1)
#define AV_RESET_N                  (1<<0)

#define LT_CTRL_MASK                0xf000

#define HDMITX_MODE_MASK            0x00040000
#define PLL_ACTIVECLK_MASK          0x00080000
#define VSYNC_FLAG_MASK             0x00100000

#define AUTO_OFF                    0
#define AUTO_CURRENT_INPUT          1
#define AUTO_MAX_COUNT              100
#define AUTO_CURRENT_MAX_COUNT      6

#define PLL_CONFIG_VG               0

// In reverse order of importance
typedef enum {
    NO_CHANGE           = 0,
    SC_CONFIG_CHANGE    = 1,
    MODE_CHANGE         = 2,
    TX_MODE_CHANGE      = 3,
    ACTIVITY_CHANGE     = 4
} status_t;

typedef enum {
    TX_HDMI_RGB         = 0,
    TX_HDMI_YCBCR444    = 1,
    TX_DVI              = 2
} tx_mode_t;

typedef struct {
    alt_u32 data[5];
} pll_config_t;

//TODO: transform binary values into flags
typedef struct {
    alt_u32 totlines;
    alt_u32 pcnt_field;
    alt_u32 hsync_width;
    alt_u32 clkcnt;
    alt_u8 progressive;
    alt_8 id;
    alt_u8 sync_active;
    alt_u8 hdmitx_pclk_level;
    alt_u32 pclk_o_hz;
    avinput_t avinput;
    // Current configuration
    avconfig_t cc;
} avmode_t;

typedef struct {
    uint8_t profile_link;
    avinput_t def_input;
    uint8_t auto_input;
    uint8_t auto_av1_ypbpr;
    uint8_t auto_av2_ypbpr;
    uint8_t auto_av3_ypbpr;
    uint8_t lcd_bl_timeout;
    uint8_t osd_enable;
    uint8_t osd_status_timeout;
    uint8_t osd_highlight_color;
    uint8_t phase_hotkey_enable;
} settings_t;

typedef struct {
    uint8_t iv_x;
    uint8_t iv_y;
    uint16_t v[16][16];
} shmask_data_arr;

typedef struct {
    char name[20];
    shmask_data_arr arr;
} c_shmask_t;

typedef union {
    struct {
        uint32_t c64_pal[16];
        uint32_t zx_pal[16];
        uint32_t msx_pal[16];
        uint32_t intv_pal[16];
        uint32_t nes_pal[64];
        uint32_t tia_pal[128];
        uint32_t gtia_pal[256];
        uint32_t maria_pal[256];
        uint32_t sms_pal[64];
        uint32_t vic20_pal[16];
        uint32_t g7000_pal[16];
        uint32_t mc6847_pal[16];
    } __attribute__((packed, __may_alias__));
    uint32_t data[880];
} lc_palette_set;

typedef struct {
    char name[20];
    lc_palette_set pal;
} c_lc_palette_set_t;

void ui_disp_menu(alt_u8 osd_mode);
void ui_disp_status(alt_u8 refresh_osd_timer);

void set_sampler_phase(uint8_t sampler_phase, uint8_t update_sc);

void set_default_c_shmask();
void set_default_c_lc_palette_set();

void print_vm_stats();
int latency_test();

void update_sc_config();

void invalidate_loaded_arrays();
void update_settings(int init_setup);

#endif
