# include "dvo.h"

// ST_SIZE is the size of the structure (must be modulo 8 bytes)
// FT_SIZE is the size of a row in the FITS table (inpt or output)
# define ST_SIZE 224
# define FT_SIZE 220

// this function is based on the one generated by the autocode of cmf-ps1-sv4.d
// this format is identical to PS1_SV3 (only non-psf tables changed)
unsigned char *gfits_convert_CMF_PS1_SV4 (unsigned char *input, off_t size, off_t nitems, char toStruct) {

  off_t i;
  unsigned char *byte = NULL;
  unsigned char *output = NULL;

  if (size != ST_SIZE) { 
    fprintf (stderr, "WARNING: mismatch in data types CMF_PS1_SV4: "OFF_T_FMT" vs %d\n",  size,  ST_SIZE);
    return (NULL);
  }

  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
  i = 0;

  // BYTE & WORD swap below is valid for the structure, not the FITS buffer
  if (toStruct) {
    // allocate a new output data buffer
    ALLOCATE (output, unsigned char, nitems*sizeof(CMF_PS1_SV4));
    unsigned char *inbyte = input;
    unsigned char *otbyte = output;

    // the data in the input table does not line up with the output structure: copy carefully.
    for (i = 0; i < nitems; i++, inbyte += FT_SIZE, otbyte += ST_SIZE) {
      memcpy (&otbyte[  0], &inbyte[  0],  76); // IPP_IDET to CAL_PSF_MAG_SIG
      memcpy (&otbyte[ 80], &inbyte[ 76],  16); // RA_PSF, DEC_PSF
      memcpy (&otbyte[ 76], &inbyte[ 92],   8); // PEAK_FLUX_AS_MAG
      memcpy (&otbyte[ 96], &inbyte[ 96], 124); // SKY to PADDING
      memset (&otbyte[220], 0, 4); // PADDING2
    }

    // after we have moved around PEAK_FLUX_AS_MAG, RA_PSF, DEC_PSF, we can swap as needed for this platform
    byte = output;
  } else {
    byte = input;
  }

# ifdef BYTE_SWAP
  char tmp = 0;
  for (i = 0; i < nitems; i++, byte += ST_SIZE) {
    /** BYTE SWAP **/
    SWAP_WORD (0);   // IPP_IDET
    SWAP_WORD (4);   // X_PSF
    SWAP_WORD (8);   // Y_PSF
    SWAP_WORD (12);  // X_PSF_SIG
    SWAP_WORD (16);  // Y_PSF_SIG
    SWAP_WORD (20);  // POSANGLE
    SWAP_WORD (24);  // PLTSCALE
    SWAP_WORD (28);  // PSF_INST_MAG
    SWAP_WORD (32);  // PSF_INST_MAG_SIG
    SWAP_WORD (36);  // PSF_INST_FLUX
    SWAP_WORD (40);  // PSF_INST_FLUX_SIG
    SWAP_WORD (44);  // AP_MAG
    SWAP_WORD (48);  // AP_MAG_RAW
    SWAP_WORD (52);  // AP_MAG_RADIUS
    SWAP_WORD (56);  // AP_FLUX
    SWAP_WORD (60);  // AP_FLUX_SIG
    SWAP_WORD (64);  // AP_NPIX
    SWAP_WORD (68);  // CAL_PSF_MAG
    SWAP_WORD (72);  // CAL_PSF_MAG_SIG

    // order in structure
    SWAP_WORD (76);  // PEAK_FLUX_AS_MAG
    SWAP_DBLE (80);  // RA_PSF
    SWAP_DBLE (88);  // DEC_PSF

    // order in FITS table
    // SWAP_WORD (76);  // RA_PSF
    // SWAP_DBLE (84);  // DEC_PSF
    // SWAP_DBLE (92);  // PEAK_FLUX_AS_MAG

    SWAP_WORD (96);  // SKY
    SWAP_WORD (100); // SKY_SIG
    SWAP_WORD (104); // PSF_CHISQ
    SWAP_WORD (108); // CR_NSIGMA
    SWAP_WORD (112); // EXT_NSIGMA
    SWAP_WORD (116); // PSF_MAJOR
    SWAP_WORD (120); // PSF_MINOR
    SWAP_WORD (124); // PSF_THETA
    SWAP_WORD (128); // PSF_CORE
    SWAP_WORD (132); // PSF_FWHM_MAJ
    SWAP_WORD (136); // PSF_FWHM_MIN
    SWAP_WORD (140); // PSF_QF
    SWAP_WORD (144); // PSF_QF_PERFECT
    SWAP_WORD (148); // PSF_NDOF
    SWAP_WORD (152); // PSF_NPIX
    SWAP_WORD (156); // MOMENTS_XX
    SWAP_WORD (160); // MOMENTS_XY
    SWAP_WORD (164); // MOMENTS_YY
    SWAP_WORD (168); // MOMENTS_M3C
    SWAP_WORD (172); // MOMENTS_M3S
    SWAP_WORD (176); // MOMENTS_M4C
    SWAP_WORD (180); // MOMENTS_M4S
    SWAP_WORD (184); // MOMENTS_R1
    SWAP_WORD (188); // MOMENTS_RH
    SWAP_WORD (192); // KRON_FLUX
    SWAP_WORD (196); // KRON_FLUX_ERR
    SWAP_WORD (200); // KRON_FLUX_INNER
    SWAP_WORD (204); // KRON_FLUX_OUTER
    SWAP_WORD (208); // FLAGS
    SWAP_WORD (212); // FLAGS2
    SWAP_BYTE (216); // N_FRAMES
    SWAP_BYTE (218); // PADDING
    SWAP_WORD (220); // PADDING2
  }
# endif  

  // BYTE & WORD swap below is valid for the structure, not the FITS buffer
  if (!toStruct) {
    // allocate a new output data buffer
    ALLOCATE (output, unsigned char, nitems*FT_SIZE);
    unsigned char *inbyte = input;
    unsigned char *otbyte = output;

    // the data in the input table does not line up with the output structure: copy carefully.
    for (i = 0; i < nitems; i++, inbyte += ST_SIZE, otbyte += FT_SIZE) {
      memcpy (&otbyte[  0], &inbyte[  0],  76); // IPP_IDET to CAL_PSF_MAG_SIG
      memcpy (&otbyte[ 76], &inbyte[ 80],  16); // RA_PSF, DEC_PSF
      memcpy (&otbyte[ 92], &inbyte[ 76],   4); // PEAK_FLUX_AS_MAG
      memcpy (&otbyte[ 96], &inbyte[ 96], 124); // SKY to PADDING
    }
  }

  return (output);
} 

int gfits_table_scale_storage_CMF_PS1_SV4 (CMF_PS1_SV4 *data, off_t Ndata) {

  off_t i;
  for (i = 0; i < Ndata; i++) {
    data[i].detID   -= 0x80000000;
    data[i].flags   -= 0x80000000;
    data[i].flags2  -= 0x80000000;
    data[i].nFrames -= 0x8000;
  }
  return TRUE;
}

/*** add test of EXTNAME and header-defined columns? ***/
/* return internal structure representation */
CMF_PS1_SV4 *gfits_table_get_CMF_PS1_SV4 (FTable *ftable, off_t *Ndata, char *swapped) {

  int Ncols;
  CMF_PS1_SV4 *data;

  Ncols = ftable[0].header[0].Naxis[0];
  if (Ncols != FT_SIZE) {
    fprintf (stderr, "ERROR: mis-match in table size: width is %d but should be %d bytes\n", Ncols, FT_SIZE);
    return NULL;
  }

  *Ndata = ftable[0].header[0].Naxis[1];
  data = (CMF_PS1_SV4 *) ftable[0].buffer;
  if ((swapped == NULL) || (*swapped == FALSE)) {
    unsigned char *newdata = gfits_convert_CMF_PS1_SV4 ((unsigned char *) data, sizeof (CMF_PS1_SV4), *Ndata, TRUE);
    if (!newdata) return NULL;
    free (ftable[0].buffer);
    ftable[0].buffer = (char *) newdata;
    data = (CMF_PS1_SV4 *) ftable[0].buffer;
    gfits_table_scale_storage_CMF_PS1_SV4 (data, *Ndata);
    if (swapped != NULL) *swapped = TRUE;
  }
  return (data);
}

int gfits_table_set_CMF_PS1_SV4 (FTable *ftable, CMF_PS1_SV4 *data, off_t Ndata) {

  Header *header;

  header = ftable[0].header;

  /* create table header */
  if (!gfits_create_table_header (header, "BINTABLE", "CMF_PS1_SV4")) return (FALSE);

  /* define table layout */
  /** TABLE DEFINITION **/
  gfits_define_bintable_column (header, "J",    "IPP_IDET",         "detection ID                     ", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "X_PSF",            "x coord",                         "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "Y_PSF",            "y coord",                         "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "X_PSF_SIG",        "x coord error",                   "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "Y_PSF_SIG",        "y coord error",                   "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "POSANGLE",         "Posangle at source",              "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PLTSCALE",         "Plate Scale at source",           "arcsec/pixel",      1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_MAG",     "inst mags",                       "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_MAG_SIG", "inst mag error",                  "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_FLUX",    "psf flux",                        "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_FLUX_SIG", "psf flux error",                  "counts      ",      1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG",           "standard aperture mag",           "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG_RAW",       "raw aperture mag",                "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG_RADIUS",    "radius used for fit",             "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_FLUX",          "aperture flux",                   "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_FLUX_SIG",      "error on ap flux",                "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "AP_NPIX",          "pixels used for aper",            "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CAL_PSF_MAG",      "calibrated psf mag",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CAL_PSF_MAG_SIG",  "zero point scatter",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PEAK_FLUX_AS_MAG", "peak flux as a mag",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "D",    "RA_PSF",           "PSF RA coord",                    "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "D",    "DEC_PSF",          "PSF DEC coord",                   "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "SKY",              "sky flux",                        "cnts/sec",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "SKY_SIG",          "sky flux error",                  "cnts/sec",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_CHISQ",        "psf fit chisq",                   "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CR_NSIGMA",        "Nsigma deviations from PSF to CF", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "EXT_NSIGMA",       "Nsigma deviations from PSF to EXT", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_MAJOR",        "psf fit major axis",              "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_MINOR",        "psf fit minor axis",              "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_THETA",        "ellipse angle",                   "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_CORE",         "extra PSF parameter",             "unitless",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_FWHM_MAJ",     "true fwhm of psf",                "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_FWHM_MIN",     "true fwhm (minor)",               "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_QF",           "quality factor",                  "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_QF_PERFECT",   "quality factor perfect",          "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PSF_NDOF",         "psf degrees of freedom",          "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PSF_NPIX",         "psf number of pixels",            "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_XX",       "second moment X",                 "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_XY",       "second moment Y",                 "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_YY",       "second moment XY",                "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M3C",      "third moment cos(t)",             "pixels^3",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M3S",      "third moment sin(t)",             "pixels^3",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M4C",      "fourth moment cos(t)",            "pixels^4",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M4S",      "fourth moment sin(t)",            "pixels^4",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_R1",       "first radial moment",             "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_RH",       "half radial moment",              "pixels^1/2",        1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX",        "kron flux",                       "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_ERR",    "kron flux error",                 "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_INNER",  "kron flux 1<R<2.5",               "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_OUTER",  "kron flux 2.5<R<4",               "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "FLAGS",            "analysis flags",                  "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "FLAGS2",           "analysis flags (2)",              "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "I",    "N_FRAMES",         "images overlapping peak",         "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "I",    "PADDING",          "padding for 8byte records",       "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PADDING2",         "padding for 8byte records",       "",                  1.0, 0.0);

  /* create table */
  if (!gfits_create_table (header, ftable)) return (FALSE);

  /* add data values */
  if (!gfits_table_scale_data (ftable)) return (FALSE);
  unsigned char *newdata = gfits_convert_CMF_PS1_SV4 ((unsigned char *) data, sizeof (CMF_PS1_SV4), Ndata, FALSE);
  if (!newdata) return (FALSE);
  free (ftable[0].buffer);
  ftable[0].buffer = (char *) newdata;
  if (!gfits_add_rows (ftable, (char *) newdata, Ndata, sizeof (CMF_PS1_SV4))) return (FALSE);

  return (TRUE);
}

int gfits_table_mkheader_CMF_PS1_SV4 (Header *header) {

  /* create table header */
  if (!gfits_create_table_header (header, "BINTABLE", "CMF_PS1_SV4")) return (FALSE);

  /* define table layout */
  /** TABLE DEFINITION **/
  gfits_define_bintable_column (header, "J",    "IPP_IDET",         "detection ID                     ", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "X_PSF",            "x coord",                         "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "Y_PSF",            "y coord",                         "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "X_PSF_SIG",        "x coord error",                   "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "Y_PSF_SIG",        "y coord error",                   "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "POSANGLE",         "Posangle at source",              "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PLTSCALE",         "Plate Scale at source",           "arcsec/pixel",      1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_MAG",     "inst mags",                       "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_MAG_SIG", "inst mag error",                  "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_FLUX",    "psf flux",                        "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_INST_FLUX_SIG", "psf flux error",                  "counts      ",      1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG",           "standard aperture mag",           "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG_RAW",       "raw aperture mag",                "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_MAG_RADIUS",    "radius used for fit",             "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_FLUX",          "aperture flux",                   "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "AP_FLUX_SIG",      "error on ap flux",                "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "AP_NPIX",          "pixels used for aper",            "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CAL_PSF_MAG",      "calibrated psf mag",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CAL_PSF_MAG_SIG",  "zero point scatter",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PEAK_FLUX_AS_MAG", "peak flux as a mag",              "mags",              1.0, 0.0);
  gfits_define_bintable_column (header, "D",    "RA_PSF",           "PSF RA coord",                    "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "D",    "DEC_PSF",          "PSF DEC coord",                   "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "SKY",              "sky flux",                        "cnts/sec",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "SKY_SIG",          "sky flux error",                  "cnts/sec",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_CHISQ",        "psf fit chisq",                   "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "CR_NSIGMA",        "Nsigma deviations from PSF to CF", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "EXT_NSIGMA",       "Nsigma deviations from PSF to EXT", "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_MAJOR",        "psf fit major axis",              "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_MINOR",        "psf fit minor axis",              "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_THETA",        "ellipse angle",                   "degrees",           1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_CORE",         "extra PSF parameter",             "unitless",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_FWHM_MAJ",     "true fwhm of psf",                "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_FWHM_MIN",     "true fwhm (minor)",               "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_QF",           "quality factor",                  "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "PSF_QF_PERFECT",   "quality factor perfect",          "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PSF_NDOF",         "psf degrees of freedom",          "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PSF_NPIX",         "psf number of pixels",            "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_XX",       "second moment X",                 "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_XY",       "second moment Y",                 "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_YY",       "second moment XY",                "pixels^2",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M3C",      "third moment cos(t)",             "pixels^3",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M3S",      "third moment sin(t)",             "pixels^3",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M4C",      "fourth moment cos(t)",            "pixels^4",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_M4S",      "fourth moment sin(t)",            "pixels^4",          1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_R1",       "first radial moment",             "pixels",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "MOMENTS_RH",       "half radial moment",              "pixels^1/2",        1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX",        "kron flux",                       "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_ERR",    "kron flux error",                 "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_INNER",  "kron flux 1<R<2.5",               "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "E",    "KRON_FLUX_OUTER",  "kron flux 2.5<R<4",               "counts",            1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "FLAGS",            "analysis flags",                  "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "FLAGS2",           "analysis flags (2)",              "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "I",    "N_FRAMES",         "images overlapping peak",         "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "I",    "PADDING",          "padding for 8byte records",       "",                  1.0, 0.0);
  gfits_define_bintable_column (header, "J",    "PADDING2",         "padding for 8byte records",       "",                  1.0, 0.0);

  return (TRUE);
}

int Send_CMF_PS1_SV4 (int device, CMF_PS1_SV4 *data, int Ndata, int copy) {

  int Nwrite, Nbytes;
  CMF_PS1_SV4 *tmpdata;

  Nbytes = Ndata * sizeof (CMF_PS1_SV4);

  if (copy) {
    ALLOCATE (tmpdata, CMF_PS1_SV4, Ndata);
    memcpy (tmpdata, data, Nbytes);
  } else {
    tmpdata = data;
  }

  unsigned char *newdata = gfits_convert_CMF_PS1_SV4 ((unsigned char *) tmpdata, sizeof (CMF_PS1_SV4), Ndata, FALSE);
  if (!newdata) return FALSE;

  SendCommand (device, 16, "NVALUE: %6d", Ndata);
  SendCommand (device, 16, "NBYTES: %6d", Nbytes);
  Nwrite = write (device, newdata, Nbytes);
  if (Nwrite != Nbytes) {
    return (FALSE);
  }
  
  /* perform handshaking? */

  return (TRUE);
}

int Recv_CMF_PS1_SV4 (int device, CMF_PS1_SV4 **data, int *Ndata) {

  int ndata;
  IOBuffer message;
  CMF_PS1_SV4 *tmpdata;

  ExpectCommand (device, 16, 1.0, &message);
  sscanf (message.buffer, "%*s %d", &ndata);
  FreeIOBuffer (&message);
  
  /* what is reasonable for timeout? */
  ExpectMessage (device, 1.0, &message);
  
  tmpdata = (CMF_PS1_SV4 *) message.buffer;
  unsigned char *newdata = gfits_convert_CMF_PS1_SV4 ((unsigned char *) tmpdata, sizeof (CMF_PS1_SV4), ndata, TRUE);
  if (!newdata) return FALSE;
  free (message.buffer);

  /* double-check data length? */
  /* perform handshaking? */

  *Ndata = ndata;
  *data = (CMF_PS1_SV4 *) newdata;

  return (TRUE);
}

