
/*  pup.c
    For use with TM.EXE Version 4
    Stephen D. Anderson --- July 5, 1994

    Function pup.c packs or unpacks HART Packed ASCII.  

    ON ENTRY:
    "which" = 0 indicates pack, "which" = 1 indicates unpack.
    "in_buf" is pointer to input array, "out_buf" is pointer to
    output array, "nbytes" is the number of bytes in "in_buf" 
    to be packed if "which" = 0 or the number of bytes in "in_buf"
    to be unpacked if "which" = 1.
    If nbytes > 200, function does nothing and returns -1.

    ON EXIT:
    Returns the number of "out_buf" locations used, else returns -1.

    REVISION LOG:


*/

#include "stdio.h"
#include "string.h"

typedef unsigned char byte;

char pup(byte which, byte *in_buf, byte *out_buf, byte nbytes)

{
    byte x[2000];
    byte i,j;
    byte bit_count;
    byte out_count;
    byte shift_byte;
    byte *pin, *pout;

    if (nbytes > 200) return(-1);   /*  quit if too many.  */

    pin = in_buf; pout = out_buf;

    out_count = 0;
    bit_count = 0;

    if (which == 1)
    {
        /*  unpack. */
    
        /*  unravel the bit string and save each bit in x[]. */
        for (i=1; i<=nbytes; ++i)
        {
            shift_byte = 0x80;
            for (j=1; j<=8; ++j)
            {
                if ( (shift_byte & *pin) == 0)
                x[bit_count] = 0; else x[bit_count] = 1;
                ++bit_count;
                shift_byte >>= 1;
            }
            ++pin;
        }

        /*  now re-assemble bit string as 6-bit characters. */
        for (i=0,j=1; i<bit_count; ++i)
        {
            if (j==1)
            {
                *pout = 0;
                shift_byte = 32;
            }
            if (x[i] == 1) *pout += shift_byte;
            shift_byte >>= 1; ++j;
            if (j==7) 
            {
                j=1;
                if ((*pout & 32) == 0) *pout += 64;
                ++pout; ++out_count;
            }
        }
        return(out_count);
    }
    else
    {
        /*  pack. */
        /*  save the bits in x[]. */
        for (i=0; i<nbytes; ++i)
        {
            shift_byte = 32;
            for (j=0; j<6; ++j)
            {
                if ((shift_byte & *pin) != 0) x[bit_count] = 1;
                else x[bit_count] = 0;
                ++bit_count;
                shift_byte >>= 1;
            }
            ++pin;
        }

        /*  now put the bits back as 8-bit units. */
        shift_byte = 128; j=1; *pout = 0;
        for (i=0; i<bit_count; ++i)
        {
            if (x[i] == 1) *pout += shift_byte;
            shift_byte >>= 1;

            ++j;
            if (j == 9)
            {
                j = 1; shift_byte = 128; ++pout; ++out_count;
                *pout = 0;
            }
        }
        return(out_count);
    }
}

