/****************************************************************************
*
*   Copyright (c) 2007 www.societyofrobots.com
*   (please link back if you use this code!)
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License version 2 as
*   published by the Free Software Foundation.
*
*   Alternatively, this software may be distributed under the terms of BSD
*   license.
*
*	SoR Utilities v1, March 10th, 2007
*
****************************************************************************/



//AVR includes
#include <avr/io.h>		    // include I/O definitions (port names, pin names, etc)
#include <avr/interrupt.h>	// include interrupt support
#include <avr/wdt.h>        // include watchdog timer

//AVRlib includes
#include "global.h"		// include global settings
#include "buffer.h"		// include buffer function library
#include "uart.h"		// include uart function library
#include "rprintf.h"	// include printf function library
#include "timerx8.h"		// include timer function library (timing, PWM, etc)
#include "a2d.h"		// include A/D converter function library


// For newer AVRs such as ATmega1281
// Function Pototype
void wdt_init(void) \

      __attribute__((naked)) \

      __attribute__((section(".init3")));

// Function Implementation
void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();
}


// Macros

//define port functions; example: PORT_ON( PORTD, 6);
#define PORT_ON( port_letter, number )			port_letter |= (1<<number)
#define PORT_OFF( port_letter, number )			port_letter &= ~(1<<number)
#define PORT_ALL_ON( port_letter, number )		port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number )		port_letter &= ~(number)
#define FLIP_PORT( port_letter, number )		port_letter ^= (1<<number)     // toggle port
#define PORT_IS_ON( port_letter, number )		( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number )		!( port_letter & (1<<number) )

// soft reset macro using watchdog timer
#define soft_reset()        \
do                          \
{                           \
    wdt_enable(WDTO_15MS);  \
    for(;;)                 \
    {                       \
    }                       \
} while(0)








//************CONFIGURE PORTS************
//configure ports for input or output - specific to ATmega8
void configure_ports(void)
	{
	DDRC = 0x00;  //configure all C ports for input
	PORTC = 0x00; //make sure pull-up resistors are turned off
	DDRD = 0xFF;  //configure all D ports for output
	rprintf( "\n\n\t\t\tPorts Configured.\n\n" );
	}
//***************************************

//************DELAY FUNCTIONS************
//wait for X amount of cycles (23 cycles is about .992 milliseconds)
//to calculate: 23/.992*(time in milliseconds) = number of cycles
//or (number of cycles)*.992/23 = time in milliseconds
void delay_cycles(unsigned long int cycles)
	{
	while(cycles > 0)
		cycles--;
	}
//***************************************

//**************RESET TIMER**************
void reset_timer_0(void)
	{
	//restart timer count
	TCNT0=0x00;//clear timer
	timer0ClearOverflowCount();//clear timer0's overflow counter.
	}
//***************************************

//*********SIMPLIFIED FUNCTIONS**********
//functions to make coding easier for a beginner
//but could cause port mixup confusion for intermediate users
void LED_on(void)
	{
	PORT_OFF(PORTD, 4);//turn LED on
	}
void LED_off(void)
	{
	PORT_ON(PORTD, 4);//turn LED off
	}
void servo_left(signed long int speed)
	{
	PORT_ON(PORTD, 2);
	delay_cycles(speed);
	PORT_OFF(PORTD, 2);//keep off
	delay_cycles(1600); // 200 * 8
	}
void servo_right(signed long int speed)
	{
	PORT_ON(PORTD, 3);
	delay_cycles(speed);		
	PORT_OFF(PORTD, 3);//keep off
	delay_cycles(1600); // 200 * 8
	}
void servo_scan(signed long int speed)
	{
	PORT_ON(PORTD, 4);
	delay_cycles(speed);		
	PORT_OFF(PORTD, 4);//keep off
	delay_cycles(1600); // 200 * 8
	}
void robot_turn_left(void)
	{
	servo_left(200); // 25 * 8
	servo_right(200); // 25 * 8
	}
void robot_turn_right(void)
	{
	servo_left(352); // 44 * 8
	servo_right(352); // 44 * 8
	}
void robot_go_straight(void)
	{
	servo_left(202); // 25 * 8
	servo_right(352); // 44 * 8
	}
void robot_go_back(void)
    {
	servo_left(352);
	servo_right(202);
	}
void hold_position(void)//37
	{
	servo_left(312);//39 * 8
	servo_right(280);//35 * 8
	}
//***************************************

//*************INITIALIZATIONS***********
void initialize(void)
	{
	//other stuff Im experimenting with for SoR
	uartInit();  // initialize the UART (serial port)
	uartSetBaudRate(57600);// set the baud rate of the UART for our debug/reporting output
	rprintfInit(uartSendByte);// initialize rprintf system


	timer0Init(); // initialize the timer system
	
	configure_ports(); // configure which ports are analog, digital, etc.
	a2dInit(); // initialize analog to digital converter (ADC)
	a2dSetPrescaler(ADC_PRESCALE_DIV32); // configure ADC scaling
	a2dSetReference(ADC_REFERENCE_AVCC); // configure ADC reference voltage

	rprintf("\t\t\tInitialization Complete\n\n");
	}
//****************************************


void resetChip(int delay_sec) {
   /* if the project does not typically receive data, and accidental chip resets are tolerable,
   * this is a simple method that should work just fine. Otherwise it is recommended that the 
   * reset request string be part of a call-response sequence, be transmitted with a
   * reserved byte or byte string, or be transmitted in some way out of band, so that it is not 
   * accidentally received.
   */
   
   rprintf("\nMCU will reset in ");
   rprintf("%d seconds...\n\r", delay_sec);
   delay_sec *= 1000;
   delay_ms(delay_sec); // wait for the specified amount of time, doing nothing
   rprintf("\nResetting NOW.\n\r");
   soft_reset(); // reset macro
}

