#include "defs.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#include "ana_structures.h"
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "command.h"
#include "errors.h"
#define ABS(x) ((x)>=0?(x):-(x))
#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))
#define X_SHORT(x,n)  (((int) x[n+1]) & 0xff) +	\
       ((((int) x[n])<<8 )& 0xff00)
#define NOOP  0xffff0000  //for both cam cmd & smem config
#define LONGFGFLAG  0xff000000  //for detecting FG long integrations
 extern	int scrat[NSCRAT];
 extern	struct sym_desc sym[];
 extern	struct sym_list		*subr_sym_list[];
 extern	int	temp_base;
 extern	int	ana_float();
 extern	char *find_sym_name(int iq);
 extern	int	ana_type_size[];
 extern	int	vfix_top, num_ana_subr, next_user_subr_num;
 extern	int	lastmin_sym, lastmax_sym;
 extern	int	num_ana_func, next_user_func_num;
 extern	float	float_arg();
 extern	double	double_arg();
 static int	result_sym;
 extern int 	get_p_c(), get_p_c_r();
 extern char    *strsave();
 union	types_ptr { byte *b; short *w; int *l; float *f; double *d;};		
 int    dim[8];
 struct ahead   *h;
 /* some stashed macro commands */
 sp_macro_command	sp_current_macro, sp_pending_macro;
 fg_macro_command	fg_current_macro, fg_pending_macro;
 /* flags for executing */
 int	sp_executing_flag, fg_executing_flag;
 int	sp_pending_flag, fg_pending_flag;
 int	loop_flag, fg_pad_time;  /* a fg loop enable for testing */
 int	test_pad_time;
 int	loop_limit;	/* limit the loop count */
 int	sp_stop_flag, fg_stop_flag, sp_pause_flag, sp_is_paused;
 unsigned char	blockerStowEnable, blockerStowWavelengthNum;
 /* a place to store the packed FG parts whilst we unpack them */
 FGimageParameters params;
 FGobsDefHeader  FGpackedHeader;
 FGimageParameters FGpackedParameters;
 SmartMemDACT	FGdact;	/* this is the one (and only) smart memory config
 				table for the FG (there is another for the SP) */
 short defaultExposure = 30; /* 22 - the default exposure for the FG (see macro cmd def) */
 /* a place for the current (unpacked) FG observational definition table */
 FGunpackedObsTableType   FGunpackedObsTable;
fbd_flt FDBarray[256] = {
  { 1, 0, NOMASK, 0, 0, 0, 0, 127, 255, 0, 0, 0},	/* full size, no summing, no binning */
  { 2, 0, NOMASK, 1, 1, 0, 0, 127, 255, 0, 0, 0},	/* full size, 2x2 summing */
  { 3, 0, NOMASK, 0, 0, 0, 0, 127, 127, 0, 0, 0},	/* 2048x2048 cutout */
  { 4, 0, NOMASK, 0, 0, 0, 0,  63,  63, 0, 0, 0},	/* 1024x1024 cutout */
  { 5, 0, NOMASK, 0, 0, 0, 0,  31,  31, 0, 0, 0},	/* 512x512 cutout */
  { 6, 0, NOMASK, 0, 0, 0, 0,  15,  15, 0, 0, 0},	/* 256x256 cutout */
  /* be conservative with the shutterless width for early tests, use 64 even though
  80 works, consider using 80 after things are more stable */
  { 7, 0, MASK4,  0, 0, 1, 0, 127,   3, 0, 0, 0},	/* shutterless, full height, 64 wide */
  { 8, 0, MASK1,  0, 0, 1, 0, 127,   3, 0, 0, 0},	/* shutterless, full height, 64 wide, wider mask */
  { 9, 0, MASK3,  0, 0, 1, 0, 127,  11, 0, 0, 0},	/* 0.2s shutterless, full height, 192 wide */
  {10, 0, NOMASK, 1, 1, 0, 0, 127, 255, 0, 0, 0},	/* full size, 2x2 summing, no binning */
  {11, 0, NOMASK, 0, 0, 0, 0, 127, 255, 1, 1, 0},	/* full size, 2x2 binning, no summing */
  {12, 0, NOMASK, 1, 1, 0, 0, 127, 127, 0, 0, 0},	/* 2048x2048 cutout, 2x2 summing */
  {13, 0, NOMASK, 2, 2, 0, 0, 127, 127, 0, 0, 0},	/* 2048x2048 cutout, 4x4 summing */
  {14, 0, MASK2,  0, 0, 1, 0, 127,  24, 0, 0, 0},	/* shutterless, full height, 400 wide */
  /* 10/7/2004 - correct FID 15, it caused 100 wide images */
  {15, 0, MASK2,  1, 1, 1, 0, 127,  23, 0, 0, 0},	/* shutterless, 2x2, full height, 384 wide */
  {16, 0, MASK1,  1, 1, 1, 0, 127,  49, 0, 0, 0},	/* shutterless, 2x2, full height, 800 wide */
  /* 144 and 288 below are conservative, could get more width, e.g., 192 and 384 or 176 and 352
  to keep the times below 94 ms */
  /* 10/7/2004 - correct FID's 17 and 18, they caused 36 wide images */
  {17, 0, MASK3,  1, 1, 1, 0, 127,  9, 0, 0, 0},	/* shutterless, 2x2, full height, 160 wide */
  //{17, 0, MASK3,  1, 1, 1, 0, 127,  8, 0, 0, 0},	/* shutterless, 2x2, full height, 144 wide */
  {18, 0, MASK2,  2, 2, 1, 0, 127,  19, 0, 0, 0},	/* shutterless, 4x4, full height, 320 wide */
  //{18, 0, MASK2,  2, 2, 1, 0, 127,  17, 0, 0, 0},	/* shutterless, 4x4, full height, 288 wide */
  /* 11/9/2004 - missed the next one, similar problem, change 800 to 768 */
  {19, 0, MASK1,  2, 2, 1, 0, 127,  47, 0, 0, 0},	/* shutterless, 4x4, full height, 768 wide */
  //{19, 0, MASK1,  2, 2, 1, 0, 127,  49, 0, 0, 0},	/* shutterless, 4x4, full height, 800 wide */
  {20, 0, MASK1,  2, 2, 1, 0, 127,  99, 0, 0, 0},	/* shutterless, 4x4, full height, 1600 wide */
  {21, 0, MASK1,  0, 0, 0, 0, 127, 255, 0, 0, 0},	/* 21 - 24 are full size with the 4 masks for */
  {22, 0, MASK2,  0, 0, 0, 0, 127, 255, 0, 0, 0},	/* testing the masked area */
  {23, 0, MASK3,  0, 0, 0, 0, 127, 255, 0, 0, 0},
  {24, 0, MASK4,  0, 0, 0, 0, 127, 255, 0, 0, 0},
  {25, 0, NOMASK, 0, 0, 0, 0, 127, 127, 1, 1, 0},	/* 2048x2048, 2x2 binning, no summing */
  {26, 0, NOMASK, 0, 0, 0, 0, 127, 127, 2, 2, 0},	/* 2048x2048, 4x4 binning, no summing */
  {27, 0, MASK1, 0, 0, 0, 0, 127, 63, 0, 0, 0},		/* 1024x2048 */
  {28, 0, MASK1, 1, 1, 0, 0, 127, 63, 0, 0, 0},		/* 1024x2048, 2x2 summing */
  {29, 0, MASK1, 2, 2, 0, 0, 127, 63, 0, 0, 0},		/* 1024x2048, 4x4 summing */
  {30, 0, NOMASK, 0, 0, 0, 0, 127, 31, 0, 0, 0},	/* 512x2048, 1x1 summing */
  {31, 0, NOMASK, 0, 0, 0, 0, 15, 255, 0, 0, 0},	/* 4096x256, 1x1 summing */
  {32, 0, NOMASK, 0, 0, 0, 0, 31, 255, 0, 0, 0},	/* 4096x512, 1x1 summing */
  {33, 0, NOMASK, 1, 1, 0, 0, 15, 255, 0, 0, 0},	/* 4096x256, 2x2 summing */
  {34, 0, NOMASK, 2, 2, 0, 0, 15, 255, 0, 0, 0},	/* 4096x256, 4x4 summing */
  {35, 0, NOMASK, 0, 0, 0, 0, 63, 127, 0, 0, 0},	/* 2048x1024, 1x1 summing */
  {36, 0, NOMASK, 2, 2, 0, 0, 127, 255, 0, 0, 0},	/* 4096x2048, 4x4 summing */
  {37, 0, NOMASK, 0, 0, 0, 0,  31, 63, 0, 0, 0},	/* 1024x512, 1x1 summing */
  {38, 0, NOMASK, 1, 1, 0, 0, 63, 127, 0, 0, 0},	/* 2048x1024, 2x2 summing */
  {39, 0, NOMASK, 1, 1, 0, 0, 63,  63, 0, 0, 0},	/* 1024x1024, 2x2 summing */

 /* next 5 are narrow shutterless with a wider mask to use for cascaded ROI's */
  {40, 0, MASK1,  0, 0, 1, 0, 127,  11, 0, 0, 0},	/* 0.2s shutterless, full height, 192 wide, like 9 but wider mask */
  {41, 0, MASK1,  0, 0, 1, 0, 127,  24, 0, 0, 0},	/* shutterless, full height, 400 wide, like 14 but wider mask */
  {42, 0, MASK1,  1, 1, 1, 0, 127,  23, 0, 0, 0},	/* shutterless, 2x2, full height, 384 wide, like 15 but wider mask */
  {43, 0, MASK1,  1, 1, 1, 0, 127,  9, 0, 0, 0},	/* shutterless, 2x2, full height, 160 wide, like 17 but wider mask */
  {44, 0, MASK1,  2, 2, 1, 0, 127,  19, 0, 0, 0},	/* shutterless, 4x4, full height, 320 wide, like 18 but wider mask */

 /* next 12 are shutterless that are half height */

  {45, 0, MASK4,  0, 0, 1, 0, 63,   3, 0, 0, 0},	/* shutterless, half height, 64 wide */
  {46, 0, MASK1,  0, 0, 1, 0, 63,   3, 0, 0, 0},	/* shutterless, half height, 64 wide, wider mask */

  {47, 0, MASK3,  0, 0, 1, 0, 63,  11, 0, 0, 0},	/* 0.2s shutterless, half height, 192 wide */
  {48, 0, MASK1,  0, 0, 1, 0, 63,  11, 0, 0, 0},	/* 0.2s shutterless, half height, 192 wide, like 47 but wider mask */

  {49, 0, MASK2,  0, 0, 1, 0, 63,  24, 0, 0, 0},	/* shutterless, half height, 400 wide */
  {50, 0, MASK1,  0, 0, 1, 0, 63,  24, 0, 0, 0},	/* shutterless, half height, 400 wide, like 49 but wider mask */

  {51, 0, MASK2,  1, 1, 1, 0, 63,  23, 0, 0, 0},	/* shutterless, 2x2, half height, 384 wide */
  {52, 0, MASK1,  1, 1, 1, 0, 63,  23, 0, 0, 0},	/* shutterless, 2x2, half height, 384 wide, like 51 but wider mask */

  {53, 0, MASK3,  1, 1, 1, 0, 63,  9, 0, 0, 0},		/* shutterless, 2x2, half height, 160 wide */
  {54, 0, MASK1,  1, 1, 1, 0, 63,  9, 0, 0, 0},		/* shutterless, 2x2, half height, 160 wide, like 53 but wider mask */

  {55, 0, MASK2,  2, 2, 1, 0, 63,  19, 0, 0, 0},	/* shutterless, 4x4, half height, 320 wide */
  {56, 0, MASK1,  2, 2, 1, 0, 63,  19, 0, 0, 0},	/* shutterless, 4x4, half height, 320 wide, like 55 but wider mask */
  {57, 0, MASK0, 0, 0, 0, 0, 127, 63, 0, 0, 0},		/* 1024x2048 w/o a mask to better de-center */

 /* here marks the end of the launch load set of frames */
 
  {58, 0, NOMASK, 0, 0, 0, 0, 63, 255, 0, 0, 0},        /* 4096x1024, 1x1 summing */
  {59, 0, NOMASK, 1, 1, 0, 0, 63, 255, 0, 0, 0},        /* 4096x1024, 2x2 summing */
  {60, 0, NOMASK, 0, 0, 0, 0, 63,  31, 0, 0, 0},        /* 512x1024, 1x1 summing */
  {61, 0, NOMASK, 1, 1, 0, 0, 63,  31, 0, 0, 0},        /* 512x1024, 2x2 summing */

  {62, 0, NOMASK, 0, 0, 0, 0, 31, 127, 0, 0, 0},        /* 2048x512, 1x1 summing */
  {63, 0, NOMASK, 1, 1, 0, 0, 31, 255, 0, 0, 0},        /* 4096x512, 2x2 summing */
  {64, 0, NOMASK, 1, 1, 0, 0, 31, 127, 0, 0, 0},        /* 2048x512, 2x2 summing */
  {65, 0, NOMASK, 1, 1, 0, 0,  31, 63, 0, 0, 0},        /* 1024x512, 2x2 summing */

 /* these are for NFI/BFI matches (to be used for NFI exposures) */

  {66, 0, NOMASK, 0, 0, 0, 0, 84, 175, 0, 0, 0},        /* 2808x1360 1x1 summing */
  {67, 0, NOMASK, 0, 0, 0, 0, 84,  87, 0, 0, 0},        /* 1408x1360 1x1 summing */
  {68, 0, NOMASK, 0, 0, 0, 0, 84,  43, 0, 0, 0},        /* 704x1360 1x1 summing */
  {69, 0, NOMASK, 0, 0, 0, 0, 84,  21, 0, 0, 0},        /* 352x1360 1x1 summing */
  {70, 0, NOMASK, 0, 0, 0, 0, 50,  43, 0, 0, 0},        /* 704x816 1x1 summing */
  {71, 0, NOMASK, 0, 0, 0, 0, 50,  87, 0, 0, 0},        /* 1408x816 1x1 summing */

  {72, 0, NOMASK, 1, 1, 0, 0, 101, 175, 0, 0, 0},       /* 2808x1632 2x2 summing */
  {73, 0, NOMASK, 1, 1, 0, 0, 101,  87, 0, 0, 0},       /* 1408x1632 2x2 summing */
  {74, 0, NOMASK, 1, 1, 0, 0, 101,  43, 0, 0, 0},       /* 704x1632 2x2 summing */
  {75, 0, NOMASK, 1, 1, 0, 0, 101,  21, 0, 0, 0},       /* 352x1632 2x2 summing */
  {76, 0, NOMASK, 1, 1, 0, 0, 63,  43, 0, 0, 0},        /* 704x1024 2x2 summing */
  {77, 0, NOMASK, 1, 1, 0, 0, 63,  87, 0, 0, 0},        /* 1408x1024 2x2 summing */

 /* the 1.5K x 1.5K fov */
  {78, 0, NOMASK, 0, 0, 0, 0, 101,  95, 0, 0, 0},       /* 1536x1632 1x1 summing */
  {79, 0, NOMASK, 1, 1, 0, 0, 101,  95, 0, 0, 0},       /* 1536x1632 2x2 summing */

 /* EIS matches */
  {80, 0, NOMASK, 0, 0, 0, 0, 127,  215, 0, 0, 0},      /* 3456x2048 1x1 summing */
  {81, 0, NOMASK, 1, 1, 0, 0, 127,  215, 0, 0, 0},      /* 3456x2048 2x2 summing */
  {82, 0, NOMASK, 0, 0, 0, 0, 127,  47, 0, 0, 0},       /* 768x2048 1x1 summing */
  {83, 0, NOMASK, 1, 1, 0, 0, 127,  47, 0, 0, 0},       /* 768x2048 2x2 summing */

 /* quarter height shutterless */
  {84, 0, MASK1,  0, 0, 1, 0, 50,  11, 0, 0, 0},        /* 0.2s shutterless, 816 high, 192 wide, wide mask */
  {85, 0, MASK1,  0, 0, 1, 0, 50,  24, 0, 0, 0},        /* shutterless, 816 high, 400 wide, wide mask */
  {86, 0, MASK1,  0, 0, 1, 0, 50,   3, 0, 0, 0},        /* shutterless, 816 high), 64 wide, wide mask */

 /* Ted's last 2 requests */
  {87, 0, NOMASK, 1, 1, 0, 0, 127, 63, 0, 0, 0},        /* 1024x2048 2x2 summing w/o a mask */
  {88, 0, NOMASK, 1, 1, 0, 0, 127, 31, 0, 0, 0},        /* 1024x2048 2x2 summing w/o a mask */
 
 /* 4 more after 4.27.8 load, Ted again */
  {89, 0, NOMASK, 1, 1, 0, 0,  87,175, 0, 0, 0},        /* 2816x1408 2x2 summing w/o a mask */
  {90, 0, NOMASK, 1, 1, 0, 0,  87, 87, 0, 0, 0},        /* 1408x1408 2x2 summing w/o a mask */
  {91, 0, NOMASK, 1, 1, 0, 0,  87, 43, 0, 0, 0},        /*  704x1408 2x2 summing w/o a mask */
  {92, 0, NOMASK, 1, 1, 0, 0,  87, 21, 0, 0, 0},        /*  352x1408 2x2 summing w/o a mask */
 /* some more, 1x1 versions of above */
  {93, 0, NOMASK, 0, 0, 0, 0,  87,175, 0, 0, 0},	/* 2816x1408 1x1 summing w/o a mask */
  {94, 0, NOMASK, 0, 0, 0, 0,  87, 87, 0, 0, 0},	/* 1408x1408 1x1 summing w/o a mask */
  {95, 0, NOMASK, 0, 0, 0, 0,  87, 43, 0, 0, 0},	/*  704x1408 1x1 summing w/o a mask */
  {96, 0, NOMASK, 0, 0, 0, 0,  87, 21, 0, 0, 0},	/*  352x1408 1x1 summing w/o a mask */
 /* 2/26/2008 tables */
  {97, 0, NOMASK, 0, 0, 0, 0,   3,  3, 0, 0, 0},	/*  64x64 cutout (mostly for dummy frames) */
  {98, 0, NOMASK, 1, 1, 0, 0, 127, 255, 1, 1, 0},	/* full size, 2x2 binning, 2x2 summing */
  {99, 0, NOMASK, 1, 1, 0, 0, 127, 215, 1, 1, 0},	/* 3456x2048, 2x2 binning, 2x2 summing */
  {100,0, NOMASK, 1, 1, 0, 0, 127, 127, 1, 1, 0},	/* 2048x2048, 2x2 binning, 2x2 summing */
  {101,0, NOMASK, 1, 1, 0, 0,  63,  63, 1, 1, 0},	/* 1024x1024, 2x2 binning, 2x2 summing */
  {102,0, NOMASK, 1, 1, 0, 0,  63, 127, 1, 1, 0},	/* 2048x1024, 2x2 binning, 2x2 summing */
  {103,0, NOMASK, 1, 1, 0, 0,  127, 63, 1, 1, 0},	/* 1024x2048, 2x2 binning, 2x2 summing */
  {104,0, NOMASK, 1, 1, 0, 0,  87, 175, 1, 1, 0},	/* 2816x1408, 2x2 binning, 2x2 summing */
  {105,0, NOMASK, 1, 1, 0, 0,  87,  87, 1, 1, 0},	/* 1408x1408, 2x2 binning, 2x2 summing */
  {106,0, NOMASK, 1, 1, 0, 0,  43,  87, 1, 1, 0},	/* 1408x704, 2x2 binning, 2x2 summing */
  {107,0, NOMASK, 1, 1, 0, 0, 101, 101, 1, 1, 0},	/* 1536x1536, 2x2 binning, 2x2 summing */
  {108,0, NOMASK, 1, 1, 0, 0, 127, 101, 1, 1, 0},	/* 1536x2048, 2x2 binning, 2x2 summing */
  {109,0, NOMASK, 1, 1, 0, 0, 127, 47, 1, 1, 0},	/* 768x2048, 2x2 binning, 2x2 summing */
  {110,0, NOMASK, 1, 1, 0, 0, 127, 31, 1, 1, 0},	/* 512x2048, 2x2 binning, 2x2 summing */
  {111,0, NOMASK, 1, 1, 0, 0, 127, 15, 1, 1, 0},	/* 256x2048, 2x2 binning, 2x2 summing */
  {112,0, NOMASK, 1, 1, 0, 0,  31, 127, 1, 1, 0},	/* 2048x512, 2x2 binning, 2x2 summing */
  {113,0, NOMASK, 1, 1, 0, 0,  15, 127, 1, 1, 0},	/* 2048x256, 2x2 binning, 2x2 summing */
  {114,0, NOMASK, 1, 1, 0, 0,  87,  43, 1, 1, 0},	/* 704x1408, 2x2 binning, 2x2 summing */

   858 * 0						/* end of list, 143 empties */
};
#define MAX_FRAMES sizeof(FDBarray)/sizeof(fbd_flt)

 short FGobsTable[4096] = {
  /* insert hex of table load here */
 // new table, 8/25/2003 - r. shine
 // new table, 3/26/2004 - r. shine
 // new table, 4/22/2004 - r. shine
 // new table, 4/26/2004 - r. shine
 // new table, 4/28/2004 - r. shine total table size = 862
 // new table, 1/07/2006 - r. shine total table size = 1446
 // new table, 1/08/2006 - r. shine total table size = 1502
 // new table, 1/12/2006 - r. shine total table size = 1534
 // new table, 1/12/2006 - r. shine total table size = 1638
 // new table, 7/21/2007 - r. shine total table size = 1896
 // new table, 7/27/2007 - r. shine total table size = 2066
 // for new load 6/18/2008
 // new table, 11/1/2007 - r. shine total table size = 2116, 4 new ones for TDT
 // new table, 11/17/2007 - r. shine total table size = 2426, 8 new ones
 // new table, 2/26/2008  - r. shine total table size = 2782, 10 new ones
 // new table, 3/5/2008   - r. shine total table size = 2730, 8 corrected, 2 removed 
 0xaa88, 0x000a, 0x0101, 0x1000, 000000, 000000, 0x3000, 0xaa88, 0x000a, 0x1501,
 0x1000, 0x0001, 000000, 0x3000, 0xaa88, 0x000a, 0x1601, 0x1000, 0x0002, 000000,
 0x3000, 0xaa88, 0x000a, 0x1701, 0x1000, 0x0003, 000000, 0x3000, 0xaa88, 0x000a,
 0x1801, 0x1000, 0x0004, 000000, 0x3000, 0xaa88, 0x000a, 0x1901, 0x1000, 0x0005,
 000000, 0x3000, 0xaa88, 0x000a, 0x1a01, 0x1000, 0x0006, 000000, 0x3000, 0xaa88,
 0x000a, 0x1b01, 0x1000, 0x0007, 000000, 0x3000, 0xaa88, 0x0010, 0x0202, 0x2000,
 000000, 000000, 0x1200, 0x0004, 000000, 0x1492, 0xaa88, 0x001c, 0x2802, 0x4000,
 000000, 000000, 0x1200, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1692, 0x000c,
 000000, 0x1492, 0xaa88, 0x0028, 0x2902, 0x6000, 000000, 000000, 0x1200, 0x0004,
 000000, 0x1492, 0x0008, 000000, 0x1692, 0x000c, 000000, 0x1492, 000000, 000000,
 0x1692, 0x0004, 000000, 0x1492, 0xaa88, 0x0034, 0x2a02, 0x8000, 000000, 000000,
 0x1200, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1692, 0x000c, 000000, 0x1492,
 000000, 000000, 0x1692, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1692, 0x000c,
 000000, 0x1492, 0xaa88, 0x0034, 0x1111, 0x8000, 000000, 000000, 0x1200, 0x0001,
 000000, 0x169a, 0x0002, 000000, 0x16da, 0x0003, 000000, 0x16d2, 0x0004, 000000,
 0x1492, 0x0005, 000000, 0x149a, 0x0006, 000000, 0x14da, 0x0007, 000000, 0x14d2,
 0xaa88, 0x0034, 0x0303, 0x8000, 000000, 000000, 0x1200, 0x0001, 000000, 0x169a,
 0x0002, 000000, 0x16da, 0x0003, 000000, 0x16d2, 0x0004, 000000, 0x1492, 0x0005,
 000000, 0x149a, 0x0006, 000000, 0x14da, 0x0007, 000000, 0x14d2, 0xaa88, 0x001c,
 0x3903, 0x4000, 0x04f5, 000000, 0x1040, 0x01a7, 000000, 0x149a, 0x04a8, 000000,
 0x16da, 0x015a, 000000, 0x1692, 0xaa88, 0x0064, 0x3a03, 000000, 000000, 000000,
 0x1200, 0x0001, 000000, 0x169a, 0x0002, 000000, 0x16da, 0x0003, 000000, 0x16d2,
 0x0004, 000000, 0x1492, 0x0005, 000000, 0x149a, 0x0006, 000000, 0x14da, 0x0007,
 000000, 0x14d2, 0x0008, 000000, 0x1692, 0x0009, 000000, 0x169a, 0x000a, 000000,
 0x16da, 0x000b, 000000, 0x16d2, 0x000c, 000000, 0x1492, 0x000d, 000000, 0x149a,
 0x000e, 000000, 0x14da, 0x000f, 000000, 0x14d2, 0xaa88, 0x0034, 0x0404, 0x8000,
 000000, 0xffa6, 0x1b24, 0x0004, 0xffa6, 0x1db6, 000000, 0xffe2, 0x1692, 0x0004,
 0xffe2, 0x1492, 000000, 0x001e, 0x1492, 0x0004, 0x001e, 0x1692, 000000, 0x005a,
 0x1db6, 0x0004, 0x005a, 0x1fb6, 0xaa88, 0x0034, 0x0505, 0x8000, 000000, 0xffa6,
 0x1b24, 0x0004, 0xffa6, 0x1db6, 000000, 0xffe2, 0x1692, 0x0004, 0xffe2, 0x1492,
 000000, 0x001e, 0x1492, 0x0004, 0x001e, 0x1692, 000000, 0x005a, 0x1db6, 0x0004,
 0x005a, 0x1fb6, 0xaa88, 0x001c, 0x0606, 0x4000, 000000, 0xffc4, 0x1200, 0x0004,
 0xffc4, 0x1492, 000000, 0x003c, 0x1492, 0x0004, 0x003c, 0x1692, 0xaa88, 0x001c,
 0x0707, 0x4000, 000000, 0xffc4, 0x1200, 0x0004, 0xffc4, 0x1492, 000000, 0x003c,
 0x1492, 0x0004, 0x003c, 0x1692, 0xaa88, 0x0010, 0x0808, 0x2000, 000000, 0xffc4,
 0x1200, 0x0004, 0xffc4, 0x1492, 0xaa88, 0x001c, 0x0909, 0x4000, 000000, 0xffa6,
 0x1200, 000000, 0xffe2, 0x1693, 000000, 0x001e, 0x1493, 000000, 0x005a, 0x1492,
 0xaa88, 0x001c, 0x3209, 0x4000, 000000, 0xff88, 0x1200, 000000, 0xffd8, 0x1693,
 000000, 0x0028, 0x1493, 000000, 0x0078, 0x1492, 0xaa88, 0x001c, 0x3309, 0x4000,
 000000, 0xffc4, 0x1200, 000000, 0xffec, 0x1693, 000000, 0x0014, 0x1493, 000000,
 0x003c, 0x1492, 0xaa88, 0x001c, 0x0a0a, 0x4000, 000000, 0xffa6, 0x1200, 000000,
 0xffe2, 0x1693, 000000, 0x001e, 0x1493, 000000, 0x005a, 0x1492, 0xaa88, 0x001c,
 0x340a, 0x4000, 000000, 0xff88, 0x1200, 000000, 0xffd8, 0x1693, 000000, 0x0028,
 0x1493, 000000, 0x0078, 0x1492, 0xaa88, 0x001c, 0x350a, 0x4000, 000000, 0xffc4,
 0x1200, 000000, 0xffec, 0x1693, 000000, 0x0014, 0x1493, 000000, 0x003c, 0x1492,
 0xaa88, 0x0010, 0x0b0b, 0x2000, 000000, 0xffc4, 0x1200, 000000, 0x003c, 0x1492,
 0xaa88, 0x0010, 0x300b, 0x2000, 000000, 0xffa6, 0x1200, 000000, 0x005a, 0x1492,
 0xaa88, 0x0010, 0x310b, 0x2000, 000000, 0xffd3, 0x1200, 000000, 0x002d, 0x1492,
 0xaa88, 0x001c, 0x2020, 0x4000, 000000, 000000, 0x1200, 0x0004, 000000, 0x1492,
 0x0008, 000000, 0x1692, 0x000c, 000000, 0x1492, 0xaa88, 0x001c, 0x2c20, 0x4000,
 000000, 000000, 0x1204, 0x0004, 000000, 0x1496, 0x0008, 000000, 0x1696, 0x000c,
 000000, 0x1496, 0xaa88, 0x0034, 0x2121, 0x8000, 000000, 000000, 0x1200, 0x0001,
 000000, 0x169a, 0x0002, 000000, 0x16da, 0x0003, 000000, 0x16d2, 0x0004, 000000,
 0x1492, 0x0005, 000000, 0x149a, 0x0006, 000000, 0x14da, 0x0007, 000000, 0x14d2,
 0xaa88, 0x0034, 0x2b21, 0x8000, 000000, 000000, 0x1204, 0x0001, 000000, 0x169e,
 0x0002, 000000, 0x16de, 0x0003, 000000, 0x16d6, 0x0004, 000000, 0x1496, 0x0005,
 000000, 0x149e, 0x0006, 000000, 0x14de, 0x0007, 000000, 0x14d6, 0xaa88, 0x0034,
 0x3621, 0x8000, 000000, 000000, 0x1a04, 0x0001, 000000, 0x1e9e, 0x0002, 000000,
 0x1ede, 0x0003, 000000, 0x1ed6, 0x0004, 000000, 0x1c96, 0x0005, 000000, 0x1c9e,
 0x0006, 000000, 0x1cde, 0x0007, 000000, 0x1cd6, 0xaa88, 0x001c, 0x2222, 0x4000,
 0x0001, 000000, 0x1008, 0x0003, 000000, 0x1492, 0x0005, 000000, 0x149a, 0x0007,
 000000, 0x1492, 0xaa88, 0x001c, 0x2d22, 0x4000, 0x0001, 000000, 0x100c, 0x0003,
 000000, 0x1496, 0x0005, 000000, 0x149e, 0x0007, 000000, 0x1496, 0xaa88, 0x001c,
 0x2323, 0x4000, 000000, 000000, 0x1000, 0x0002, 000000, 0x14d2, 0x0004, 000000,
 0x1492, 0x0006, 000000, 0x14d2, 0xaa88, 0x001c, 0x2e23, 0x4000, 000000, 000000,
 0x1004, 0x0002, 000000, 0x14d6, 0x0004, 000000, 0x1496, 0x0006, 000000, 0x14d6,
 0xaa88, 0x001c, 0x2424, 0x4000, 000000, 000000, 0x1200, 0x0002, 000000, 0x16d2,
 0x0004, 000000, 0x1492, 0x0006, 000000, 0x14d2, 0xaa88, 0x001c, 0x2f24, 0x4000,
 000000, 000000, 0x1204, 0x0002, 000000, 0x16d6, 0x0004, 000000, 0x1496, 0x0006,
 000000, 0x14d6, 0xaa88, 0x001c, 0x2626, 0x4000, 000000, 000000, 0x1200, 0x0002,
 000000, 0x16d2, 0x0004, 000000, 0x1492, 0x0006, 000000, 0x14d2, 0xaa88, 0x001c,
 0x3726, 0x4000, 000000, 000000, 0x1204, 0x0002, 000000, 0x16d6, 0x0004, 000000,
 0x1496, 0x0006, 000000, 0x14d6, 0xaa88, 0x0034, 0x2727, 0x8000, 000000, 000000,
 0x1200, 0x0001, 000000, 0x169a, 0x0002, 000000, 0x16da, 0x0003, 000000, 0x16d2,
 0x0004, 000000, 0x1492, 0x0005, 000000, 0x149a, 0x0006, 000000, 0x14da, 0x0007,
 000000, 0x14d2, 0xaa88, 0x0034, 0x3827, 0x8000, 000000, 000000, 0x1204, 0x0001,
 000000, 0x169e, 0x0002, 000000, 0x16de, 0x0003, 000000, 0x16d6, 0x0004, 000000,
 0x1496, 0x0005, 000000, 0x149e, 0x0006, 000000, 0x14de, 0x0007, 000000, 0x14d6,
 0xaa88, 0x000a, 0x0c0c, 0x1000, 000000, 000000, 0x3000, 0xaa88, 0x000a, 0x0d0d,
 0x1000, 000000, 000000, 0x3000, 0xaa88, 0x000a, 0x1010, 0x1000, 000000, 000000,
 0x3000, 0xaa88, 0x000a, 0x0e0e, 0x1000, 000000, 000000, 0x3000, 0xaa88, 0x000a,
 0x0f0f, 0x1000, 000000, 000000, 0x3000, 0xaa88, 0x0034, 0x3b03, 0x8000, 0x0001,
 000000, 0x1208, 0x0007, 000000, 0x14d2, 0x000e, 000000, 0x14da, 0x0008, 000000,
 0x1692, 0x0003, 000000, 0x16d2, 0x000d, 000000, 0x149a, 0x0004, 000000, 0x1492,
 0x000a, 000000, 0x16da, 0xaa88, 0x0034, 0x3c03, 0x8000, 0x0003, 000000, 0x1240,
 0x000d, 000000, 0x149a, 0x0004, 000000, 0x1492, 0x0002, 000000, 0x16da, 0x0009,
 000000, 0x169a, 0x0007, 000000, 0x14d2, 0x000e, 000000, 0x14da, 0x0008, 000000,
 0x1692, 0xaa88, 0x0016, 0x3d02, 0x3000, 000000, 000000, 0x1a04, 0x000c, 000000,
 0x1492, 0x0008, 000000, 0x1e96, 0xaa88, 0x001c, 0x3e02, 0x4000, 000000, 000000,
 0x1200, 0x000c, 000000, 0x1492, 0x0004, 000000, 0x1492, 000000, 000000, 0x1692,
 0xaa88, 0x001c, 0x3f02, 0x4000, 000000, 000000, 0x1200, 0x000c, 000000, 0x1492,
 0x000c, 000000, 0x1492, 0x0008, 000000, 0x1692, 0xaa88, 0x0034, 0x4002, 0x8000,
 000000, 000000, 0x1200, 0x000c, 000000, 0x1492, 0x000c, 000000, 0x1492, 0x0008,
 000000, 0x1692, 0x0008, 000000, 0x1692, 0x0004, 000000, 0x1492, 0x0004, 000000,
 0x1492, 000000, 000000, 0x1692, 0xaa88, 0x0016, 0x4102, 0x3000, 000000, 000000,
 0x1a04, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1e96, 0xaa88, 0x001c, 0x4202,
 0x4000, 000000, 000000, 0x1200, 0x0004, 000000, 0x1492, 0x0004, 000000, 0x1492,
 0x0008, 000000, 0x1692, 0xaa88, 0x0034, 0x4302, 0x8000, 000000, 000000, 0x1200,
 0x0004, 000000, 0x1492, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1692, 0x0008,
 000000, 0x1692, 0x000c, 000000, 0x1492, 0x000c, 000000, 0x1492, 000000, 000000,
 0x1692, 0xaa88, 0x0034, 0x4403, 0x8000, 000000, 000000, 0x1200, 0x000d, 000000,
 0x149a, 0x000e, 000000, 0x14da, 0x000b, 000000, 0x16d2, 0x000a, 000000, 0x16da,
 0x0007, 000000, 0x14d2, 0x0004, 000000, 0x1492, 0x0001, 000000, 0x169a, 0xaa88,
 0x002e, 0x4503, 0x7000, 0x0c80, 0xff60, 0x1b64, 0x0c8c, 0xff60, 0x1db6, 0x0c80,
 0x00a0, 0x1fbe, 0x0c8c, 0x00a0, 0x14da, 0x0c88, 0x00a0, 0x1fbe, 0x0c8c, 0xff60,
 0x1db6, 0x0c88, 0xff60, 0x1ff6, 0xaa88, 0x002e, 0x4603, 0x7000, 0x0c80, 0xff60,
 0x1b64, 0x0c84, 0xff60, 0x1db6, 0x0c80, 0x00a0, 0x1fbe, 0x0c84, 0x00a0, 0x14da,
 0x0c88, 0x00a0, 0x1fbe, 0x0c84, 0xff60, 0x1db6, 0x0c88, 0xff60, 0x1ff6, 0xaa88,
 0x000a, 0x4701, 0x1000, 000000, 0xf060, 0x3000, 0xaa88, 0x000a, 0x4801, 0x1000,
 000000, 0x0fa0, 0x3000, 0xaa88, 0x001c, 0x4907, 0x4000, 000000, 0xff74, 0x1000,
 000000, 0x008c, 0x1692, 000000, 0x008c, 0x1692, 000000, 0xff74, 0x1492, 0xaa88,
 0x002e, 0x4a03, 0x7000, 0x0c80, 0xff88, 0x1b64, 0x0c8c, 0xff88, 0x1db6, 0x0c80,
 0x0078, 0x1fbe, 0x0c8c, 0x0078, 0x14da, 0x0c88, 0x0078, 0x1fbe, 0x0c8c, 0xff88,
 0x1db6, 0x0c88, 0xff88, 0x1ff6, 0xaa88, 0x002e, 0x4b03, 0x7000, 0x0c80, 0xff88,
 0x1b64, 0x0c84, 0xff88, 0x1db6, 0x0c80, 0x0078, 0x1fbe, 0x0c84, 0x0078, 0x14da,
 0x0c88, 0x0078, 0x1fbe, 0x0c84, 0xff88, 0x1db6, 0x0c88, 0xff88, 0x1ff6, 0xaa88,
 0x002e, 0x4c03, 0x7000, 0x0c80, 0xff8c, 0x1b64, 0x0c8c, 0xff8c, 0x1db6, 0x0c80,
 0x0074, 0x1fbe, 0x0c8c, 0x0074, 0x14da, 0x0c88, 0x0074, 0x1fbe, 0x0c8c, 0xff8c,
 0x1db6, 0x0c88, 0xff8c, 0x1ff6, 0xaa88, 0x002e, 0x4d03, 0x7000, 0x0c80, 0xff8c,
 0x1b64, 0x0c84, 0xff8c, 0x1db6, 0x0c80, 0x0074, 0x1fbe, 0x0c84, 0x0074, 0x14da,
 0x0c88, 0x0074, 0x1fbe, 0x0c84, 0xff8c, 0x1db6, 0x0c88, 0xff8c, 0x1ff6, 0xaa88,
 0x001c, 0x4e09, 0x4000, 000000, 0xff74, 0x1000, 000000, 0x008c, 0x1692, 000000,
 0x008c, 0x1692, 000000, 0xff74, 0x1492, 0xaa88, 0x001c, 0x4f09, 0x4000, 000000,
 0xff60, 0x1000, 000000, 0x00a0, 0x1692, 000000, 0x00a0, 0x1692, 000000, 0xff60,
 0x1492, 0xaa88, 0x001c, 0x5009, 0x4000, 000000, 0xff8c, 0x1000, 000000, 0x0074,
 0x1692, 000000, 0x0074, 0x1692, 000000, 0xff8c, 0x1492, 0xaa88, 0x001c, 0x5106,
 0x4000, 000000, 000000, 0x1200, 0x000c, 000000, 0x1492, 0x0004, 000000, 0x1492,
 000000, 000000, 0x1692, 0xaa88, 0x001c, 0x5206, 0x4000, 000000, 000000, 0x1200,
 0x000c, 000000, 0x1492, 0x000c, 000000, 0x1492, 0x0008, 000000, 0x1692, 0xaa88,
 0x0034, 0x5304, 0x8000, 000000, 000000, 0x1200, 0x000c, 000000, 0x1492, 0x000c,
 000000, 0x1492, 0x0008, 000000, 0x1692, 0x0008, 000000, 0x1692, 0x0004, 000000,
 0x1492, 0x0004, 000000, 0x1492, 000000, 000000, 0x1692, 0xaa88, 0x001c, 0x5406,
 0x4000, 000000, 000000, 0x1200, 0x0004, 000000, 0x1492, 0x0004, 000000, 0x1492,
 0x0008, 000000, 0x1692, 0xaa88, 0x0034, 0x5504, 0x8000, 000000, 000000, 0x1200,
 0x0004, 000000, 0x1492, 0x0004, 000000, 0x1492, 0x0008, 000000, 0x1692, 0x0008,
 000000, 0x1692, 0x000c, 000000, 0x1492, 0x000c, 000000, 0x1492, 000000, 000000,
 0x1692, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000, 000000,
  /* expand to 4096 shorts */
 2726 * 000000 };

 /*------------------------------------------------------------------------- */
void throwErr( UINT16 errcode)
{
  printf("throwErr got a 0x%x\n", errcode);
}
 /*------------------------------------------------------------------------- */
void throwErr5( UINT16 errcode, UINT16 p1, UINT16 p2, UINT16 p3, UINT16 p4 )
{
  printf("throwErr got a 0x%x\n", errcode);
}
 /*------------------------------------------------------------------------- */
int decode_fdb(int fdb_id, fg_expanded_parameters* fg_p)
 {
 /* decodes a frame definition block */
 fbd_flt	*fdbp;
 int		count, fid, fdb_pixel_unit;
 /* find the table for this id (or return an error) */
 /* decode the bit fields into a more convenient form in fdb */
 /* search the table of fdb's for this ID, an ID of 0 marks end of
 table, also we have the # of fdb's stored in num_fdbs. This is the
 maximum size of the table */
 fdb_pixel_unit = FDB_PIXEL_UNIT;
 fdbp = FDBarray;
 count = 0;
 /* note that an ID of 0 marks end of table */
 printf("fdb_id = %d\n", fdb_id);
 while (fid = fdbp->fid) {
  printf("fid = %d\n", fid);
  if (fid == fdb_id) {
   /* got it, decode it into the passed structure */
   //printf("found fid %d\n", fid);
   fg_p->ccd_mode = fdbp->ccd_mode;
   fg_p->mask = fdbp->mask_position;
   fg_p->sumx = fdbp->row_sum;
   fg_p->sumy = fdbp->col_sum;
   fg_p->binx = fdbp->row_bin;
   fg_p->biny = fdbp->col_bin;
   fg_p->shutter_mode = fdbp->shutter_mode;
   fg_p->nxCCD = ((fdbp->width + 1)* fdb_pixel_unit);
   fg_p->nyCCD = ((fdbp->height + 1)* fdb_pixel_unit);
   /* the width and height can't be more than 4096 and 2048, clamp just in case */
   fg_p->nxCCD = MIN(fg_p->nxCCD, 2048);
   fg_p->nyCCD = MIN(fg_p->nyCCD, 4096);
   //printf("fdb nxCCD, nyCCD = %d %d\n", fg_p->nxCCD, fg_p->nyCCD);
   return 0;
   }
  fdbp++;
  if (count++ >= MAX_FRAMES) break;
  }
 /* we throw this error in the caller */
 return 1;
 }
 /*------------------------------------------------------------------------- */
int unpackFGtable(int id)
 {
 /* 7/22/2002 - also create the smart memory table, only used for shutterless */
 /* look for and unpack table id */
 short	synch, offset, woff;
 char	*p;
 int	nim, nsize, npsize, i, sanity, phase, nphases, lastphase, ip, gapcarry;
 int	shutterless_flag, thisID;
 p = (char *) FGobsTable;  /* start of the table */
 sanity = 255;	/* a sanity countdown just in case */
 while (1) {	/* scan until we find our target or reach end of table
 		or find an error */
 synch = X_SHORT(p,0);
 /* because we have the table defined as a series of shorts, we have to
 swap synch now (rather than swap the whole table and cause other problems) */
#if linux | LITTLEENDIAN
 printf("little endian situation\n");
 swapb(&synch, 2);
#endif
 if ( synch != (short) 0xaa88) {
   if (synch == 0) {
    throwErr5(FG_NO_SUCH_OBS_ID_ERR, id,0,0,0);
    //printf("end of table, target ID not found\n");
   } else {
    throwErr5(FG_BAD_SYCN_OBS_ID_ERR, id,0,0,0);
    //printf("bad synch in FG table = %d\n", synch);
    }
    return 1;
   }
 offset = X_SHORT(p,2);
#if linux | LITTLEENDIAN
 swapb(&offset, 2);
 /* clumsy but avoids copying the structure just to check the id */
 thisID = (int) p[5];
#else
 thisID = (int) p[4];
#endif

 //if (p[4] == (unsigned char) id) {
 if (thisID == (unsigned char) id) {
   /* found the target, unpack it */
   p = p + 4;
   bcopy(p, (char *) &FGpackedHeader, sizeof(FGobsDefHeader));
   p += sizeof(FGpackedHeader);
   /* check nimages */
   nim = FGpackedHeader.nimages;
   /* bump up to 16 if we got 0 */
   if (nim == 0) nim = 16;
   /* don't mess with the FGdact unless it is shutterless */
   if (FGpackedHeader.gen_function > 31) shutterless_flag = 1; else shutterless_flag = 0;
   printf("shutterless_flag = %d\n", shutterless_flag);
//    if (shutterless_flag) {
//      /* make sure the semaphore is off */
//      semTake(semExpose, NO_WAIT);
//      FGdact.semaphore = semExpose;
//    }
   FGunpackedObsTable.obs_id = id;
   
   FGunpackedObsTable.gen_function = FGpackedHeader.gen_function;
   FGunpackedObsTable.nimages = nim;
   FGunpackedObsTable.repeat_count = FGpackedHeader.repeat_count;
   /* the offset can be checked against nimages */
   nsize = sizeof(FGobsDefHeader) + nim * 6;
   if (offset != nsize) {
    throwErr5(FG_BAD_OFFSET_OBS_ERR,offset, nsize, 0,0);
    //printf("offset and nsize disagree, %d vs %d\n", offset, nsize);
    return 1;
    }
   /* unpack the image parameters */
   npsize = sizeof(FGimageParameters) - sizeof(params.junk);
   gapcarry = 0;
   //printf("# of camera frames in table %d\n", nim);
   for (i=0; i<nim;i++) {
    bcopy(p, (char *) &FGpackedParameters, npsize);
    p = p + npsize;
    FGunpackedObsTable.p[i].delay = FGpackedParameters.delay;
    phase = FGpackedParameters.phase;
    //printf("phase = %d\n", phase);
    /* don't mess with the FGdact unless it is shutterless */
    if (shutterless_flag) {
      if (i == 0) {
	 FGdact.start_phase = phase;  nphases = 1; lastphase = phase;
	 ip = 0;
       } else {
	 /* check for skipped phases, this indicates integrations that are
	 longer than 0.1s and means we have to pack the phase gap with
	 appropiate commands */
	 //printf("i = %d, ip = %d, phase, lastphase = %d, %d\n", i,ip,phase,lastphase);
	 while (phase < lastphase) phase = phase + 16;  /*wraparound? */
	 if ( (phase - lastphase) > 1) {
           /* fill the gap, shifting the DMA config */
	   int ngap = (phase - lastphase) - 1;
	   /* ip is still the last entry filled, shift up and backfill with NOOP's */
	   FGdact.p[ip+ngap].DMA_config =FGdact.p[ip].DMA_config;
	   gapcarry = ngap;
	   while (ngap--) {
	     nphases++;
	     /* note that the very first one is or'ed with LONGFGFLAG and used in pmuISRfg
	     to detect long integrations, the lower 16 bits (containing the config) must be
	     preserved since they are used for the throwaway read */
	     if (ip == 0) FGdact.p[ip].DMA_config |= LONGFGFLAG; else FGdact.p[ip].DMA_config = NOOP;
	     ip++;
	   }
	 }
	 ip++;  nphases++;
	 lastphase = phase;
      }
    }
    FGunpackedObsTable.p[i].phase = phase;
    /* 3/18/2004 - the addWaveOffset member is now a signed short, it was a 12
    bit field which then required the sign extension below */
    woff = FGpackedParameters.addWaveOffset;
    //if (woff & (short) 0x0800) woff = woff | (short) 0xf000;
    FGunpackedObsTable.p[i].addWaveOffset = woff;
    FGunpackedObsTable.p[i].DMA_buffer_mode = FGpackedParameters.DMA_buffer_mode;
    FGunpackedObsTable.p[i].DMA1_scale = FGpackedParameters.DMA1_scale;
    FGunpackedObsTable.p[i].DMA1_op = FGpackedParameters.DMA1_op;
    FGunpackedObsTable.p[i].DMA2_scale = FGpackedParameters.DMA2_scale;
    FGunpackedObsTable.p[i].DMA2_op = FGpackedParameters.DMA2_op;
    FGunpackedObsTable.p[i].DMA3_scale = FGpackedParameters.DMA3_scale;
    FGunpackedObsTable.p[i].DMA3_op = FGpackedParameters.DMA3_op;
    FGunpackedObsTable.p[i].DMA4_scale = FGpackedParameters.DMA4_scale;
    FGunpackedObsTable.p[i].DMA4_op = FGpackedParameters.DMA4_op;
    FGunpackedObsTable.p[i].DMA_config =
		  (int) *(short *)((char *) &FGpackedParameters + 4);
    /* don't mess with the FGdact unless it is shutterless */
    if (shutterless_flag) {
     /* command below subject to shifting if a gap */
     FGdact.p[ip].DMA_config = FGunpackedObsTable.p[i].DMA_config;
     /* camera commands not supported anymore (could make a comeback?) */ 
     //FGdact.p[ip].camcmd = NOOP;
     if (ip >= MAXOBSIMAGES) {
      //printf("FGdact table overflow, FG observation terminated\n");
      throwErr5(FG_NO_SUCH_OBS_ID_ERR, id,0,0,0);
      return 1;
      }
   }
   }   /* end of for (i=0; i<nim;i++) */
   /* don't mess with the FGdact unless it is shutterless */
   if (shutterless_flag) {
     /* there may still be an end game if we have a gapcarry */
     if (gapcarry > 0) {
	   FGdact.p[ip + gapcarry].DMA_config = FGdact.p[ip].DMA_config;	   
	   while (gapcarry--) {
	     nphases++;
	     FGdact.p[ip++].DMA_config = PMUISR_NOOP;
	   }

     }
   FGdact.nphases = nphases;
//    if (PMUdebug) printf("starting phase (for first integration) = %d, number of phases = %d\n",
//    	FGdact.start_phase, nphases);
   }
   
   return 0;
   }
 /* not found, keep looking */
 if ( --sanity <= 0) {
   throwErr5(FG_NO_SUCH_OBS_ID_ERR, id,1,0,0);
   //printf("FG table search exceeds the sane limit\n");
   return 1;
  }
 p = p + 4 + offset;
 }
 }
 /*------------------------------------------------------------------------- */
int ana_fppmacroread(narg,ps)
 int narg, ps[];
 /* a function, takes a raw macro command returns a status, the status is 0 for success */
 {
 char * macro_com;
 int 	n, class;
 int	ixc, iyc, ix0, iy0, ix1, iy1, rq, rqd2;
 int	dxm1, dym1, stat, gen_func;
 int	sub1_flag, sub2_flag, ny1, ny2, ny, nxp, nyp, nx, npack1, npack2;
 int	iq, y2s, iscale, tf_flag, loop_count = 0;
 int	status2Size, shutterLessFlag;
 fg_expanded_parameters		fg_p;
 iq = ps[0];
 n = get_p_c(&iq, &macro_com);
 class = sym[iq].class;
 if (class != ARRAY) return execute_error(66);
 if (n < sizeof(fg_macro_command)) {
 	printf("FPPMACROREAD, MC too small, n = %d\n", n);
	return -1; }
 bcopy(macro_com+1, (char *) &fg_current_macro, sizeof(fg_macro_command));
#if linux | LITTLEENDIAN
 printf("little endian MC swab\n");
 swapb(&fg_current_macro,sizeof(fg_macro_command) );
#endif
 
 printf("fg_obs begins ...\n");
 /* indicate start of FG observation */
 //fgStatus2.FPP_FG_state = 1;
 /* fg_executing_flag now set before giving sem_fg_run for better protection of macro
 command copy */
 //fg_executing_flag = 1;
 /* set the status fields for 0.25 status */
 /* but the fg_ready has changed, it only goes to 0 if we have both a current
 and pending FG command, so now handle it in process_fg_macro_command */
 //fgStatus1.fg_ready = 0;
 //fgStatus1.fg_id = (fg_current_macro.main_id & 0x7f);

 /* decode the fg macro command and put values in expanded format */
 /* we are working with fg_current_macro */
 fg_p.obs_id = fg_current_macro.parameters.obs_id;
 //logMsg("fg_p.obs_id = %d\n",fg_p.obs_id,0,0,0,0,0);
 printf("fg_p.obs_id = %d\n", fg_p.obs_id);
 /* a special escape here for buffer flushing, this is an FG with ID 255
 but don't want to check that the rest is legal so just handle inline here */
 /* removed 4/30/2004 - hasn't been used for a while since it crashes the
 "fixed" FEP, people now flush with a small FG image which has its problems
 when system isn't fully up */
  /* re-cycle 255 for a delay, use exposure time for delay */
  if (fg_p.obs_id == 255) {
   /* compute the # of ticks to match the exposure parameter */
   int ticks = (fg_current_macro.parameters.exp * 14848)/100000;
   //taskDelay(ticks);
   //   flush8k();
   goto wrap_up; }
/* allow for a no-op FG macro command with obs ID 254 */
  if (fg_p.obs_id == 254) {
   goto wrap_up; }
  if (fg_p.obs_id == 253) {
   /* to avoid decoding and possible mechanism calls, do the looping for this mode
   entirely here */
   while (1) {
     if (fg_stop_flag) {
 	    loop_flag = 0;  //printf("looped ended via stop command\n");
	    fg_stop_flag = 0;
	    break; }
     //fgStatus2.obs_count++;
     //fgStatus2.obs_frame_count = 0;		/* reset frame counter in this obs */
     printf("testPackets called\n");
     //testPackets(1);
     loop_count++;
     if (loop_count > loop_limit) { /* printf("hit FG loop limit\n");*/ loop_count = 0; loop_flag = 0; }
     if (!loop_flag) break; //else taskDelay(fg_pad_time);
   }
   goto wrap_up; }
 fg_p.frame_def_id = fg_current_macro.parameters.frame_def_id;
 /* also set these ID's in the status 2 area */
 //fgStatus2.obs_id = fg_p.obs_id;
 /* the obs_id just tells us which table to get (later), the table tells
 us what kind of observation it actually is */
 //fgStatus2.fdb_id = fg_p.frame_def_id;
 
 fg_p.wave = fg_current_macro.parameters.wave;
 /* note - for wave_off the units are 4mA for the macro parameter but 1 mA in fp_p */
 fg_p.wave_off = fg_current_macro.parameters.wave_off;
 /* the offset wavelength is actually a signed quantity */
 if (fg_p.wave_off & (short) 0x0400) fg_p.wave_off = fg_p.wave_off | (short) 0xf800;
 /* now mulitple by 4 (unit change noted above) */
 fg_p.wave_off = fg_p.wave_off * 4;
 fg_p.exposure = fg_current_macro.parameters.exp;
 /* 6/26/2003 - add support for a default exposure set via ctSetOpParam */
 if (fg_p.exposure == 0) fg_p.exposure = defaultExposure;
 fg_p.dark_flag = fg_current_macro.parameters.dark_flag;
 /* find the fdb and load an expanded version */
 fg_p.wscan_npos = (short) fg_current_macro.parameters.wscan_npos;
 /* we will add 1 to fg_p.wscan_npos using (later though) */
 fg_p.wscan_step = (short) fg_current_macro.parameters.wscan_step;
 /* this wave step is signed, so ... */
 if (fg_p.wscan_step & (short) 0x0400) fg_p.wscan_step = fg_p.wscan_step | (short) 0xf800;
 if (decode_fdb(fg_p.frame_def_id, &fg_p)) {
   throwErr5(FG_NO_SUCH_FDB_ERR, fg_p.frame_def_id,0,0,0);
   /* code now goes to wrap up section so we can still do next observation */
   goto wrap_up;
   }
 //printf("returned fdb nxCCD, nyCCD = %d %d\n", fg_p.nxCCD, fg_p.nyCCD);
 /* the fdb and the center determine the CCD area */
 /* get the center in pixels, the values we get are arc sec from center of CCD,
 hence the scale is different for BF and TF */
 ixc = fg_current_macro.ext_reg.center_row;  /* this is N/S direction */
 iyc = fg_current_macro.ext_reg.center_col;  /* this is E/W direction */
 /* 4/19/2005 - shutterless mode does not accept a E/W offset, this affects
 some calculations below */
 shutterLessFlag = (int) fg_p.shutter_mode;
 if (shutterLessFlag) iyc = 0;
 /* about the coordinates, the CCD x is solar N/S, x is row index, y is column
 index (or row number) */
 tf_flag = (fg_p.wave >= NFI_NO_MOVE);
 if (tf_flag) iscale = NFI_SCALE; else iscale = BFI_SCALE;
 ixc = (1000 * ixc) / iscale;
 iyc = (1000 * iyc) / iscale;
 /* offset to center (actually a half pixel beyond) */
 ixc = ixc + 1024;
 iyc = iyc + 2048;
 ix0 = ixc - fg_p.nxCCD/2;
 ix0 = MAX(ix0, 0);	/* clamp at 0 */
 iy0 = iyc - fg_p.nyCCD/2;
 iy0 = MAX(iy0, 0);	/* clamp at 0 */
//  rq = MAX(8, (0x1 << (fg_p.sumx + fg_p.binx)));
//  rq = MAX(rq, (0x1 << (fg_p.sumy + fg_p.biny)));
 /* we have to ensure both sides obey the 8x8 rule regardless of summing or binning */
 rq = 8 * (0x1 << (fg_p.sumx + fg_p.binx));
 rq = MAX(rq, 8 * (0x1 << (fg_p.sumy + fg_p.biny)));
 rqd2 = rq/2;
 ix0 = rq * ((ix0 + rqd2)/rq);
 /* 4/19/2005 - do not apply to iy0 if shutterless, otherwise a FBD with a bad
 width for the halves could be offset. That makes the packet sizes OK but
 we don't want offsets in y for shutterless */
 if (!shutterLessFlag) iy0 = rq * ((iy0 + rqd2)/rq);
 dxm1 = fg_p.nxCCD - 1;
 dym1 = fg_p.nyCCD - 1;
 ix1 = ix0 + dxm1;
 iy1 = iy0 + dym1;
 /* clip the max but don't clip the size (butt, don't crop) */
 if (ix1 > 2047) { ix1= 2047;  ix0 = ix1 - dxm1; }
 if (iy1 > 4095) { iy1= 4095;  iy0 = iy1 - dym1; }
 //printf("CCD area is (%d:%d, %d:%d)\n", ix0, ix1, iy0, iy1);
 /* put these in the structure, may want to make this global? */
 fg_p.ix0 = ix0; fg_p.ix1 = ix1; fg_p.iy0 = iy0; fg_p.iy1 = iy1;
 /* work out how many packets we need for each image (if a set) */
 /* first determine which halves contain some of the image */ 
 if (iy0 <= 2047) sub1_flag = 1; else sub1_flag = 0;
 if (iy1 >  2047) sub2_flag = 1; else sub2_flag = 0;
 /* figure out the ROI parameters, modified 2/25/2003 */
 {
  /* FG has 2 modes, check if we must use full camera mode */
  if (iy0 < 1024 || iy1 > 3072) {
    /* we need to use full readout mode, note that the 1025 acts a flag, each
    side reads out 0:2047 */
    fg_p.roi_start = 0;
    fg_p.roi_stop = 1025;
  } else {
    /* the frame transfer mode, also use for any cutout restricted to the
    middle half */
    /* span the center ? */
    if (sub1_flag && sub2_flag) {
     /* yes, so ... */
    fg_p.roi_start = MIN(iy0, 4095 - iy1) - 1024;
    fg_p.roi_stop = 1024;
  } else {
    /* only one side being used, the camera still does both but we can restrict
    the area somewhat */
    if (sub1_flag) {
      fg_p.roi_start = iy0 -1024;
      fg_p.roi_stop  = iy1 -1024 + 1;
    } else {
      fg_p.roi_start = 4095 - iy1 - 1024;
      fg_p.roi_stop  = 4095 - iy0 - 1024 + 1;
    }
  }
 }
 }

 //printf("ROI start/stop = %d, %d\n", fg_p.roi_start, fg_p.roi_stop);
 ny = iy1 - iy0 + 1;
 nx = ix1 - ix0 + 1;
 /* time to check for sums and bins, note that (ix0:ix1, iy0:iy1) above are in CCD
 units and independent of summing and binning, neither sums/bins affects the ROI. But they
 do affect the image size that is sent */
 fg_p.nx = nx = (fg_p.nxCCD >> (fg_p.sumx + fg_p.binx));
 fg_p.ny = ny = (fg_p.nyCCD >> (fg_p.sumy + fg_p.biny));
 //printf("after summing: nx, ny %d %d\n", nx, ny);
 
 nyp = 65536/nx;	/* defines max y size of a partial image */
 /* 7/21/2007 - ensure nyp is a multiple of 8 */
 nyp = 8 * (nyp/8);
 nxp = nx;		/* all partials have full nx */
 npack1 = npack2 = ny1 = ny2 = 0;
 /* for the LHS (sub1) */
 if (sub1_flag) {
  ny1 = MIN(fg_p.nyCCD, 2048 - iy0);  /* don't use ny, it may have been shifted */
  npack1 = 1;
  /* account for summing/binning, note that this depends on iy0 being rounded properly */
  ny1 = ny1 >> (fg_p.sumy + fg_p.biny);
  iq = ny1;
  while ( (iq = iq - nyp) > 0 ) npack1++;
 }

 /* for the RHS (sub2) */
 if (sub2_flag) {
  y2s = MAX(iy0, 2048);
  ny2 = iy1 - y2s + 1;
  npack2 = 1;
  ny2 = ny2 >> (fg_p.sumy + fg_p.biny);
  iq = ny2;
  while ( (iq = iq - nyp) > 0 ) npack2++;
 }
 /* and some checks to make sure we don't break any size rules */
 if ( (ny1%8) || (ny2%8) ) { throwErr(FG_BAD_CUTOUT_ERR);  goto wrap_up; }

 /* load in fg_obs_p */
 fg_p.ny1 = ny1;		fg_p.ny2 = ny2;
 fg_p.npack1 = npack1;     	fg_p.npack2 = npack2;
 fg_p.nyp = nyp;

 /* use the obs_id to find the appropiate FG table, note that there is only
 one table running at a time, this means that all operations depending on the table must
 be complete before the next FG observation starts up */
 if (unpackFGtable(fg_p.obs_id)) {
   /* if problem, code now goes to wrap up section so we can still do next observation */
   /* don't throw an error here, it would cover the error in unpackFGtable */
   goto wrap_up; }
 gen_func = FGunpackedObsTable.gen_function;

 /* another cutout rule involves using the 4 buffer mode in smart memory with 1x1 summing,
 this affects all gen_func's except 1 and 12-16 at present (1/17/2005) */
 if (gen_func != 1 && (gen_func < 12 || gen_func > 16)) {
   int sq = fg_p.sumy + fg_p.sumx;
   if ( sq == 0) {
     /* here we must have fg_p.roi_start > 512 */
     if (fg_p.roi_start < 512) { throwErr(FG_BAD_4BUF_CUTOUT_ERR);  goto wrap_up; }
   } else if (sq == 1) {
     /* this covers 1x2 and 2x1 cases, they can't be full camera readouts, note that
     we don't actually plan to use these cases but who knows? */
     if (fg_p.roi_stop == 1025) { throwErr(FG_BAD_4BUF_CUTOUT_ERR);  goto wrap_up; }
   }
 }

 /* 9/30/2003 - the check below is obsolete, all observables can use the
 wscan_npos parameter */
 //  /* check if a wavelength scan and if legal for the gen function */
 //  if (fg_p.wscan_npos) {
 //   if ( gen_func != 12 && gen_func !=13 && gen_func !=14 &&  gen_func > 3) {
 //     //printf("********** wavescan illegal for gen function %d\n", gen_func);
 //     throwErr(FG_ILLEGAL_WSCAN_ERR, gen_func,0,0,0);
 //     goto wrap_up; }
 //   }
 /* allow a continuous repeat option */
 while (1) {
 if (fg_stop_flag) {
 	loop_flag = 0;  //printf("looped ended via stop command\n");
	fg_stop_flag = 0;
	break; }
 /* increment the obs count here, hence it reflects the one currently being
 worked on rather than the last one completed */
 //fgStatus2.obs_count++;
 //fgStatus2.obs_frame_count = 0;		/* reset frame counter in this obs */
 /* setup the filter wheel here, we presently assume that the function
 blocks until done */
// disabled
//  stat = movFilter(fg_p.wave, fg_p.mask);
//  if (stat) break;

 /* the gen_function determines which function gets called to take
 the image(s), this comes from the table unpacked above */
 printf("gen f # %d\n", FGunpackedObsTable.gen_function);

// disabled
//  switch (FGunpackedObsTable.gen_function) {
//   case FGmaskless:  		stat = FGmaskless_gf(&fg_p); break;
//   case FGshutteredIV: 		stat = FGshutteredIV_gf(&fg_p); break;
//   /* 1/8/2006 - new mode for shuttered IV using IQUV mode but not downloading
//   the QU and U */
//   case FGshutteredIV2:
//   case FGshutteredStokes:	stat = FGshutteredStokes_gf(&fg_p); break;
//   case FGshutteredMG1:
//   case FGshutteredMG2:
//   case FGshutteredMG4: 		stat = FGshutteredMG_gf(&fg_p); break;
//   case FGshutteredMG2IV:
//   case FGshutteredMG4IV: 	stat = FGshutteredMGIV_gf(&fg_p); break;
//   case FGshutteredDG2:
//   case FGshutteredDG4:  	stat = FGshutteredDG_gf(&fg_p); break;
//   case FGshutteredDG4_A_B:  	stat = FGshutteredDG4_A_B_gf(&fg_p); break;
//   case FGshutteredFocusScan:  	stat = FGmasklessFocus_gf(&fg_p); break;
//   case FGintegratedWaveScanUpdate:
//   case FGintegratedWaveScan:  	stat = FGintegratedWaveScan_gf(&fg_p); break;
//   case FGlaserTune:  		stat = FGlaserTune_gf(&fg_p); break;
//   case FGemiTest:  		stat = FGemiTest_gf(&fg_p); break;
//   /* 4/16/2003 - combine all shutterless into one call */
//   case FGshutterlessIV:
//   case FGshutterlessIQUV:
//   case FGshutterlessIQ:
//   case FGshutterlessIU:
//   case FGshutterlessIUV:
//   /* note that a FGshutterlessIQV mode is not supported */
//   /* new modes to allow longer integration I/V's */
//   case FGshutterlessIV2:
//   case FGshutterlessIV3:
//     stat = FGshutterless_gf(FGunpackedObsTable.gen_function, &fg_p);
//     break;
//   default: 
//     throwErr5(FG_NO_SUCH_GENFUNC_ERR, FGunpackedObsTable.gen_function,0,0,0);
//     //printf("unsupported generating func in fg_obs = %d\n",FGunpackedObsTable.gen_function);
//     loop_flag = 0; break;  /* kill looping if we get this error */
//  }

// disabled
//   if (stat) {
//     /* delay for 3s before throwing an error to avoid masking a previous one
//     that may have led to this */
//     /* don't throw an error here since it would cover the one that caused this */
//     //printf("generating function returned with a STOP or an error\n");
//     taskDelay(450);
//     if (fg_stop_flag) {
//       throwErr5(FG_GEN_STOP_ERR, FGunpackedObsTable.gen_function,0,0,0);
//       fg_stop_flag = 0;
//     } else  throwErr5(FG_GEN_FUNC_ERR, FGunpackedObsTable.gen_function,0,0,0);
//     break;
//     }
   //printf("finished FG loop count %d\n", loop_count);
   loop_count++;
   /* 2/26/2007 - change logic slightly to allow a taskDelay for a single loop */
   //if (loop_count > loop_limit) { /* printf("hit FG loop limit\n");*/ loop_count = 0; loop_flag = 0; }
   //if (!loop_flag) break; else taskDelay(fg_pad_time);
   if (loop_count >= loop_limit) break;
 }
 /* wrap up */
 wrap_up:	/* sorry about the goto, but too many situations where we
 		have an error but still need to get down here because life
		must go on */
 //fgStatus2.FPP_FG_state = 0;
 /* the fg_ready flag has changed, comment out reset here */
 //fgStatus1.fg_ready = 1;
 //printf("**** fg_obs done ***\n");
 /* leave the fgStatus1.stat.fg_id at the last value for the time being */
 
 /* TF blocker stow code added 7/21/2007 */
 /* if blocker stow is activated and no TF MC is pending, we stow to the position */
 if (blockerStowEnable) {
   if (!fg_pending_flag || fg_pending_macro.parameters.wave < NFI_NO_MOVE) {
   /* stow if not already there, movFilter will check, note we use 6 for the mask
   to avoid moving the mask wheel (movFilter was modified to have this feature) */
   printf("call to movFilter with blockerStowWavelengthNum = %d\n", blockerStowWavelengthNum);
   //stat = movFilter(blockerStowWavelengthNum, 6);
   }
 }
 
 /* if nobody pending, we just break, otherwise we go back for more */
 //if (!fg_pending_flag) break;
 /* must have someone waiting in the wings */
 
 //semTake( semFgMCcopy, WAIT_FOREVER );  // DPM; 20040524
 bcopy( (char *) &fg_pending_macro, (char *) &fg_current_macro, sizeof(fg_macro_command));
 //semGive( semFgMCcopy );  // DPM; 20040524
 
 fg_pending_flag = 0;
 //fgStatus1.fg_ready = 1;	/* and now we can pend another command */

 return 4;  /* 4 is an ana zero (symbol), use for success return */
 }
/*----------------------------------------------------------------------*/
