/*
**  unpack.c -- Unpacks readings from the 44702A/B High Speed Voltmeter
**              For each 16-bit packed reading a 64-bit IEEE floating
**              point number is returned. Reads packed data via stdin,
**              outputs unpacked data via stdout. The readings are 
**              assumed to be in binary format.
**
**              This program is meant to be used with the Execute Program
**              object of HP VEE, hence it is written to loop indefinitely,
**              accepting packed reading and outputing unpacked read-
**              ings. For best results, specify "Wait for child exit"
**              equal to "No" on the Execute Program object. This process
**              will not exit until the parent process exits, in this 
**              case HP VEE.
**
**              Usage: unpack  [number of elements]
**               
**
**  Copyright (c) 1991, by: Hewlett Packard
**  All Rights Reserved.
**
**  ** This program is free software. It can be redistributed
**     and/or modified.
**  ** It is distributed in the hope that it will be useful,
**     but WITHOUT ANY WARRANTY.
**  ** Without even the implied warranty of MERCHANTABILITY
**     or FITNESS FOR A PARTICULAR PURPOSE.
**
**  - this code can be compiled, as is, using the 'C' compiler:
**     cc -O -o unpack.exe unpack.c
*/
#include <stdio.h>

#define MAX_RDGS            100000  /* packed readings maximum */
#define STDIN               0       /* libvio.h not included, so define here */
#define STDOUT              1       /* ditto */

main(argc, argv)
int argc;
char *argv[];
{
    short     pack[MAX_RDGS];       /* input buffer for packed readings */
    double    readings[MAX_RDGS];   /* output buffer for unpacked readings */
    double    data[4];              /* hold scaling factors */
    int       i;
    int       num;                  /* hold command line argument */

    data[0] = 256;
    data[1] = 32;
    data[2] = 4;
    data[3] = 1;
    
    setbuf( stdout, NULL );         /* No buffers, please */
    num = atoi( argv[1] );
    while( 1 )                      /* loop forever */
    {                                 
        (void)read( STDIN, (char*)pack, (int)sizeof(short) * num );
        for( i = 0; i < num; i++ )
        {
            if( (pack[i] > 0) || ((pack[i] & 4095) == 4095) )
            {
                readings[i] = 1.0e+38;
            }
            else
            {
                readings[i] = ((pack[i] & 4095)*.0025)/data[((pack[i]>>13)&3)];
                if( pack[i] & 4096 )
                {
                    readings[i] = -readings[i];
                }
            }
        }
        (void)write( STDOUT, (char*)readings, (int)sizeof(double) * num );
    }
}

