/******************************************************************************
 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.
 ******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "updt_sys.h"
/******************************************************************************
* This typedef is also found in demo.h but since demo.h is not included in
* this file, this declaration appears here by itself.
*****************************************************************************/
#define SHRINKFACTOR 1.3
#define LISTLEN      NUM_OF_OLD*4+1
typedef enum    {false, true} boolean;
typedef enum {up,down} direction;

typedef struct
{
    short temp;
    short humid;
    float ave_temp;
    float ave_humid;
} old_el;

/********************************
 * Global Variable Declarations
 *******************************/

old_el  old_data[NUM_OF_OLD];           /* History of temp and humid data. */
short   target_temp;                    /* Target temperature. */
short   target_humid;                   /* Target humidity. */
char    ascii_old_data[LISTLEN][8];     /* ASCII history of temp and humid data. */

float   float_temp;
float   float_humid;
float   aver_temp;
short   current_temp;                   /* Current temperature. */
short   current_humid;                  /* Current humidity. */

int     num_checks;                     /* Counts the number of times */
                                        /* update_state_of_system() is called */

int     curr_loc;                       /* location to write old temp and humid */

/******************************************************************************
 * func_needed is the byte that indicates what the environment control system
 * needs to do to the environment.   The following specifies the values it
 * may have:
 *
 * <bit>:        bit #3         bit #2         bit #1          bit #0
 * <function
 *   needed>:   dehumidify     humidify         cool            heat
 *
 *  The only valid values for this char are:
 *     (hex)   (binary)
 *      (1)     0001         heat
 *      (2)     0010         cool
 *      (4)     0100         humidify
 *      (8)     1000         dehumidify
 *      (9)     1001         dehumidify and heat
 *      (A)     1010         dehumidify and cool
 *      (5)     0101         humidify and heat
 *      (6)     0110         humidify and cool
 *****************************************************************************/
 char     func_needed;

/******************************************************************************
 * hdwr_encode is the encoded 16-bit quantity output by the system which is
 * interpreted by external devices.  It tells the external devices what to do,
 * for example, turning the air conditioner on (indicated by hdwr_encode =
 * 0010).  There are four sets of four bits within the 16 bit quantity
 * hdwr_encode.  These sets of bits are encoded as folows:
 *
 *     Value of            Value of           Value of          Value of
 *   bits 15 - 12         bits 11 - 8        bits 7 - 4        bits 3 - 0
 *   Dehumidifier         Humidifier       Air Conditioner       Heater
 *      0 = off            0 = off            0 = off            0 = off
 *      1 = on             1 = on             1 = on             1 = on
 *****************************************************************************/
unsigned short     hdwr_encode;

direction humid_dir,temp_dir;       /* direction for current_vars */

extern void init_system();          /* initialize system */
extern void update_system();        /* update system variables */
extern void interrupt_sim();        /* simulate an interrupt */
extern void do_sort();              /* sets up ascii array and calls combsort */

main()
{
    init_system();

    while (true)
    {
        update_system();
        num_checks++;
        interrupt_sim(&num_checks);
    }
}

/******************************************************************************
 * FUNCTION: interrupt_sim
 * PARMS:    counter -- loop counter passed in from main
 * DESCRIPTION:
 *   create a simulation of a (usually) long interrupt service routine that
 *   also has a duration profile to use with a SPA duration trigger.
 *
 ******************************************************************************/
void
interrupt_sim(counter)
int *counter;
{
    short outer;
    short inner;
    short limit;

    limit = (*counter % 10) * (*counter % 10) / 3;

    for ( outer = 0; outer < limit; outer++ )
        for ( inner = 0; inner < 270; inner++ )
            inner++;

    if ( ! ( (*counter ) % 4 ) )
        do_sort( old_data, ascii_old_data, limit % NUM_OF_OLD );
}

/******************************************************************************
 * FUNCTION: strcpy8
 * DESCRIPTION:
 *   Copy only 7 chars (8 with NULL)
 *
 ******************************************************************************/
int strcpy8( dest, src ) 
char *dest;
char *src; 
{
    int i;

    /* Copy it */
    for ( i=0; i < 7 && *src; i++ )
        *dest++ = *src++;
    *dest = '\0';
}

/******************************************************************************
 * FUNCTION: gen_ascii_data
 * DESCRIPTION:
 *   Generate ascii data from binary data
 *
 ******************************************************************************/
int gen_ascii_data( data, ascii_data, size )
old_el  data[];
char    ascii_data[][8];
int      size;
{
    int  i, j;                  /* counters */
    char buf[16];

    /* Place ascii data in the ascii array */
    for (j=0, i=0; i < size; i++)
    {
        sprintf( buf, "%7d", data[i].temp );
        strcpy8(ascii_data[j++], buf );

        sprintf( buf, "%7d", data[i].humid );
        strcpy8(ascii_data[j++], buf );

        sprintf( buf, "%7.2f", data[i].ave_temp );
        strcpy8(ascii_data[j++], buf );

        sprintf( buf, "%7.2f", data[i].ave_temp );
        strcpy8(ascii_data[j++], buf );
    }
    strcpy8(ascii_data[j++], "\0" );
}

/******************************************************************************
   These variables made static for debugging purposes 
    (used by combsort function) 
 ******************************************************************************/
static int len,         /* number of strings to sort */
        switches,       /* any element switches this pass? */
        switch_total,   /* total number of switches performed in sort */
        i, j,           /* loop counters */
        top,            /* top of current passes in len */
        passes,         /* number of passes for sort */
        gap;            /* current gap size */

/******************************************************************************
 * FUNCTION: combsort
 * DESCRIPTION:
 *   A combsort(11) for arrays of ascii data 8 chars wide
 *
 ******************************************************************************/
int combsort( array )
char array[][8];
{
    char hold[100];     /* temp var for element swap */

    /* Determine length of array */
    for (len=0; *array[len] != '\0';)
        len++;

    /* Main sort loop */
    gap = len;                  /* set comb gap to len to start */
    passes = 0;                 /* pass counter */
    switch_total = 0;           /* total switches */
    do
    {
        passes++;               /* ran another pass */
        gap = (int)((float)gap / SHRINKFACTOR);
        switches = 0;           /* dirty pass flag */

        /* Force gap to conform to comb11 */
        switch (gap)
        {
        case 0:     gap = 1;    /* smallest gap is 1 = bubble */
                    break;
        case 9:
        case 10:
        case 11:    gap = 11;   /* force comb sort 11 */
                    break;
        default:    break;
        }

        /* Do the comb sort loop for this comb gap */
        for (top=len-gap,i=0; i < top; i++)
        {
            j = i + gap;        /* j is higher than i by gap */
            if (strncmp(array[i], array[j], 7) > 0)
            {                   /* swap elements if required */
                switches++;
                switch_total++;
                /* strncpy(hold, array[i], 7);
                strncpy(array[i], array[j], 7);
                strncpy(array[j], hold, 7); */
                strcpy8(hold, array[i]);
                strcpy8(array[i], array[j]);
                strcpy8(array[j], hold);
            }
        }
    } while (switches || (gap > 1));

    /* Show sort performance summary data in elements 1, 2, 3 */
    /* for display memory blocked repetitive */
    sprintf( hold, "#Pas%3d", passes );
    strcpy8( array[1], hold );
    sprintf( hold, "#Swi%3d", switch_total );
    strcpy8( array[3], hold );
    sprintf( hold, "Len%4d", switch_total );
    strcpy8( array[5], hold );

    /* NOTE: This has been an example of how to monitor complex C variables
             while your program is running.  If you issue a 'Mem Bloc ()'
             action key with 'ascii_old_data' in the entry buffer you will
             see a snapshot of your sprintf results.  You may also add a
             Display->Memory->Repetitively command to see this dynamically! */
}

/******************************************************************************
 * FUNCTION: do_sort
 * DESCRIPTION:
 *   Generate ascii data from binary data and sort it
 *
 ******************************************************************************/
void do_sort( data, ascii_data, size )
old_el  data[];
char    ascii_data[][8];
int      size;
{
    int  i=0;                   /* counter */
    char buf[16];

    /* Clear the array first */
    for (i=0; i < NUM_OF_OLD*4; i++)
        strcpy8(ascii_data[i], "CLEARED");

    /* Generate the array to sort */
    gen_ascii_data( data, ascii_data, size );

    /* Sort the array */
    combsort( ascii_data );

    /* Print the floating point average temp also */
    sprintf( buf, "Ave%5.2f", aver_temp );
    strcpy8(ascii_data[7], buf );
}

