/*
 *  pwm2.c
 *  $Id: pwm2.c,v 1.2 2002/03/02 03:49:04 bryce Exp $
 *
 *  Pulse width modulation example code for AVR uC
 *  Bryce Denney <bryce@tlw.com>
 *
 *  This code extends pwm1.c so that you can control two channels.
 *
 *  Disadvantages:
 *    - It uses all the processor's attention.  To improve this, we
 *      will need to use the AVR's timers and interrupts.
 *
 *  This software is distributed under the GNU public license.
 *  See http://www.gnu.org/licenses/gpl.html for details.
 *
 */

#include <io.h>

/* 
 *  pwm_2_channel(ON1, OFF1, LIMIT1, ON2, OFF2, LIMIT2, PERIOD)
 *
 *  All variables are 8 bit values.
 *
 *  This function controls two pulse width channels on different pins of
 *  PORTD.  Let's say that PD0 and PD1 control motor 1, and PD4 and PD5
 *  control motor 2.  The two-bit code to turn a motor on is "11" and
 *  to turn the motor off is "00".  For these codes, you would choose:
 *    on1=00000011=0x03
 *    off1=0
 *    on2=00110000=0x30
 *    off2=0
 *  Knowing these values, the function can use an OR operation to
 *  get the correct combinations which motor is on and which is off.
 *  For example:
 *      on1 | off2 = 0x03 | 0x00 = 0x03.  motor 1 on.
 *      on1 | on2  = 0x03 | 0x30 = 0x33.  both motors on.
 *  
 *  The function is implemented just like the one in pwm1.c.  But this
 *  time it has to check 'i' against two different limits.  Whenever
 *  a limit is reached for either motor, that motor is turned off but
 *  the other remains unchanged.  
 *
 *  Again, the function produces only one pulse.  You must call it 
 *  over and over to get a stream of pulses.  Because this loop has more 
 *  to do than in pwm1.c, the frequencies will be lower for the same value 
 *  of PERIOD.  With my 5MHz crystal, PERIOD=255 gives 2.4MHz.
 *  PERIOD=40 gives 14MHz.
 */
void pwm_2_channel (
  unsigned char on1, unsigned char off1, unsigned char limit1,
  unsigned char on2, unsigned char off2, unsigned char limit2,
  unsigned char period)
{
  unsigned char i;
  unsigned char motor1 = on1;
  unsigned char motor2 = on2;
  // start with both motors on
  outp (motor1 | motor2, PORTD);
  for (i=0; i<period; i++) {
    if (i == limit1) {
      // turn off motor1.  motor2 is unchanged.
      motor1 = off1;
      outp (motor1 | motor2, PORTD);
    }
    if (i == limit2) {
      // turn off motor2.  motor1 is unchanged.
      motor2 = off2;
      outp (motor1 | motor2, PORTD);
    }
  }
}

int main ()
{
  unsigned int i, j;

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

  /* run two motors with different power.  Motor 1 is controlled by
     pins PD1 and PD0  (0x03=on).  Motor1 will be on 25% of the time, or 10
     counts out of 40.  Motor 2 is controlled by pins PD4 and PD5 (0x30=on).
     Motor2 will be on 75% of the time, or 30 counts out of 40.

   Waveforms:
		_____                     _____
	       |     |                   |     | 
    motor1  ___|     |___________________|     |__________________
		_________________         _________________
	       |                 |       |                 |
    motor2  ___|                 |_______|                 |______

  */
  while(1)   // infinite loop
  {
    pwm_2_channel (
      0x03, 0x00, 10,
      0x30, 0x00, 30,
      40);
  }

  return 0;
}
