/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////                        ex_usb_serial.c                          ////
////                                                                 ////
//// A demonstration of the USB CDC API that is provided by CCS.     ////
//// The USB CDC API that CCS provides will create a virtual UART    ////
//// port.  USB CDC drivers are included with most versions of       ////
//// Microsoft Windows, and when properly loaded will create a COMx  ////
//// port from which you can write and read to your PIC device       ////
//// like any serial device that has a COMx port.                    ////
////                                                                 ////
//// This example creates a USB<->UART converter.  Open              ////
//// Hyperterminal to COM1 (or whatever COM port is your usual RS232 ////
//// serial COM port).  Plug the PIC to USB.  Open Hypertimernal to  ////
//// the new COM port that is the USB<->UART COM port (for this      ////
//// example say it is COM2).  Typing a character in COM1 will cause ////
//// it to be sent out COM2, and vice-versa.                         ////
////                                                                 ////
//// See usb_cdc.h for API documentation.                            ////
////                                                                 ////
//// This file is part of CCS's PIC USB driver code.  See USB.H      ////
//// for more documentation and a list of examples.                  ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// VERSION HISTORY                                                 ////
////                                                                 ////
//// March 5th, 2009:                                                ////
////   Cleanup for Wizard.                                           ////
////   PIC24 Initial release.                                        ////
////                                                                 ////
//// July 1st, 2005: Initial Release.                                ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////

//set to 1 to use a PIC's internal USB Peripheral
//set to 0 to use a National USBN960x peripheral
#define __USB_PIC_PERIF__ 1

//if using a 16bit PIC on an Explorer 16 borad, set this to 1
#define __USB_PIC_EXPLORER16__   1

#if (defined(__PCM__) || defined(__PCB__))
 #error USB CDC Library requires PIC18, PIC24, dsPIC30 or dsPIC33
#endif

#if __USB_PIC_PERIF__
 #DEFINE LED1  PIN_A5
 #if defined(__PCH__)
    #include <18F4550.h>
    #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
    #use delay(clock=48000000)
 #elif defined(__PCD__)
   #include <24FJ256GB110.h>
   
   #fuses HS,PR_PLL,NOWDT,DISUVREG,ICSP2

   #if __USB_PIC_EXPLORER16__
    #use delay(clock=32M)  //8MHz clock is 4x because of PLL
    #fuses PLL2   //Divide 8MHz by 2 to get the 4MHz required for USB
    #pin_select U1TX = PIN_F5
    #pin_select U1RX = PIN_F4
   #endif
 #endif
#else //use the National USBN960x peripheral
 #DEFINE LED1  PIN_B3
 #include <18F452.h>
 #fuses HS,NOWDT,NOPROTECT,NOLVP
 #use delay(clock=20000000)
#endif   //endif check to see which peripheral to use

#use rs232(UART1, baud=9600, errors)

/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here.  If you are
// not using connection sense, comment out this line.  Without connection
// sense you will not know if the device gets disconnected.
//       (connection sense should look like this:
//                             100k
//            VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
//                     |
//                     +----/\/\/\/\/\-----GND
//                             100k
//        (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
///only the 18F4550 development kit has this pin
#if __USB_PIC_PERIF__ && defined(__PCH__)
 #define USB_CON_SENSE_PIN PIN_B2
#endif


#include <usb_cdc.h>

/////////////////////////////////////////////////////////////////////////////
//
// Configure the demonstration I/O
//
/////////////////////////////////////////////////////////////////////////////
#if defined(__PCD__) && __USB_PIC_EXPLORER16__
 #undef  LED1
 #define LED1 PIN_A0
 #define LED2 PIN_A1
 #define LED3 PIN_A2
 #define LED_ON(x) output_high(x)
 #define LED_OFF(x) output_low(x)
 #define BUTTON_PRESSED() !input(PIN_D6)
#else
 #define LED2 PIN_B4
 #define LED3 PIN_B5
 #define LED_ON(x) output_low(x)
 #define LED_OFF(x) output_high(x)
 #define BUTTON_PRESSED() !input(PIN_A4)
#endif


/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states.  Also lights LED1 based upon
// enumeration and status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) 
{
   static int8 last_connected;
   static int8 last_enumerated;
   int8 new_connected;
   int8 new_enumerated;
   static int8 last_cdc;
   int8 new_cdc;

   new_connected=usb_attached();
   new_enumerated=usb_enumerated();
   new_cdc=usb_cdc_connected();

   if (new_enumerated)
      LED_ON(LED1);
   else
      LED_OFF(LED1);

   if (new_cdc)
      LED_ON(LED2);
   else
      LED_OFF(LED2);

   if (usb_cdc_carrier.dte_present)
      LED_ON(LED3);
   else
      LED_OFF(LED3);

   if (new_connected && !last_connected)
      printf("USB connected, waiting for enumaration...\r\n\n");
   if (!new_connected && last_connected)
      printf("USB disconnected, waiting for connection...\r\n\n");
   if (new_enumerated && !last_enumerated)
      printf("USB enumerated by PC/HOST\r\n\n");
   if (!new_enumerated && last_enumerated)
      printf("USB unenumerated by PC/HOST, waiting for enumeration...\r\n\n");
   if (new_cdc && !last_cdc)
      printf("Serial program initiated on USB<->UART COM Port\r\n\n");

   last_connected=new_connected;
   last_enumerated=new_enumerated;
   last_cdc=new_cdc;
}

void main(void) 
{
   char c;

   LED_OFF(LED1);
   LED_OFF(LED2);
   LED_OFF(LED3);

   printf("\r\n\nCCS CDC (Virtual RS232) Example\r\n");

  #if defined(__PCH__)
   printf("\r\nPCH: v");
   printf(__PCH__);
  #elif defined(__PCD__)
   printf("\r\nPCD: v");
   printf(__PCD__);
  #else
   printf("\r\n\PCM: v");
   printf(__PCM__);
  #endif
   printf("\r\n");

   usb_init_cs();

  #if !(__USB_PIC_PERIF__)
   printf("USBN: 0x%X", usbn_get_version());
   printf("\r\n\n");
  #endif


   while (TRUE) 
   {
      usb_task();
      usb_debug_task();

      if (kbhit()) 
      {
         c=getc();
         if (c=='\n') {usb_cdc_putc('\r'); usb_cdc_putc('\n');}
         else if (c=='\r') {usb_cdc_putc('\r'); usb_cdc_putc('\n');}
         else if (c=='!') {printf(usb_cdc_putc,"HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-HELLO-WORLD-DONE");}
         else {usb_cdc_putc(c);}
      }
      if (usb_cdc_kbhit()) 
      {
         c=usb_cdc_getc();
         if (c=='\n') {putc('\r'); putc('\n');}
         else if (c=='\r') {putc('\r'); putc('\n');}
         else {putc(c);}
      }
   }
}
