/*
 *  pwm1.c
 *  $Id: pwm1.c,v 1.3 2002/03/02 04:06:10 bryce Exp $
 *
 *  Pulse width modulation example code for AVR uC
 *  Bryce Denney <bryce@tlw.com>
 *
 *  These examples show a very simple way to do PWM.  One function
 *  called do_one_pulse() does all the work.
 *
 *  Disadvantages:
 *    - it uses all the processor's attention
 *    - only one channel: all motors would have the same amount of power,
 *      when you might want to control different motors separately.
 *
 *  This software is distributed under the GNU public license.
 *  See http://www.gnu.org/licenses/gpl.html for details.
 *
 */

#include <io.h>

/* 
 *  do_one_pulse(ON, OFF, LIMIT, PERIOD)
 *
 *  ON,OFF,LIMIT,PERIOD are all 8 bit values.  0 - 255.
 *
 *  This function creates just one pulse.  To make a stream of pulses, you
 *  must call it over and over.  First, the 8-bit ON value is written to 
 *  port D.  Then, using the variable 'i', it counts from 0 to PERIOD,
 *  increasing i by 1 each time.  When i reaches the value of LIMIT, it
 *  changes port D to the OFF value.  When i reaches the value of 
 *  PERIOD, the function returns.
 *
 *  So, if LIMIT is 0, you will get the ON value for a very short time
 *  and then the OFF value for a long time.  If LIMIT is about half of
 *  PERIOD, you get the ON value for half the time and the OFF value
 *  for the other half.  
 *
 *  The PERIOD setting controls the total time the function takes.  
 *  1.0/PERIOD is proportional to the frequency.  For example, 
 *  if PERIOD=255 and your crystal is 5MHz, the PWM
 *  frequency turns out to be 3.3khz.  If PERIOD=40 with the same
 *  crystal, the PWM frequency is 20khz.
 *
 */
void do_one_pulse (
  unsigned char on,
  unsigned char off,
  unsigned char limit,
  unsigned char period)
{
  unsigned char i;
  outp (on, PORTD);
  for (i=0; i<period; i++) {
    if (i==limit)
      outp (off, PORTD);
  }
}

int main ()
{
  unsigned int i, j;

  /* enable all bits of PORTD as outputs */
  outp (0xff, DDRD);

  /* Create 40000 pulses by calling do_one_pulse() 40000 times.
     The on value is 1, and the off value is 0.  So only pin PD0 will
     be changing.  The period is 255 (the maximum) and the limit is 60.
     The output looks something like:
           

          ______                ______              
          |    |                |    |              
       ___|    |________________|    |______________
            on       off          on         off

     This lasts about 12 seconds.
  */
  for (i=0; i<40000; i++) {
    do_one_pulse (1, 0, 60, 255);
  }

  /* Create 655350 pulses.  Since this is more than one variable can hold,
     use two loops (i and j).  For each i count from 0 to 10, j must count
     from 0 to 65535.  This time the on value is 15, or in base 16: 0F,
     or in binary bits: 00001111.  So pins PD0,PD1,PD2,PD3 will all be
     wiggling, and PD4-7 will be zero.  The limit is 35 out of a period
     of 40, so it will be ON most of the time.  The period is much 
     smaller than the first example.

           ___   ___   ___   ___   ___   ___   ___   ___   ___  
          |   | |   | |   | |   | |   | |   | |   | |   | |   | 
       ___|   |_|   |_|   |_|   |_|   |_|   |_|   |_|   |_|   |_
           on off  etc.

     This lasts about 30 seconds.
  */
  for (i=0; i<10; i++) {
    for (j=0; j<65535; j++) { 
      do_one_pulse (15, 0, 35, 40);
    }
  }

  /* this one lasts forevere, until you reset */
  while (1) {   // infinite loop
    // 50% on, 50% off.  All port D pins wiggling because value is 0xff.
    do_one_pulse (0xff, 0, 40, 80);
  }
  return 0;
}
