/////////////////////////////////////////////////////////////////////////
////                           EX_PWM.C                              ////
////                                                                 ////
////  This program will show how to use the built in PIC PWM.        ////
////  The program takes an analog input and uses the digital         ////
////  value to set the duty cycle.  The frequency is set by          ////
////  the user over the RS-232.                                      ////
////                                                                 ////
////  Configure the CCS prototype card as follows:                   ////
////      Connect a scope to pin C2                                  ////
////      Connect pin A0 to output of the POT                        ////
////                                                                 ////
////  Configure the CCS PCD 30F2010 development board as follows:    ////
////      Connect a scope to pin D0                                  ////
////                                                                 ////
////  Jumpers:                                                       ////
////     PCM,PCH    pin C7 to RS232 RX, pin C6 to RS232 TX           ////
////     PCD        none                                             ////
////                                                                 ////
////  This example will work with the PCM, PCH, and PCD compilers.   ////
////  The following conditional compilation lines are used to        ////
////  include a  valid device for each compiler.  Change the device, ////
////  clock and RS232 pins for your hardware if needed.              ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2007 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.              ////
/////////////////////////////////////////////////////////////////////////


#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)

#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)

#elif defined(__PCD__)
#include <30F2010.h>
#fuses HS,NOWDT
#device ADC=10
#use delay(clock=20000000)
#use rs232(baud=9600, UART1A)
#endif

#if !defined(__PCD__)

void main(void)
{
   
   /* PWM EXAMPLE FOR 8-BIT PICS */
   
   char selection;
   unsigned int8 value;

   printf("\r\nFrequency:\r\n");
   printf("    1) 19.5 khz\r\n");
   printf("    2) 4.9 khz\r\n");
   printf("    3) 1.2 khz\r\n");

   do {
     selection=getc();
   } while((selection<'1')||(selection>'3'));

   setup_ccp1(CCP_PWM);   // Configure CCP1 as a PWM

          //   The cycle time will be (1/clock)*4*t2div*(period+1)
          //   In this program clock=10000000 and period=127 (below)
          //   For the three possible selections the cycle time is:
          //     (1/10000000)*4*1*128 =  51.2 us or 19.5 khz
          //     (1/10000000)*4*4*128 = 204.8 us or 4.9 khz
          //     (1/10000000)*4*16*128= 819.2 us or 1.2 khz

   switch(selection) {
     case '1' : setup_timer_2(T2_DIV_BY_1, 127, 1);
                break;
     case '2' : setup_timer_2(T2_DIV_BY_4, 127, 1);
                break;
     case '3' : setup_timer_2(T2_DIV_BY_16, 127, 1);
                break;
   }

  setup_port_a(ALL_ANALOG);
  setup_adc(adc_clock_internal);
  set_adc_channel( 0 );
  printf("%c\r\n",selection);

  while( TRUE ) {
    value=read_adc();

    printf("%2X\r",value);

    set_pwm1_duty(value);          // This sets the time the pulse is
                                   // high each cycle.  We use the A/D
                                   // input to make a easy demo.
                                   // the high time will be:
                                   //  if value is LONG INT:
                                   //    value*(1/clock)*t2div
                                   //  if value is INT:
//    value*4*(1/clock)*t2div
                                   // for example a value of 30 and t2div
                                   // of 1 the high time is 12us
                                   // WARNING:  A value too high or low will
                                   //           prevent the output from
                                   //           changing.
  }

}
#else

void main(void) 
{

   /* PWM EXAMPLE FOR 16-BIT PICS */
   
   char selection;
   unsigned int16 value;

   printf("\r\nFrequency:\r\n");
   printf("    1) 76.37 hz\r\n");
   printf("    2) 9.55  hz\r\n");
   printf("    3) 1.19  hz\r\n");
   
   do {
     selection=getc();
   } while((selection<'1')||(selection>'3'));

          //   The cycle time will be (1/clock)*4*t2div*(period+1)
          //   In this program clock=20000000 and period=127 (below)
          //   For the three possible selections the cycle time is:
          //     (1/20000000)*4*1*65473  =  13.1 ms or 76.37 hz
          //     (1/20000000)*4*8*65473  = 104.7 ms or 9.55  hz
          //     (1/20000000)*4*64*65473 = 838.1 ms or 1.19  hz

   switch(selection) {
     case '1' : setup_timer2(TMR_INTERNAL | TMR_DIV_BY_1, 0xFFC0);
                break;
     case '2' : setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8, 0xFFC0);
                break;
     case '3' : setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 0xFFC0);
                break;
   }

  setup_adc_ports(ALL_ANALOG);
  setup_adc(adc_clock_internal);
  set_adc_channel(0);
  printf("%c\r\n",selection);
  
  setup_compare(1, COMPARE_PWM | COMPARE_TIMER2);
  
  while(TRUE) 
  {
    value=read_adc();

    printf("%LX\r",value);
    
    /* set the duty cycle using the adc reading.  the adc reading is in 10 bits,
      the duty cylce is in 16 bits, multiplying by 64 brings adc up to 16 bits */
    set_pwm_duty(1,value * (int16)64); // This sets the time the pulse is
                                       // high each cycle.  We use the A/D
                                       // input to make a easy demo.
                                       // the high time will be:
                                       // value is int16, clock = 20MHz, t2div = 1
                                       // This will give period of 13.1 ms
                                       // For example if value = 200, then
                                       //  value*64*4*(1/clock)*t2div = 2.56 ms
                                       // This will give an duty cycle of about 20 %
                                       // WARNING:  A value too high or low will
                                       //           prevent the output from
                                       //           changing.
                                   
  }

}
#endif
