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

	Microchip USB Firmware - USB CDC Serial Device Demo Main Application File
	
**********************************************************************	
Description:
    This file contains a sample application framework for the
    Microchip USB CDC Serial Emulation Demo.  
 
Note: This file forms the backbone of the application, defining its 
over all behavior.  However, it should not access any hardware directly.
It should rely on HW-specific libraries and device drivers to manage the 
hardware.
**********************************************************************
	FileName:       main.c
	Dependencies:   None
	Processor:      PIC32MX USB Family Devices
	Complier:       MPLAB C Compiler for PIC32 v1.04 or later
					MPLAB IDE v8.15 or later

	Copyright (c) 2008 Microchip Technology, Inc.
**********************************************************************
Software License Agreement

The software supplied herewith by Microchip Technology Incorporated
(the “Company”) for its PICmicro® Microcontroller is intended and
supplied to you, the Company’s customer, for use solely and
exclusively on Microchip PICmicro Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.

THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
***********************************************************************/

/************
 * Includes *
 ************/
#include "HardwareProfile.h"
#include "GenericTypeDefs.h"
#include "usb/usb.h"
#include "usb/usb_device_cdc_serial.h"
//#include "io_cfg.h"
#include <plib.h>
#include "ex16lcd.h"


/**********************
 * Configuration Bits *
 **********************/

#ifndef OVERRIDE_CONFIG_BITS
        
    #pragma config UPLLEN   = ON            // USB PLL Enabled
    #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
    #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
    #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
    #pragma config FPLLODIV = DIV_1         // PLL Output Divider
    #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
    #pragma config FWDTEN   = OFF           // Watchdog Timer 
    #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
    #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
    #pragma config OSCIOFNC = OFF           // CLKO Enable
    #pragma config POSCMOD  = HS            // Primary Oscillator
    #pragma config IESO     = OFF           // Internal/External Switch-over
    #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable
    #pragma config FNOSC    = PRIPLL        // Oscillator Selection
    #pragma config CP       = OFF           // Code Protect
    #pragma config BWP      = OFF           // Boot Flash Write Protect
    #pragma config PWP      = OFF           // Program Flash Write Protect
    #pragma config ICESEL   = ICS_PGx2      // ICE/ICD Comm Channel Select
    #pragma config DEBUG    = ON            // Debugger Disabled for Starter Kit
            
#endif // OVERRIDE_CONFIG_BITS

/***************
 * Global Data *
 ***************/

typedef enum _app_state
{
    BUFFER_EMPTY = 0,       // Buffer is empty & available to receive data.
    RECEIVING_DATA,         // App is waiting to receive data from USB.
    DATA_AVAILABLE,         // Data has been received, app can act on the data.
    SENDING_DATA            // App is waiting for data to finish sending on USB.

} APP_STATE;

// Loop back echo data buffer.
#define BUFFER_SIZE 64
char      gBuffer[BUFFER_SIZE];
BYTE      gSize;                    // Uninitialized data, cleared to zero.
APP_STATE gState;                   // Uninitialized data, cleared to zero.

// AT Command String
char gCommand[8];

// Test String
char gTestStr[] = "Hello from the Microchip USB CDC Serial Demo!\r";

// Notification Data
CDC_NOTIFICATION gNotification = CDC_INIT_NOTIFICATION(RESPONSE_AVAILABLE,0,CDC_COMM_INTF_ID,0);

// Response String
char *gRespStr = "\r\nOK\r\n";


/*******************
 * Switch routines *
 *******************/

WORD old_sw3,old_sw6;

BOOL Switch3IsPressed(void)
{
    if(sw3 != old_sw3)
    {
        old_sw3 = sw3;                  // Save new value
        if(sw3 == 0)                    // If pressed
            return TRUE;                // Was pressed
    }//end if
    return FALSE;                       // Was not pressed
}//end Switch3IsPressed

BOOL Switch6IsPressed(void)
{
    if(sw6 != old_sw6)
    {
        old_sw6 = sw6;                  // Save new value
        if(sw6 == 0)                    // If pressed
            return TRUE;                // Was pressed
    }//end if
    return FALSE;                       // Was not pressed
}//end Switch6IsPressed


/*************************************************************************
 * Function:        CdcDemoEventHandler
 *
 * Preconditions:   1. The system must have been built with the CDC Serial
 *                     Emulation function driver.
 *
 *                  2. This routine must be linked as the CDC Serial 
 *                     function driver's application event handler.
 *
 *                  3. USBInitialize must have been called to initialize 
 *                     the USB SW Stack.
 *
 *                  4. The host must have configured the system as a USB
 *                     CDC Serial Emulation Device. 
 *                  
 * Input:           event       Identifies the bus event that occured
 *
 *                  data        Pointer to event-specific data
 *
 *                  size        Size of the event-specific data
 *
 * Output:          none
 *
 * Returns:         TRUE if the event was handled, FALSE if not
 *
 * Side Effects:    Event-specific actions have been taken.
 *
 * Overview:        This routine is called by the CDC Serial Emulation 
 *                  function driver to notify the application of events 
 *                  that occur on the USB.  If the event is recognized,
 *                  it is handled and the routine returns TRUE.  Otherwise,
 *                  it is ignored and the routine returns FALSE.
 *************************************************************************/
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif

PUBLIC BOOL CdcDemoEventHandler ( USB_EVENT event, void *data, int size )
{
    UINT16      cmd_size;
    LINE_CODING line_coding;


    // Handle specific events.
    switch ((UINT)event)
    {
    // The host has changed our line-control status.
    case EVENT_CDC_LINE_CTRL:

        // Read the new line coding.  
        //
        // (We don't really care, but if we did, we could
        // do something about it here after reading it.)
        return USBUSARTGetLineCoding (&line_coding);


    // The host is about to send an encapsulated command.
    case EVENT_CDC_CMD:

        // Read the command string.
        if (size == sizeof(UINT16) && data != NULL)
        {
            cmd_size = (UINT16)min(sizeof(gCommand), size);
            return USBUSARTGetCmdStr (gCommand, cmd_size);
        }
        break;


    } // switch (event)


    // Wasn't ours.
    return FALSE;

} // CdcDemoEventHandler


/***************************
 * Application Entry Point *
 ***************************/

/*************************************************************************
 * Function:        main
 *
 * Precondition:    System has been initialized sufficiently to execute
 *                  C language code.
 *
 * Input:           none
 *
 * Output:          none
 *
 * Returns:         none
 *
 * Side Effects:    Keeps system running.
 *
 * Overview:        This is the system's main C-language entry point.  It
 *                  initializes the application and contains the main
 *                  processing loop.
 *
 * Notes:           Never exits.
 *************************************************************************/
 
int main ( void )
{
    /* 
    PIC32 Peripheral Library functions SYSTEMConfigPerformance() and SYSTEMConfig()
    configures system parameters, such as Flash wait states, RAM wait states, 
    enable cache and set Peripheral Bus Clock (PBCLK) frequency for optimal
    system performance based on the system clock frequency argument.
    
    SYSTEMConfigPerformance() ignores the PBCLK fuse selection FPBDIV and calculates
    the fastest possible PBCLK based on the system clock frequency parameter.
    Use this function if you want to set the fastest PBCLK frequency.
    Example: SYSTEMConfigPerformance(80000000);  //@80MHz PBCLK ratio = 1:1
    
    SYSTEMConfig() uses the PBCLK defined by configuration fuse selection FPBDIV 
    set in code or from the MPLAB IDE Configuration Bits menu.
    Use this function if you want to maintain the PBCLK frequency set by FPBDIV.
    Example: SYSTEMConfig(80000000, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
    */
    SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
    
    // Init LCD and display message
    INTEnableSystemMultiVectoredInt();

    // Initialize and display the user messages
    mInitMessage();
    mSendMessage1();
    mSendMessage2();

    // Initialize the USB stack.
    USBInitialize(0);

    // Main Processing Loop
    while(1)
    {
        // Check USB for events and 
        // handle them appropriately.
        USBTasks();
        
        // App State Machine
        switch (gState)
        {
        case BUFFER_EMPTY:      // Buffer is empty & available to receive data.
                                // (Initial state due to zero value.)

            // If the buffer is free, read any available data.
            if (USBUSARTRxIsReady())
            {
                gState = RECEIVING_DATA;
                USBUSARTRx(gBuffer, BUFFER_SIZE);
            }
            break;

        case RECEIVING_DATA:    // App is waiting to receive data from USB.

            // Check to see if we have data yet.
            if ( (gSize = USBUSARTRxGetLength()) > 0 ) 
            {
                gState = DATA_AVAILABLE;
                // Intentional Fall Through!  Avoids unnecessary loop iteration.
            }
            else
            {
                break;
            }

        case DATA_AVAILABLE:    // Data has been received, app can act on the data.

            // If the transmitter is ready, echo the data back to the host.
            if (USBUSARTTxIsReady())
            {
                gState = SENDING_DATA;
                USBUSARTTx(gBuffer, gSize);
            }
            break;

        case SENDING_DATA:      // App is waiting for data to finish sending on USB.

            // If we're done transmitting, free up the buffer to receive new data.
            if (USBUSARTTxIsReady()) {
                gSize  = 0;
                gState = BUFFER_EMPTY;
            }
            break;

        default:
            while(1);           // Invalid state, hang the application.
        }


        // Display message if button is pressed.
        if(Switch3IsPressed())
        {
            if(USBUSARTTxIsReady())
            {
                USBUSARTPuts(gTestStr);
            }
        }
    }

    return 0;

} // main
 
 
/*************************************************************************
 * EOF
 */

