/*********************************************************************
 *
 *  Main Application Entry Point and TCP/IP Stack Demo
 *  Module for Microchip TCP/IP Stack
 *   -Demonstrates how to call and use the Microchip TCP/IP stack
 *	 -Reference: Microchip TCP/IP Stack Help (TCPIP Stack Help.chm)
 *
 *********************************************************************
 * FileName:        MainDemo.c
 * Dependencies:    TCPIP.h
 * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
 * Compiler:        Microchip C32 v1.11b or higher
 *					Microchip C30 v3.24 or higher
 *					Microchip C18 v3.36 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * Copyright (C) 2002-2010 Microchip Technology Inc.  All rights
 * reserved.
 *
 * Microchip licenses to you the right to use, modify, copy, and
 * distribute:
 * (i)  the Software when embedded on a Microchip microcontroller or
 *      digital signal controller product ("Device") which is
 *      integrated into Licensee's product; or
 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
 *		ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
 *		used in conjunction with a Microchip ethernet controller for
 *		the sole purpose of interfacing with the ethernet controller.
 *
 * You should refer to the license agreement accompanying this
 * Software for additional information regarding your rights and
 * obligations.
 *
 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
 *
 * File Description:
 * Change History:
 * Rev   Description
 * ----  -----------------------------------------
 * 1.0   Initial release
 * V5.36 ---- STACK_USE_MPFS support has been removed 
 ********************************************************************/
/*
 * This macro uniquely defines this file as the main entry point.
 * There should only be one such definition in the entire project,
 * and this file must define the AppConfig variable as described below.
 */
#define THIS_IS_STACK_APPLICATION

// Include all headers for any enabled TCPIP Stack functions
#include "TCPIP Stack/TCPIP.h"


// Include functions specific to this stack application
#include "prvTaskTCPIP.h"

#include "FreeRTOS.h"
#include "queue.h"
#include "lcd.h"

#include <string.h>

// Declare AppConfig structure and some other supporting stack variables
static unsigned short wOriginalAppConfigChecksum;	// Checksum of the ROM defaults for AppConfig
BYTE AN0String[8];

// Private helper functions.
// These may or may not be present in all applications.
static void InitAppConfig(void);

void	DstarRoomClientTCP(void);

void	ReadMacFromEEPROM(BYTE *SerializedMACAddress);

static	BYTE	LCDText[32];
	
//
// Main application entry point.
//
void prvTaskTCPIP (void *pvParameters)
{
	static DWORD t = 0;
	static DWORD dwLastIP = 0;
	#if defined(WF_USE_POWER_SAVE_FUNCTIONS)
	BOOL  PsPollEnabled;
	BOOL  psConfDone = FALSE;
	#endif

	strcpypgm2ram((char*)LCDText, "TCPStack " TCPIP_STACK_VERSION "  "
		"                ");
	xMessage.pcMessage = LCDText;
	xMessage.xMinDisplayTime = 2000 / portTICK_RATE_MS;
	xQueueSend( xLCDQueue, &xMessage, 0 );

	// Initialize stack-related hardware components that may be 
	// required by the UART configuration routines
    TickInit();

	MPFSInit();

	// Initialize Stack and application related NV variables into AppConfig.
	InitAppConfig();

	// Initialize core stack layers (MAC, ARP, TCP, UDP) and
	// application modules (HTTP, SNMP, etc.)
    StackInit();


	// Now that all items are initialized, begin the co-operative
	// multitasking loop.  This infinite loop will continuously 
	// execute all stack-related tasks, as well as your own
	// application's functions.  Custom functions should be added
	// at the end of this loop.
    // Note that this is a "co-operative mult-tasking" mechanism
    // where every task performs its tasks (whether all in one shot
    // or part of it) and returns so that other tasks can do their
    // job.
    // If a task needs very long time to do its job, it must be broken
    // down into smaller pieces so that other tasks can have CPU time.

    while(1)
    {
	#if defined(WF_USE_POWER_SAVE_FUNCTIONS)
		if (!psConfDone && WFisConnected()) {	
			PsPollEnabled = (MY_DEFAULT_PS_POLL == WF_ENABLED);
			if (!PsPollEnabled) {	 
				/* disable low power (PS-Poll) mode */
				#if defined(STACK_USE_UART)
				putrsUART("Disable PS-Poll\r\n");		 
				#endif
				WF_PsPollDisable();
			} else {
				/* Enable low power (PS-Poll) mode */
				#if defined(STACK_USE_UART)
				putrsUART("Enable PS-Poll\r\n");		
				#endif
				WF_PsPollEnable(TRUE);
			}	
			psConfDone = TRUE;
		}
	#endif
        // Blink LED0 (right most one) every second.
        if(TickGet() - t >= TICK_SECOND/2ul)
        {
            t = TickGet();
            LED0_IO ^= 1;
        }

        // This task performs normal stack task including checking
        // for incoming packet, type of packet and calling
        // appropriate stack entity to process it.
        StackTask();

        // This tasks invokes each of the core stack application tasks
        StackApplications();


		// Process application specific tasks here.
		// For this demo app, this will include the Generic TCP 
		// client and servers, and the SNMP, Ping, and SNMP Trap
		// demos.  Following that, we will process any IO from
		// the inputs on the board itself.
		// Any custom modules or processing you need to do should
		// go here.
		#if defined(STACK_USE_GENERIC_TCP_CLIENT_EXAMPLE)
		GenericTCPClient();
		#endif
		
		#if defined(STACK_USE_GENERIC_TCP_SERVER_EXAMPLE)
		GenericTCPServer();
		#endif
		
		#if defined(STACK_USE_SMTP_CLIENT)
		SMTPDemo();
		#endif
		
		#if defined(STACK_USE_ICMP_CLIENT)
		PingDemo();
		#endif
		
		#if defined(STACK_USE_SNMP_SERVER) && !defined(SNMP_TRAP_DISABLED)
		//User should use one of the following SNMP demo
		// This routine demonstrates V1 or V2 trap formats with one variable binding.
		SNMPTrapDemo();
		
		#if defined(SNMP_STACK_USE_V2_TRAP) || defined(SNMP_V1_V2_TRAP_WITH_SNMPV3)
		//This routine provides V2 format notifications with multiple (3) variable bindings
		//User should modify this routine to send v2 trap format notifications with the required varbinds.
		//SNMPV2TrapDemo();
		#endif 
		if(gSendTrapFlag)
			SNMPSendTrap();
		#endif
		
		#if defined(STACK_USE_BERKELEY_API)
		BerkeleyTCPClientDemo();
		BerkeleyTCPServerDemo();
		BerkeleyUDPClientDemo();
		#endif

		DstarRoomClientTCP();

        // If the local IP address has changed (ex: due to DHCP lease change)
        // write the new IP address to the LCD display, UART, and Announce 
        // service
		if(dwLastIP != AppConfig.MyIPAddr.Val)
		{
			dwLastIP = AppConfig.MyIPAddr.Val;
			
			memcpy (LCDText, "New IP Address  ",16);
			DisplayIPValue(AppConfig.MyIPAddr, LCDText);

//			#if defined(STACK_USE_ANNOUNCE)
//				AnnounceIP();
//			#endif

//            #if defined(STACK_USE_ZEROCONF_MDNS_SD)
//				mDNSFillHostRecord();
//			#endif
		}

	}
}


// Writes an IP address to the LCD display and the UART as available
void DisplayIPValue(IP_ADDR IPVal, BYTE XLCDText[])
{
    BYTE IPDigit[4];
	BYTE i;
	BYTE j;
	BYTE LCDPos=16;

	for(i = 0; i < sizeof(IP_ADDR); i++)
	{
	    uitoa((WORD)IPVal.v[i], IPDigit);


			for(j = 0; j < strlen((char*)IPDigit); j++)
			{
				XLCDText[LCDPos++] = IPDigit[j];
			}
			if(i == sizeof(IP_ADDR)-1)
				break;
			XLCDText[LCDPos++] = '.';

	}

		if(LCDPos < 32u)
			LCDText[LCDPos] = 0;
			xMessage.pcMessage = XLCDText;
 			xMessage.xMinDisplayTime = 2000 / portTICK_RATE_MS;
			xQueueSend( xLCDQueue, &xMessage, 0 );

}


/*********************************************************************
 * Function:        void InitAppConfig(void)
 *
 * PreCondition:    MPFSInit() is already called.
 *
 * Input:           None
 *
 * Output:          Write/Read non-volatile config variables.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
// MAC Address Serialization using a MPLAB PM3 Programmer and 
// Serialized Quick Turn Programming (SQTP). 
// The advantage of using SQTP for programming the MAC Address is it
// allows you to auto-increment the MAC address without recompiling 
// the code for each unit.  To use SQTP, the MAC address must be fixed
// at a specific location in program memory.  Uncomment these two pragmas
// that locate the MAC address at 0x1FFF0.  Syntax below is for MPLAB C 
// Compiler for PIC18 MCUs. Syntax will vary for other compilers.
//#pragma romdata MACROM=0x1FFF0

static BYTE SerializedMACAddress[6];
BOOL	MACWriteArray(BYTE address, BYTE AppConfig[], WORD length);
void	MACReadArray(BYTE address, BYTE AppConfig[], WORD length);


//#pragma romdata



static void InitAppConfig(void)
{

		MACReadArray (0x00,(BYTE *)&AppConfig, sizeof(AppConfig));
		wOriginalAppConfigChecksum = CalcIPChecksum((BYTE*)&AppConfig, sizeof(AppConfig)-2);
//		if (wOriginalAppConfigChecksum != AppConfig.CheckSum)
		{
			memset((void*)&AppConfig, 0x00, sizeof(AppConfig));
			AppConfig.Flags.bIsDHCPEnabled = TRUE;
			AppConfig.Flags.bInConfigMode = TRUE;
			memcpypgm2ram((void*)&AppConfig.MyMACAddr, (ROM void*)SerializedMACAddress, sizeof(AppConfig.MyMACAddr));
			AppConfig.MyIPAddr.Val = MY_DEFAULT_IP_ADDR_BYTE1 | MY_DEFAULT_IP_ADDR_BYTE2<<8ul | MY_DEFAULT_IP_ADDR_BYTE3<<16ul | MY_DEFAULT_IP_ADDR_BYTE4<<24ul;
			AppConfig.DefaultIPAddr.Val = AppConfig.MyIPAddr.Val;
			AppConfig.MyMask.Val = MY_DEFAULT_MASK_BYTE1 | MY_DEFAULT_MASK_BYTE2<<8ul | MY_DEFAULT_MASK_BYTE3<<16ul | MY_DEFAULT_MASK_BYTE4<<24ul;
			AppConfig.DefaultMask.Val = AppConfig.MyMask.Val;
			AppConfig.MyGateway.Val = MY_DEFAULT_GATE_BYTE1 | MY_DEFAULT_GATE_BYTE2<<8ul | MY_DEFAULT_GATE_BYTE3<<16ul | MY_DEFAULT_GATE_BYTE4<<24ul;
			AppConfig.PrimaryDNSServer.Val = MY_DEFAULT_PRIMARY_DNS_BYTE1 | MY_DEFAULT_PRIMARY_DNS_BYTE2<<8ul  | MY_DEFAULT_PRIMARY_DNS_BYTE3<<16ul  | MY_DEFAULT_PRIMARY_DNS_BYTE4<<24ul;
			AppConfig.SecondaryDNSServer.Val = MY_DEFAULT_SECONDARY_DNS_BYTE1 | MY_DEFAULT_SECONDARY_DNS_BYTE2<<8ul  | MY_DEFAULT_SECONDARY_DNS_BYTE3<<16ul  | MY_DEFAULT_SECONDARY_DNS_BYTE4<<24ul;
			AppConfig.DefaultOutPort = 39999;
			AppConfig.DefaultInPort = 39998;
			memcpy (AppConfig.ServerName, "gw.jk1zrw.org", 64);;
			memcpy (AppConfig.DefaultRoomName, "TST000  ", 8);
			memcpy (AppConfig.DefaultNodeName, "7M3TJZ N", 8);
			AppConfig.CheckSum = CalcIPChecksum((BYTE*)&AppConfig, sizeof(AppConfig)-2);
			MACWriteArray(0x00, (BYTE *)&AppConfig, sizeof(AppConfig));
		}

		ReadMacFromEEPROM(SerializedMACAddress);
		memcpy ((BYTE *)&AppConfig.MyMACAddr, SerializedMACAddress, 6);
}

