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

* FileName:        Application.c
* Dependencies:    Image decoding library, SD192x SD-Driver;
* Processor:       PIC24/PIC32MX
* Compiler:        C30 v3.1/C32 v1.05
* 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
Bruce T Elliott      23-Jun-2009    Adapted to use Aik Hong Tok's SSD192x SD Code
*******************************************************************************/

/******************************************************************************
* Revision:
* Modified to support TechToys SSD1928 and SSD1928 driver development using
*    the PIC24/32-Eval-Rev C2 board and either LVC75Z779 Eval Board (SSD1928)
*    or SSD1963 Eval Rev 2A
* Programmer: John Leung, Company: TechToys Co.
* Programmer: Bruce Elliott added SSD1928 HardwareProfile and PIC33F NON-PMP
* 
* Select the correct HardwareProfile _PIC_EVK_V2V_16PMP_SSD1963_EVK_V2A_xxx.h
* 
* Caveats:
* (1) Configuration Bits assume Internal Fast OSC for some processors. 
*	  Check this carefully.
* (2) PIC33FJ256GP710 PIM, PIC24H256GP610 PIM without PMP supported (Port E)
* (3) Board, Graphics Controller and Processor used in #defines
*     see EEPROM.x, TouchScreen.x
* (4) panelBrightness, SetTearingCfg() and SetBacklight() functions for SSD1963
*
* TechToys Company
* Web site: www.TechToys.com.hk
* Date: 3rd Feb 2010
******************************************************************************/

/*
******************************************************************************
* Revision:
* Demo to display jpeg or bmp files from SD card.
* Hardware : SSD1963EVK R3B as the display controller
*			 MCU host can be PIC24/32 EVK RD4 with PIC32MX360F512L option -or-
*			 MMEVK R1A with Microchip PIC32GP SK stacked.
* 		     There are three choices on display panel:
*			 4.3" TFT 480x272, 5" TFT 800x480, or 7" TFT 800x480
*			 Choice of TFT panel is selected at compile time under hardware profile
*			 
*			 First, pick the appropriate hardware combination from HardwareProfile.h
*
*			 If it is SSD1963EVK R3B + PIC24/32 EVK RD4 with PIC32MX360F512L option
*		     #include "Alternative Configurations\HardwareProfile_PIC32MX_EVK_RD4_16PMP_SSD1963EVK_R3B.h" 
*
*			 If it is SSD1963EVK R3B + MMEVK R1A with Microchip PIC32GP SK on board
*			 #include "Alternative Configurations\HardwareProfile_PIC32_STK_ON_PIC32STKSSD1963EVKR1A.h"
*
*			 Second, select the panel size to use.
*			 Under both hardware profiles, there are compile time directives:
* 			 //#define DISPLAY_PANEL TY700TFT800480
*			 #define DISPLAY_PANEL TY430TFT480272
*			 //#define DISPLAY_PANEL TY500TFT800480
*			 Selective only one panel and Build All from Project->Build All
******************************************************************************
*/
#include <stdio.h>							// Only used to allow printf statements
#include "Graphics\Graphics.h"
#include "FSConfig.h"
#include "Graphics\Primitive.h"
#include "Image Decoders\ImageDecoder.h"
#include "MDD File System\FSIO.h"
#ifdef __PIC32MX__
#else
	#include <uart.h>
#endif

// Configuration bits
#if defined(__dsPIC33F__) || defined(__PIC24H__)
_FOSCSEL(FNOSC_PRI);
_FOSC(FCKSM_CSECMD &OSCIOFNC_OFF &POSCMD_XT);
_FWDT(FWDTEN_OFF);
#elif defined(__PIC32MX__) //TechToys
	// If a 8.0MHz crystal and 32kHz crystal soldered onboard
	//#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_8
	//#pragma config OSCIOFNC = ON, POSCMOD = XT, FSOSCEN = ON, FNOSC = PRIPLL
	//#pragma config CP = OFF, BWP = OFF, PWP = OFF
	// If a 8.0MHz crystal and 32kHz crystal soldered onboard
	#if (GRAPHICS_HARDWARE_PLATFORM==PIC32MX_EVK_RD4)
	#pragma config FNOSC = PRIPLL, POSCMOD = XT, OSCIOFNC = OFF			
	#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_3, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
	#pragma config FSOSCEN = ON, IESO = OFF
	#pragma config CP = OFF, BWP = OFF, PWP = OFF
	#elif defined (PIC32_STARTER_KIT)
	#pragma config FNOSC = PRIPLL, POSCMOD = XT, OSCIOFNC = OFF			
	#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FCKSM = CSECME, FPBDIV = DIV_1
	#pragma config FSOSCEN = ON, IESO = OFF
	#pragma config CP = OFF, BWP = OFF, PWP = OFF
	#endif

	// If no crystal soldered onboard, use internal fast OSC
	//#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

/*
	#if defined  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
    #if defined(__PIC24FJ256GB110__)
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
_CONFIG2(0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV2 & IOL1WAY_OFF)
    #endif
    #if defined(__PIC24FJ256GA110__)
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2)
_CONFIG2(IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRIPLL & IOL1WAY_OFF)
    #endif
    #if defined(__PIC24FJ128GA010__)	//TechToys
_CONFIG2(FNOSC_FRCPLL) 					// Fast RC oscillator with PLL
_CONFIG1(JTAGEN_OFF & FWDTEN_OFF)   	// JTAG off, watchdog timer off
    #endif
	#if defined (__PIC24FJ256DA210__)
_CONFIG1( WDTPS_PS32768 & FWPSA_PR128 & ALTVREF_ALTVREDIS & WINDIS_OFF & FWDTEN_OFF & ICS_PGx2 & GWRP_OFF & GCP_OFF & JTAGEN_OFF) 
_CONFIG2( POSCMOD_HS & IOL1WAY_OFF & OSCIOFNC_OFF & OSCIOFNC_OFF & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_ON)
_CONFIG3( WPFP_WPFP255 & SOSCSEL_SOSC & WUTSEL_LEG & ALTPMP_ALTPMPEN & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM) 
	#endif	        
#endif


#define DELAY_MS 1500
#define DELAY_NEXT 3000

BYTE	panelBrightness = 255;	//Set panel brightness on system reset


// Use small font to print out the directory listing on the graphics screen
// Otherwise use GOLFontDefault
extern const FONT_FLASH GOLSmallFont; 	

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();
    }    
}


int main(void)
{
    FSFILE * pointer;			// File pointer of opened file to be passed
    SearchRec searchRecord;	// Search record for SDCard directory scan
    char filename[16];			// Filename to search for - here *.*
    char buffer[50];				// Buffer to set up caption text with sprintf
    IMG_FILE_SYSTEM_API FileApi;
    BYTE bTextHeight;
    WORD X, Y, cnt;				// Positioning for text captions

#ifdef __PIC32MX__
    DWORD pbClk;					// UART2 setup for printf statements
#endif

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

    /////////////////////////////////////////////////////////////////////////////
#if defined(__dsPIC33F__) || defined(__PIC24H__)
	// Configure Oscillator to operate the device at 40Mhz
	// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
	// Fosc= 8M*40(2*2)=80Mhz for 8M input clock
	PLLFBD = 38;                    // M=40
	CLKDIVbits.PLLPOST = 0;         // N1=2
	CLKDIVbits.PLLPRE = 0;          // N2=2
	OSCTUN = 0;                     // Tune FRC oscillator, if FRC is used

	// Disable Watch Dog Timer
	RCONbits.SWDTEN = 0;

	// Clock switching to incorporate PLL
	__builtin_write_OSCCONH(0x03);  // Initiate Clock Switch to Primary

	// Oscillator with PLL (NOSC=0b011)
	__builtin_write_OSCCONL(0x01);  // Start clock switching
	while(OSCCONbits.COSC != 0b011);

	// Wait for Clock switch to occur	
	// Wait for PLL to lock
	while(OSCCONbits.LOCK != 1)
	{ };
    
	// Set PMD0 pin functionality to digital
	AD1PCFGL = AD1PCFGL | 0x1000;
    
	OpenUART2(UART_EN, UART_TX_ENABLE, 129);

#elif defined(__PIC32MX__)
	INTEnableSystemMultiVectoredInt();
	pbClk = SYSTEMConfigPerformance(GetSystemClock());	

	// OpenUART2 only used for printf statements. 19200 Baud
	OpenUART2(UART_EN, 		// Module is ON
              UART_RX_ENABLE | UART_TX_ENABLE,		// Enable TX & RX
              (pbClk/16/19200)-1);					// 19200 bps, 8-N-1
	printf("\r\nUART initialized\r\n");

#elif defined (__PIC24F__)			//TehcToys
	CLKDIV = 0x0000;				//FRC postscaler divided by 1 (8MHz from internal RC)	
	// OpenUART2 only used for printf statements. 19200 Baud
	OpenUART2(UART_EN, UART_TX_ENABLE, 51);
#endif

	//TechToys
#ifdef __PIC24FJ256GA110__
	pps_spi2();
#endif

	InitGraph();

#if (DISPLAY_CONTROLLER == SSD1963)
	//TechToys
	SetTearingCfg(1,0);					// set tearing effect on with V-blanking information only
	SetBacklight(panelBrightness);	
#endif

#if (GRAPHICS_HARDWARE_PLATFORM==PIC32MX_EVK_RD4)
DDPCONbits.JTAGEN = 0;
#endif


	// Show a few colors as an opening screen
	SetColor(WHITE);
	ClearDevice();
	DelayMs(500);

	SetColor(BLUE);
	ClearDevice();
	DelayMs(500);

	SetColor(LIGHTRED);
	ClearDevice();
	DelayMs(500);

	SetColor(GREEN);
	ClearDevice();
	DelayMs(500);

	SetColor(BLACK);
	ClearDevice();

	ImageDecoderInit();
	SetClipRgn(0,0,GetMaxX(),GetMaxY());
	SetClip(CLIP_ENABLE);

	// In order to show the pictures, the ImageDecoder routine uses a structure
	// containing the read, seek, tell and eof routines of the file system.
	//SSD192xFileApi.pFread = FSfread;
	//SSD192xFileApi.pFseek = FSfseek;
	//SSD192xFileApi.pFtell = FSftell;
	//SSD192xFileApi.pFeof = FSfeof;

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

	Y = (GetMaxY()+1-(3*bTextHeight))/2;
	SetColor(LIGHTBLUE);
	X = GetMaxX()+1-GetTextWidth("Initialize SDCard", (void*)&GOLFontDefault);
	OutTextXY(X/2, Y, "Initialize SDCard");

	if (!FSInit())
	{
		printf("FSinit failed\r\n");
		X = GetMaxX()+1-GetTextWidth("failed: system halted", (void*)&GOLFontDefault);
		OutTextXY(X/2, Y + bTextHeight + 1, "failed: system halted");
		while (1);
	}
	else
	{
		printf("FSinit succeeded\r\n");
		X = GetMaxX()+1-GetTextWidth("success: show root", (void*)&GOLFontDefault);
		OutTextXY(X/2, Y + bTextHeight + 3, "success: show root");
		DelayMs(DELAY_MS);
	}

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

	SetColor(BLACK);
	ClearDevice();

	cnt = 0;
	sprintf(filename, "*.*");
	SetColor(WHITE);
	if (!FindFirst (filename, ATTR_READ_ONLY | ATTR_ARCHIVE, &searchRecord))
	{
		do {
			sprintf( buffer, "       %.42s", searchRecord.filename );
			if (searchRecord.attributes &     ATTR_READ_ONLY           )
			{
                buffer[0] = 'R';
            }
            if (searchRecord.attributes &     ATTR_HIDDEN           )
            {
                buffer[1] = 'H';
            }
            if (searchRecord.attributes &     ATTR_SYSTEM           )
            {
                buffer[2] = 'S';
            }
            if (searchRecord.attributes &     ATTR_ARCHIVE           )
            {
                buffer[3] = 'A';
            }
            OutTextXY(0, cnt, buffer);
            cnt += bTextHeight + 3;

        } while (!FindNext( &searchRecord ));
    }
    DelayMs(DELAY_MS);
    DelayMs(DELAY_MS);

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

    SetColor(BLACK);
    ClearDevice();
    Y = (GetMaxY()+1-(3*bTextHeight))/2;
    SetColor(LIGHTRED);
    X = GetMaxX()+1-GetTextWidth("Welcome to the demo of", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y, "Welcome to the demo of");
    DelayMs(DELAY_MS/3);
    SetColor(LIGHTBLUE);
	#if (DISPLAY_CONTROLLER == SSD1963)
    	X = GetMaxX()+1-GetTextWidth("SSD1963 SDCard Interface and", (void*)&GOLFontDefault);
    	OutTextXY(X/2, Y + bTextHeight + 1, "SSD1963 SDCard Interface and");
	#elif (DISPLAY_CONTROLLER == SSD1928)
    	X = GetMaxX()+1-GetTextWidth("SSD1928 SDCard Interface and", (void*)&GOLFontDefault);
    	OutTextXY(X/2, Y + bTextHeight + 1, "SSD1928 SDCard Interface and");
	#endif	
    DelayMs(DELAY_MS/3);
    SetColor(LIGHTRED);
    X = GetMaxX()+1-GetTextWidth("Image Decoding Library", (void*)&GOLFontDefault);
    OutTextXY(X/2, Y + 2*bTextHeight + 2, "Image Decoding Library");
    DelayMs(DELAY_NEXT);

    while(1)
    {
        SetColor(BLACK);
        ClearDevice();
        SetColor(LIGHTRED);
        OutTextXY(0, 0, "1. Full screen decoding of");
        DelayMs(DELAY_MS);
        SetColor(YELLOW);
		#if ((DISPLAY_PANEL == TY700TFT800480)||(DISPLAY_PANEL == TY500TFT800480))
        	OutTextXY(0, bTextHeight + 2, "yose700.bmp");
		#elif (DISPLAY_PANEL == TY430TFT480272)
	        OutTextXY(0, bTextHeight + 2, "yose430.bmp");	
		#elif (DISPLAY_PANEL == LVC75Z779V1S)
	        OutTextXY(0, bTextHeight + 2, "yose350.bmp");	
		#endif
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
		#if ((DISPLAY_PANEL == TY700TFT800480)||(DISPLAY_PANEL == TY500TFT800480))
        	if ((pointer = FSfopen("yose700.bmp", "r")) == NULL)
		#elif (DISPLAY_PANEL == TY430TFT480272)
        	if ((pointer = FSfopen("yose430.bmp", "r")) == NULL)
		#elif (DISPLAY_PANEL == LVC75Z779V1S)
        	if ((pointer = FSfopen("yose350.bmp", "r")) == NULL)			
		#endif
           printf("Last Error FSfopen  = %d\r\n", FSerror());	
        ImageFullScreenDecode(pointer, IMG_BMP, NULL, PixelOutput);
        if (FSfclose(pointer))
            printf("Last Error FSfclose = %d\r\n", FSerror());
        DelayMs(DELAY_NEXT);

        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 240 - 4*(bTextHeight + 2), "2. Decoding of Sunset.bmp");
        DelayMs(DELAY_MS);
        SetColor(LIGHTRED);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Flags = 0");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "Rect = (0, 0) to (320, 240)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        if ((pointer = FSfopen("SUNSET.BMP", "r")) == NULL)
            printf("Last Error FSfopen  = %d\r\n", FSerror());
        ImageFullScreenDecode(pointer, IMG_BMP, NULL, PixelOutput);
        if (FSfclose(pointer))
            printf("Last Error FSfclose = %d\r\n", FSerror());
        DelayMs(DELAY_NEXT);

        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 240 - 4*(bTextHeight + 2), "3. Decoding of Sunset.jpg");
        DelayMs(DELAY_MS);
        SetColor(LIGHTRED);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Flags = 0");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "Rect = (0, 0) to (320, 240)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        if ((pointer = FSfopen("SUNSET.JPG", "r")) == NULL)
            printf("Last Error FSfopen  = %d\r\n", FSerror());
        ImageFullScreenDecode(pointer, IMG_JPEG, NULL, PixelOutput);
        if (FSfclose(pointer))
            printf("Last Error FSfclose = %d\r\n", FSerror());
        DelayMs(DELAY_NEXT);

        SetColor(BLACK);
        ClearDevice();
        SetColor(YELLOW);
        OutTextXY(0, 240 - 4*(bTextHeight + 2), "4. Decoding of Football.jpg");
        DelayMs(DELAY_MS);
        SetColor(LIGHTRED);
        OutTextXY(0, 240 - 3*(bTextHeight + 2), "Flags = 0");
        DelayMs(DELAY_MS);
        SetColor(LIGHTBLUE);
        OutTextXY(0, 240 - 2*(bTextHeight + 2), "Rect = (0, 0) to (320, 240)");
        DelayMs(DELAY_MS);
        SetColor(WHITE);
        OutTextXY(0, 240 - 1*(bTextHeight + 2), "(w/o Double Buffering)");
        DelayMs(DELAY_MS);
        if ((pointer = FSfopen("FOOTBALL.BMP", "r")) == NULL)
            printf("Last Error FSfopen  = %d\r\n", FSerror());
        ImageFullScreenDecode(pointer, IMG_BMP, NULL, PixelOutput);
        if (FSfclose(pointer))
            printf("Last Error FSfclose = %d\r\n", FSerror());
        DelayMs(DELAY_NEXT);

    }

    return 0;
}

