/*******************************************
 * This is the library of functions for
 * the Team Awesome-O Senior Design Project.

 * Team Awesome-O is John Burke, Blake Jones,
 * Dave Ladao, and Bryan Winther.

 * Copyright Team Awesome-0, 2008-2009.
********************************************/

#include <system.h>
#include "AwesomeLIB.h"
#include "buttons.h"
#include "a2d.h"
#include "lcd.h"


//only used in this file
char fcf1;
char fcf2;
char pan1;
char pan2;
char addr1;
char addr2;
char sequence = 0;
char buttons1;
char buttons2;
char buttons3;
char switches;
char jlv;
char jlh;
char jrv;
char jrh;
char play = 0;

void spi_init(void) 

{	

	sspcon1.5 = 0;

	intcon.7 = 0; //Global Interrupt disable*

	intcon.6 = 0; //Peripheral Interrupt disable*

	

	// Enabling SPI1 I/O

	trisc.3 = 0; // set SCK1 to output* 

	trisc.4 = 1; // set SDI1 in input*

	trisc.5 = 0; // SDO1 to output*

    // Configure ZigBee I/O 

    trisc.0 = 0; // set chip select to output Z_CS*

    trisc.1 = 0; // set slp to output*

    trisd.0 = 1; // Set IRQ to input*
    
    //LCD output
    trise.2 = 0;
        
    trisc.2 = 0; // Set set RESET to output*
	// Configure SPI options
	sspstat.7 = 1; // data sampled at end if 1*****??????
	sspstat.6 = 0; // rising edge triggered if 1*
	
	sspcon1.4 = 1; //CKP idle state set low*********
	sspcon1.3 = 0;  //SET 3-0 FOR TIMING OF SPI CLOCK (see below)* //set lower, faster rate could be lower rate	
	sspcon1.2 = 0;
	sspcon1.1 = 1;
	sspcon1.0 = 0;
	sspcon1.5 = 1; // Serial Port enable bit (SPEN)*
	/*********************************************
	Choices for SSP1CON1.3-0:
	0011 = SPI Master mode, clock = TMR2 output/2 
	0010 = SPI Master mode, clock = FOSC/64 
	0001 = SPI Master mode, clock = FOSC/16 
	0000 = SPI Master mode, clock = FOSC/4
	**********************************************/  
	
	intcon.3 = 0; //disable interrupt on change port
	
	intcon.4 = 1;  //Enables interrupt on b0*
	intcon2.6 = 1;  //Enables interrupt on rising edge*
	intcon.1 = 0; //clear flag bit*
	
	
	// Configure Interrupts needed for SPI
//	intcon.7 = 1; //Global Interrupt Enable*
//	intcon.6 = 1; //Peripheral Interrupt Enable*
//	pie1.3 = 1;  //Enables MSSP1 interrupt
	

	Z_WC = 0;
	Z_INT = 0;

	

	
   /* trx_reg_write(RG_IRQ_MASK, 1);
    trx_bit_write(SR_IRQ_MASK_MODE, 1);
    trx_bit_write(SR_TX_AUTO_CRC_ON, 1);  //Turn on automatic FCS generation*/
    
    
	return;

}


void zigbee_init(void)
{
	sspcon1.5 = 0;
	intcon.7 = 0; //Global Interrupt disable*
	intcon.6 = 0; //Peripheral Interrupt disable*

		// Configure SPI options

	sspstat.7 = 1; // data sampled at end if 1*****??????
	sspstat.6 = 1; // rising edge triggered if 1*

	sspcon1.4 = 0; //CKP idle state set low*********
	sspcon1.3 = 0;  //SET 3-0 FOR TIMING OF SPI CLOCK (see below)* //set lower, faster rate could be lower rate	
	sspcon1.2 = 0;
	sspcon1.1 = 1;
	sspcon1.0 = 0;
	sspcon1.5 = 1; // Serial Port enable bit (SPEN)*

	/*********************************************
	Choices for SSP1CON1.3-0:
	0011 = SPI Master mode, clock = TMR2 output/2 
	0010 = SPI Master mode, clock = FOSC/64 
	0001 = SPI Master mode, clock = FOSC/16 
	0000 = SPI Master mode, clock = FOSC/4
	**********************************************/  

	intcon.3 = 0; //disable interrupt on change por
	

	intcon.4 = 1;  //Enables interrupt on b0*
	intcon2.6 = 1;  //Enables interrupt on rising edge*
	intcon.1 = 0; //clear flag bit*

	// Configure Interrupts needed for SPI
//	intcon.7 = 1; //Global Interrupt Enable*
//	intcon.6 = 1; //Peripheral Interrupt Enable*
//	pie1.3 = 1;  //Enables MSSP1 interrupt

	

	Z_WC = 0;
	Z_INT = 0;

	

	
	trx_reg_write(RG_IRQ_MASK, 1);
	delay_ms(1);
    trx_bit_write(SR_IRQ_MASK_MODE, 1);
    delay_ms(1);
    trx_bit_write(SR_TX_AUTO_CRC_ON, 1);  //Turn on automatic FCS generation*/
    delay_ms(1);
    
    
	return;

}

void setup_fcf(void)
{        
	//Set up valid packet

	//FCF - Byte 1
	char frametype = 0b001; //Data
	char security = 0; //No
	security <<= 3;
	char pendingframe = 0; //No
	pendingframe <<= 4;
	char acknowledgement = 0; //No
	acknowledgement <<= 5;
	char intrapan = 0; // Yes
	intrapan <<= 6;
	//char fcf1 = 0x01;
	fcf1 = frametype | security | pendingframe | acknowledgement | intrapan;
	
	//FCF - Byte 2
	char sourceaddressing = 0b00; // Addressing type - 16 bit short address
	sourceaddressing <<= 6;
	char frameversion = 0b00; // Compatible w/ IEEE 2003
	frameversion <<= 4;
	char destinationaddressing = 0b10;
	destinationaddressing <<= 2;
	//char fcf2 = 0x08;
	fcf2 = sourceaddressing | frameversion | destinationaddressing;
	return;
}

void setup_pan(char panid1, char panid2)
{
	pan1 = panid1;
	pan2 = panid2;
	return;
}

void setup_addr(char address1,char address2)
{
	addr1 = address1;
	addr2 = address2;
	return;
}

void setup_buttons(void)
{

	buttons1 = check_topbuttons();
	delay_ms(1);
	buttons2 = check_bottombuttons();
	delay_ms(1);
	
	return;


}

void setup_joysticks(void)
{
	char jvalues[4]; 		// joystick values
	a2d_convert_all();   		// get joystick positions
	a2d_scale_all(jvalues);  		// get scaled joystick values

	jlv = jvalues[1];
	jlh = jvalues[2];
	jrv = jvalues[3];
	jrh = jvalues[4];
	return;
}

void send_packet(void)
{
		char trxarray[] = {fcf1, fcf2, sequence, pan1, pan2, addr1, addr2, buttons1, buttons2, jlv, jlh, jrv, jrh};
		char *frame;
		frame = &trxarray[0];
		
		//Ready for frame write
		TRX_PIN_SLP_TR = 1;
		delay_us(tTR10);
		delay_us(1);
		TRX_PIN_SLP_TR = 0;
		
		//Write to frame and send
		trx_frame_write(15, trxarray);
        
        //Increase sequence number
        sequence = sequence + 1;
        return;
}

void setup(void)
{
	char switches;
	switches = check_switches();
	if(switches != 0)
		spi_init();
	if(switches == 3)
		a2d_calibrate();
	if(switches == 2)
		play_calls();
	return;
}

void play_calls(void)
{
	char switches;
	char buttons;
	char i;
	

	switches = check_switches();
	init_buttons();
	buttons = check_topbuttons();
	buttons &= 0x0C;
	buttons = (buttons >>2);

	if(buttons == 0x01)
	{
	play++;
	if(play>5)
		play=0;
	}
	if(buttons ==0x02)
	{
	play--;
	if(play>5)
		play=5;
	}
	 
	/*switch (play)
		{
		case 0:
		lcd_hex(buttons);

		lcd_cmd(0x56);
		delay_ms(1);
		lcd_cmd(0x56);
		delay_ms(1);
		break;
		case 1:
			lcd_clear();
			delay_ms(1);
			lcd_printf("Blue 42");
			break;
		case 2:
			lcd_clear();
			delay_ms(1);
			lcd_printf("Hike");
			break;
		case 3:
			lcd_clear();
			delay_ms(1);
			lcd_printf("Notre Dame 7");
			break;
		case 4:
			lcd_clear();
			delay_ms(1);
			lcd_printf("Winther 31");
			break;
		case 5:
			lcd_clear();
			delay_ms(1);
			lcd_printf("Burke smells");
			break;
	}*/
	set_led(play);
	display_led();
	play(play);
	delay_ms(200);

	
	return;
}

void play(char playnum)
{
	lcd_clear();
	delay_ms(1);
	if(playnum == 0)
	{
	lcd_printf("Select A Play");
	}
	if(playnum == 1)
	{
	lcd_printf("Blue 42");
	}
	if(playnum == 2)
	{
		lcd_printf("Notre Dame 31");

	}
	if(playnum == 3)
	{
		lcd_printf("Irish 45");
	}
	if(playnum == 4)
	{
		lcd_printf("Winther 37");
	}
	if(playnum == 5)
	{
		lcd_printf("Burke Smells");
	}
	return;
}
void spi_put_data(char data)  // Send data via SPI to ZigBee 
{
	   Z_INT = 0; //Reset interrupt flag
       Z_CS = 0;  // Turn chip select on
       sspbuf = data;  //place inputted data into the buffer (prepared for transmit)
       while(!Z_INT){} // Wait until transmission is complete
	   Z_CS = 1;  //Turn chip select off
	   return;
}

char spi_get_data(void)  // wait for information from SPI (send dummy data first!)
{	  
	  Z_CS = 0;  // Turn chip select on
      while(!Z_INT){}  // wait until reception is complete
      char data = sspbuf;  // load the character into data from the receive register
      Z_CS = 1;  //Turn chip select off
      Z_INT = 0;
      return data;
}

char trx_reg_read(char addr)
{
      char data;   // Initialize return data
      Z_CS = 0;  // Turn chip select on
      Z_INT = 0;  // Reset the interrupt flag
      Z_WC = 0; // Clear the Write Collision Detect bit  
      
      sspbuf = 0b10000000 + addr;  //Put transmit bits (10), then the address into the buffer
      
      while(!Z_INT){} // Wait until transmission is complete
      
      Z_INT = 0;  // Reset the interrupt flag
      sspbuf = 0x00;  // Send dummy data (allows for receive)
      
      while(!Z_INT){} // Wait until reception is complete
      data = sspbuf;  // Load received data from buffer into variable
      
      Z_INT = 0;      // Reset interrupt flag
      Z_CS = 1;      //Turn chip select off
      return data;
}


void trx_reg_write(char addr, char val)
{
       Z_CS = 0;  // Turn chip select on
       
       sspbuf = 0b11000000 + addr;  //Put transmit bits (10), then the address into the buffer
       
       while(!Z_INT){} // Wait until transmission is complete
       
       Z_INT = 0;  // Reset the interrupt flag
       sspbuf = val;  // Put the data bits into the buffer
       
       while(!Z_INT){} // Wait until transmission is complete
       
       Z_INT = 0;  // Reset the interrupt flag
       Z_CS = 1;  //Turn chip select off
       return;
}

char trx_bit_read(char addr, char mask, char pos)
{
	char regdata;  //Initialize regdata
	
    regdata = trx_reg_read(addr);  //Gather byte that subreg is from
    regdata &= mask;  //Mask the subregister
    regdata >>= pos; //Shift bit to subregister
    
	return regdata;
}


void trx_bit_write(char addr, char mask, char pos, char val)	
{
    char regdata;
    //Read current register value and mask area outside the subregister.
    regdata = trx_reg_read(addr);
    regdata &= ~mask;
    
    //Start preparing the new subregister value. shift in place and mask.
    val <<= pos;
    val &= mask;
    val |= regdata; //Set the new subregister value.

    //Write the modified register value.
    trx_reg_write(addr, val);
    return;
}

void transceiver_reset(void)
{
	char state;
	
	delay_us(tTR1);  //Wait for CLKM to turn on
    TRX_RESET = 0;   //Throw /RST low (turns reset on)
    TRX_PIN_SLP_TR = 0;  //Throw SLP_TR low
    delay_us(1); //Wait reset pulse width (625 ns)
    TRX_RESET = 1;  //Throw /RST high again (completes reset)
    trx_reg_write(RG_IRQ_MASK, TRX_IRQ_AWAKE_END);  //Write the AWAKE flag to register
    trx_bit_write(SR_TRX_CMD, CMD_TRX_OFF);  //Send chip to TRX_OFF state
    delay_us(tTR13);  //Wait for chip to go from RESET -> TRX_OFF
    state = trx_bit_read(SR_TRX_STATUS);  //Check the status
  /*while(state != TRX_OFF)  //If the chip ends up in correct state (TRX_OFF), alternate LED's
    {

    }*/
    
    return;
}

void transceiver_pll_on(void)
{
	trx_bit_write(SR_TRX_CMD, CMD_PLL_ON);
    delay_us(tTR4);
    char trxstat = trx_bit_read(SR_TRX_STATUS);
    /*while(trxstat!=PLL_ON)
    {
    }*/
}

void trx_frame_write(char length, char *frame)
{
     Z_CS = 0;  // Turn chip select on
     sspbuf = 0x60; // Send the frame write command byte
     while(!Z_INT){} // Wait until SPI transmission is complete
     Z_INT = 0;  // Reset the interrupt flag

     //Send the length byte
     sspbuf = length;
     while(!Z_INT){} // Wait until SPI transmission is complete
     Z_INT = 0;  // Reset the interrupt flag

     //Write to frame buffer
     do{
        sspbuf = *frame++;
        --length;
        while(!Z_INT){} // Wait until SPI transmission is complete
        Z_INT = 0;  // Reset the interrupt flag
     } while (length > 0);

     Z_CS = 1; //Turn chip select off

}
