/*
 * Xbee_transceiver.c
 *
 *  Created on: Jan 6, 2011
 *      Author: Curtis Mayberry
 */

#include "usart.h"
#include "gpio.h"
#include "intc.h"
#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
//#include "Xbee_transceiver.h"

// User Interface Addresses


#define UI1_16bit_Address_MSB  0x01
#define UI2_16bit_Address_MSB  0x02
#define UI3_16bit_Address_MSB  0x03
#define UI4_16bit_Address_MSB  0x04
#define UI5_16bit_Address_MSB  0x05
#define TX_complete			   0x0A

// Need to set during configuration
#define Number_of_UIs          0x05
#define UI_current_16bit_Address_MSB UI1_16bit_Address_MSB

// RX_buffer/RX Queue - modified from the notes of Professor Zhang Zhao
#define DATA_SIZE 3		// Size of the buffer
#define RX_BUF_SIZE (DATA_SIZE+1)

//USART
#define USART_0               (&AVR32_USART1)
#define USART2                (&AVR32_USART2)
#define USART_RX_PIN          AVR32_USART1_RXD_0_0_PIN
#define USART_RX_FUNCTION     AVR32_USART1_RXD_0_0_FUNCTION
#define USART_TX_PIN          AVR32_USART1_TXD_0_0_PIN
#define USART_TX_FUNCTION     AVR32_USART1_TXD_0_0_FUNCTION
#define USART_IRQ             AVR32_USART1_IRQ
#define USART_BAUDRATE        57600
#define TARGET_PBACLK_FREQ_HZ FOSC0  // PBA clock target frequency, in Hz




/********************
 * Buffer functions *
 ********************/



typedef struct measurement_storage_struct {

	unsigned int curr_temp_measurement_UI[Number_of_UIs];
	unsigned int set_pt_measurement_UI[Number_of_UIs];

  } measurement_storage;


// Buffer_R was defined here
  typedef struct queue {
  volatile int tail;
  volatile unsigned char buf[RX_BUF_SIZE];
  volatile unsigned char newest_data;
  } Buffer_R;

Buffer_R *RX_Buffer;

volatile int RX_Byte;
int packet_ready_flag = 0;


/*
 * Initializes the RX_buffer
 */
void init_queue(Buffer_R *q) {
	q->tail = 0;
	return;
}

void init_measurement(measurement_storage *q) {
	int i = 0;

	for(i = 0; i < Number_of_UIs; i++){
		q->curr_temp_measurement_UI[i] = 0;
		q->set_pt_measurement_UI[i] = 0;

	}
}

// initializes the RX_Buffer
void init_RX_Buffer(void) {
	RX_Buffer->tail = 0;
	RX_Buffer->buf[0] = 0;
	RX_Buffer->buf[1] = 0;
	RX_Buffer->buf[2] = 0;
	RX_Buffer->buf[3] = 0;
	RX_Buffer->newest_data = 0;

}


/* Gets data from the RX_Buffer
 * return 0 if queue is empty */
void dequeue(measurement_storage *q) {
	RX_Buffer->tail = 0;
	char mes[5];

	while(packet_ready_flag == 0){

		if(RX_Buffer->tail == 4){
			RX_Buffer->tail %= RX_BUF_SIZE;
			packet_ready_flag = 1;

		}

	}

	if(RX_Buffer->buf[0] == UI1_16bit_Address_MSB) {
		q->curr_temp_measurement_UI[0] = RX_Buffer->buf[1];
		q->set_pt_measurement_UI[0] = RX_Buffer->buf[2];
	}
	else if(RX_Buffer->buf[0] == UI2_16bit_Address_MSB) {
		q->curr_temp_measurement_UI[1] = RX_Buffer->buf[1];
		q->set_pt_measurement_UI[1] = RX_Buffer->buf[2];
	}
	else if(RX_Buffer->buf[0] == UI3_16bit_Address_MSB) {
		q->curr_temp_measurement_UI[2] = RX_Buffer->buf[1];
		q->set_pt_measurement_UI[2] = RX_Buffer->buf[2];
	}
	else if(RX_Buffer->buf[0] == UI4_16bit_Address_MSB) {
		q->curr_temp_measurement_UI[3] = RX_Buffer->buf[1];
		q->set_pt_measurement_UI[3] = RX_Buffer->buf[2];
	}
	else if(RX_Buffer->buf[0] == UI5_16bit_Address_MSB) {
		q->curr_temp_measurement_UI[4] = RX_Buffer->buf[1];
		q->set_pt_measurement_UI[4] = RX_Buffer->buf[2];
	}

	int i = 0;
	for(i = 0;i < RX_BUF_SIZE;i++){
		RX_Buffer->buf[i] = 0;
	}

	packet_ready_flag = 0;
	RX_Buffer->tail = 0;

	return;
}

/* Gets data from the RX_Buffer
 * return 0 if queue is empty */
unsigned char dequeue_Rx_Buffer(void) {

	unsigned char data = RX_Buffer->newest_data;

	RX_Buffer->newest_data = 0;

	return data;

}

/*********************************
 * Measurement storage functions *
 *********************************/


/* USART interrupt handler
* Receives a USART message, byte by byte and adds it to the buffer to be parsed later
*/
#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
static void usart_int_handler(void) {//char RX_Buffer[], int RX_Buffer_size, int *RX_Buffer_handler_index) {


	// In the code line below, the interrupt priority level does not need to be
	// explicitly masked as it is already because we are within the interrupt
	// handler.
	// The USART Rx interrupt flag is cleared by side effect when reading the
	// received character.
	// Waiting until the interrupt has actually been cleared is here useless as
	// the call to usart_write_char will take enough time for this before the
	// interrupt handler is leaved and the interrupt priority level is unmasked by
	// the CPU.
	usart_read_char(USART_0, &RX_Byte);


	RX_Buffer->newest_data = RX_Byte;
	RX_Buffer->buf[RX_Buffer->tail++] = RX_Buffer->newest_data;

}

// Initialize the Xbee transceiver
void Init_Xbee(void) {
	//Setup USART Options
	static const usart_options_t Xbee_usart_options =
	{
		.baudrate     = USART_BAUDRATE,
		.charlength   = 8,
		.paritytype   = USART_NO_PARITY,
		.stopbits     = USART_1_STOPBIT,
		.channelmode  = USART_NORMAL_CHMODE
	};

	// Assign GPIO to USART
	static const gpio_map_t USART_GPIO_MAP =
	{
		{USART_RX_PIN, USART_RX_FUNCTION},
		{USART_TX_PIN, USART_TX_FUNCTION}
	};
	gpio_enable_module(USART_GPIO_MAP,
	                   sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

	// Initialize USART 0
	usart_init_rs232(USART_0, &Xbee_usart_options, TARGET_PBACLK_FREQ_HZ);

	// Disable all interrupts.   NOTE: Will this interfere with the interrupts established elsewhere?
	Disable_global_interrupt();

	// Initialize interrupt vectors.
	//INTC_init_interrupts();

	// Register the USART interrupt handler to the interrupt controller.
	// usart_int_handler is the interrupt handler to register.
	// EXAMPLE_USART_IRQ is the IRQ of the interrupt handler to register.
	// AVR32_INTC_INT0 is the interrupt priority level to assign to the group of
	// this IRQ.
	// void INTC_register_interrupt(__int_handler handler, unsigned int irq, unsigned int int_level);
	INTC_register_interrupt(&usart_int_handler, USART_IRQ, AVR32_INTC_INT0);

	// Enable USART Rx interrupt.
	USART_0->ier = AVR32_USART_IER_RXRDY_MASK;

	// Enable all interrupts.
	Enable_global_interrupt();
}


void request_data(int room){

	usart_bw_write_char( USART_0, room);

	return;
}

// Transparent mode protocol
// Transmit a message of variable length
// Transmit a message of variable length
void Send_Message_Transparent(int current_temp, int set_pt) {
	usart_bw_write_char( USART_0, UI_current_16bit_Address_MSB);
	usart_bw_write_char( USART_0, current_temp);
	usart_bw_write_char( USART_0, set_pt);
	usart_bw_write_char( USART_0, TX_complete);

}


void Send_Message_Transparent_variable_length(int message_out[], int message_length) {
	int message_index = 0;
	//usart_bw_write_char( USART_0, UI_current_16bit_Address_MSB);
	for (message_index = 0; message_index < message_length; message_length++) {
		usart_bw_write_char( USART_0, message_out[message_index]);
	}
}


