/*-----------------------------------------------------------------------*/
/*                                  TIGA                                 */
/*          Copyright (c) 1990 Texas Instruments Incorporated.           */
/*                         All Rights Reserved                           */
/*-----------------------------------------------------------------------*/
/*  TMS340 Graphics Library						 */
/*-----------------------------------------------------------------------*/
/*									 */
/*   Support for double-buffered video and scan-line synchronization	 */
/*									 */
/*	  FUNCTION NAME      DESCRIPTION				 */
/*	  -------------      -----------				 */
/*	    page_flip	     Change drawing and display pages		 */
/*	    page_busy	     Return status of drawing page		 */
/*	    wait_scan	     Wait until specified line is scanned	 */
/*									 */
/*  Note that the TMS340 Graphics Library implementation of these	 */
/*  functions necessarily differs from that of TIGA.  In TIGA, the	 */
/*  display interrupt service routine is written to share the display	 */
/*  interrupt request among a variety of functions, whereas the TMS340	 */
/*  Graphics Library polls the display interrupt request, and assumes	 */
/*  that the display interrupt is disabled.				 */
/*-----------------------------------------------------------------------*/
/*   03/20/90...Original version written..................J.R. Van Aken  */
/*-----------------------------------------------------------------------*/
#include <gsptypes.h>	      /* TIGA type definitions */
#include <gspglobs.h>	      /* TIGA global variables */
#include <gspreg.h>	      /* 340x0 register names */
#include "oem.h"              /* OEM-defined parameters */

#define DIE  (INTENB+10)      /* display interrupt enable bit */
#define DIP  (INTPEND+10)     /* display interrupt pending bit */

typedef enum { FIELDSIZE = 1 } BIT;
typedef struct { unsigned lcstrt : 2; unsigned srstrt : 14; } DPYSTRT10;

static DPYSTRT10 *dpystrt10 = (DPYSTRT10 *)DPYSTRT;

/*----------------------------------------------------------------------
 *
 *   Schedule swap of display and drawing pages for bottom of screen.
 *
 *----------------------------------------------------------------------
 */
void page_flip(display, drawing)
short display, drawing;
{
    int n;

    /* Ensure that args are legal video page numbers. */
    n = config.mode.num_pages;
    if (drawing >= n || drawing < 0 || display >= n || display < 0)
	drawing = display = 0;

    /* Schedule page flip to occur at bottom of screen. */
    poke_breg(OFFSET, page[drawing].BaseAddr);
#if GSP_34010
    dpystrt10->srstrt = ~(page[display].DpyStart >> 10);
    n = *(ushort *)VSBLNK10;	  /* bottom of screen */
#endif
#if GSP_34020
    *(ulong *)DPYST20 = page[display].DpyStart;
    n = *(ushort *)VSBLNK20;	  /* bottom of screen */
#endif

    /* Schedule display interrupt to occur at bottom of screen. */
    if (*(BIT *)DIE)
	return; 		   /* oops!--display interrupt enabled */
    *(ushort *)DPYINT = n;	   /* specify scan line number */
    *(BIT *)DIP = 0;		   /* clear interrupt request */
}


/*----------------------------------------------------------------------
 *
 *   Return non-zero value unless scheduled page swap has completed.
 *
 *----------------------------------------------------------------------
 */
int page_busy()
{
    if (*(BIT *)DIE)
	return (0);		   /* oops!--display interrupt enabled */
    return (!*(BIT *)DIP);	   /* flip sense of interrupt request */
}


/*----------------------------------------------------------------------
 *
 *	       Wait until specified line has been scanned.
 *
 *----------------------------------------------------------------------
 */
void wait_scan(line)
short line;
{
    /* Ensure display interrupt is not enabled. */
    if (*(BIT *)DIE)
	return; 		   /* oops!--display interrupt enabled */

    /* Convert scan line number to legal vertical count. */
    if (line < 0)
	line = 0;
#if GSP_34010
    line += (*(ushort *)VEBLNK10) + 1;
    if (line > *(ushort *)VSBLNK10)
	line = *(ushort *)VSBLNK10;
#endif
#if GSP_34020
    line += (*(ushort *)VEBLNK20) + 1;
    if (line > *(ushort *)VSBLNK20)
	line = *(ushort *)VSBLNK20;
#endif

    /* Schedule display interrupt for specified scan line. */
    *(ushort *)DPYINT = line;

    /* Wait until specified line has been scanned. */
    for (*(BIT *)DIP = 0; !*(BIT *)DIP; )
	;
}

