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

* FileName:        Application.c
* Dependencies:    Image decoding library;
* Processor:       PIC24/dsPIC30/dsPIC33/PIC32MX
* Compiler:        C30 v2.01/C32 v0.00.18
* Company:         Microchip Technology, Inc.

 * Software License Agreement
 *
 * Copyright ?2008 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           Comments
--------------------------------------------------------------------------------
Pradeep Budagutta    25-Jun-2008    First release
*******************************************************************************/


/*
*******************************************************************************
* Version 140309
* (1) Add support for PIC32_STARTER_KIT under the Configuration Bits section
* 		comment out #define PIC32_STARTER_KIT if you are not using 
*		PIC32MX Starter kit for PIC24_Eval_Board C2
* (2) Add support for PIC24 series under the Configuration Bits section.
* 		Internal Fast Osc option used for PIC24_Eval_Board C2 hardware.
* (3) Add CLKDIV = 0x0000; under Main for 8MHz osc.
* 
* Programmer: John Leung
* Date: 14-03-09
*******************************************************************************
*/

/*
*******************************************************************************
 * Version 310309
 * (1) Add MDD File System directories (*.c and *.h) to Microchip directories
 *	  to support CFIO and SDIO File System.
 * (2) Under Build Options -> Include Search Paths, add the search path
 *	  "..\Microchip\Include\MDD File System"
 * (3) Add FSConfig.h to project directory
 * (4) Changes on HardwareProfile.h to support MDD FS
 * (5) Include FSIO.h under Application.c
 * (6) Include \MDDFS\FSIO.c and SD-SPI.c files under project workspace
 * (7) Modification to HardwareProfile.h
 * 	   #define	GetInstructionClock()		(GetSystemClock())
 * (8) Solder a 32.768kHz crystal to PIC32MX Starter Kit at Y3, 
 *	   15pF capacitors added, too.
 * (9) Under Build Options -> MPLAB PIC32 C Compiler option
 * 	   Switch on "Generate debugging information" checkbox to monitor an array just in case...
 * (10) Under ImageDecoderConfig.h, uncomment #define IMG_USE_ONLY_MDD_FILE_SYSTEM_FOR_INPUT
 *			THIS IS VERY IMPORTANT; OTHERWISE, DECODE IMAGES FROM SD DOES NOT WORK!
 * (11) Finally, remove all FlashImage related files from project
 *
 * Author: John Leung
 * File: HardwareProfile.h
 * Company: TechToys Company
 * Web presence: www.TechToys.com.hk
 * Date: 31th March 2009

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

/*
 ********************************************************************
 * Version 080409
 * (1) Add support for PIC24FJ series under HardwareProfile.h
 * (2) Remove virtual display feature from GraphicsConfig.h file
 *
 * Author: John Leung
 * Company: TechToys Company
 * Web presence: www.TechToys.com.hk
 * Date: 08 April 2009
 ********************************************************************
*/

/*
*****************************************************************************
* Project for QA the development platform
* PIC24/32-Eval-Board C2 + 3.5" TFT LCD module (LVC75Z779 Eval Board (Version 1E))
* + OV9650 CMOS camera module (TGA130V10)
*
* (1) 	Add support for ov9650.h in ssd1928.h, project modified for CMOS camera module ov9650
* (2)	Add Button 0 action to quit CMOS camera demo and continue image codec demo
* (3)	Update ssd1928 at the function ResetDevice(). Version = 170409 now.
* 		Modified ResetDevice() for the following in order to make GetReg() to work.
*		Bug uncovered during development for CMOS camera interface with PIC24 series
*
*		#ifdef __PIC32MX
*		    PMMODEbits.WAITM  = 15;
*		#else
*		    PMMODEbits.WAITM  = 2;	//original value "1"
*		#endif
*	(4) Comment the whole random graphics drawing port for it is not stable running 
*		on PIC32MX onboard model.
* Programmer: John Leung
* Date: 17-04-2009
* Version 170409
*****************************************************************************
*/

/*
*****************************************************************************
* Project for QA the development platform
* PIC24/32-Eval-Board C2 + 3.5" TFT LCD module (LVC75Z779 Eval Board (Version 1E))
* + OV9650 CMOS camera module (TGA130V10)
*
* (1) 	Bug reported and solved for 3.5" TFT module (LVC75Z779 Eval Board version 1E).
*		Random Graphics drawing enabled after a simple modification to TFT module
*		by soldering a 0.1uF 0603 ceramic capacitor on top of R5.
*
* Programmer: John Leung
* Date: 29-04-2009
* Version 290409
*****************************************************************************
*/


#include "Graphics\Graphics.h"
#include "Image Decoders\ImageDecoder.h"
#include "FSIO.h"
#include "trigotable.h"

#ifdef __PIC24FJ256GA110__
#include "pps.h"
#endif

// comment the following line if your are using Internal Fast Osc for PIC24 Eval BoardC2
// #define PIC32_STARTER_KIT

// Configuration bits
#ifdef __PIC32MX
#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_18, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1, FPLLIDIV = DIV_2
#pragma config OSCIOFNC = ON, FSOSCEN = OFF, IESO = OFF
#pragma config CP = OFF, BWP = OFF, PWP = OFF

#ifdef PIC32_STARTER_KIT
// PIC32MX Starter Kit
#pragma config FNOSC = PRIPLL, POSCMOD = XT
#else
// PIC24 Eval board RevC2 with PIC32MX360F512L onboard, Internal Fast Osc for 8MHz*18= 72MHz
#pragma config FNOSC = FRCPLL, POSCMOD = OFF, ICESEL = ICS_PGx2
#endif

#else
_CONFIG2(FNOSC_FRCPLL) 				// Fast RC oscillator with PLL
_CONFIG1(JTAGEN_OFF & FWDTEN_OFF)   // JTAG off, watchdog timer off
#endif


#define DELAY_MS 1500
#define DELAY_NEXT 3000

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

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

void PixelOutput(IMG_PIXEL_XY_RGB_888 *pPix);	// For image display from SD card

/////////////////////////////// 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;

/////////////////////////////// MAIN  ///////////////////////////////////////
int main(void)
{
	//variable section for image file API
	FSFILE * pointer;
    IMG_FILE_SYSTEM_API FlashFileApi;
    BYTE bTextHeight;
    WORD X, Y;
	
	//variable section for 3D objects
	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;

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

#ifdef __PIC24F__
	CLKDIV = 0x0000;	//FRC postscaler divided by 1 (8MHz from internal RC)
#endif

#ifdef __PIC32MX__
    INTEnableSystemMultiVectoredInt();
    SYSTEMConfigPerformance(GetSystemClock());	
#endif

#ifdef __PIC24FJ256GA110__
	pps_spi2();
#endif
	
    InitGraph();

    SetFont((void*)&GOLFontDefault);
    bTextHeight = GetTextHeight((void*)&GOLFontDefault);

	SetColor(BRIGHTRED);
	Y = (GetMaxY()+1-(3*bTextHeight))/2;
    SetColor(LIGHTRED);
    X = GetMaxX()+1-GetTextWidth("Please insert SD Card", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y, "Please insert SD Card");

   	while (!MDD_MediaDetect());

   	// Initialize the library
   	while (!FSInit());

    ImageDecoderInit();

    SetColor(BLACK);
    ClearDevice();
    Y = (GetMaxY()+1-(3*bTextHeight))/2;
    SetColor(LIGHTRED);
    X = GetMaxX()+1-GetTextWidth("Welcome to the demo", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y, "Welcome to the demo");
    DelayMs(DELAY_MS/3);
    X = GetMaxX()+1-GetTextWidth("of", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y + bTextHeight, "of");
    DelayMs(DELAY_MS/3);
    //X = GetMaxX()+1-GetTextWidth("Image Decoding Library", (void*)&GOLFontDefault);
    //OutTextXY(X/2, Y + 2*bTextHeight, "Image Decoding Library");
    X = GetMaxX()+1-GetTextWidth("CMOS Camera", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y + 2*bTextHeight, "CMOS Camera");
    DelayMs(DELAY_NEXT);

	#define BUT0_TRIS		TRISAbits.TRISA14
	#define BUT0			PORTAbits.RA14

	BUT0_TRIS = 1;			//set Button 0 as input

    while(1)
    {
		//********************************************
		// Demo section for camera module (OV9650 in this example)
		// Only Video Display on the Main Window is supported for 320*240 matrix
		camInit();
		camVideoPreview(0,TRUE);
		
		srand(25);

		do{
			
	 		// Set or Randomize the variables before each Animation cycle
	 		for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
			 	 {
				 Px[Ct1] = (rand()%300) + 10;
				 Py[Ct1] = (rand()%220) + 10;
				 Lx1[Ct1] = (rand()%300) + 10;
				 Ly1[Ct1] = (rand()%220) + 10;
				 Lx2[Ct1] = (rand()%300) + 10;
				 Ly2[Ct1] = (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] = (rand()%5) + 2;
				 Col[Ct1] = (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] = (rand()%4) -2;
				 while (Dy[Ct1] == 0)
					Dy[Ct1] = (rand()%4) -2;
				 while (Dx1[Ct1] == 0)
					Dx1[Ct1] = (rand()%4) -2;
				 while (Dy1[Ct1] == 0)
					Dy1[Ct1] = (rand()%4) -2;
				 while (Dx2[Ct1] == 0)
					Dx2[Ct1] = (rand()%4) -2;
				 while (Dy2[Ct1] == 0)
					Dy2[Ct1] = (rand()%4) -2;
				 }

				  // *************** Circle ******************
				 Counter =  (rand()%AnimLenght) + 200;
				  while ((Counter > 1)&&(BUT0!=0))
					{
					for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
						{
						Px[Ct1] += Dx[Ct1];
						Py[Ct1] += Dy[Ct1];
						if ((Px[Ct1] + Rayon[Ct1]) >= 318)
							Dx[Ct1] = -((rand()%4)+1);
						if ((Px[Ct1] - Rayon[Ct1]) <= 1)
							Dx[Ct1] = (rand()%4)+1;
						if ((Py[Ct1] + Rayon[Ct1]) >= 239)
							Dy[Ct1] = -((rand()%4)+1);
						if ((Py[Ct1] - Rayon[Ct1]) <= 1)
							Dy[Ct1] = (rand()%4)+1;
			    		SetColor(Couleur[Col[Ct1]]);
						Circle(Px[Ct1],Py[Ct1],Rayon[Ct1]);
						}
					Counter--;
					}

			  // ******************* Lines ******************
			 Counter =  (rand()%AnimLenght) + 200;
			  while ((Counter > 1)&&(BUT0!=0))
				{
				for (Ct1 = 0 ; Ct1 < ObjectNum;Ct1++)
					{
					Lx1[Ct1] += Dx1[Ct1];
					Ly1[Ct1] += Dy1[Ct1];
					if ((Lx1[Ct1]) >= 315)
						Dx1[Ct1] = -((rand()%4)+1);
					if ((Lx1[Ct1]) <= 5)
						Dx1[Ct1] = (rand()%4)+1;
					if ((Ly1[Ct1]) >= 235)
						Dy1[Ct1] = -((rand()%4)+1);
					if ((Ly1[Ct1]) <= 5)
						Dy1[Ct1] = (rand()%4)+1;
					Lx2[Ct1] += Dx2[Ct1];
					Ly2[Ct1] += Dy2[Ct1];
					if ((Lx2[Ct1]) >= 315)
						Dx2[Ct1] = -((rand()%4)+1);
					if ((Lx2[Ct1]) <= 5)
						Dx2[Ct1] = (rand()%4)+1;
					if ((Ly2[Ct1]) >= 235)
						Dy2[Ct1] = -((rand()%4)+1);
					if ((Ly2[Ct1]) <= 5)
						Dy2[Ct1] = (rand()%4)+1;
		    		SetColor(Couleur[Col[Ct1]]);
					Line(Lx1[Ct1],Ly1[Ct1],Lx2[Ct1],Ly2[Ct1]);
					}
				Counter--;
				}

			Obj3D();
			
		} while(BUT0!=0);

		camVideoPreview(0,FALSE);
		
	    SetColor(BLACK);
	    ClearDevice();
	    Y = (GetMaxY()+1-(3*bTextHeight))/2;
	    SetColor(LIGHTRED);
	    X = GetMaxX()+1-GetTextWidth("Welcome to the demo", (void*)&GOLFontDefault);
	    OutTextXY(X/2, Y, "Welcome to the demo");
	    DelayMs(DELAY_MS/3);
	    X = GetMaxX()+1-GetTextWidth("of", (void*)&GOLFontDefault);
	    OutTextXY(X/2, Y + bTextHeight, "of");
	    DelayMs(DELAY_MS/3);
	    X = GetMaxX()+1-GetTextWidth("Image Decoding Library", (void*)&GOLFontDefault);
	    OutTextXY(X/2, Y + 2*bTextHeight, "Image Decoding Library");
	    DelayMs(DELAY_NEXT);
		
        SetColor(BLACK);
        ClearDevice();
        SetColor(LIGHTRED);
        OutTextXY(0, 0, "1. Full screen decoding of");
        DelayMs(DELAY_MS);
        SetColor(YELLOW);
        OutTextXY(0, bTextHeight + 2, "Sunset.bmp");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
		pointer = FSfopen("SUNSET.BMP", "r");
		ImageFullScreenDecode(pointer, IMG_BMP, NULL, PixelOutput);
		FSfclose(pointer);
        DelayMs(DELAY_NEXT);
				

        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 240 - 5*(bTextHeight + 2), "2. Decoding of Sunset.jpg");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Rect = (0, 0) to (320, 240)");
        DelayMs(DELAY_MS);
        SetColor(LIGHTGREEN);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
		pointer = FSfopen("SUNSET.JPG", "r");
		ImageFullScreenDecode(pointer, IMG_JPEG, NULL, PixelOutput);
		FSfclose(pointer);
        DelayMs(DELAY_NEXT);
		
        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 0, "3. Decoding of Present.jpg");
        DelayMs(DELAY_MS);
        SetColor(LIGHTRED);
        OutTextXY(0, bTextHeight + 2, "Flags = IMG_DOWN_SCALE");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Image fit (0, 0) to (240, 180)");
        DelayMs(DELAY_MS);
        SetColor(LIGHTGREEN);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(Original image in 480x360)");
        DelayMs(DELAY_MS);
		pointer = FSfopen("PRESENT.JPG", "r");
        ImageDecode(pointer, IMG_JPEG, 0, 0, 240, 180, IMG_DOWN_SCALE, NULL, PixelOutput);
		FSfclose(pointer); 
        DelayMs(DELAY_NEXT);
		
        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 0, "4. Decoding of Football.bmp");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Image size is 240x180");
        DelayMs(DELAY_MS);
        SetColor(LIGHTGREEN);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(Image is smaller than 320x240)");
        DelayMs(DELAY_MS);
		pointer=FSfopen("FOOTBALL.BMP", "r");
		ImageFullScreenDecode(pointer, IMG_BMP, NULL, PixelOutput);
		FSfclose(pointer);
        DelayMs(DELAY_NEXT);
    }

    return 0;
}


void PixelOutput(IMG_PIXEL_XY_RGB_888 *pPix)
{
    SetColor(RGB565CONVERT(pPix->R, pPix->G, pPix->B));
    if(pPix->X <= GetMaxX() && pPix->Y <= GetMaxY())
    {
        PutPixel(pPix->X, pPix->Y);
    }    
    if(pPix->X > GetMaxX() && pPix->Y > GetMaxY())
    {
        ImageAbort();
    }    
}

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;

   Counter = (rand()%AnimLenght) + 500;

	while((Counter>1)&&(BUT0!=0))
	{
    
    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;

           // 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;
        }

    for (i=0; i<12; i++)
        {
			 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--;

	}
}
