/******************************************************************************
 A Hewlett-Packard Software Product
 Copyright Hewlett-Packard Co. 1992

 All Rights Reserved. Reproduction, adaptation, or translation without prior
 written  permission  is prohibited, except as allowed under copyright laws.
 ******************************************************************************/
/******************************************************************************
 * Function: update_system()
 *
 * Description: update_system() is the service routine which
 *        alters the state of the entire environmental control system.
 *        It calls several functions, each of which have a particular part
 *        of the system which they alter or update.  The following action
 *        is taken when this routine is called.
 *
 *   1) New temperature and humidity targets are read in.
 *   2) New environment conditions are read.
 *   3) The func_needed is modified based on the actual state of the
 *           environment versus the desired state to indicate what needs to
 *           happen in the current environment.
 *   4) func_needed is used to derive hdwr_encode (the 16-bit quantity that
 *           indicates what the hardware needs to do to achieve the correct
 *           change in the environment).
 *   5) The environment conditions are saved for posterity.
 *          THERE IS A BUG IN THIS ROUTINE (ON PURPOSE!!!)
 *
 * Parameters: None.
 *
 * References:
 *      get_targets()
 *      read_conditions()
 *      save_points()
 *      set_outputs()
 *      update_system()
 *      write_hdwr()
 *
 *****************************************************************************/
#include  "updt_sys.h"
#include  "demo.h"
#include <stdio.h>

void
update_system()
{
     /* get new targets */
     get_targets(&target_temp, &target_humid);

     /* Read the environment conditions. */
     read_conditions(&current_temp, &current_humid);

     /* Set the func_needed based on the actual environment condition
        versus the desired environment condition. */
     set_outputs(&func_needed, current_temp, current_humid);

     /* Update the hdwr_encode value so the external devices can react
        to modify the environment.*/
     write_hdwr(func_needed, hdwr_encode);

     /* Save the current temp and humid for later processing */
     save_points();

}

/******************************************************************************
 * Function: get_targets()
 *
 * Description: Ramp target temperature and humidity up and down
 *
 * Parameters:
 *      temperature - Pointer to target temperature.
 *      humidity    - Pointer to target humidity.
 *
 * References: None.
 *
 * Returns: Nothing.
 *****************************************************************************/
void
get_targets(short *temperature, short *humidity)
{

    /* Ramp the temperature and humidity targets up and down */

    if (temp_dir == up){
        (*temperature) +=2;
        if (*temperature >= MAX_TEMP) temp_dir = down;
    }
    else {
        (*temperature)--;
        if (*temperature <= MIN_TEMP) temp_dir = up;
    }

    if (humid_dir == up){
        (*humidity)++;
        if (*humidity >= MAX_HUMID) humid_dir = down;
    }
    else {
        (*humidity)--;
        if (*humidity <= MIN_HUMID) humid_dir = up;
    }
}

/******************************************************************************
 * Function: read_conditions()
 *
 * Description: Come up with new temperature and humidity values
 *              Uses the last NUM_OF_OLD values and the current target
 *              to create the new values.
 *
 * Parameters:
 *      temperature - Pointer to current temperature.
 *      humidity    - Pointer to current humidity.
 *
 * References: None.
 *
 * Returns: Nothing.
 *****************************************************************************/
void
read_conditions(short *temperature, short *humidity)
{
    int i,temp_tot,humid_tot;
    
    temp_tot=0;
    humid_tot=0;
    for (i=0;i<NUM_TO_AVE;i++)
    {
        temp_tot += old_data[i].temp;
        humid_tot += old_data[i].humid;
    }
    *temperature = (temp_tot/NUM_TO_AVE + target_temp)/2;
    *humidity = (humid_tot/NUM_TO_AVE + target_humid)/2;
}

/*****************************************************************************
 * Function: set_outputs()
 *
 * Description: Analyzes the environment and is set to indicate what needs
 *      to happen in the current environment to get the environment backk
 *      to target conditions. It uses a simple algorithm which simply
 *      compares the actual temperature/humidity against the desired
 *      temp/humid.  If the temperature/humidity is too high or low then
 *      the appropriatte external device will either be turned on or off.
 *
 * Parameters:
 *      function        - Pointer to byte indicating how the environment
 *                        needs to change
 *      temperature     - Current temperature.
 *      humidity        - Current humidity.
 *
 * References: None.
 *
 * Returns: Nothing.
 *****************************************************************************/
void
set_outputs(char *function, short temperature, short humidity)
{

     if (temperature <= target_temp)
          *function &= ~COOL;   /* Cooling off */
     if (temperature > target_temp)
          *function |= COOL;    /* Cooling on */
     if (temperature >= target_temp)
          *function &= ~HEAT;   /* Heating off */
     if (temperature < target_temp)
          *function |= HEAT;    /* Heating on */

     if (humidity <= target_humid)
          *function &= ~DEHUMIDIFY;   /* Dehumidify off */
     if (humidity > target_humid)
          *function |= DEHUMIDIFY;    /* Dehumidify on */
     if (humidity >= target_humid)
          *function &= ~HUMIDIFY;     /* Humidify off */
     if (humidity < target_humid)
          *function |= HUMIDIFY;      /* Humidify on */

}

/******************************************************************************
 * Function: write_hdwr()
 *
 * Description: Sets the hardware encoded 16-bit quantity to indicate what the
 *              hardware needs to do to achieve the changes in the environment
 *              that 'change' indicates are needed.
 *
 * Parameters:
 *      change   - change needed in environment
 *      hdwr_val - value of hardware encoded quantity.
 *
 * References: None.
 *
 * Returns: Nothing.
 *****************************************************************************/
void
write_hdwr(char change, unsigned short hdwr_val)
{

     if (change & HEAT)
          hdwr_val |= FURNACE_ON;
     if (change & COOL)
          hdwr_val |= AIR_COND_ON;
     if (change & HUMIDIFY)
          hdwr_val |= HUMID_ON;
     if (change & DEHUMIDIFY)
          hdwr_val |= DE_HUMID_ON;

     /* If the value of hdwr_encode should change, change it */
     if (hdwr_encode != hdwr_val)
         hdwr_encode = hdwr_val;

}

/******************************************************************************
 * Function: save_points()
 *
 * Description: This code saves the current values of the temperature and
 *              humidity into an array of structures of integers defined to
 *              be NUM_OF_OLD in size.  The current_temp and current_humid values
 *              are then inserted into the array in the next position using
 *              curr_loc. Note there is a bug inserted on purpose in this code.
 *              "curr_loc" takes on values between 0 and NUM_OF_OLD, which
 *              causes writes beyond the end of the array. This causes
 *              "target_temp" and "target_humid" to be overwritten every
 *              (NUM_OF_OLD+1) times the routine is called.
 *
 *
 * Parameters: none
 *
 * References: None.
 *
 * Returns: Nothing.
 *****************************************************************************/
void
save_points()
{
    short i;
    short temp_tot,humid_tot;

    old_data[curr_loc].temp = current_temp;
    old_data[curr_loc].humid = current_humid;
    curr_loc++;
    if (curr_loc > NUM_OF_OLD) curr_loc = 0;  /*BUG!!!!!*/

    temp_tot=0;
    for (i=0;i<NUM_OF_OLD;i++)
        temp_tot += old_data[i].temp;

    old_data[curr_loc].ave_temp = (float)temp_tot/(float)(NUM_OF_OLD);

    humid_tot=0;
    for (i=0;i<NUM_OF_OLD;i++)
        humid_tot += old_data[i].humid;

    old_data[curr_loc].ave_humid = (float)humid_tot/(float)(NUM_OF_OLD);

}

