/*****************************************************************************/
/*
 * NTSC/CRT - integer-only NTSC video signal encoding / decoding emulation
 *
 *   by EMMIR 2018-2023
 *
 *   YouTube: https://www.youtube.com/@EMMIR_KC/videos
 *   Discord: https://discord.com/invite/hdYctSmyQJ
 */
/*****************************************************************************/
#ifndef _CRT_NTSC_VHS_H_
#define _CRT_NTSC_VHS_H_

#ifdef __cplusplus
extern "C" {
#endif

/* crt_ntscvhs.h
 *
 * An interface to convert a digital image to an analog NTSC signal with VHS
 * quality and some optional signal aberration at the bottom.
 *
 */
/* 0 = vertical  chroma (228 chroma clocks per line) */
/* 1 = checkered chroma (227.5 chroma clocks per line) */
#define CRT_CHROMA_PATTERN 1

/* chroma clocks (subcarrier cycles) per line */
#if (CRT_CHROMA_PATTERN == 1)
#define CRT_CC_LINE 2275
#else
/* this will give the 'rainbow' effect in the famous waterfall scene */
#define CRT_CC_LINE 2280
#endif

/* NOTE, in general, increasing CRT_CB_FREQ reduces blur and bleed */
#define CRT_CB_FREQ     4 /* carrier frequency relative to sample rate */
#define CRT_HRES        (CRT_CC_LINE * CRT_CB_FREQ / 10) /* horizontal res */
#define CRT_VRES        262                       /* vertical resolution */
#define CRT_INPUT_SIZE  (CRT_HRES * CRT_VRES)

#define CRT_TOP         21     /* first line with active video */
#define CRT_BOT         261    /* final line with active video */
#define CRT_LINES       (CRT_BOT - CRT_TOP) /* number of active video lines */

#define CRT_CC_SAMPLES  4 /* samples per chroma period (samples per 360 deg) */
#define CRT_CC_VPER     1 /* vertical period in which the artifacts repeat */

/* search windows, in samples */
#define CRT_HSYNC_WINDOW 8
#define CRT_VSYNC_WINDOW 8

/* accumulated signal threshold required for sync detection.
 * Larger = more stable, until it's so large that it is never reached in which
 *          case the CRT won't be able to sync
 */
#define CRT_HSYNC_THRESH 4
#define CRT_VSYNC_THRESH 94

/*
 *                      FULL HORIZONTAL LINE SIGNAL (~63500 ns)
 * |---------------------------------------------------------------------------|
 *   HBLANK (~10900 ns)                 ACTIVE VIDEO (~52600 ns)
 * |-------------------||------------------------------------------------------|
 *
 *
 *   WITHIN HBLANK PERIOD:
 *
 *   FP (~1500 ns)  SYNC (~4700 ns)  BW (~600 ns)  CB (~2500 ns)  BP (~1600 ns)
 * |--------------||---------------||------------||-------------||-------------|
 *      BLANK            SYNC           BLANK          BLANK          BLANK
 *
 */
#define LINE_BEG         0
#define FP_ns            1500      /* front porch */
#define SYNC_ns          4700      /* sync tip */
#define BW_ns            600       /* breezeway */
#define CB_ns            2500      /* color burst */
#define BP_ns            1600      /* back porch */
#define AV_ns            52600     /* active video */
#define HB_ns            (FP_ns + SYNC_ns + BW_ns + CB_ns + BP_ns) /* h blank */
/* line duration should be ~63500 ns */
#define LINE_ns          (FP_ns + SYNC_ns + BW_ns + CB_ns + BP_ns + AV_ns)

/* convert nanosecond offset to its corresponding point on the sampled line */
#define ns2pos(ns)       ((ns) * CRT_HRES / LINE_ns)
/* starting points for all the different pulses */
#define FP_BEG           ns2pos(0)
#define SYNC_BEG         ns2pos(FP_ns)
#define BW_BEG           ns2pos(FP_ns + SYNC_ns)
#define CB_BEG           ns2pos(FP_ns + SYNC_ns + BW_ns)
#define BP_BEG           ns2pos(FP_ns + SYNC_ns + BW_ns + CB_ns)
#define AV_BEG           ns2pos(HB_ns)
#define AV_LEN           ns2pos(AV_ns)

/* somewhere between 7 and 12 cycles */
#define CB_CYCLES   10

#define VHS_OFF 0
#define VHS_SP 1
#define VHS_LP 2
#define VHS_EP 3

#define VHS_MODE VHS_OFF

/* frequencies for bandlimiting */
#define L_FREQ           1431818 /* full line */

#define Y_FREQ_OFF          420000  /* Luma   (Y) 4.2  MHz of the 14.31818 MHz */
#define I_FREQ_OFF          150000  /* Chroma (I) 1.5  MHz of the 14.31818 MHz */
#define Q_FREQ_OFF           55000   /* Chroma (Q) 0.55 MHz of the 14.31818 MHz */

#define Y_FREQ_SP           300000  /* Luma   (Y) 3.0  MHz of the 14.31818 MHz */
#define I_FREQ_SP            62700   /* Chroma (I) 627  kHz of the 14.31818 MHz */
#define Q_FREQ_SP            62700   /* Chroma (Q) 627  kHz of the 14.31818 MHz */

#define Y_FREQ_LP           240000  /* Luma   (Y) 2.4  MHz of the 14.31818 MHz */
#define I_FREQ_LP            40000   /* Chroma (I) 400  kHz of the 14.31818 MHz */
#define Q_FREQ_LP            40000   /* Chroma (Q) 400  kHz of the 14.31818 MHz */

#define Y_FREQ_EP           200000  /* Luma   (Y) 2.0  MHz of the 14.31818 MHz */
#define I_FREQ_EP            37000   /* Chroma (I) 370  kHz of the 14.31818 MHz */
#define Q_FREQ_EP            37000   /* Chroma (Q) 370  kHz of the 14.31818 MHz */


/* IRE units (100 = 1.0V, -40 = 0.0V) */
#define WHITE_LEVEL      100
#define BURST_LEVEL      20
#define BLACK_LEVEL      7
#define BLANK_LEVEL      0
#define SYNC_LEVEL      -40

struct NTSC_SETTINGS {
    const unsigned char *data; /* image data */
    int w, h;       /* width and height of image */
    int raw;        /* 0 = scale image to fit monitor, 1 = don't scale */
    int as_color;   /* 0 = monochrome, 1 = full color */
    int field;      /* 0 = even, 1 = odd */
    int frame;      /* 0 = even, 1 = odd */
    int hue;        /* 0-359 */
    int xoffset;    /* x offset in sample space. 0 is minimum value */
    int yoffset;    /* y offset in # of lines. 0 is minimum value */
    int do_aberration; /* 0 = no aberration, 1 = with aberration */

    // these are changed by the vhs mode
    int vhs_mode;
    int y_freq;
    int i_freq;
    int q_freq;

    /* make sure your NTSC_SETTINGS struct is zeroed out before you do anything */
    int iirs_initialized; /* internal state */
};

#ifdef __cplusplus
}
#endif

#endif
