/*******************************************************************************
 * Name:        Module 6 - Task 2: Complete Ski Area Base Meteorological System
 *
 * Filename:    base_station_II.c
 * Author(s):   Rafal Piersiak (4/24/12)
 *
 * path: X:\ESE381\Module6\Mod6Code\base_station_II.c
 *
 * Description: A program that has the ability to read measurements from either a
 *              base station or a remote station using RS232 and XBee wireless
 *              transmission. The results are displayed on the LCD display.
 *
 * Base Station Operation: On reset, the LCD will ask the user to enter a station
 *                         number using the numbered keys on the front panel. Next,
 *                         the user will be asked to a select a measurement using
 *                         the four data keys. If the user wishes to change the
 *                         scale used to display the measurements, the scale key
 *                         may be pressed to change the scale used for the measurement.
 *             
 * Select New Station:     To select a station, press a new number and then select a
 *                         data key.
 *
 * Select New Measurement: To select a new measurement, press a new data key.
 *
 * Select New Scale:       To select a new scale, press the scale key and then select
 *                         a data key.
 *
 * inputs: 
 *    PE0 (RXD0) = receive data
 *        PF3:PF0 = 4-bit DIP switch address
 *        PD4 = Sonar pulse input capture (ICP1)
 *        PD1 (INT1) = Temperature Output
 *        PD2 (INT2) = Relative Humidity Output
 *
 * outputs: 
 *        PE1 (TXD0) = transmit data
 *        PA1 = sends trigger to Sonar sensor
 *        PG2 = sends trigger to Chipcap/VCC for ChipCap
 * 
 * Assignments/Purposes
 *        Macros are given for the RXD0 and TXD0 pins.
 *        Macros are given for the Sonar trigger and input capture pins.
 *        Macros are given for the CCstart, temp, and hum pins.
 *
 * Functions:
 *        USART0_Init = initialize the USART
 *        USART0_Receive = receive data from the terminal
 *        USART0_Transmit = transmit data to the terminal
 *        DataInReceiveBuffer = checks if data is in the USART receive buffer
 *        keypad_fsm = converts a keycode to a key type
 *        transmit_command = transmits a command for a measurement from a remote station
 *        parse_data = parses the received data for completeness and stores it in a char array
 * 
 * Variables:
 *        var16 = holds sonar pulse length
 *        tvalue = holds temperature data
 *        hvalue = holds relative humidity data
 *************************************************************************/

#include <iom128.h>         //file with register addresses for ATmega128
#include <avr_macros.h>     //macro for test, set, clear bit
#include <stdio.h>          //provides printf
#include <intrinsics.h>     //provides enable interrupt command
#include <stdbool.h>        //provides boolean type

// Declarations for functions in files lcd_ext.c and lcd_dog_iar_driver.asm
#include "lcd.h"

/********************************FSM CODE**************************************/
// states in the FSM
typedef enum{disp_tem, disp_hum, disp_dep, disp_all, disp_stn, disp_wind} state ;

// keys on the keypad
// eol is a psuedo key used as a default in the state table
typedef enum {keynum, tem, hum, dep, all, scale, eol, wind} key ;

// functions to implement the task(s) associated with a state transition
// all functions must have the same signature (parameters and return type)

extern void set_stn_fn();   //display the station
extern void set_tem_fn();   //display temperature
extern void set_hum_fn();   //display humidity
extern void set_dep_fn();   //display snow depth
extern void set_wind_fn();  //display wind
extern void set_all_fn();   //display all measurements
extern void set_scale_fn(); //display the measurement scale
extern void error_fn();     //generate error beep
extern void null_fn();      //do nothing

// global variables for measured values and settings

// global variable for present state of FSM
state present_state;

// declare type task_fn_ptr as a pointer to a task function
typedef void (* task_fn_ptr) ();

// A structure transition represents one row of a state transition table
// it has a field for the input key value, the next state, and a pointer
// to the task function.
// Declare type transition as a structure with fields for input key value,
// next state value, and pointer to the task function

typedef struct {
  key keyval;
  state next_state;
  task_fn_ptr tf_ptr;
} transition;

// The state transition table consists of an array of arrays of structures.
// Each array of structures corresponds to a particular present state value.
// Each structure in such an array corresponds to a transition from the
// state for a given input value and the task function associated with the
// transition. Accordingly, each structure in an array has fields
// corresponding to an input value, the next state for this input value,
// and a pointer to the function task for this input value.
// The last transition structure in each array has a keyval field value
// of eol. This is a default value meaning any key value that has not
// been explcitly listed in a previous transition structure in the array.

const transition disp_tem_transitions [] =  // subtable for disp_tem state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_tem,       set_scale_fn},
    {eol,       disp_tem,       error_fn}
};
    
const transition disp_hum_transitions [] =    // subtable for disp_hum state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_hum,       set_scale_fn},
    {eol,       disp_hum,       error_fn}
};

const transition disp_dep_transitions [] =    // subtable for disp_dep state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_dep,       set_scale_fn},
    {eol,       disp_dep,       error_fn}
};

const transition disp_wind_transitions [] =    // subtable for disp_wind state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_dep,       set_scale_fn},
    {eol,       disp_dep,       error_fn}
};

const transition disp_all_transitions [] =    // subtable for disp_all state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_all,       set_scale_fn},
    {eol,       disp_all,       error_fn}
};
    
const transition set_stn_transitions [] =    // subtable for set_stn state
{
//  INPUT       NEXT_STATE      TASK
    {keynum,    disp_stn,       set_stn_fn},
    {tem,       disp_tem,       set_tem_fn},
    {hum,       disp_hum,       set_hum_fn},
    {dep,       disp_dep,       set_dep_fn},
    {wind,      disp_wind,      set_wind_fn},
    {all,       disp_all,       set_all_fn},
    {scale,     disp_stn,       error_fn},
    {eol,       disp_stn,       error_fn}
};    


// The outer array is an array of pointers to an array of transition
// structures for each present state.

const transition * ps_transitions_ptr[6] =
{
  disp_tem_transitions,    // 
  disp_hum_transitions,
  disp_dep_transitions,
  disp_wind_transitions,
  disp_all_transitions,
  set_stn_transitions
};


// The finite state machine is implemented as a fumction with parameters
// corresponding to the present state and key value that has been input.

void fsm (state ps, key keyval)
{
// Search the array of transition structures corresponding to the
// present state for the transition structure that has has keyvalue
// field value that is equal to current input key value or equal
// to eol.
  
int i;
for (i = 0; (ps_transitions_ptr[ps][i].keyval != keyval)
     && (ps_transitions_ptr[ps][i].keyval != eol); i++);

// i now has the value of the index of the transition structure
// corresponding to the current intput key value.

// Invoke the task function pointed to by the task function pointer
// of the current transition structure.

ps_transitions_ptr[ps][i].tf_ptr();

// Make present state equal to the next state value of the current
// transition structure.

present_state = ps_transitions_ptr[ps][i].next_state;

}//end fsm

/*******************************END FSM CODE***********************************/


/*******************************Main Program***********************************/

//Pin Definitions
#define rx0   0  //PE0(RXD0)
#define tx0   1  //PE1(TXD0)

/********EZ2 Sonar*************************/
#define button   0  //PA0
#define trigger  1  //PA1
#define oneout   4  //PD4 Input Capture ICP1
/********EZ2 Sonar*************************/

/**********ChipCap*************************/
#define CCstart   2  //PG2
#define tempin    1  //PD1
#define humpin    2  //PD2
/**********ChipCap*************************/

/* global variables */
key keypressed;         //holds value of key that was pressed from keypad
extern char keycode;    //holds keycode of key pressed
char buttonpressed;     //detects a keypress

extern unsigned short int tvalue, hvalue;
extern unsigned long int var16;
extern char which_scale, which_mode, which_station;
char countkeys = 0;
extern char Rxreceive[] = {"T0000H000D000"};
extern unsigned long int wind_direction = 0;
extern unsigned long int windspeed = 0;
extern bool windspeed_flag = false;
extern bool one_hertz_complete = false;

char address;

/* flags */
extern bool sonar_data_ready;
extern bool chipcap_data_ready;
extern bool command_success = false;
extern bool time_out = false;
  
/* function prototypes */
void keypad_fsm(void);  //parses keycode from keypad isr and outputs a state
void refresh_all_data(void); //refreshes all data, while in all data mode
void refresh_temp(void); //refreshes temperature
void refresh_humidity(void); //refreshes humidity
void refresh_depth(void); //refreshes depth
void refresh_wind(void); //refreshes depth

void init_adc_wind_dir(void);
void read_adc(void);
void init_windspeed(void);


/**************************************************************************/
#define FOSC 16000000               //clock speed
#define BAUD 9600                   //baud rate
#define MYUBRR FOSC/16/BAUD-1       //calculated baud value

/* UART Buffer Defines */
#define USART_RX_BUFFER_SIZE 128     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_TX_BUFFER_SIZE 128     /* 2,4,8,16,32,64,128 or 256 bytes */
#define USART_RX_BUFFER_MASK ( USART_RX_BUFFER_SIZE - 1 )
#define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 )
#if ( USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK )
    #error RX buffer size is not a power of 2
#endif
#if ( USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK )
    #error TX buffer size is not a power of 2
#endif

/* Static Variables */
static unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];
static volatile unsigned char USART_RxHead;
static volatile unsigned char USART_RxTail;
static unsigned char USART_TxBuf[USART_TX_BUFFER_SIZE];
static volatile unsigned char USART_TxHead;
static volatile unsigned char USART_TxTail;

/* Prototypes */
void USART0_Init( unsigned int baudrate );

extern unsigned char USART0_Receive(void);
extern void USART0_Transmit(unsigned char data);
extern unsigned char DataInReceiveBuffer(void);
extern void parse_data(void);
extern void transmit_command(void);

/****************************RS232 Configuration*******************************/



void main(void)
{
  
/*****************************Initialize RS232*********************************/ 
  //configure Port E
  DDRE = 0x01;     //PE0(RXD0) = in, PE1(TXD0) = out
  PORTE = 0xFF;    //PE1-PE0 pullups enabled (0b00000011)
  
  //configure Port F (address port)
  DDRF = 0x00;     //PF3-PF0 are inputs
  PORTF = 0x0F;    //PF3-PE0 pullups enabled (0b00001111)
  
  USART0_Init(103);   //Set the baudrate to 9,600 bps using a 16MHz crystal
                      //UBRR = 103.167 (Error of 0.16%)
                      //Can use MYUBRR in place of 103, which is calculated above
/*****************************Initialize RS232*********************************/ 
  

/***************************Configure Keypad***********************************/
  //configure PortD for INT0 interrupt
  DDRD |= 0x00;           //INT0 input
  PORTD |= 0x01;          //INT0 pullup enabled
  
  //configure PortC for keypad, initial configuration
  DDRC |= 0xF0;           //high nibble outputs, low nibble inputs 
  PORTC |= 0x0F;
  
  //configure PortB for DOG LCD module's SPI interface
  DDRB |= 0xFF;           //set PortB to outputs
  SETBIT(PORTB, 0);       //unassert slave select
    
  MCUCR = 0x30;           //sleep enabled for power down mode.
  EIMSK = 0x01;           //enable interrupt INT0. 
  EICRA |= (1<<ISC01|0<<ISC00);   //negative edge, 1<<ISC01|0<<ISC00
/***************************Configure Keypad***********************************/
  
  
/**********************************EZ2 Sonar***********************************/
  //configure Port A
  DDRA |= 0x02;     //PA1 output
  PORTA &= 0xFF;    //PA1 off (0b00000000)
  
  //configure PD4(ICP1) port
  DDRD |= 0x00;     //PD4 (ICP1) input (0b00000000)
  PORTD |= 0x10;    //PD4 (ICP1) pullup enabled (0b00010000)

  //set up input capture registers
  TCNT1 = 0x0000;     //clear counter
  TCCR1B = (0<<ICNC1|1<<ICES1|0<<CS12|1<<CS11|1<<CS10); //set 64 prescaler
                                                        //ICES1=1, rising edge
  TIFR = 1<<ICF1;     //clear ICF1, clear pending interrupts
  TIMSK = 1<<TICIE1;  //enable Timer1 capture event interrupt
/**********************************EZ2 Sonar***********************************/

  
/**********************************ChipCap*************************************/
  //configure PG2
  DDRG = 0x04;     //PG2 output (0b00000100)
  PORTG = 0x00;    //PG2 off (0b00000000)
  
  //configure Port D
  DDRD |= 0x00;     //PD1(INT1), PD2(INT2) input (0b00000000)
  PORTD |= 0x06;    //PD1(INT1), PD2(INT2) pullup enabled (0b00000110)

  //set up INT1, INT2, falling edge initially
  SETBIT(EIMSK,INT1);            //enable interrupt INT1 (0b00000010)
  SETBIT(EIMSK,INT2);            //enable interrupt INT2 (0b00000100)
  EICRA |= (1<<ISC21|0<<ISC20|1<<ISC11|0<<ISC10);  //interrupt detects falling edge (1,0)
/**********************************ChipCap*************************************/
  
  init_adc_wind_dir();    //initialize registers to read wind direction
  
  init_windspeed();       //initialize registers to read wind speed
  
  init_lcd_dog();         //call to asm subroutine init_dsp()

  clear_dsp();            //call to C function clear_dsp()
  printf("Select Station  ");
  printf("Select Data     ");
  update_lcd_dog();       //call to C function update_lcd_dog()
  
  present_state = disp_stn;   //set present state
  
  __enable_interrupt();   //enable global interrupts

while(1)
{
  address = PINF;     //read DIP switch
  address &= 0x0F;    //mask first 4 bits
  address += 0x30;    //convert to ASCII
    
  if(buttonpressed == 1)              //if a key is pressed, run fsm
  {
    keypad_fsm();                     //parse key, convert to state
    fsm(present_state, keypressed);   //run fsm
    buttonpressed = 0;                //key is not pressed
  }
  else
  {
    
    SETBIT(PORTA,trigger);            //set sonar trigger
    while(sonar_data_ready == false); //wait here until sonar reading is complete
    sonar_data_ready = false;         //reset sonar flag for next reading

    SETBIT(PORTG, CCstart);             //enable ChipCap and begin conversion
    while(chipcap_data_ready == false); //wait here until chipcap reading is complete
    chipcap_data_ready = false;         //reset chipcap flag for next reading
    
    read_adc();                         //read adc to get wind direction
    
    if(which_mode == 4)               //if refresh all temps, then
    {
      refresh_all_data(); //display all data, when in all measurements mode
    }
    if(which_mode == 1)               //if refresh temp, then
    {
      refresh_temp(); //display all data
    }
    if(which_mode == 2)               //if refresh humidity, then
    {
      refresh_humidity(); //display all data
    }
    if(which_mode == 3)               //if refresh depth, then
    {
      refresh_depth(); //display all data
    }
    if(which_mode == 5)               //if refresh wind, then
    {
      refresh_wind(); //display wind
    }
    
  }
  
}//while
  
}//main




//******************************************************************************
// Function             : void keypad_fsm(void)
// Date and version     : 04/11/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function parses the variable "keycode" used in the keypad ISR and
// converts it to a state that is placed into "keypressed".
//
//******************************************************************************
void keypad_fsm(void)
{ 
  switch(keycode)
  {
    case '0': keypressed = keynum; break;
    case '1': keypressed = keynum; break;
    case '2': keypressed = keynum; break;
    case '3': keypressed = keynum; break;
    case '4': keypressed = keynum; break;
    case '5': keypressed = keynum; break;
    case '6': keypressed = keynum; break;
    case '7': keypressed = keynum; break;
    case '8': keypressed = keynum; break;
    case '9': keypressed = keynum; break;
    case 'A': keypressed = tem;    break;
    case 'B': keypressed = hum;    break;
    case 'C': keypressed = dep;    break;
    case 'D': keypressed = all;    break;
    case 'E': keypressed = scale;  break;
    case 'F': keypressed = wind;   break;  
    default:                       break;
  }
  return;
}//end keypad_fsm





//******************************************************************************
// Function             : void refresh_all_data(void)
// Date and version     : 04/18/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function reads the measurements values, performs math, and refreshes the
// display with new values on the LCD.
//
//******************************************************************************
void refresh_all_data(void)
{
  if(which_station == '0')  //if not reading base station, transmit command
  {
  
/****************************CONVERT SNOW DEPTH********************************/
  unsigned short int tensd, onesd;
  
  var16 = var16 * 40;   //multiply result by (1/16MHz)*64 prescaler = 4uS
  var16 = var16 / 58;   //divide by 58 to get result in cm
  
  if(which_scale == 1) //convert to inches
  { //(40/58)*(39/100)    1cm = 0.39in
    var16 = var16 * 39;   //multiply result by 39
    var16 = var16 / 100;  //divide by 100 to get result in inches
  }  
  
  tensd = onesd = 0;        //clear digits for conversion  
    
  while(var16 >= 100)       //find first digit of snow depth
  {
    var16 -= 100;
    tensd++;
  }
  while(var16 >= 10)        //find second digit of snow depth
  {
    var16 -= 10;
    onesd++;
  }                        //last digit of temperature is var16

/************************END CONVERT SNOW DEPTH********************************/
  

/*********************CONVERT TEMPERATURE/HUMIDITY*****************************/
  static unsigned long int tvalue_ext = 0; //set long tvalue for arithmatic
  unsigned short int hundredst, tenst, onest, tensh, onesh;
  
  tvalue_ext = tvalue;              //transfer short t to long t
  tvalue_ext = tvalue_ext * 2000;   //multiply by 200
  tvalue_ext = tvalue_ext / 1023;   //divide by 1023
  tvalue_ext = tvalue_ext - 500;    //subtract 50
      
  if(which_scale == 1)              //convert to fahrenheit
  {
    tvalue_ext = tvalue_ext * 9;
    tvalue_ext = tvalue_ext / 5;
    tvalue_ext = tvalue_ext + 320;
  }
      
  hvalue = hvalue * 100;            //multiply by 100
  hvalue = hvalue / 255;            //divide by 255
      
  hundredst = tenst = onest = 0;  //clear digits for conversion
      
    while(tvalue_ext >= 1000) //find first digit of temperature
    {
      tvalue_ext -= 1000;
      hundredst++;
    }
    while(tvalue_ext >= 100)  //find second digit of temperature
    {
      tvalue_ext -= 100;
      tenst++;
    }
    while(tvalue_ext >= 10)   //find third digit of temperature
    {
      tvalue_ext -= 10;
      onest++;
    }                         //last digit of temperature is tvalue_ext
    
  //hundredst |= 0x30;
  //tenst |= 0x30;
  //onest |= 0x30;
  //tvalue_ext |= 0x30;
    
 tensh = onesh = 0;                  //clear digits for conversion  
    
    while(hvalue >= 100)             //find first digit of humidity
    {
      hvalue -= 100;
      tensh++;
    }
    while(hvalue >= 10)              //find second digit of humidity
    {
      hvalue -= 10;
      onesh++;
    }                                //last digit of humidity is hvalue
    
  //tensh |= 0x30;
  //onesh |= 0x30;
  //hvalue |= 0x30;
  
/*********************END CONVERT TEMPERATURE/HUMIDITY*************************/
  
  which_mode = 4;     //set which_mode to 4, display all measurements
  
  if(which_scale == 0)  //display in Celsius and centimeters
  {
    clear_dsp();      //call to C function clear_dsp()
    printf("Temp: %hd%hd%hd.%ld%cC   ", hundredst, tenst, onest, tvalue_ext, 0xDF); //temp
    printf("Hum:  %hd%hd%hd%%      ", tensh, onesh, hvalue);                        //hum
    printf("Snow: %hd%hd.%ldcm", tensd, onesd, var16);                          //snow
  }

  if(which_scale == 1)  //display in Fahrenheit and inches
  {
    clear_dsp();      //call to C function clear_dsp()
    printf("Temp: %hd%hd%hd.%ld%cF   ", hundredst, tenst, onest, tvalue_ext, 0xDF); //temp
    printf("Hum:  %hd%hd%hd%%      ", tensh, onesh, hvalue);                        //hum
    printf("Snow: %hd%hd.%ldin", tensd, onesd, var16);                          //snow
  }
  
  update_lcd_dog();         //call to C function update_lcd_dog()
  
  }//end display of base station data
  
}//end refresh_all_data
//******************************************************************************
//                           END of refresh_all_data                           
//******************************************************************************




//******************************************************************************
// Function             : void refresh_temp(void)
// Date and version     : 04/18/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function reads the measurements values, performs math, and refreshes the
// display with new temperature on the LCD.
//
//******************************************************************************
void refresh_temp(void)
{
  static unsigned long int tvalue_ext = 0; //set long tvalue for arithmatic
  unsigned short int hundredst, tenst, onest;
  
  if(which_station == '0')  //if not reading base station, transmit command
  {
      tvalue_ext = tvalue;              //transfer short t to long t
      tvalue_ext = tvalue_ext * 2000;   //multiply by 200
      tvalue_ext = tvalue_ext / 1023;   //divide by 1023
      tvalue_ext = tvalue_ext - 500;    //subtract 50
      
      if(which_scale == 1)              //convert to fahrenheit
      {
        tvalue_ext = tvalue_ext * 9;
        tvalue_ext = tvalue_ext / 5;
        tvalue_ext = tvalue_ext + 320;
      }
      
      hundredst = tenst = onest = 0;  //clear digits for conversion
      
    while(tvalue_ext >= 1000) //find first digit of temperature
    {
      tvalue_ext -= 1000;
      hundredst++;
    }
    while(tvalue_ext >= 100)  //find second digit of temperature
    {
      tvalue_ext -= 100;
      tenst++;
    }
    while(tvalue_ext >= 10)   //find third digit of temperature
    {
      tvalue_ext -= 10;
      onest++;
    }                         //last digit of temperature is tvalue_ext
    
    //hundredst |= 0x30;
    //tenst |= 0x30;
    //onest |= 0x30;
    //tvalue_ext |= 0x30;
  
  which_mode = 1;             //set which_mode to 1, display temperature

  if(which_scale == 0)  //display in Celsius
  {
    clear_dsp();                                    //call to C function clear_dsp()
    printf("Station %c       ", which_station);     //print "Station #"
    printf("Temperature     ");                     //print "temperature"
    printf("%hd%hd%hd.%ld%cCelsius", hundredst, tenst, onest, tvalue_ext, 0xDF); //print temp value in C
  }

  if(which_scale == 1)  //display in Fahrenheit
  {
    clear_dsp();                                    //call to C function clear_dsp()
    printf("Station %c       ", which_station);     //print "Station #"
    printf("Temperature     ");                     //print "temperature"
    printf("%hd%hd%hd.%ld%cFahrenheit", hundredst, tenst, onest, tvalue_ext, 0xDF); //print temp value in F
  }
  
  /*if(time_out == true)                //if remote timed out, print statement
  {
    clear_dsp();                      //call to C function clear_dsp()
    printf("Remote Station  ");       //print "Remote Station"
    printf("Time Out  ");             //print "Time Out"
  }*/
  
  update_lcd_dog();       //call to C function update_lcd_dog()
  
  }//end display of base station data

}//end refresh_temp






//******************************************************************************
// Function             : void refresh_humidity(void)
// Date and version     : 04/18/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function reads the measurements values, performs math, and refreshes the
// display with new humidity on the LCD.
//
//******************************************************************************
void refresh_humidity(void)
{
  if(which_station == '0')  //if not reading base station, transmit command
  {
    
  unsigned short int tensh, onesh;
  
  if(command_success == true)     //remote data received and parsed successfully
  {
    //Rxreceive[] = {"T0000H000D000"};
    tensh = Rxreceive[6] * 100;         //store first digit of hum in Rxreceive
    onesh = Rxreceive[7] * 10;          //store second digit of hum in Rxreceive
    hvalue = Rxreceive[8];              //store third digit of hum in Rxreceive
    
    hvalue = tensh + onesh + hvalue;    //convert digits to whole number
    
  }//convert remote data to one number
      
      hvalue = hvalue * 100;            //multiply by 100
      hvalue = hvalue / 255;            //divide by 255
    
    tensh = onesh = 0;                  //clear digits for conversion  
    
    while(hvalue >= 100)                //find first digit of humidity
    {
      hvalue -= 100;
      tensh++;
    }
    while(hvalue >= 10)                 //find second digit of humidity
    {
      hvalue -= 10;
      onesh++;
    }                                   //last digit of humidity is hvalue
    
    //tensh |= 0x30;
    //onesh |= 0x30;
    //hvalue |= 0x30;
  
  which_mode = 2;                       //set which_mode to 2, display humidity

  //display humidity in precent
    clear_dsp();                                    //call to C function clear_dsp()
    printf("Station %c       ", which_station);     //print "Station #"
    printf("Humidity        ");                     //print "Humidity"
    printf("%hd%hd%hd%%", tensh, onesh, hvalue);    //print humidity value in %
  
  /*if(time_out == true)
  { 
    clear_dsp();                      //call to C function clear_dsp()
    printf("Remote Station  ");       //print "Remote Station"
    printf("Time Out  ");             //print "Time Out"
  }*/
  
  update_lcd_dog();         //call to C function update_lcd_dog()
  
  }//end display of base station data

}//end refresh_humidity




//******************************************************************************
// Function             : void refresh_depth(void)
// Date and version     : 04/18/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function reads the measurements values, performs math, and refreshes the
// display with new snow depth on the LCD.
//
//******************************************************************************
void refresh_depth(void)
{ 
  if(which_station == '0')  //if not reading base station, transmit command
  {
  
  unsigned short int tensd, onesd;
  
  var16 = var16 * 40;   //multiply result by (1/16MHz)*64 prescaler = 4uS
  var16 = var16 / 58;   //divide by 58 to get result in cm
  
  if(which_scale == 1) //convert to inches
  { //(40/58)*(39/100)    1cm = 0.39in
    var16 = var16 * 39;   //multiply result by 39
    var16 = var16 / 100;  //divide by 100 to get result in inches
  }  
  
  tensd = onesd = 0;        //clear digits for conversion  
    
  while(var16 >= 100)       //find first digit of snow depth
  {
    var16 -= 100;
    tensd++;
  }
  while(var16 >= 10)        //find second digit of snow depth
  {
    var16 -= 10;
    onesd++;
  }                        //last digit of snow depth is var16
    
  //tensd |= 0x30;
  //onesd |= 0x30;
  //var16 |= 0x30;
  
  which_mode = 3;          //set which_mode to 3, display snow depth

  if(which_scale == 0)  //display in centimeters
  {
    clear_dsp();                                    //call to C function clear_dsp()
    printf("Station %c       ", which_station);     //print "Station #"
    printf("Snow Depth      ");                     //print "Snow Depth"
    printf("%hd%hd.%ld centimeters", tensd, onesd, var16);  //print snow depth value in cm
  }

  if(which_scale == 1)  //display in inches
  {
    clear_dsp();                                    //call to C function clear_dsp()
    printf("Station %c       ", which_station);     //print "Station #"
    printf("Snow Depth      ");                     //print "Snow Depth"
    printf("%hd%hd.%ld inches", tensd, onesd, var16); //print snow depth value in in
  }
  
  /*if(time_out == true)
  {
    clear_dsp();                      //call to C function clear_dsp()
    printf("Remote Station  ");       //print "Remote Station"
    printf("Time Out  ");             //print "Time Out"
  }*/
  
  update_lcd_dog();       //call to C function update_lcd_dog()
  
  }//end display of base station data
 
}//end refresh_depth


//******************************************************************************
// Function             : void refresh_wind(void)
// Date and version     : 05/1/2012, version 1.0
// Target MCU           : ATmega128
// Author               : Rafal Piersiak
// DESCRIPTION
// This function reads the measurement values, performs math, and refreshes the
// display with new wind direction on the LCD.
//
//******************************************************************************
void refresh_wind(void)
{ 
  if(/*which_station == '0' & */ one_hertz_complete == true)  //only refresh if selected station is '0'
  {
  
  unsigned short int tenswd, oneswd;
  
  wind_direction *= 3519;    //multiply by degrees/bit ratio
  wind_direction /= 10000;   //divide by 10000 to get result before decimal
  
  tenswd = oneswd = 0;      //clear digits for conversion  
    
  while(wind_direction >= 100)   //find first digit of wind direction
  {
    wind_direction -= 100;
    tenswd++;
  }
  while(wind_direction >= 10)   //find second digit of wind direction
  {
    wind_direction -= 10;
    oneswd++;
  }                        //last digit of wind direction is windspeed
  
  
  unsigned short int tensws, onesws;
  
  windspeed *= 25;         //multiply by degrees/bit ratio
  windspeed /= 2;         //multiply by degrees/bit ratio
  
  tensws = onesws = 0;      //clear digits for conversion  
    
  while(windspeed >= 100)   //find first digit of wind direction
  {
    windspeed -= 100;
    tensws++;
  }
  while(windspeed >= 10)   //find second digit of wind direction
  {
    windspeed -= 10;
    onesws++;
  }                        //last digit of wind direction is windspeed
  

  which_mode = 5;          //set which_mode to 5, display windspeed

  clear_dsp();                                //call to C function clear_dsp()
  printf("Station %c       ", which_station); //print "Station #"
  printf("Wind Dir: %hd%hd%ld%c  ", tenswd, oneswd, wind_direction, 0xDF);  //print wind_direction value in degrees              
  printf("WindSpd: %hd%hd.%ldmph", tensws, onesws, windspeed);  
  
  update_lcd_dog();       //call to C function update_lcd_dog()
  
  one_hertz_complete = false;
  windspeed = 0;
  SETBIT(EIMSK, INT3);
  
  }//end display of base station data
 
}//end refresh_wind


















/*******************************************************************************
 * Name:        transmit_command
 * Author(s):   Rafal Piersiak (4/18/12)
 *
 * Description: Transmit command to remote station when operator presses a remote
 *              station key. Once the proper data is received, the system displays 
 *              the measurands to the LCD.
 ******************************************************************************/
void transmit_command(void)
{
    //U
    USART0_Transmit('U');
    //x
    //keycode &= 0x0F; //mask 4 LSB's, make non-ascii
    USART0_Transmit(which_station);
    //space
    USART0_Transmit(0x20); //space character
    //M
    USART0_Transmit('M');
    //<CR>
    USART0_Transmit(0x0D); //carriage return
    //<LF>
    USART0_Transmit(0x0A); //line feed

}//end transmit_command

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



/*******************************************************************************
 * Name:        parse_data
 * Author(s):   Rafal Piersiak (4/18/12)
 *
 * Description: Checks whether proper data sequence was sent. If so, a flag
 *              is set to indicate that a correct format was sent.
 ******************************************************************************/
void parse_data(void) //Ux Tttt.t Hhhh Ddd.d <CR><LF>
{
    if(USART_RxBuf[USART_RxHead-22 & USART_RX_BUFFER_MASK] == 'U') //position 22
    {
      if(USART_RxBuf[USART_RxHead-21 & USART_RX_BUFFER_MASK] == which_station) //position 21
      {
        if(USART_RxBuf[USART_RxHead-20 & USART_RX_BUFFER_MASK] == 0x20) //position 20
        {     
          if(USART_RxBuf[USART_RxHead-19 & USART_RX_BUFFER_MASK] == 'T') //position 19
          {           
            if(USART_RxBuf[USART_RxHead-12 & USART_RX_BUFFER_MASK] == 'H') //position 12
            {             
              if(USART_RxBuf[USART_RxHead-7 & USART_RX_BUFFER_MASK] == 'D') //position 7
              {
                if(USART_RxBuf[USART_RxHead-1 & USART_RX_BUFFER_MASK] == 0x0D) //position 1 //carriage return
                {
                  if(USART_RxBuf[USART_RxHead & USART_RX_BUFFER_MASK] == 0x0A ) //line feed
                  {
                    USART_RxBuf[USART_RxHead & USART_RX_BUFFER_MASK] = 0;     //clear line feed for new command
                    USART_RxBuf[USART_RxHead-1 & USART_RX_BUFFER_MASK] = 0;   //clear carriage return for new command
                    
                    //Rxreceive[] = {"T0000H000D000"};
                    Rxreceive[12] = (USART_RxBuf[USART_RxHead-3 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[11] = (USART_RxBuf[USART_RxHead-5 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[10] = (USART_RxBuf[USART_RxHead-6 & USART_RX_BUFFER_MASK]) & 0x0F;//D0
                    Rxreceive[8] = (USART_RxBuf[USART_RxHead-9 & USART_RX_BUFFER_MASK])  & 0x0F;// 0
                    Rxreceive[7] = (USART_RxBuf[USART_RxHead-10 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[6] = (USART_RxBuf[USART_RxHead-11 & USART_RX_BUFFER_MASK]) & 0x0F;//H0
                    Rxreceive[4] = (USART_RxBuf[USART_RxHead-14 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[3] = (USART_RxBuf[USART_RxHead-16 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[2] = (USART_RxBuf[USART_RxHead-17 & USART_RX_BUFFER_MASK]) & 0x0F;// 0
                    Rxreceive[1] = (USART_RxBuf[USART_RxHead-18 & USART_RX_BUFFER_MASK]) & 0x0F;//T0
                    USART_RxHead = 0;         //command read, clear RxBuf index
                    USART_RxTail = 0;         //command read, clear RxBuf index
                    command_success = true;
                  }//\n line feed (10) 
                }//\r carriage return (13) 
              }//'D'            
            }//'H'          
          }//'T'        
        }// ' '
      }//keycode
    }//'U'
    
}//end parse_data
/***************************Parse Command**************************************/







/* Initialize USART */
void USART0_Init( unsigned int baudrate )
{
    unsigned char x;

    /* Set the baud rate */
    UBRR0H = (unsigned char) (baudrate>>8);                  
    UBRR0L = (unsigned char) baudrate;
    
    /* Enable UART receiver complete, receiver, and transmitter interrupt */
    UCSR0B = ( ( 1 << RXCIE0 ) | ( 1 << RXEN0 ) | ( 1 << TXEN0 ) ); 
    
    /* Set frame format: 8bit data 1stop 0parity*/
    UCSR0C = (0<<UMSEL0)|(0<<USBS0)|(0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00);
        //UMSEL0 = '0' Asynchronous, USBS0 = '0' One stop bit, UCSZ = "011" 8bit data
        //can use UPMn1:0 to control parity, 00 = disabled
    
    /* Flush receive buffer */
    x = 0;              

    USART_RxTail = x;
    USART_RxHead = x;
    USART_TxTail = x;
    USART_TxHead = x;
}

/* Interrupt handlers */
#pragma vector=USART0_RXC_vect 
__interrupt void USART0_RX_interrupt( void )
{
    unsigned char data;
    unsigned char tmphead;

    /* Read the received data */
    data = UDR0;                 
    /* Calculate buffer index */
    tmphead = ( USART_RxHead + 1 ) & USART_RX_BUFFER_MASK;
    USART_RxHead = tmphead;      /* Store new index */

    if ( tmphead == USART_RxTail )
    {
        /* ERROR! Receive buffer overflow */
    }
    
    USART_RxBuf[tmphead] = data; /* Store received data in buffer */
}

#pragma vector=USART0_UDRE_vect
__interrupt void USART0_TX_interrupt( void )
{
    unsigned char tmptail;

    /* Check if all data is transmitted */
    if ( USART_TxHead != USART_TxTail )
    {
        /* Calculate buffer index */
        tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;
        USART_TxTail = tmptail;      /* Store new index */
    
        UDR0 = USART_TxBuf[tmptail];  /* Start transmition */
    }
    else
    {
        UCSR0B &= ~(1<<UDRIE0);         /* Disable UDRE interrupt */
    }
}

/* Read and write functions */
unsigned char USART0_Receive( void )
{
    unsigned char tmptail;
    
    while ( USART_RxHead == USART_RxTail );  /* Wait for incomming data */

    tmptail = ( USART_RxTail + 1 ) & USART_RX_BUFFER_MASK;/* Calculate buffer index */
    
    USART_RxTail = tmptail;                /* Store new index */
    
    return USART_RxBuf[tmptail];           /* Return data */
}

void USART0_Transmit( unsigned char data )
{
    unsigned char tmphead;
    /* Calculate buffer index */
    tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; /* Wait for free space in buffer */
    while ( tmphead == USART_TxTail );

    USART_TxBuf[tmphead] = data;           /* Store data in buffer */
    USART_TxHead = tmphead;                /* Store new index */

    UCSR0B |= (1<<UDRIE0);                    /* Enable UDRE interrupt */
}

unsigned char DataInReceiveBuffer( void )
{
    return ( USART_RxHead != USART_RxTail ); /* Return 0 (FALSE) if the receive buffer is empty */
}