/*                                                 -*-mode:C;tab-width:8-*-
 * cx100.h -- the header file for the dos compatibility library
 *
 * Copyright (C) 1995 ImageNation Corporation  (Version 1.3)
 * Copyright (C) 1995 Alessandro Rubini  --  rubini@ipvvis.unipv.it
 *
 *   Which licence does this fall into?
 */

/*
 * This header file must be included to get at least some compatibility
 * in porting dos programs (those written for the dos library as released
 * by ImageNation. Some features are intrinsically incompatible, as Unix
 * doesn't downgrade to segment/offset problems.
 *
 * Refer to the docs to get more information
 */

#ifndef _CX100_H_
#define _CX100_H_

#include <unistd.h> /* usleep */

#include <cxdrv.h> /* to get basic support */

/*==========================================================================
 * First of all, put herein all the strange material from ImageNation.
 * This is meant to minimize changes to be made to dos programs before
 * compiling them on Linux
 */ 

typedef unsigned char  BYTE;
typedef unsigned short WORD;
typedef unsigned long  DWORD;
#define far  /* nothing */
#define farmalloc(size)  malloc((size_t)size)
#define farfree(block)   free(block)
#define hugemalloc(size) malloc((size_t)size)
#define hugefree(block)  free(block)

/* What?   #define mvdata(a,b,c,d,e) movedata(a,b,c,d,e) */
/* What?   #define MK_FP(seg, offset)  */

/* keep the structures, by now */

/* SEGDATA doesn't make sense in U*x */

typedef struct tagFGDATA {
  int   cx,     /* TRUE if this port addresses a CX100 */
        fgp,    /* base port address */
        addr,   /* RAM segment */
        video,  /* TRUE if video input is present */
        ccir,   /* 0 = NTSC (default); 1 = CCIR/PAL */
        rev,    /* revision number; not presently used internally */
        off;    /* TRUE if the power has been turned off */
  } FGDATA;

typedef struct tagRGB {
  int red,
      green,
      blue;
  } RGB;


/* Keep this one */
#define NTSC            0
#define CCIR            1

/* These seem unavoidable :-( */
#ifndef TRUE
#  define TRUE            1
#endif
#ifndef FALSE
#  define FALSE           0
#endif

#if 0
/* Must look in these ones... */
#define    CREATEX         O_CREAT | O_EXCL | O_RDWR | O_BINARY
#define    CREATE          O_CREAT | O_RDWR | O_BINARY
#define    APPEND          O_APPEND | O_RDWR | O_BINARY
#define    TRUNC           O_TRUNC | O_RDWR | O_BINARY
#define    RWB             O_RDWR | O_BINARY
#define    RB              O_RDONLY | O_BINARY
#define    RW              S_IWRITE | S_IREAD
#define    Create(f)       open(f, CREATE, RW)
#define    CreateExcl(f)   open(f, CREATEX, RW)
#define    OpenAppend(f)   open(f, APPEND)
#define    OpenTrunc(f)    open(f, TRUNC)
#define    Open(f)         open(f, RWB)
#define    OpenR(f)        open(f, RB)
#define    Rewind(f)       rewind(f)
#endif

#if 0
#define PORT0 Fd[fg].fgp
#define PORT1 Fd[fg].fgp+1
#define PORT2 Fd[fg].fgp+2
#define PORT3 Fd[fg].fgp+3
#define PORT4 Fd[fg].fgp+4
#define PORT5 Fd[fg].fgp+5
#define PORT6 Fd[fg].fgp+6
#define PORT7 Fd[fg].fgp+7
#endif

#if 0
/* These ones should be redundant */
#define  PORT_BASE           0x0230
#define  MAX_PORTS           8
#define  MAX_SEGS            8
#endif

#if 0
#define  UNDEFINED_DISPLAY      250                /* initialization value */
#define  UNKNOWN_DISPLAY        255       /* cannot determine display type */

/* I can't use live display */
#define  fgEGA                  1                           /* EGA display */
#define  fgVGA                  2                           /* VGA display */
#endif


/* bits: unavoidable */
#define PAGE_SELECT_0     0
#define PAGE_SELECT_1     1
#define VERTICAL_ACCESS   2
#define ACQUIRE_REQUEST   3
#define DISPLAY_RAM       4
#define LOW_RESOLUTION    5
#define STROBE            6
#define HALF_PAGE         7

#define INTERRUPT_ENABLE  8
#define TRIGGER_ENABLE    9
#define IN_LUT_ENABLE    10
#define BLANK_DISPLAY    11
#define AB_SELECT        12
#define RAM_ENABLE       13
#define MP_ACCESS        14
#define BUF_FULL         15

#define FIELD_GRAB       16
#define FRAME_GRAB       17
#define OUT_LUT_ENABLE   18
#define DISPLAY_OVERLAY  19
#define OVERLAY_ENABLE   20
#define MASK_ENABLE      21
#define INDEPENDENT_PAGE 22

#define INTERRUPT_ACK    23
#define ADC_OVERFLOW     24
#define FIELD            25
#define VERTICAL_BLANK   26
#define TRIGGER_ACK      27
#define ACQUIRING_ACK    28
#define ADC_UNDERFLOW    29
#define HAVE_VIDEO       30

/* these work */
#define set(bit)         Cxg_SetBit(_cxg_fd,(bit))
#define clr(bit)         Cxg_ClrBit(_cxg_fd,(bit))

/* get_page, inc_page, dec_page are asyntactic.... */
#define get_page      (Cxg_GetPorts(_cxg_fd,&_cxg_ports),_cxg_ports[0]&3)
#define set_page(p)   Cxg_SetPage(_cxg_fd,(p))
#define inc_page      (set_page(get_page+1))
#define dec_page      (set_page(get_page-1))

/* --------------------------------------------------------------------------*/
#define get_column(buf,column) (copy_line((BYTE far *)buf,column,'R','V'))
#define get_row(buf,row)       (copy_line((BYTE far *)buf,row,'R','H'))
#define put_column(buf,column) (copy_line((BYTE far *)buf,column,'W','V'))
#define put_row(buf,row)       (copy_line((BYTE far *)buf,row,'W','H'))

/* these are asyntactic too... */
#define blank         (set(BLANK_DISPLAY))
#define unblank       (clr(BLANK_DISPLAY))

#define display       (clr(ACQUIRE_REQUEST),set(DISPLAY_RAM))
#define live          (clr(DISPLAY_RAM))

#define low_res       (set(LOW_RESOLUTION))
#define high_res      (clr(LOW_RESOLUTION))

/* Keep these ones, though there's no overhead in using <ctype.h> */
#define UPCASE(c)     (c&=~0x20)
#define LOWCASE(c)    (c|=0x20)


/******************************/
#define SAVE_PORTS(tmp) (Cxg_GetPorts(_cxg_fd,&_cxg_ports), \
						 tmp[0]=_cxg_ports[0],tmp[1]=_cxg_ports[1])

#define RELOAD_PORTS(tmp) {\
  outp(PORT0,tmp[0]); \
  outp(PORT1,tmp[1]); }

#define CLEAR_PORTS {\
  outp(PORT0,0); \
  outp(PORT1,0); }

/***************************************************************************
 *                            GLOBAL VARIABLES                             *
 ***************************************************************************/
#ifdef  __cplusplus                                             /* for CPP */
extern "C" {
#endif

#define MAX_PORTS 8
extern FGDATA Fd[MAX_PORTS];           /* see above description for FGDATA */
extern int lastrow;                           /* last useable row of video */
extern int videolen[2];                        /* 485 is NTSC; 511 is CCIR */
extern int fm;                           /* multiplier for font enlargment */
extern int x_char;                       /* character width * fm in pixels */
extern int y_char;                      /* character height * fm in pixels */

extern int fg;

/*==========================================================================
 * Then, global variables used by me
 */ 

extern int _cxg_fd; /* we need a global file descriptor, to access the board */
extern char _cxg_ports[4]; /* to read/write them */

/*==========================================================================
 * The following are the functions released by ImageNation.
 * Some of them are macros, and some of them are simply not available ;-)
 * Sometimes numbers are replaced by symbols (more readable)
 */

#define ClockDelay(i)  usleep((i)*55000)

/* functions indented by three spaces are not available */
/* functions commented out don't make sense under Linux */

#define acquire()              (waitvb(),acquiref())
#define acquiref()             set(ACQUIRE_REQUEST)
#define board_off()            (clr(IN_LUT_ENABLE),clr(OUT_LUT_ENABLE), \
                                cx_command(CXG_CMD_SHUTDOWN))
   void board_on(void);
#define ccir_mode()            (cx_command(CXG_CMD_GETSTATUS)& CXG_SBIT_CCIR \
                                ? 1 : 0)
#define clear_field_counter()  cx_command(CXG_CMD_CLRCOUNT)
#define clear_field_counter_high()  cx_command(CXG_CMD_CLRCOUNTH)

   void copy_line(BYTE far *buf, WORD row, BYTE dir, BYTE orient);
#define cx_command(data)       Cxg_Command(_cxg_fd,(data))
   void erase_ram(void);
#define exit_library()         (close(_cxg_fd),_cxg_fd=-1,0) /* WARN */

   void fill_column(WORD column, int color);
   void fill_ram(int color);
   void fill_row(WORD row, int color);
   int get_address(void);
   long get_clock(void);
   int get_pixel(WORD x, WORD y);
   void get_rectangle(BYTE *buf, WORD x1, WORD y1, WORD dx, WORD dy);
#define grab()                  Cxg_GrabFrame(_cxg_fd,1)
#define grab_field()            Cxg_GrabField(_cxg_fd,1)
#define grab_specific(f)        (Cxg_GrabFieldN(_cxg_fd,f,0),grab_field)
#define grab_specific_field(f)  Cxg_GrabFieldN(_cxg_fd,f,1)
   WORD grab_triggered(WORD delay, WORD timeout);
   void gray_scale_fill(void);
   /* int have_egavga(void); */
   char *init_library(void);
#define internal_sync()         cx_command(0x4F)
   void load_input_lut(int address, int data);
   void load_input_lut_buf(int *buf);
   void load_output_lut(int address, int data);
   void load_output_lut_buf(int *buf);
   void load_overlay_lut(int address, int red, int green, int blue);
   void load_rgb_lut(int address, int red, int green, int blue);
   void load_rgb_lut_buf(RGB buf[]);
   int put_pixel(WORD x, WORD y, int color);
   void put_rectangle(BYTE *buf, WORD x1, WORD y1, WORD dx, WORD dy);
#define ram_off()             Cxg_RamPage(_cxg_fd,CXG_RAMPAGE_NONE)
#define ram_on()              Cxg_RamPage(_cxg_fd,CXG_AUTODETECT)
#define read_dips()                cx_command(0x40)
#define read_field_counter_high()  cx_command(0x49)
#define read_field_counter_low()   cx_command(0x48)
   int read_file_to_buf(char *fname, BYTE *buf, DWORD buflen);
   int read_file_to_ram(char *fname);
#define read_key()                 cx_command(0x45)
int read_revision(void);
#define read_status2()             cx_command(0x43)
void reset_cx(void);
   int segment_vacant(int addr);
   char *select_fg(int index);
#define set_address(addr)          Cxg_RamPage(_cxg_fd,CXG_RAMPAGE,addr)
#define set_ccir()                 cx_command(0x5F)
   void set_display_mask(int mask);
   void set_gain(int gain);
   void set_gross_gain(int ggain);
   /* int set_half_page(int row); */
   /* int set_interrupt_polarity(int pos); */
#define set_ntsc()                 cx_command(0x5e)
   void set_offset(int offset);
   void set_overlay_mask(int mask);
#define set_trig_edge_sensitive()  cx_command(0x5a)
#define set_trig_level_sensitive() cx_command(0x5b)
#define set_trig_polarity(pol)     cx_command(04c+((pol)&1))
#define show_both_fields()         cx_command(0x52)
#define show_field(field)          (cx_command(0x53), \
									cx_command(0x64+((field)&1))
#define status(bit)                (!!Cxg_GetBit(_cxg_fd,(bit)))
#define sync_to_video()            cx_command(0x4e)
#define toggle(bit)                Cxg_SetBitV(_cxg_fd,(bit), \
											   !Cxg_GetBit(_cxg_fd,(bit)))
   /* void vga_off(void); */
   /* void vga_on(void); */
#define waitvb(void)               ioctl(_cxg_fd,CXG_WAITVB,-1)
#define waitvb_field(field)        ioctl(_cxg_fd,CXG_WAITVB,(field))
   WORD wait_for_trigger(WORD timeout);
   int write_buf_to_file(char *fname, int erase, BYTE *buf, DWORD buflen);
   int write_ram_to_file(char *fname, int erase);
   void zip_dn(void);
   void zip_up(void);

#if 0 /* averaging not supported */
   int avg_column(int column, int y1, int y2);
   int avg_line(int x1, int y1, int x2, int y2);
   int avg_row(int row, int x1, int x2);
#endif

#if 0 /* text writing not supported */
   void ft_clrscr(void);
   void ft_gotoxy(int x, int y);
   int ft_maxx(void);
   int ft_maxy(void);
   void ft_print(char *st);
   void ft_resizefont(int size);
   void ft_setbkcolor(int color);
   void ft_setcolor(int color);
   int ft_setfont(int font);
   int ft_wherex(void);
   int ft_wherey(void);
#endif

#if 0 /* graphics not supported */
   void fg_aspect(int denom);
   void fg_circle(int cx, int cy, int r);
   int fg_getcolor(void);
   void fg_line(int x1, int y1, int x2, int y2);
   void fg_linerel(int dx, int dy);
   void fg_lineto(int x, int y);
   int fg_maxx(void);
   int fg_maxy(void);
   void fg_moverel(int dx, int dy);
   void fg_moveto(int x, int y);
   void fg_rectangle(int x1, int y1, int x2, int y2);
   void fg_setcolor(int color);
   int fg_wherex(void);
   int fg_wherey(void);
#endif
   
#endif /* _CX100_H_ */
   
