/*
 *****************************************************************************
 * Microchip Graphics Library Demo Application
 * This program shows how to use the Graphics Primitives Layer.
 *****************************************************************************
 * FileName:        MainDemo.c
 * Dependencies:    MainDemo.h
 * Processor:       PIC24
 * Compiler:       	MPLAB C30
 * Linker:          MPLAB LINK30
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * Copyright ?2007 Microchip Technology Inc.  All rights reserved.
 * Microchip licenses to you the right to use, modify, copy and distribute
 * Software only when embedded on a Microchip microcontroller or digital
 * signal controller, which is integrated into your product or third party
 * product (pursuant to the sublicense terms in the accompanying license
 * agreement).  
 *
 * You should refer to the license agreement accompanying this Software
 * for additional information regarding your rights and obligations.
 *
 * SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS?WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
 * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
 * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
 * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION,
 * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
 * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
 * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
 * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY
 * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
 * OR OTHER SIMILAR COSTS.
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Anton Alkhimenok		30/05/07	...
 *****************************************************************************
*/

/*
******************************************************************************
* Description: This is a demo program for LVC75Z779 Eval Board Version 1E.
* The microcontroller is PIC24FJ128GA010 on PIC24-Eval-RevC
* stack with a CMOS camera module OV9650_BO. 
* The intention of this project is to develop the drivers for :
* (1) Solomon SSD1928
* (2) OV9650 CMOS camera
* (3) SD card driver for SSD1928 with jpeg encode and decode functions
* 
* Microchip Graphic Library has been used as the GUI because it is a free
* GUI provided that Microchip microcontroller would be used as the host.
* 
* At time of writing (version 23012009), basic support of primitive graphic,
* CMOS camera preview on LCD, and basic IO for SD card has been achieved.
* User may study this source code, compile, and download to the target
* mcu with OV9650_BO and a SD card (1GB for my case) inserted in the microSD
* connection to use this demo. Serial monitoring program such as Hyperterminal
* can be used to learn that the SD card would be initialised successfully, 
* and finally this program will hold at CMOS camera preview. Serial monitoring
* program should be adjusted to 19200bps, 8-n-1 for data monitor.
*
* 
* This project modified for PIC24-Eval RevC from previous PIC24 board version
* There are two changes:
* (1) UART in comm.h changed from uart1 to uart2
* (2) pinout definition under ssd1928.h changed for PIC24 Eval RevC board

* Programmer: John Leung
* Company: TechToys Co.
* Web presence: www.TechToys.com.hk
* Date: 23 Jan 2009
* Version : 23012009
******************************************************************************

* Programmer: Fabrice Muller
* Company: 
* Modified: Pic24 Pins for Pic32MX Companion board prototype
* Date: 28 Jan 2009
* added : Circle Demo
*		: Rectangle Demo
*		: FillCircle Demo
*		: Bar Demo
*		: Line Demo
*		: 3D Cube Demo
******************************************************************************
*/

#include "MainDemo.h"
#include <stdlib.h>
#include "trigotable.h"

// Configuration bits
// Configure fast RC oscillator with PLL and RC15 pin for Fosc/2 function	
_CONFIG2(FNOSC_FRCPLL & OSCIOFNC_OFF)
_CONFIG1(JTAGEN_OFF & FWDTEN_OFF)   // JTAG off, watchdog timer off

// Maximum Objects to Show
#define ObjectNum 30
// Number of Animation step
#define AnimLenght 300

///////////////////////////////// FONTS ///////////////////////////////////////
extern FONT_FLASH Font25;

/////////////////////////////// Functions ///////////////////////////////////////
void Obj3D (void);                   // Calculer et tracer le cube


/////////////////////////////// Variables ///////////////////////////////////////

// Variables globales composant les points et les faces du Cube
const signed int px[8]={-10,10,10,-10,-10,10,10,-10};   // Les points X du cube
const signed int py[8]={-10,-10,10,10,-10,-10,10,10};   // Les points Y du cube
const signed int pz[8]={-10,-10,-10,-10,10,10,10,10};   // Les points Z du cube

const int face[12][3]={{0,1,2},{2,3,0},{1,5,6},{6,2,1}, // Les faces du cube
                       {5,4,7},{7,6,5},{4,0,3},{3,7,4},
                       {3,2,6},{6,7,3},{0,4,5},{5,1,0}};



WORD Couleur[21] = {
BRIGHTBLUE,BRIGHTGREEN,BRIGHTCYAN,BRIGHTRED,BRIGHTMAGENTA,BRIGHTYELLOW,
BLUE,GREEN,CYAN,RED,MAGENTA,BROWN,LIGHTGRAY,DARKGRAY,LIGHTBLUE,LIGHTGREEN,
LIGHTCYAN,LIGHTRED,LIGHTMAGENTA,YELLOW,WHITE};
short Counter;

int main(void){

	short Px[ObjectNum],Py[ObjectNum],OldPx[ObjectNum],OldPy[ObjectNum],Rayon[ObjectNum],Dx[ObjectNum],Dy[ObjectNum],Col[ObjectNum];
	short Ct1;
	short Lx1[ObjectNum],Ly1[ObjectNum],Lx2[ObjectNum],Ly2[ObjectNum],Dx1[ObjectNum],Dy1[ObjectNum],Dx2[ObjectNum],Dy2[ObjectNum];
	short OldLx1[ObjectNum],OldLy1[ObjectNum],OldLx2[ObjectNum],OldLy2[ObjectNum];
	SHORT width, height;

	CLKDIV = 0x0000;	//FRC postscaler divided by 1 (8MHz from internal RC)
	//_EI();				//enable interrupt for uart


	uart_init();					//Initialize uart for parameters setup
	DelayMs(1);						//For PLL stablization
	//UART rate at 19200bps, 8-n-1.
	xputs("\nSSD1928 display driver development for PIC24F\n");

	ResetDevice();					//For low level pck generation


	//********************************************
	// Demo section for Main Window, simple primitive function performed	
											
	ssd1928_MainWndEnable(FALSE);										//blank display
	ssd1928_MainWndInit(0, SCREEN_HOR_SIZE, 16, 0, 1);					//init display with full physical display width, 16bpp, no rotation, and RGB mode
	ssd1928_FloatWndInit(PAGE_MEM_SIZE, 100, 160, 120, 100, 100, 1);	//init floating window to RGB mode at PAGE_MEM_SIZE
	ssd1928_FocusWnd(0);												//argument '0' indicates the main window

	SetColor(BLACK);
	ClearDevice();
	ssd1928_MainWndEnable(TRUE);
	SetColor(BRIGHTBLUE);
	ClearDevice();
	DelayMs(1000);		
	SetColor(BLACK);
	ClearDevice();
	DelayMs(1000);

    SetFont(&Font25);
    SetColor(BRIGHTGREEN);
    width = GetTextWidth("SupraBotics",&Font25);
    height = GetTextHeight(&Font25);

    OutTextXY( (GetMaxX()-width)>>1,
               (GetMaxY()-height)>>1,
                "SupraBotics");

    DelayMs(1000);

	ssd1928_SDInit(0);
	
	DelayMs(1000);

	//********************************************

	//********************************************
	// Demo section for camera module (OV9650 in this example)
	// Only Video Display on the Main Window is supported for 320*240 matrix
	// RGB/YUV Setting Register at REG[1A4h] has to be 0xC0 (i.e. RGB for both Main Window and Floating Window)
	// to preview CMOS camera properly
	camInit();
	camVideoPreview(0,TRUE);
	DelayMs(1000);
	
	srand(25);

	while(1)
	{
	 // Set or Randomize the variables before each Animation cycle
	 for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
	 	 {
		 Px[Ct1] = __builtin_modud(rand(),300) + 10;
		 Py[Ct1] = __builtin_modud(rand(),220) + 10;
		 Lx1[Ct1] = __builtin_modud(rand(),300) + 10;
		 Ly1[Ct1] = __builtin_modud(rand(),220) + 10;
		 Lx2[Ct1] = __builtin_modud(rand(),300) + 10;
		 Ly2[Ct1] = __builtin_modud(rand(),220) + 10;
		 OldPx[Ct1] = Px[Ct1];
		 OldPy[Ct1] = Py[Ct1];
		 OldLx1[Ct1] = Lx1[Ct1];
		 OldLy1[Ct1] = Ly1[Ct1];
		 OldLx2[Ct1] = Lx2[Ct1];
		 OldLy2[Ct1] = Ly2[Ct1];
		 Rayon[Ct1] = __builtin_modud(rand(),5) + 2;
		 Col[Ct1] = __builtin_modud(rand(),21); 
		 Dx[Ct1] = 0;
		 Dy[Ct1] = 0;
		 Dx1[Ct1] = 0;
		 Dy1[Ct1] = 0;
		 Dx2[Ct1] = 0;
		 Dy2[Ct1] = 0;
		 while (Dx[Ct1] == 0)
			Dx[Ct1] = __builtin_modud(rand(),4) -2;
		 while (Dy[Ct1] == 0)
			Dy[Ct1] = __builtin_modud(rand(),4) -2;
		 while (Dx1[Ct1] == 0)
			Dx1[Ct1] = __builtin_modud(rand(),4) -2;
		 while (Dy1[Ct1] == 0)
			Dy1[Ct1] = __builtin_modud(rand(),4) -2;
		 while (Dx2[Ct1] == 0)
			Dx2[Ct1] = __builtin_modud(rand(),4) -2;
		 while (Dy2[Ct1] == 0)
			Dy2[Ct1] = __builtin_modud(rand(),4) -2;
		 }

	  // *************** Circle ******************
//	 SetColor(BLACK);
//	 ClearDevice();
	 Counter =  __builtin_modud(rand(),AnimLenght) + 200;
	  while (Counter > 1)
		{
		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			{
			Px[Ct1] += Dx[Ct1];
			Py[Ct1] += Dy[Ct1];
			if ((Px[Ct1] + Rayon[Ct1]) >= 318)
				Dx[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Px[Ct1] - Rayon[Ct1]) <= 1)
				Dx[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Py[Ct1] + Rayon[Ct1]) >= 239)
				Dy[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Py[Ct1] - Rayon[Ct1]) <= 1)
				Dy[Ct1] = __builtin_modud(rand(),4)+1;
//    		SetColor(BLACK);
//			Circle(OldPx[Ct1],OldPy[Ct1],Rayon[Ct1]);
    		SetColor(Couleur[Col[Ct1]]);
			Circle(Px[Ct1],Py[Ct1],Rayon[Ct1]);
//			OldPx[Ct1] = Px[Ct1];
//			OldPy[Ct1] = Py[Ct1];
			}
		Counter--;
		}
	  // ************** Rectangle ***************
//	 SetColor(BLACK);
//	 ClearDevice();
	 Counter =  __builtin_modud(rand(),AnimLenght) + 200;
	  while (Counter > 1)
		{
		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			{
			Px[Ct1] += Dx[Ct1];
			Py[Ct1] += Dy[Ct1];
			if ((Px[Ct1] + Rayon[Ct1]) >= 318)
				Dx[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Px[Ct1] - Rayon[Ct1]) <= 1)
				Dx[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Py[Ct1] + Rayon[Ct1]) >= 239)
				Dy[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Py[Ct1] - Rayon[Ct1]) <= 1)
				Dy[Ct1] = __builtin_modud(rand(),4)+1;
//    		SetColor(BLACK);
//			Rectangle(OldPx[Ct1] - Rayon[Ct1],OldPy[Ct1] - Rayon[Ct1],OldPx[Ct1] + Rayon[Ct1],OldPy[Ct1] + Rayon[Ct1]);
    		SetColor(Couleur[Col[Ct1]]);
			Rectangle(Px[Ct1] - Rayon[Ct1],Py[Ct1] - Rayon[Ct1],Px[Ct1] + Rayon[Ct1],Py[Ct1] + Rayon[Ct1]);
//			OldPx[Ct1] = Px[Ct1];
//			OldPy[Ct1] = Py[Ct1];
			}
		Counter--;
		}
	  // ************** FillCircle *************
//	 SetColor(BLACK);
//	 ClearDevice();
	 Counter =  __builtin_modud(rand(),AnimLenght) + 200;
	  while (Counter > 1)
		{
		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			{
			Px[Ct1] += Dx[Ct1];
			Py[Ct1] += Dy[Ct1];
			if ((Px[Ct1] + Rayon[Ct1]) >= 318)
				Dx[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Px[Ct1] - Rayon[Ct1]) <= 1)
				Dx[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Py[Ct1] + Rayon[Ct1]) >= 239)
				Dy[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Py[Ct1] - Rayon[Ct1]) <= 1)
				Dy[Ct1] = __builtin_modud(rand(),4)+1;
//    		SetColor(BLACK);
//			FillCircle(OldPx[Ct1],OldPy[Ct1],Rayon[Ct1]);
    		SetColor(Couleur[Col[Ct1]]);
			FillCircle(Px[Ct1],Py[Ct1],Rayon[Ct1]);
//			OldPx[Ct1] = Px[Ct1];
//			OldPy[Ct1] = Py[Ct1];
			}
		Counter--;
		}
	  // ******************* Bar ******************
//	 SetColor(BLACK);
//	 ClearDevice();
	 Counter =  __builtin_modud(rand(),AnimLenght) + 200;
	  while (Counter > 1)
		{
		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			{
			Px[Ct1] += Dx[Ct1];
			Py[Ct1] += Dy[Ct1];
			if ((Px[Ct1] + Rayon[Ct1]) >= 318)
				Dx[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Px[Ct1] - Rayon[Ct1]) <= 1)
				Dx[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Py[Ct1] + Rayon[Ct1]) >= 239)
				Dy[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Py[Ct1] - Rayon[Ct1]) <= 1)
				Dy[Ct1] = __builtin_modud(rand(),4)+1;
//    		SetColor(BLACK);
//			Bar(OldPx[Ct1] - Rayon[Ct1],OldPy[Ct1] - Rayon[Ct1],OldPx[Ct1] + Rayon[Ct1],OldPy[Ct1] + Rayon[Ct1]);
    		SetColor(Couleur[Col[Ct1]]);
			Bar(Px[Ct1] - Rayon[Ct1],Py[Ct1] - Rayon[Ct1],Px[Ct1] + Rayon[Ct1],Py[Ct1] + Rayon[Ct1]);
//			OldPx[Ct1] = Px[Ct1];
//			OldPy[Ct1] = Py[Ct1];
			}
		Counter--;
		}
	  // ******************* Lines ******************
//	 SetColor(BLACK);
//	 ClearDevice();
	 Counter =  __builtin_modud(rand(),AnimLenght) + 200;
	  while (Counter > 1)
		{
		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			{
			Lx1[Ct1] += Dx1[Ct1];
			Ly1[Ct1] += Dy1[Ct1];
			if ((Lx1[Ct1]) >= 315)
				Dx1[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Lx1[Ct1]) <= 5)
				Dx1[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Ly1[Ct1]) >= 235)
				Dy1[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Ly1[Ct1]) <= 5)
				Dy1[Ct1] = __builtin_modud(rand(),4)+1;
			Lx2[Ct1] += Dx2[Ct1];
			Ly2[Ct1] += Dy2[Ct1];
			if ((Lx2[Ct1]) >= 315)
				Dx2[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Lx2[Ct1]) <= 5)
				Dx2[Ct1] = __builtin_modud(rand(),4)+1;
			if ((Ly2[Ct1]) >= 235)
				Dy2[Ct1] = -(__builtin_modud(rand(),4)+1);
			if ((Ly2[Ct1]) <= 5)
				Dy2[Ct1] = __builtin_modud(rand(),4)+1;
//    		SetColor(BLACK);
//			Line(OldLx1[Ct1],OldLy1[Ct1],OldLx2[Ct1],OldLy2[Ct1]);
    		SetColor(Couleur[Col[Ct1]]);
			Line(Lx1[Ct1],Ly1[Ct1],Lx2[Ct1],Ly2[Ct1]);
//			OldLx1[Ct1] = Lx1[Ct1];
//			OldLy1[Ct1] = Ly1[Ct1];
//			OldLx2[Ct1] = Lx2[Ct1];
//			OldLy2[Ct1] = Ly2[Ct1];
			}
		Counter--;
		}
	Obj3D();
	}

}

void Obj3D()
{
   // Calculer et tracer le cube
   float  tx,ty,tz,x,y,z;              // Coordonnées temporaires
   short i,j;                          // Compteur
   float sx,sy,sz,cx,cy,cz;            // Sin et Cos precalcul?
   short ax,ay,az;                     // Les angles de 0 ?359 degrées
   short dx,zoom;                      // Centrage x,y et zoom du cube
   short dy;
   short nx[8];                        // Coordonnées de tracage
   short ny[8];
   short oldx[8];                      // Sauvegarde des ancienne coordonnées
   short oldy[8];
   short polyPoints[6];

   // Angles de départ
   ax = 45;
   ay = 20;
   az = 0;

   // Zoom du cube
   zoom = 6;

   // Centrage du cube
   dx = 159;
   dy = 119;

   // Rotation du cube
//  SetColor(BLACK);
//  ClearDevice();
  Counter =  __builtin_modud(rand(),AnimLenght) + 500;
  while (Counter > 1)
   {
    // Tranfers des sin et cos précalcul?dans les variables de travail
    sx = si[ax]; sy = si[ay]; sz = si[az];
    cx = co[ax]; cy = co[ay]; cz = co[az];


    // Calculer les nouvelles coordonnées des points
    for (i=0; i<8; i++)
        {
           tx = px[i] * zoom; ty = py[i] * zoom; tz = pz[i] * zoom;

           // Sauvegarde des anciennes coordonnées
//           oldx[i] = nx[i]; oldy[i] = ny[i];

           // Rotation sur Axe X
           y = ty * cx - tz * sx;
           z = ty * sx + tz * cx;
           ty =y; tz = z;
           // Rotation en Z
           x = tx * cz - ty * sz;
           y = tx * sz + ty * cz;
           tx = x; ty = y;
           // Rotation en Y
           x = tx * cy - tz * sy;
           z = tx * sy + tz * cy;
           // Sauver les coordonnées ecran
           nx[i] = (short)x + dx;
           ny[i] = (short)y + dy;
        }
//        DelayMs(10);

    // Effacer l'ancien cube et afficher le nouveau
    for (i=0; i<12; i++)
        {
//			 polyPoints[0] = oldx[face[i][0]];
//			 polyPoints[1] = oldy[face[i][0]];
//			 polyPoints[2] = oldx[face[i][1]];
//			 polyPoints[3] = oldy[face[i][1]];
//			 polyPoints[4] = oldx[face[i][2]];
//			 polyPoints[5] = oldy[face[i][2]];
//    		 SetColor(BLACK);
//			 DrawPoly(3,polyPoints);
			 polyPoints[0] = nx[face[i][0]];
			 polyPoints[1] = ny[face[i][0]];
			 polyPoints[2] = nx[face[i][1]];
			 polyPoints[3] = ny[face[i][1]];
			 polyPoints[4] = nx[face[i][2]];
			 polyPoints[5] = ny[face[i][2]];
    		 SetColor(YELLOW);
			 DrawPoly(3,polyPoints);
        }
    // Incrementer les angles
    ax = ax + 3; if (ax > 359) ax = ax - 360;
    ay = ay + 3; if (ay > 359) ay = ay - 360;
    az = az + 3; if (az > 359) az = az - 360;
	Counter--;
   }
}

