/********************************************************************************
*
*   Compiler: AVR-GCC
*   
*   This little program outputs two PWM channels for standard motors 
*	(PB3 AND PD7) and 2 remote-control style pwm channels for the ATMega16. 
*	Each motor should be continuously moving, so plug them
*   in and test them. Use this program as a basis to build bigger programs..
*   
*   
*   The chip: ATMega8
*
*                   +------\_/-----+
*	reset	PC6     |  1        40 |    PC5
*			PD0     |  2        39 |    PC4
*			PD1     |  3        38 |    PC3
*			PD2     |  4        37 |    PC2
*           PD3     |  5        36 |    PC1
*			PD4     |  6        35 |    PC0 
*	 vcc	VCC     |  7        34 |    GND 
*	 gnd	GND		|  8        33 |    AREF
*			PB6		|  9        32 |    AVCC
*           PB7     | 10        31 |    PB5		sck
*           PD5     | 11        30 |    PB4		miso
*           PD6		| 12        29 |    PB3		mosi
*           PD7		| 13        28 |    PB2		servoB  ->
*			PB0     | 14        27 |    PB1		servoA	->
*                   +--------------+
*
*
*
********************************************************************************/

#include <avr/io.h>
#include <delay.h>

// some constants to keep track of what directions things are moving:
#define UP              1
#define DOWN            -1
// to help make code more transparent:
#define TRUE			1
#define FALSE			0


/********************************************************************************
*		INIT_CHIP
********************************************************************************/
void init_chip(void)
{
	// init stuff for the 8 bit timers:
//	TCCR0 = 0x72;	// set phase correct PWM for timer 0
//	OCR0 =  128;	// set starting duty cycle for timer 0 - pin PB3

	TCCR2 = 0x72;	// set phase correct PWM for timer 2
	OCR2 =  128;	// set starting duty cycle for timer 2 - pin PD7

	// init stuff for the 16 bit timer
    TCCR1A  = 0xA2;		// 0xFX versus 0xAX to invert waveform
    TCCR1B  = 0x19;		// 0x19 for 20ms prescaler
    ICR1    = 20000;	// TOP value of counter set at 20ms (base freq = 50Hz)
    OCR1A   = 1500;		// Starting duty cycle (1500=center) motor A - pin PD5
    OCR1B   = 1500;		// Starting duty cycle (1500=center) motor B - pin PD4    

	// set output pins
	DDRD  = 0xB0;     // set output bits (OCR 1A 1B & motor 2 compare)
	DDRB  = 0x08;     // set output motor 1
}



/********************************************************************************
*		MAIN
********************************************************************************/
void main (void)
{    
  uint16_t	pw_A		= 1500;	// duty cycle for servo A
  uint16_t	pw_B		= 1500; // duty cycle for servo B
  uint8_t	pw_1		= 127;	// duty cycle for motor 1
  uint8_t	pw_2		= 127;	// duty cycle for motor 2

  int8_t directionA	= UP;
  int8_t directionB	= DOWN;
  int8_t direction1	= UP;
  int8_t direction2	= DOWN;

  uint8_t speedA		= 2;    
  uint8_t speedB		= 3;
  uint8_t speed1		= 1;
  uint8_t speed2		= 1;

  init_chip();    // initializes registers and pin stuff

  _delay_loop_2(5000); // wait 5ms for stuff to turn on
    
  while (TRUE){

	//check if pulse width changes need to switch directions:
	if(pw_A >= 2000) directionA	= DOWN;
	if(pw_A <= 1000) directionA	= UP;

	if(pw_B >= 2000) directionB	= DOWN;
	if(pw_B <= 1000) directionB	= UP;

	if(pw_1 >= 245) direction1	= DOWN;
	if(pw_1 <= 10) direction1	= UP;

	if(pw_2 >= 245) direction2	= DOWN;
	if(pw_2 <= 10) direction2	= UP;
	
	pw_A += (directionA * speedA);
	pw_B += (directionB * speedB);
	pw_1 += (direction1 * speed1);
	pw_2 += (direction2 * speed2);
    
    OCR1A	= pw_A;   // replace output compare registers
    OCR1B	= pw_B;   // with the new pulse widths 
//    OCR0	= pw_1;
    OCR2	= pw_2;

    _delay_loop_2(5000); // delay some number of microseconds

    }
}



// ************************* 16 Bit timer reference *******************************
//
// TCCR1A bits:
//    |                |                                 |            = 0xA2 
// COM1A1 - COM1A0 - COM1B1 - COM1B0 - FOC1A - FOC1B - WGM11 - WGM10
//
// TCCR1B bits:
//                              |        |                        |   = 0x19
// ICNC1  - ICES1  -   -    - WGM13  - WGM12  - CS12  - CS11  - CS10
//
// WGM - turn bits 11 12 & 13 on for fast PWM where ICR1 defines TOP
// COM - in fast PWM mode, A1 & B1 on. A0 & B0 off and on toggles wave invert
// FOC1A, FOC1B - set these bits for channel A and channel B, respectively
// CS - prescaling 0-5: none - 1 - 8 - 64 - 256; 
//
// OCR1AH & OCR1AL (to specify high and low bytes - may be needed)

// ************************* 8 Bit timer reference *******************************
//
// TCCR0 bits:
//          1       1       1                      1      1      = 0x73
// FOC0 - WGM00 - COM01 - COM00 - WGM01 - CS02 - CS01 - CS00
//
//
//
// WGM - turn bits 11 12 & 13 on for fast PWM where ICR1 defines TOP
// COM - in fast PWM mode, A1 & B1 on. A0 & B0 off and on toggles wave invert
// FOC - always 0 for pwm
// CS - prescaling 0-5: none - 1 - 8 - 64 - 256; 


