//  ****************************************************************************
//   John Barclough's mega32 Usartint program example ported to mega128 by Owen Allison
//   uses both usart0 and usart1

// ******************************************************************************

//ICC-AVR application builder : 20/06/2006 3:57:01 PM
// Target : M128
// Crystal: 4.0000Mhz

#define _AVR          
 //  #define _AVR TO LET SPLINT KNOW THAT HEADERS ARE FOR ICCV7AVR

#include <iom128v.h>
#include <macros.h>
#include <string.h>
//  #include "Usart.h"



// -----------------------------------------------------------------------
// -------------             UART DEFINES       ---------------------------
//  UART0 RX
 #pragma interrupt_handler              UART0_RX_interrupt:iv_USART0_RX  
//  UART1 RX
 #pragma interrupt_handler              UART1_RX_interrupt:iv_USART1_RXC
//  UART0 TX 
 #pragma interrupt_handler              UART0_TX_interrupt:iv_USART0_TX
//  UART1 TX
 #pragma interrupt_handler              UART1_TX_interrupt:iv_USART1_TXC


 
//    DEFINES UART0
#define ENABLE_RX_INT0                  UCSR0B|=BIT(RXCIE0)
#define DISABLE_RX_INT0                 UCSR0B&=~BIT(RXCIE0)
#define ENABLE_TX_INT0                  UCSR0B|=BIT(TXCIE0)
#define DISABLE_TX_INT0                 UCSR0B&=~BIT(TXCIE0)

//    DEFINES UART1
#define ENABLE_RX_INT1                  UCSR1B|=BIT(RXCIE1)
#define DISABLE_RX_INT1                 UCSR1B&=~BIT(RXCIE1)
#define ENABLE_TX_INT1                  UCSR1B|=BIT(TXCIE1)
#define DISABLE_TX_INT1                 UCSR1B&=~BIT(TXCIE1)



/* UART 0  Buffer definitions */
#define BUFFER_SIZE0                    4
#define NUMBER_OF_BUFFERS0              4

/* UART 1  Buffer definitions */
#define BUFFER_SIZE1                    4
#define NUMBER_OF_BUFFERS1              4



/* Global Variables UART 0  */
unsigned char Buffers0[NUMBER_OF_BUFFERS0][BUFFER_SIZE0+1];
volatile unsigned char RxBuffer0 = 0;
volatile unsigned char TxBuffer0;
volatile unsigned char gucFlags0 = 0;
volatile unsigned char RxCount0 = 0;
volatile unsigned char *RxPtr0;
volatile unsigned char *TxPtr0;


/* Global Variables UART 1 */
unsigned char Buffers1[NUMBER_OF_BUFFERS1][BUFFER_SIZE1+1];
volatile unsigned char RxBuffer1 = 0;
volatile unsigned char TxBuffer1;
volatile unsigned char gucFlags1 = 0;
volatile unsigned char RxCount1 = 0;
volatile unsigned char *RxPtr1;
volatile unsigned char *TxPtr1;


//    DEFINES  UART0
#define TEST_MSG_FLAG0                  gucFlags0&BIT(0)
#define SET_MSG_FLAG0                   gucFlags0|=BIT(0)
#define CLEAR_MSG_FLAG0                 gucFlags0&=~BIT(0)

//   DEFINES  UART1
#define TEST_MSG_FLAG1                  gucFlags1&BIT(0)
#define SET_MSG_FLAG1                   gucFlags1|=BIT(0)
#define CLEAR_MSG_FLAG1                 gucFlags1&=~BIT(0)








// -------------  END UART DEFINES ------------------------------------
//----------------------------------------------------------------------

void port_init(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0x00;
 DDRB  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRC  = 0x00;
 PORTD = 0x00;
 DDRD  = 0x00;
 PORTE = 0x00;
 DDRE  = 0x00;
 PORTF = 0x00;
 DDRF  = 0x00;
 PORTG = 0x00;
 DDRG  = 0x00;
}


//************************************************************************************************

// *******************   CRYSTAL  3.8640MHZ   **********
//UART0 initialize
// desired baud rate: 2400
// actual: baud rate:2400 (0.0%)
// char size: 8 bit
// parity: Disabled

void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x06;
 UBRR0L = 0x5F; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0xD8;
}

//********************************************************************************************

//  *******************  CRYSTAL   3.8640MHZ   ************
//UART1 initialize
// desired baud rate: 2400
// actual: baud rate:2400 (0.0%)
// char size: 8 bit
// parity: Disabled

void uart1_init(void)
{
 UCSR1B = 0x00; //disable while setting baud rate
 UCSR1A = 0x00;
 UCSR1C = 0x06;
 UBRR1L = 0x5F; //set baud rate lo
 UBRR1H = 0x00; //set baud rate hi
 UCSR1B = 0xD8;
}



//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 XDIV  = 0x00; //xtal divider
 XMCRA = 0x00; //external memory
 port_init();
 //timer0_init();
// timer1_init();
// timer2_init();
 //timer3_init();
 uart0_init();
 uart1_init();
 

 MCUCR = 0x00;
 EICRA = 0x00; //extended ext ints
 EICRB = 0x00; //extended ext ints
 EIMSK = 0x00;
 TIMSK = 0x00;    //0x45; //timer interrupt sources
 ETIMSK = 0x00;   //0x04; //extended timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}






/* ************************************************************************ *\
  Function: 'SendMessage0()'.

  Action:	1. Set the transmit pointer to the start of the current receive
             buffer and increments the buffer pointer. If the last buffer has
             been used the pointer cycles round to the first buffer.

          2. Send the first character of the message.

          3. If there are more characters to send then enable the transmit
             interrupt.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
  
  Notes:
\* ************************************************************************ */
void SendMessage0(void)
{
  _CLI();                                      // Disable interrupts

  TxPtr0 = Buffers0[RxBuffer0++];                 // Set the transmit pointer to the start of the most recent receive buffer.
  if(RxBuffer0 == NUMBER_OF_BUFFERS0)            // Do we need to cycle around to the first buffer again?
  {
    RxBuffer0 = 0;
  }

  RxPtr0 = Buffers0[RxBuffer0];                   // Set the receive pointer to the start of the next receive buffer.
  RxCount0 = 0;                                 // Clear the receive counter.

  UDR0 = *TxPtr0++;                              // There must be at least one charcter in the buffer.
  if(*TxPtr0 != 0)                              // If the next character isn't NULL then enable the TX interrupt.
  {
    ENABLE_TX_INT0;
  }
  _SEI();                                      // Now enable the global interrupt flag.
}


/* ************************************************************************ *\
  Function: 'SendMessage1()'.

  Action:	1. Set the transmit pointer to the start of the current receive
             buffer and increments the buffer pointer. If the last buffer has
             been used the pointer cycles round to the first buffer.

          2. Send the first character of the message.

          3. If there are more characters to send then enable the transmit
             interrupt.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
  
  Notes:
\* ************************************************************************ */
void SendMessage1(void)
{
  _CLI();                                      // Disable interrupts

  TxPtr1 = Buffers1[RxBuffer1++];                 // Set the transmit pointer to the start of the most recent receive buffer.
  if(RxBuffer1 == NUMBER_OF_BUFFERS1)            // Do we need to cycle around to the first buffer again?
  {
    RxBuffer1 = 0;
  }

  RxPtr1 = Buffers1[RxBuffer1];                   // Set the receive pointer to the start of the next receive buffer.
  RxCount1 = 0;                                 // Clear the receive counter.

  UDR1 = *TxPtr1++;                              // There must be at least one charcter in the buffer.
  if(*TxPtr1 != 0)                              // If the next character isn't NULL then enable the TX interrupt.
  {
    ENABLE_TX_INT1;
  }
  _SEI();                                      // Now enable the global interrupt flag.
}

/* ************************************************************************ *\
  Function: 'UART_RX_interrupt()'.

  Action:	1. Places the received character in the buffer.

          2. Check if if the received character is <CR> or if the buffer is full.
             If so then terminate the buffer and set the message flag.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
 
  Notes:
\* ************************************************************************ */
 void UART1_RX_interrupt(void)

 
{
  unsigned char Temp1;

  Temp1 = UDR1;                                  // Reading the data register clears the interrupt.
  *RxPtr1++ = Temp1;                             // Save the data in the buffer and ...
  RxCount1++;                                   // ... increment the count.

  if((Temp1==0x0d)||(RxCount1==BUFFER_SIZE1))     // Is it a <CR> or is the buffer full?
  {
    *RxPtr1 = 0;                                // Terminate the message and ...
    SET_MSG_FLAG1;                              // ... tell 'main()' that the buffer is ready.
  }
}
 
 
  
 // Notes:
/* ************************************************************************ */




void UART0_RX_interrupt(void)
{
  unsigned char Temp0;

  Temp0 = UDR0;                                  // Reading the data register clears the interrupt.
  *RxPtr0++ = Temp0;                             // Save the data in the buffer and ...
  RxCount0++;                                   // ... increment the count.

  if((Temp0==0x0d)||(RxCount0==BUFFER_SIZE0))     // Is it a <CR> or is the buffer full?
  {
    *RxPtr0 = 0;                                // Terminate the message and ...
    SET_MSG_FLAG0;                              // ... tell 'main()' that the buffer is ready.
  }
}


/* ************************************************************************ *\
  Function: 'UART0_TX_interrupt()'.

  Action:	1. Send the next character and increment the pointer.
  
          2. Check that there are more characters to go and if not disable the
             transmit interrupt as it is not needed until the current receive
             buffer is full.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
  
  Notes:
\* ************************************************************************ */
void UART0_TX_interrupt(void)
{
  UDR0 = *TxPtr0++;                              // Writing the data register clears the interrupt.
  if(*TxPtr0 == 0)                              // Is it the end of the message?
  {
    DISABLE_TX_INT0;                            // Yes, so no more to send.
  }
}



/* ************************************************************************ *\
  Function: 'UART1_TX_interrupt()'.

  Action:	1. Send the next character and increment the pointer.
  
          2. Check that there are more characters to go and if not disable the
             transmit interrupt as it is not needed until the current receive
             buffer is full.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
  
  Notes:
\* ************************************************************************ */
void UART1_TX_interrupt(void)
{
  UDR1 = *TxPtr1++;                              // Writing the data register clears the interrupt.
  if(*TxPtr1 == 0)                              // Is it the end of the message?
  {
    DISABLE_TX_INT1;                            // Yes, so no more to send.
  }
}



/* ************************************************************************ *\
  Function: 'main()'.

  Action:	1. Sets up the device.

          2. Monitor the message flag. If this flag goes true it is cleared
             and the current message sent.

  Inputs: None
  Ouputs: None
  
  Author:	John Baraclough
  Date:		2005-10-06
  
  Notes:
\* ************************************************************************ */







//
void main(void)
{
 init_devices();
 //insert your functional code here...
 
 
  RxPtr0 = Buffers0[RxBuffer0];                   // Set the receive pointer uart0 to the start of the first receive buffer.

  RxPtr1 = Buffers1[RxBuffer1];                   // Set the receive pointer uart1 to the start of the first receive buffer.
  
	 _SEI();                                      // Enable interrupts.

	 
 while(1)
 {
	  if(TEST_MSG_FLAG0)
    {
      CLEAR_MSG_FLAG0;

	  TxBuffer0 =5;
	  
      SendMessage0();                           // Send the current recieve buffer and switch buffers.
    }  // end of 'if(TEST_MSG_FLAG0)'.
	  

  if(TEST_MSG_FLAG1)
    {
      CLEAR_MSG_FLAG1;

	  TxBuffer1 =5;
	  
      SendMessage1();                           // Send the current recieve buffer and switch buffers.
    }  // end of 'if(TEST_MSG_FLAG1)'.
	  //1 end of 'while(1)'. 
}
}
