#pragma once

#ifndef MAKE_TAPROUTE_C
# include "common.h"
#else
# define extern_c extern
#endif

enum TAP_STATE
{
    TAP_TEST_LOGIC_RESET = 0,
    TAP_RUN_TEST_IDLE    = 1,
    TAP_SELECT_DR_SCAN   = 2,
    TAP_CAPTURE_DR       = 3,
    TAP_SHIFT_DR         = 4,
    TAP_EXIT1_DR         = 5,
    TAP_PAUSE_DR         = 6,
    TAP_EXIT2_DR         = 7,
    TAP_UPDATE_DR        = 8,
    TAP_SELECT_IR_SCAN   = 9,
    TAP_CAPTURE_IR      = 10,
    TAP_SHIFT_IR        = 11,
    TAP_EXIT1_IR        = 12,
    TAP_PAUSE_IR        = 13,
    TAP_EXIT2_IR        = 14,
    TAP_UPDATE_IR       = 15
};

/*
 * Short (3-letter) name of states (tap.c)
 */
extern_c const char tap_state_names[16][4];

/*
 * Where to we end up if we do a transition [state][tms]? (tap.c)
 */
extern_c const uint8_t tap_state_next[16][2];

/*
 * Bitmap to get to state [to]: use TMS in bit #from
 * (repeat until from == to). (taproute.c)
 */
extern_c const uint16_t tap_state_route[16];

#ifndef MAKE_TAPROUTE_C

enum jtag_io_flags {
    JIO_TDI       =  1,	/* TDI high if tdi == NULL */
    JIO_TMS       =  2,	/* TMS high on last clock (go to EXIT1) */
    JIO_CS        =  4	/* Raise TMS *after* the last clock (used for SPI) */
};

struct jtag_config {
    unsigned long hz;		/* JTAG frequency */
    uint8_t pin_tdi;		/* TDI/MOSI */
    uint8_t pin_tdo;		/* TDO/MISO */
    uint8_t pin_tms;		/* TMS/CS# */
    uint8_t pin_tck;		/* TCK/SCLK */
    bool be;			/* Bigendian (for SPI) */
};

typedef struct spz_stream spz_stream;

/*
 * Low-level TAP hardware operation interface
 */
extern_c int jtag_init(void);
extern_c int jtag_enable(const struct jtag_config *);
extern_c int jtag_disable(const struct jtag_config *);
extern_c int jtag_goto_state(enum TAP_STATE state);
extern_c int jtag_set_tms(bool tms);
extern_c void jtag_delay(unsigned int us);
extern_c uint32_t jtag_pulse(unsigned int bits, uint32_t tdi, uint32_t tms);
extern_c int jtag_io(unsigned int bits, enum jtag_io_flags flags,
		     const void *tdi, void *tdo);
extern_c int jtag_shift_spz(spz_stream *spz, enum jtag_io_flags flags);

extern_c int tap_goto_state(enum TAP_STATE state);
extern_c int tap_reset(void);
extern_c void tap_set_ir(uint32_t ir, unsigned int bits);
extern_c void tap_run_test_idle(unsigned int clocks);

#endif	/* MAKE_TAPROUTE_C */
