/****************************************************************************
*
*   This file is based on the SOR Axon applicaation note
*   Copyright (c) 2008 www.societyofrobots.com
*
*   and my ATmega8 PS2 controller code.
*   http://mrdunk.googlepages.com/ps2controlleronanavr
*
*   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 Include
#include "SoR_Utils.h" //includes all the technical stuff
#include "hardware.c" //declare hardware variables and ports
//#include "CMUcam.c" //not yet written
#include "sensors.c" //not yet written, sensor libraries for sonar, sharp IR, etc.
//#include "Blackfin_Axon.c" //files for Blackfin Robot camera
#include "control.c" //your code goes in here
//#include "axon_test.c" //include this is doing a function test for the Axon
//#include "axon_oscope_test.c" //include this is doing a function test for the Axon
#include "Axon.h"


/****************AVR pin defines****************/
#define PSclock            	3               // PA3	blue wire
#define PSdata             	4               // PA4	brown
#define PSacknowledge  		5               // PA5	green
#define PScommand   		6               // PA6	orange
#define PSattention     	7               // PA7	yellow

int gameByte(short int );


int main(void)
	{
	//declare variables here
	int i=0;//useless variable
	int j=0;//useless variable


	/****************INITIALIZATIONS*******************/
	//other stuff Im experimenting with for SoR
	uartInit();  // initialize the UART (serial port)
    uartSetBaudRate(0, 38400); // set UARTE speed, for Bluetooth
    uartSetBaudRate(1, 115200); // set UARTD speed, for USB connection
    uartSetBaudRate(2, 38400); // set UARTH speed
    uartSetBaudRate(3, 38400); // set UARTJ speed, for Blackfin
	//G=Ground, T=Tx (connect to external Rx), R=Rx (connect to external Tx)

	rprintfInit(uart1SendByte);// initialize rprintf system and configure uart1 (USB) for rprintf

	timer0Init(); // initialize the timer system
	timer2Init(); // 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

	LED_on();

	rprintf("\r\nSystem Warming Up");

	//let system stabelize for X time
	for(i=0;i<=16;i++)
		{
		delay_cycles(5000);
		rprintf(".");
		}

	delay_cycles(6000);

	//read each ADC once to get it working accurately
	for(i=0;i<16;i++)
		j=a2dConvert8bit(i);

	reset_timer_0();
	reset_timer_2();

	LED_off();

	
	rprintf("Axon initialization Complete. \r\n");
	rprintf("Now initialising  PS2 controller....\r\n");


    // PSx controller I/O pin setup:
    sbi(DDRA, PSclock);                // clock. output. (blue)

    cbi(DDRA, PSdata);                 // data. input. (brown)
    sbi(PORTA, PSdata);                //    enable pullup resistor

    cbi(DDRA, PSacknowledge);            // acknowledge. input. (green)
    sbi(PORTA, PSacknowledge);           //    enable pullup resistor

    sbi(DDRA, PScommand);              // command. output. (orange)

    sbi(DDRA, PSattention);            // attention. output. (yellow)


    // enable interupts
    sei();

    // this loop continues to put PSx controller into analouge mode untill the
    // controller responds with 0x73 in the 2nd byte. 
    // (PS2 controller responds with 0x73 when in analouge mode.)
    // the status LEDs will continue to count upwards untill a controller is found.
    // if everything is working correctly this should happen on the first pass of
    // this loop but occasionally errors occur and a 2nd or 3rd itteration happen.
    unsigned char chk_ana =1;
	unsigned int cnt=0;
    while(chk_ana != 0x73){
	   // put controller in config mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // put controller in analouge mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x44);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x03);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // exit config mode
       sbi(PORTA, PScommand);
       sbi(PORTA, PSclock);
       cbi(PORTA, PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);

       delay_ms(1);

       // poll controller and check in analouge mode.
       sbi(PORTA, PScommand);
	   sbi(PORTA, PSclock);
	   cbi(PORTA, PSattention);

       gameByte(0x01);
       chk_ana = gameByte(0x42);            // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller.
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       sbi(PORTA, PScommand);
       delay_us(1);
       sbi(PORTA, PSattention);
       delay_ms(1);

       rprintf("\r\nPass number %d.  Controller returned 0x%x (expected 0x0073)", cnt++, chk_ana);
   }

   rprintf("\r\nPS2 controller initialised.");

   delay_ms(100);

   short int temp, data0, data1, data2, data3, data4, data5;
  // main program loop:
  // ADD YOUR CODE TO THIS LOOP!
  // data from PS2 controller will be stored in data0, data1, data2, etc...
   while (1){

        sbi(PORTA, PScommand);                          // start communication with PSx controller
        sbi(PORTA, PSclock);
        cbi(PORTA, PSattention);

        gameByte(0x01);                                 // bite 0. header.
        temp = gameByte(0x42);                          // bite 1. header. (should possibly put test on this byte to detect unplugging of controller.)
        gameByte(0x00);                                 // bite 2. header.

        data0 = gameByte(0x00);                         // bite 3. first data bite.
        data1 = gameByte(0x00);                         // bite 4.
        data2 = gameByte(0x00);                         // bite 5.
        data3 = gameByte(0x00);                         // bite 6.
        data4 = gameByte(0x00);                         // bite 7.
        data5 = gameByte(0x00);                         // bite 8.

        sbi(PORTA, PScommand);                          // close communication with PSx controller
        delay_us(1);
        sbi(PORTA, PSattention);                        // all done.



        // display data from PS2 controller
		rprintf("\r\n%x   %x   %x   %x   %x   %x", data0, data1, data2, data3, data4, data5);


		delay_ms(10);

		}


	return 0;
}



// PSx controller communication function.
// send a byte on the command line and receive one on the data line.
// needs Attention pin to have gone low before called to activate controller.
int gameByte(short int command)
{
        short int i ;
        delay_us(1);
        short int data = 0x00;                                   // clear data variable to save setting low bits later.
        for(i=0;i<8;i++)
        {
				if(command & _BV(i)) sbi(PORTA, PScommand);      // bit bang "command" out on PScommand wire.
                else cbi(PORTA, PScommand);
                cbi(PORTA, PSclock);                             // CLOCK LOW
                delay_us(1);                                              // wait for output to stabilise
                if((PINA & _BV(PSdata))) {sbi(data, i); }  		 // read PSdata pin and store
                //else {cbi(data, i);}
                sbi(PORTA, PSclock);                             // CLOCK HIGH
        }
        sbi(PORTA, PScommand);

        delay_us(20);                                            // wait for ACK to pass.
		

        return(data);
}
