//-------------------------------------------------------------------------------//
//                            LIXUE 电子工作室                                   //
//                       http://lixuediy.taobao.com                              //
//                                版权所有                                       //
//                       EMAIL:lixue51@126.com                                   //
//                       Mobile:13109884800                                      //
//                       MCU: PIC32MX795F512L                                    //
//                       Compiler: MAPLAB IDE V8.87   C32 V2.02                  //
//                       File: LX-100PIN-USB.c                                   //
//                       DATE: 2013-04-30    Version:  2.2                       //
//-------------------------------------------------------------------------------// 
//
// 实验描述：编译程序,下载到单片机后,插上MINI USB线,会有新设备识别
//           安装驱动,驱动文件路径：.\LX-100PIN-USB\CDC 驱动
//
//           打开串口助手,设置如图片。
//
//           USB-CDC类,上传ADC值,程序运行后,按下KEY1,在串口助手里会看到ADC值
//           调整POT电位器旋钮,按下KEY1键,ADC值更新
//
//           
//
// 头 文 件：C:\Program Files\Microchip\MPLAB C32 Suite\pic32-libs\include\proc
//
// 配 置 位：菜单栏 -> Help -> Topics.. -> PIC32MX Config Setting 
//          
// 注意事项：在写操作后,须加5mS以上延时,才可以正确读、写操作。否则会出错误!
//
//           串口波特设置：57600 N 8 1 
//
//           由于用户水平不同,USB部分不做技术支持.
//
//-------------------------------------------------------------------------------

#include <plib.h>                    //调用通用头文件

//-------------------------------------------------------------------------------

#include "Compiler.h"
#include "HardwareProfile.h"
#include "USB\usb.h"
#include "USB\usb_function_cdc.h"
#include "Temperature.h"

/** CONFIGURATION *************************************************************/
#pragma config UPLLEN   = ON        // USB PLL Enabled
#pragma config FPLLMUL  = MUL_20    // PLL Multiplier
#pragma config UPLLIDIV = DIV_1     // USB PLL Input Divider
#pragma config FPLLIDIV = DIV_1     // 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
                                            // (KLO was off)
#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_PGx1  // ICE/ICD Comm Channel Select
#pragma config DEBUG    = ON        // Background Debugger Enable


/** VARIABLES *****************************************************************/
char USB_Out_Buffer[64];
char USB_In_Buffer[64];

unsigned short DelayCnt = 0;

/** PRIVATE PROTOTYPES ********************************************************/
static void InitializeSystem(void);
void ProcessIO(void);
void UserInit(void);


/** DECLARATIONS **************************************************************/
//#pragma code

/*******************************************************************************
 * Function:        void main(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Main program entry point.
 *
 * Note:            None
 ******************************************************************************/
int main(void)
{   
    InitializeSystem();
    USBDeviceAttach();
    while(1)
    {
		// Application-specific tasks.
		// Application related code may be added here,
		// or in the ProcessIO() function.
        ProcessIO();     
  
        if(DelayCnt >= 0x7FFF)    //系统运行指示
		{
			DelayCnt = 0;
	        _LATE7 = !_LATE7;
	        _LATE6 = !_LATE7;
		} 
		else
		{
			DelayCnt ++; 
		}	
    }
}


/*******************************************************************************
 * Function:        static void InitializeSystem(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        InitializeSystem is a centralize initialization
 *                  routine. All required USB initialization routines
 *                  are called from here.
 *
 *                  User application initialization routine should
 *                  also be called from here.                  
 *
 * Note:            None
 ******************************************************************************/
static void InitializeSystem(void)
{
	DDPCONbits.JTAGEN =0;
	AD1PCFG = 0xFFFF;

//	The USB specifications require that USB peripheral devices must never source
//	current onto the Vbus pin.  Additionally, USB peripherals should not source
//	current on D+ or D- when the host/hub is not actively powering the Vbus line.
//	When designing a self powered (as opposed to bus powered) USB peripheral
//	device, the firmware should make sure not to turn on the USB module and D+
//	or D- pull up resistor unless Vbus is actively powered.  Therefore, the
//	firmware needs some means to detect when Vbus is being powered by the host.
//	A 5V tolerant I/O pin can be connected to Vbus (through a resistor), and
// 	can be used to detect when Vbus is high (host actively powering), or low
//	(host is shut down or otherwise not supplying power).  The USB firmware
// 	can then periodically poll this I/O pin to know when it is okay to turn on
//	the USB module/D+/D- pull up resistor.  When designing a purely bus powered
//	peripheral device, it is not possible to source current on D+ or D- when the
//	host is not actively providing power on Vbus. Therefore, implementing this
//	bus sense feature is optional.  This firmware can be made to use this bus
//	sense feature by making sure "USE_USB_BUS_SENSE_IO" has been defined in the
//	HardwareProfile.h file.    
    #if defined(USE_USB_BUS_SENSE_IO)
    tris_usb_bus_sense = INPUT_PIN; // See HardwareProfile.h
    #endif
    
//	If the host PC sends a GetStatus (device) request, the firmware must respond
//	and let the host know if the USB peripheral device is currently bus powered
//	or self powered.  See chapter 9 in the official USB specifications for details
//	regarding this request.  If the peripheral device is capable of being both
//	self and bus powered, it should not return a hard coded value for this request.
//	Instead, firmware should check if it is currently self or bus powered, and
//	respond accordingly.  If the hardware has been configured like demonstrated
//	on the PICDEM FS USB Demo Board, an I/O pin can be polled to determine the
//	currently selected power source.  On the PICDEM FS USB Demo Board, "RA2" 
//	is used for	this purpose.  If using this feature, make sure 
//	"USE_SELF_POWER_SENSE_IO" has been defined in HardwareProfile.h, and that an 
//	appropriate I/O pin has been mapped to it in HardwareProfile.h.
    #if defined(USE_SELF_POWER_SENSE_IO)
    tris_self_power = INPUT_PIN;	// See HardwareProfile.h
    #endif
    
    UserInit();

    USBDeviceInit();	//usb_device.c.  Initializes USB module SFRs and firmware
    					//variables to known states.
}//end InitializeSystem



/*******************************************************************************
 * Function:        void UserInit(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This routine should take care of all of the demo code
 *                  initialization that is required.
 *
 * Note:            
 *
 ******************************************************************************/
void UserInit(void)
{
    
    mInitAllLEDs();
    mInitAllSwitches();
	InitTempSensor();
    
}//end UserInit

/*******************************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is a place holder for other user
 *                  routines. It is a mixture of both USB and
 *                  non-USB tasks.
 *
 * Note:            None
 ******************************************************************************/
void ProcessIO(void)
{   
    // User Application USB tasks
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

    if(SwitchIsPressed())
	{
		if (USBUSARTIsTxTrfReady())
		{
			AcquireTemperature();// Perform temperature reading from sensor using "AcquireTemperature()"
			UpdateCelsiusASCII();// Convert to ASCII string using "UpdateCelsiusASCII()
       		putsUSBUSART(tempString);
		}
	}
    CDCTxService();
}//end ProcessIO

// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************

/*******************************************************************
 * Function:        BOOL USER_USB_CALLBACK_EVENT_HANDLER(
 *                        USB_EVENT event, void *pdata, WORD size)
 *
 * PreCondition:    None
 *
 * Input:           USB_EVENT event - the type of event
 *                  void *pdata - pointer to the event data
 *                  WORD size - size of the event data
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is called from the USB stack to
 *                  notify a user application that a USB event
 *                  occured.  This callback is in interrupt context
 *                  when the USB_INTERRUPT option is selected.
 *
 * Note:            None
 *******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size)
{
    switch(event)
    {
        case EVENT_CONFIGURED: 
            CDCInitEP();
            break;
        case EVENT_EP0_REQUEST:
            USBCheckCDCRequest();
            break;
        default:
            break;
    }      
    return TRUE; 
}

/** EOF main.c ****************************************************************/
