/*
   Copyright (c) 2015, Digi International Inc.

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/***********************************************************
     
	bufflock.c

	This sample program is for the OP7200 series controllers.
	
   Demonstration of increased LCD performance with using
   glBuffLock and glBuffUnlock functions.


   Instructions
   ------------
	1. Compile and run program.
	2. View the LCD screen as it executes the demo.
	     		
************************************************************/
#class auto
#memmap xmem  // Required to reduce root memory usage 

//----------------------------------------------------------
// Structures, arrays, variables
//----------------------------------------------------------
fontInfo fi8x12, fi10x16, fi12x16;


#define BOXTOPLEFTX 	20   	//box upper left x-coordinate
#define BOXTOPLEFTY 	50		//box upper left y-coordinate
#define BOXWIDTH 		300	//box width
#define BOXHEIGHT 	180  	//box height

nodebug
void msDelay(unsigned int delay)
{
	auto unsigned long done_time;
	
	done_time = MS_TIMER + delay;
   while( (long) (MS_TIMER - done_time) < 0 );
} 


//////////////////////////////////////////////////////////
// draws box outline
//////////////////////////////////////////////////////////
void drawBox(int x, int y, int w, int h)
{
 	glPlotLine(x, y, w, y);		//north line
 	glPlotLine(w, y, w, h);		//east line
 	glPlotLine(w, h, x, h);		//south line
 	glPlotLine(x, h, x, y);		//west line
}

//////////////////////////////////////////////////////////
// Pixel bitmap 
//////////////////////////////////////////////////////////

xdata demo_figure {
'\x0F','\xFF','\xF0',
'\x1F','\xFF','\xF8',
'\x3F','\xFF','\xFC',
'\x7F','\xFF','\xFE',
'\xEF','\xFF','\xFF',
'\xEF','\xFF','\xFF',
'\xEF','\xFF','\xFF',
'\xEF','\xFF','\xFF',
'\x7F','\xFF','\xFE',
'\x3F','\xFF','\xFC',
'\x1F','\xFF','\xF8',
'\x0F','\xFF','\xF0'
};



//////////////////////////////////////////////////////////
// Function to position and draw image for demo program   
//////////////////////////////////////////////////////////
nodebug
void buffLock_cntrl(int* dx, int* dy, int* px, int* py, int glbuff_cnt  )
{
	auto int nx,ny;		// New Position         
	auto int lock_cnt;
	
	for(lock_cnt = 0; lock_cnt < glbuff_cnt; lock_cnt++)
   {	
		// Try New Position
		nx = *px + *dx;               	     
		ny = *py + *dy;

		// Avoid Collision
		if (nx <= BOXTOPLEFTX || ((nx+24) >= BOXWIDTH))     
		{
			glXPutBitmap (*px,*py,24,12,demo_figure);
			*dx = -*dx;
		}
		if (ny <= BOXTOPLEFTY || ((ny+12) >= BOXHEIGHT))
		{
			glXPutBitmap (*px,*py,24,12,demo_figure);
			*dy = -*dy;
		}

		// Next Position 
		nx = *px + *dx;               	
		ny = *py + *dy;
      
		glXPutBitmap (*px,*py,24,12, demo_figure);
	
		// Move Ball
		*px = nx; *py = ny;
	}
}

//////////////////////////////////////////////////////////
// Display sign-on message on the LCD and run Demo.
//////////////////////////////////////////////////////////
nodebug
void demo( void )
{
	auto int	px,py;      // Current Position     
	auto int dx,dy;      // Current Direction    
	auto int lock_cnt;
	auto int viewloop;
	auto int iterations;

	glBuffLock();
	glBlankScreen();
	drawBox(BOXTOPLEFTX, BOXTOPLEFTY,
			  BOXWIDTH, BOXHEIGHT);
	glPrintf(20,10, &fi10x16,  "glBuffer lock/unlocking Demo");
	glPrintf(20,200, &fi10x16, "Increase lock/unlocking usage");
	glPrintf(20,216, &fi10x16, "to 0.");	  
	glBuffUnlock();
	
   px = BOXTOPLEFTX + 1;   py = BOXTOPLEFTY + 1;    
   // Give Direction
   dx = 2;   dy = 2;                 			 

   
  	for(iterations = 1; iterations < 30; iterations++)
  	{
  		for(viewloop=0; viewloop < 10; viewloop++)
		{
			glBuffLock();
			glPrintf(20,216, &fi10x16, "to %d.", iterations);	  
			// By increasing the number of iterations between
			// locking and unlocking the graphic buffer you can
			// get increased performance.
         //
         // Note: Functions glBuffLock() and glBuffUnlock() can be
         // nested up to a level of 255, but be sure to balance the
         // calls.
         //
			
  			buffLock_cntrl(&dx, &dy, &px, &py, iterations);
     		glBuffUnlock();
     	}
     	
   }
}

//////////////////////////////////////////////////////////

void main ()
{
	brdInit();

	glInit();			// Initialize the graphic driver
	glBackLight(1);
	glSetContrast(24);
	
	glXFontInit(		//	initialize the font info structure needed later
		&fi10x16,		//	pointer to the font info structure to fill
		10,				//	horizontal size (in pixels) of each character
		16,				//	vertical size (in pixels) of each character
		32,				//	beginning code of printable characters
		127,				//	ending code of printable characters
		Font10x16		//	address of font bitmap in xmem
	);

	for(;;)
	{
		demo();
	
	}
}
