/*============================================================================
                         TRACE Sequencer Instructions

V0.00: 15 Aug 96 Dnyanesh Mathur
       Copied from \trace\trinstr.cpp (v4). This base version contains
       a set of instructions sufficient for a defining an observation
       which takes a set number of pictures.

V0.01: 26 Aug 96 Dnyanesh Mathur
       The instructions setr2v and TSI_stop have been verified.

V0.02: 26 Aug 96 Dnyanesh Mathur
    1. TAPT instruction modified extensively. The state machine is now
       run by the CC. Added SetConfigParam and DecodeFrame routines.

V0.03:  4 Sep 96 Dnyanesh Mathur
    1. Added other time wait routines, Delay and Tim.
    2. Rearranged Opcodes. Defined all 256 possible opcodes. Most map
       to NOI____ (No Instructions).

V0.04: 16 Sep 96 Dnyanesh Mathur
    1. Added STTG instruction. The ACS test will be run with a sequence.
    2. Added Call and Return instructions.

V0.05: 26 Sep 96 Dnyanesh Mathur
    1. Major reassignment of opcodes. This has become necessary to
       streamline operand decoding. The new opcodes are described in
       /tra/opcodes.txt. All opcodes are now decoded by GetOperand function
       in trseq.c.
    2. Added arithmatic instructions (ADD, SUB, MUL and DIV).
    3. Renamed several old instruction routines.

V0.06: 16 Oct 96 Dnyanesh Mathur
    1. Added Wavelength, PZT configuration code in FRAME instruction.
    2. Updated DecFrame routine to reflect the latest format of the
       the Frame Definition Block.
    3. Added an instruction to select CCD Readout Amplitfier and set
       the ADC offset.

v0.07     Apr 97 Dnyanesh Mathur
    1. Corrected start address calculation for extracted regions.
    2. Corrected WAIT 0 error (it used to wait for 65535 tics).
    3. Store error codes in global variables rather than defined symbols.
       This will allow codes to be changed more easily during the mission.
    4. Save TickCount on sequence Calls.
    5. Copy sequence ID to register 14 and 15.
    6. Added a NOID instruction which *does not* set the ID but still
       provides pointer to the next sequence.

v0.08:  8 May 97 Dnyanesh Mathur
    1. Added HTML tags to each instruction function.

v0.09: 12 May 97 Dnyanesh Mathur
    1. Changed FocusPos to s *signed* int to enable both positive and negative
       offsets.
    2. Added RUNDHCP instruction to execute a DHC program.
    3. Added SETDHCR instruction to set a DHC register.  (DEV instruction is
       no longer available).
    4. Added instructions to open and close the ISS loop.

v0.10: 19 Jun 97 Dnyanesh Mathur
    1. Corrected setting of AEC-Execute Flag (AECX) in the IPB. It was being
       if "specific exposure" flag was *not* set in the exposure control word.
    2. Histogram bin is set to 127 if it is greater than 127.
       (AEHB, SFHB, FHB).
    3. Corrected an error in computing AEHC and AELC. Extractsize of 0 was
       not being set to 16. Made similar correction for Rowblocks and
       Column blocks.
    4. Corrected the scaling for ADC Offset. It was divided by 32768 instead
       of 32.

v0.11: 24 Jun 97 Dnyanesh Mathur
    1. Made ADCOffset and Rowlengths tables to global arrays.
    2. Determine the currently selected amplifier from cct.amp rather than
       using fb->RdOutAmp as the latter can be set to 3, resulting in
       array index which is out of bounds.
    3. Corrected AEC adjustment code. The else clause of the (-1, Decrease)
       case was executed even for (+1, Increase exposure) case.
    4. Abort sequence if DHC detects a dangerous event (Flare in EUV quadrent).

    5. Corrected RESETAEC instruction to update all AEC CUR values.
    6. Corrected UPDIMX instruction to compute the max location from
       DHCRES block directly rather than using the values computed by FRAME.
    7. If a buffer is locked the output to that buffer is stopped.

V0.12: 26 Jun 97 Dnyanesh Mathur
    1. Initialize slew_delay to 60. Correct the test for busy in STTG.
    2. Correct dark frame exposure setting (RAR)

v0.13:  9 Jul 97 Dnyanesh Mathur
    1. Corrected AEC offset exposures.
    2. Corrected bad pixel table number. It could be incorrect is "default"
       amplifier was specified - since it used cct.amp * 4 to compute the
       bad pixel table number.

v0.14: 11 Jul 97 Dnyanesh Mathur
    1. Corrected the check for slew flag in STTG routine. This change was
       actually made in v0.12. However, it was lost because the next set
       of changes were made to an older version.
    2. Update Flare flag, Super flare flag and the transient flags only
       if they have been set in the frame definition block.
    3. Corrected binning factor for  normalising counts (SFHC and FHC)
       in the image processing block.
    4. The Bad Pixel Offset and Length (number of rows) are filled in
       for camera modes 0-3 (They were set to zero).
============================================================================*/

#include "..\l2\tlm.h"
#include "..\l4\cmd.h"
#include "..\l4\tim.h"
#include "..\l6\cam.h"
#include "..\l8\trsymdef.h"
#include "..\l8\trseqdef.h"

#define TRACE2   1
#include "..\l8\sqtables.h"

#define ULI unsigned long int

#define MAX_EXP_INDEX   72

int ADCoffset[2][8] = {94, 376, 1504, 6106, 94, 94, 94, 94,
                            94, 376, 1504, 6106, 94, 94, 94, 94};

int PXdone;
extern        int sh_exp;
unsigned      int WaitDur;
unsigned long int RefTicks;
unsigned long int MarkTicks;
unsigned     char *curr_instr_addr;
unsigned     char *next_instr_addr;
     unsigned int TargIndx = 0;
     unsigned int PZTindx = 0;
              int FocusPos = 0;
     unsigned int InstOp[3];
     unsigned int OpRegn[3];
              int PRVrow = 512;
     unsigned int TASample = 0;
              int WL_indx;
              int AEC_indx;
              int AEC_Offset;
              int AEC_Offset_sign;
     unsigned int CamFrmPg[2] = {0, 1};
     unsigned int PageIndx = 1;
              int RdoutAmp, prv_RdOutAmp;
              int A1RO, A1CO, A1RB, A1CB;
              int RefRow, RefCol;
              int prv_RefRow = 512, prv_RefCol = 512;
              int bad_pic = 0;
     unsigned int slew_delay = 60;
     unsigned int sttg_delay;
         long int OverFlow = 0;
     unsigned int ExtractSize;
     unsigned int RowBlks[2];
     unsigned int ColBlks[2];

struct CCDLOC {
    unsigned int Row;
    unsigned int Col;
    };

struct CCDLOC MaxLoc;
struct CCDLOC MinLoc;

struct shtr_ex {
    long int actual;
    unsigned int exp;
    unsigned int rep;
    };

extern struct shtr_ex extab[];

extern void opnLT (unsigned int LT_state);
extern void clsLT (void);
extern void runmac (unsigned int *qadr);
extern void ipreg (unsigned int *regp);

#define sh_exp  sa1E.kshnexp

#define INT_OP       *((int *)(*sp))++
#define CHAR_OP      *(*sp)++

//#include "\tra\l6\exp_tb.h"

/*----- GetOperands ----------------------------------------------------------
This routine returns the operands in a unsigned int array.
--..........................................................................*/

void GetOperands (unsigned char **sp, unsigned int *op, unsigned int *rnum)
{
int numop;
int i;

if      (TSRopcode < 0x80) numop = 3;
else if (TSRopcode < 0xB0) numop = 2;
else if (TSRopcode < 0xE0) numop = 1;
else                       numop = 0;

for (i = 0; i < numop; i++) {
    if (TSRopcode & (1 << (3 - i))) {
        *(op + i) = INT_OP;
        *(rnum + i) = -1;
        }
    else {
        *(rnum + i) = CHAR_OP;
        *(op + i) = *(SeqReg + *(rnum + i));
        }
    }

return;
}


/*----------------------------------------------------------------------
Arithmatic Instructions:
------------------------------------------------------------------------*/
// 

ADD Instruction

struct ErrBlk ADD (unsigned char **sp)
{
struct ErrBlk  EB;
int     i;

GetOperands (sp, InstOp, OpRegn);
*(SeqReg + OpRegn[0]) = InstOp[1] + InstOp[2];

EB.status = 0;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

SUB Instruction

struct ErrBlk SUB (unsigned char **sp)
{
struct ErrBlk  EB;
int     i;

GetOperands (sp, InstOp, OpRegn);
*(SeqReg + OpRegn[0]) = InstOp[1] - InstOp[2];

EB.status = 0;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

MUL Instruction

struct ErrBlk MUL (unsigned char **sp)
{
struct ErrBlk  EB;
int     i;
long int result;

GetOperands (sp, InstOp, OpRegn);
result = (long)InstOp[1] * (long)InstOp[2];
*(SeqReg + OpRegn[0]) = result & 0xffff;
OverFlow = (result & 0xffff0000) >> 16;

EB.status = 0;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

DIV Instruction

struct ErrBlk DIV (unsigned char **sp)
{
struct ErrBlk  EB;
int     i;

GetOperands (sp, InstOp, OpRegn);
if (InstOp[2]) *(SeqReg + OpRegn[0]) = InstOp[1] / InstOp[2];
else           *(SeqReg + OpRegn[0]) = 0;

EB.status = 0;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}
/*----------------------------------------------------------------------*/

/*----------------------------------------------------------------------
Register Instructions:
------------------------------------------------------------------------*/

// 

SET Instruction

struct ErrBlk SET (unsigned char **sp)
{
struct ErrBlk EB;
int i;

GetOperands (sp, InstOp, OpRegn);
*(SeqReg + OpRegn[0]) = InstOp[1];
EB.status = 1;

EB.status = 0;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

INC Instruction

struct ErrBlk INC (unsigned char **sp) {
struct ErrBlk EB;
int    regnum;

EB.status = 0;
regnum = *(*sp)++;
*(SeqReg + regnum) += 1;

EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

DEC Instruction

struct ErrBlk DEC (unsigned char **sp) {
struct ErrBlk EB;
int    regnum;

EB.status = 0;
regnum = *(*sp)++;
*(SeqReg + regnum) -= 1;

EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

/*----------------------------------------------------------------------
Branch Instructions:
------------------------------------------------------------------------*/
// 

BRANCH Instructions


struct ErrBlk BRANCHIF (unsigned char **sp) {
struct ErrBlk EB;
char *sqp;
int  dest_addr;
int  new_addr;
int  op1, op2;
int  i;

GetOperands (sp, InstOp, OpRegn);
new_addr = (int) (*sp - &seq[0]);
dest_addr = InstOp[0];
switch (TSRopcode & 0x00F0) {
    case 0x0000: if (InstOp[1] == InstOp[2]) new_addr = dest_addr; break; //BEQ
    case 0x0010: if (InstOp[1] != InstOp[2]) new_addr = dest_addr; break; //BNE
    case 0x0020: if (InstOp[1] <  InstOp[2]) new_addr = dest_addr; break; //BLT
    case 0x0030: if (InstOp[1] <= InstOp[2]) new_addr = dest_addr; break; //BLE
    case 0x0040: if (InstOp[1] >  InstOp[2]) new_addr = dest_addr; break; //BGT
    case 0x0050: if (InstOp[1] >= InstOp[2]) new_addr = dest_addr; break; //BGE
    case 0x0080: if (InstOp[1] != 0)         new_addr = dest_addr; break; //BZ
    case 0x0090: if (InstOp[1] == 0)         new_addr = dest_addr; break; //BNZ
    case 0x00C0:                             new_addr = dest_addr; break; //UBR
    }

if (new_addr > MAX_ADDR) {
    EB.status = 91; //TSI_goto_ADDRESS_ERROR;
    EB.OpCode = TSRopcode;
    EB.param = (int) new_addr;
    EB.TrSqAddr = (int) *sp;
	 }
else {
    *sp = &seq[0] + new_addr;
    EB.status = 0;
    EB.OpCode = **sp;
    EB.param = 0;
    EB.TrSqAddr = (int) *sp;
    }

EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}
/*----------------------------------------------------------------------
Control Instructions:
------------------------------------------------------------------------*/

// 

EXIT Instruction

struct ErrBlk EXIT (unsigned char **sp)
{
struct ErrBlk EB;
char *sqaddr;
int           i;
int           *pSeqID;
int           *ptr;


    GetOperands (sp, InstOp, OpRegn);

    if (CallDepth != 0) {

        BlkRptCount = *(--SqCallStack);
        for (i = NLCLREG-1; i >= 0; i--)
            *(SeqReg + i) = *(--SqCallStack);
        ptr = (int *) &TRefSec;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        ptr = (int *) &TickCount;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        ptr = (int *) &SeqID;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        *sp = (unsigned char *) *(--SqCallStack);
        CallDepth--;
        EB.status = 1;
        }
    else {
        EB.status = SEQ_EXIT;
        //SeqActive = 0;
        //EB.status = 100;
        EB.OpCode = **sp;
        EB.TrSqState = 0;
        EB.TrSqAddr = (int) *sp;
        TSSActive = 0;
        }

    RBI_RTN = InstOp[0];
    return EB;
    }

// 

TERM Instruction

struct ErrBlk TERM (unsigned char **sp) {
struct ErrBlk EB;
char   *sqaddr;

    sqaddr = *sp;
    //SeqActive = 0;
    EB.status = SEQ_END;
    EB.OpCode = **sp;
    EB.TrSqState = 0;
    EB.TrSqAddr = (int) sqaddr;
    TSSActive = 0;
    return EB;
}

// 

SQABORT Instruction

struct ErrBlk SQABORT (unsigned char **sp) {
struct ErrBlk EB;

    EB.status = SEQ_ABORT + 1;
    EB.OpCode = **sp;
    EB.TrSqState = 0;
    TSSActive = 0;
    EB.TrSqAddr = (int) *sp;
return EB;
}


/*----------------------------------------------------------------------
Timing Instructions:
------------------------------------------------------------------------*/

// 

SRT Instruction

struct ErrBlk SRT (unsigned char **sp)
{
struct ErrBlk EB;

TRefSec = lulobt;
/* TRefSec = 0;  */

EB.status = 0;
EB.OpCode = **sp;
EB.TrSqState = 11;
EB.TrSqAddr = (int) *sp;

return EB;
}


// 

DELAY Instruction

struct ErrBlk DELAY (unsigned char **sp)
{
char *sqaddr;
struct ErrBlk EB;
int    i;

    switch (DELAY_state) {
        case 0:
            curr_instr_addr = *sp - 1;
            //SeqReg[7] = (int) curr_instr_addr;
            GetOperands (sp, InstOp, OpRegn);
            DelayTime = InstOp[0];
            next_instr_addr = *sp;
            //SeqReg[8] = (int) next_instr_addr;
            DELAY_state = 1;
        case 1:
            if (TickCount >= DelayTime) {
                TickCount = 0;
                *sp = next_instr_addr;
                DELAY_state = 0;
                }
            else *sp = curr_instr_addr;
            break;
        }

    //SeqReg[6] = DelayTime;
    sqaddr = *sp;
    EB.status = 51;
    EB.OpCode = **sp;
    EB.TrSqState = 31;
    EB.TrSqAddr = (int) sqaddr;
    return EB;
    }


// 

TIM Instruction

struct ErrBlk TIM (unsigned char **sp)
{
char *sqaddr;
struct ErrBlk EB;
int    i;

    switch (TIM_state) {
        case 0:
            curr_instr_addr = *sp - 1;
            //SeqReg[7] = (int) curr_instr_addr;
            GetOperands (sp, InstOp, OpRegn);
            TimeOffset = InstOp[0];
            next_instr_addr = *sp;
            //SeqReg[8] = (int) next_instr_addr;

            TIM_state = 1;
            // There is no "break" here to handle the case where Time Mark
            // has already passed.
        case 1:
            if (lulobt >= TRefSec + TimeOffset) {
                   *sp = next_instr_addr;
                   TIM_state = 0;
                   }
            else   *sp = curr_instr_addr;
            break;
        }

    //SeqReg[6] = TimeOffset;
    sqaddr = *sp;
    EB.status = 51;
    EB.OpCode = **sp;
    EB.TrSqState = 31;
    EB.TrSqAddr = (int) sqaddr;
    return EB;
    }


// 

WAIT Instruction

struct ErrBlk WAIT (unsigned char **sp)
{
char *sqaddr;
struct ErrBlk EB;
int    i;

    switch (WAIT_state) {
        case 0:
            curr_instr_addr = *sp - 1;
            GetOperands (sp, InstOp, OpRegn);
            WaitDur = InstOp[0];
            if (0 == WaitDur) WaitDur = 1;   // Wait Duration of 0 & 1 are same
            next_instr_addr = *sp;
            WAIT_state = 1;
            *sp = curr_instr_addr;
            break;
        case 1:
            if (0 == --WaitDur) {
                WAIT_state = 0;
                *sp = next_instr_addr;
                }
            else *sp = curr_instr_addr;
            break;
        }

    sqaddr = *sp;
    EB.status = 51;
    EB.OpCode = **sp;
    EB.TrSqState = 31;
    EB.TrSqAddr = (int) sqaddr;
    return EB;
    }

// 

NOI Instruction

struct ErrBlk NOI____ (unsigned char **sp)
{
struct ErrBlk EB;
char *sqaddr;
    sqaddr = *sp;
    EB.status = 101;
    EB.TrSqState = 21;
    EB.TrSqAddr = (int) sqaddr;
    return EB;
    }

/*-------------------------------------------------------------------------*/

// Make Camera Control Table
void mk_cct (struct FRMDEFB *fb, struct CCD_CT *ct)
{
int summing_mode;

if (fb->CameraMode <= 3) {
    summing_mode = (1 << fb->CameraMode);
    ct->xsum = summing_mode;
    ct->ysum = summing_mode;
    ct->ofst = 0;
    ct->len = 0;
    }
else {
    ct->xsum = 1;
    ct->ysum = 1;
    ct->len = ExtractSize * 64;
    switch (fb->CameraMode) {
        case 4: ct->ofst = 512 - (ExtractSize * 32); PRVrow = 512; break;
        case 5: ct->ofst = PRVrow - (ExtractSize * 32); break;
        case 6: ct->ofst = RBI_MXR - (ExtractSize * 32); PRVrow = RBI_MXR; break;
        case 7: ct->ofst = RBI_MNR - (ExtractSize * 32); PRVrow = RBI_MNR; break;
        }
    }
if (fb->RdoutAmp < 2) ct->amp = fb->RdoutAmp;
}

/*-----------------------------------------------------------------------*/

void set_exp (int ecword)
{
int exp_idx;

if ((ecword & 0x4000) != 0) {                // specific exposure
    pic_idx = ecword & 0x007f;               // from bits 0-6
    }
else {                                       // AEC Exposure
    WL_indx = (ecword & 0x0f80) >> 7;
    AEC_indx = (FrmPCT.TC << 5) | WL_indx;
    if ((ecword & 0x2000) != 0) exp_idx = (*(TS_AECT + AEC_indx)).DEF;
    else                        exp_idx = TS_AECT[AEC_indx].CUR;
    AEC_Offset = ecword & 0x003f;
    AEC_Offset_sign = ecword & 0x0040;
    if (AEC_Offset_sign) AEC_Offset = -AEC_Offset;
    exp_idx += AEC_Offset;
    if (exp_idx > MAX_EXP_INDEX) exp_idx = MAX_EXP_INDEX;
    if (exp_idx < 0)  exp_idx = 0;
    pic_idx = exp_idx;
    }
if ((ecword & 0x8000) != 0) shtr_md = 0;         // dark frame
else {
    shtr_md = 3;
    sh_exp = extab[pic_idx].exp;
    if (sh_exp) shtr_md = 1;
    }
}

/*-------------------------------------------------------------------------*/
unsigned long int GetStartAddr (struct FRMDEFB *fb, int an)
{
unsigned long int StartAddr;
     //int an;
//unsigned long int camsz;
unsigned      int SumFactor;
unsigned long int RowLen;
unsigned long int NumRows;
unsigned long int RowOffset, ColOffset;
unsigned long int IMaxRow, IMaxCol;
unsigned long int IMinRow, IMinCol;
unsigned long int ES;
unsigned long int maxA1RO;
unsigned long int maxA1CO;
unsigned      int RotTrack;
unsigned long int PntgLOBT;
         long int StartRow, EndRow;
         long int StartCol, EndCol;


RowLen = RowLengths[fb->CameraMode];

if (4 == fb->SubArea[an].Ref) {
    A1RO = FrmPCT.SubArea[an].RowOffset;
    A1CO = FrmPCT.SubArea[an].ColOffset;
    A1RB = FrmPCT.SubArea[an].RowBlks;
    A1CB = FrmPCT.SubArea[an].ColBlks;
    }
else {
    A1RO = fb->SubArea[an].RowOffset;
    A1CO = fb->SubArea[an].ColOffset;
    A1RB = fb->SubArea[an].RowBlks;
    A1CB = fb->SubArea[an].ColBlks;
    }

if (0 == A1RB) A1RB = 16;
if (0 == A1CB) A1CB = 16;


//if (fb->CameraMode < 4) {
//    A1RO = A1RO >> fb->CameraMode;
//    A1CO = A1CO >> fb->CameraMode;
//    A1RB = A1RB >> fb->CameraMode;
//    A1CB = A1CB >> fb->CameraMode;
//    NumRows = 1024 >> fb->CameraMode;
//    }
if (fb->CameraMode > 3) {
    ES = ExtractSize;
    A1RB = (A1RB > ES ? ES : A1RB);
    //maxA1RO = (ES - A1RB) << 5;
    //A1RO = (A1RO > maxA1RO ? maxA1RO : A1RO);
    A1CB = (A1CB > 16 ? 16 : A1CB);
    //maxA1CO = (16 - A1CB) << 5;
    //A1CO = (A1CO > maxA1CO ? maxA1CO : A1CO);
    NumRows = ES * 64;
    }
else {
    SumFactor = 1 << fb->CameraMode;
    A1RB = (A1RB >= SumFactor ? A1RB : SumFactor);
    A1CB = (A1CB >= SumFactor ? A1CB : SumFactor);
    NumRows = 1024;
    }


if (cct.amp & 1) {
//    if (fb->CameraMode < 4) camsz = 1024 / (fb->CameraMode + 1);
//    else                    camsz = fb->ExtractSize * 64;
    A1RO = - A1RO;
    A1CO = - A1CO;
    IMaxRow = NumRows - RBI_MXR;
    IMaxCol = (RowLen - 16) - RBI_MXC;
    IMinRow = NumRows - RBI_MNR;
    IMinCol = (RowLen - 16) - RBI_MNC;
    }
else {
//    camsz = 0;
    IMaxRow = RBI_MXR;
    IMaxCol = RBI_MXC;
    IMinRow = RBI_MNR;
    IMinCol = RBI_MNC;
    }

switch (fb->SubArea[an].Ref) {
    case 0:
//        if (fb->CameraMode > 3) RefRow = cct.len / 2;
//        else RefRow = (RowLen - 16) / 2;
//        RefCol = (RowLen - 16) / 2;
        RefRow = NumRows / 2;
        RefCol = 512;
        break;
    case 1:
        RefRow = prv_RefRow;
        RefCol = prv_RefCol;
        break;
    case 2:
        RefRow = IMaxRow;
        RefCol = IMaxCol;
        break;
    case 3:
        RefRow = IMinRow;
        RefCol = IMinCol;
        break;
    }

prv_RefRow = RefRow;
prv_RefCol = RefCol;

StartRow = RefRow + A1RO - (A1RB * 32);
if (StartRow < 0) StartRow = 0;
EndRow = StartRow + (A1RB * 64);
if (EndRow >= NumRows) StartRow = NumRows - (A1RB * 64);

StartCol = RefCol + A1CO - (A1CB * 32);
if (StartCol < 0) StartCol = 0;
EndCol = StartCol + (A1CB * 64);
if (EndCol >= 1024) StartCol = 1024 - (A1CB * 64);


StartAddr = ((StartRow / cct.xsum) * RowLen) + (StartCol / cct.ysum) + 1300;

//StartAddr =  (((RefRow + A1RO - (A1RB * 32)) * RowLen) / cct.xsum) +
//              ((RefCol + A1CO - (A1CB * 32)) / cct.ysum) + 1300;


return StartAddr;
}
/*-------------------------------------------------------------------------*/
/*
  Area Parameters:
  This function sets up the area parameters as per Table 17 of the TRACE Science
  Sequences document.
  Calling Seq:  status = AreaParam (struct AREASPEC *ap, int an);
                 where ap is a pointer to an area parameters structure
                       an is the area number; 0=Full Camera, 1=Area 1, 2=area 2
*/


int AreaParams (struct AREASPEC *ap, struct FRMDEFB *fb, int an)
{
int n;
int num_rows, num_cols;
if (0 == an) {             /* Full Camera Output */
    ap->out = fb->FullCamOP;
    ap->TMS = 0;
    if (1 == fb->DoTimeAvg) {
        ap->TMS = fb->TimeAvgIntrvl;
        if (0 == ap->TMS) ap->TMS = 16;
        ap->TM0 = ((TASample == 1)? 1:0);
        }
    ap->SA = 1300;
    ap->RL = RowLengths[fb->CameraMode];
    if (fb->CameraMode > 3) ap->NR = cct.len;
    else ap->NR = ap->RL - 16;
    ap->NC = ap->RL - 16;
    ap->BM = 1 << fb->FullCamBin;
    if (1 == ap->BM) ap->BM = 0;
    ap->APID = AppIDSet[fb->FullCamOP];
    if (fb->FullCamOP > 1) {
        if (0 == EventsFile[RBI_CBF]) ap->APID += (RBI_CBF * 2);  // Correct apid for op to events buf
        else                          ap->APID = 0;
        }
    ap->CMP = (fb->FullCamOpFmt & 0x0100) >> 8;
    if (ap->CMP) {
        ap->QT_PCK = (fb->FullCamOpFmt & 0x0030) >> 4;
        ap->HT_LUT = (fb->FullCamOpFmt & 0x00C0) >> 6;
        ap->QM = fb->FullCamOpFmt & 0x000F;
        }
    else {
        ap->QT_PCK = (fb->FullCamOpFmt & 0x00F0) >> 4;
        ap->HT_LUT = fb->FullCamOpFmt & 0x000F;
        ap->QM = 0;
        }
    }
else {
    n = an - 1;
    ap->out = fb->SubArea[n].OP;
    ap->TMS = 0;
    if (1 == an) {
        if (2 == fb->DoTimeAvg) {
            ap->TMS = fb->TimeAvgIntrvl;
            if (0 == ap->TMS) ap->TMS = 16;
            ap->TM0 = ((TASample == 1)? 1:0);
            }
        }
    ap->SA = GetStartAddr (fb, n);
    ap->RL = RowLengths[fb->CameraMode];

    num_rows = A1RB * 64;
    //num_rows = fb->SubArea[n].RowBlks * 64;
    //if (0 == num_rows) num_rows = 1024;
    if (fb->CameraMode > 3) ap->NR = ((num_rows < cct.len) ? num_rows : cct.len);
    if (fb->CameraMode < 4) ap->NR =  num_rows >> fb->CameraMode;

    num_cols = A1CB * 64;
    //num_cols = fb->SubArea[n].ColBlks * 64;
    //if (0 == num_cols) num_cols = 1024;
    if (fb->CameraMode > 3) ap->NC = ((num_cols < 1024) ? num_cols : 1024);
    if (fb->CameraMode < 4) ap->NC =  num_cols >> fb->CameraMode;

    ap->BM = 1 << fb->SubArea[n].Bin;
    if (1 == ap->BM) ap->BM = 0;
    ap->APID = AppIDSet[fb->SubArea[n].OP];
    if (fb->SubArea[n].OP > 1) {
        if (0 == EventsFile[RBI_CBF]) ap->APID += (RBI_CBF * 2);
        else                          ap->APID = 0;
        }
    ap->CMP = (fb->SubArea[n].OpFmt & 0x0100) >> 8;
    if (ap->CMP) {
        ap->QT_PCK = (fb->SubArea[n].OpFmt & 0x0030) >> 4;
        ap->HT_LUT = (fb->SubArea[n].OpFmt & 0x00C0) >> 6;
        ap->QM = fb->SubArea[n].OpFmt & 0x000F;
        }
    else {
        ap->QT_PCK = (fb->SubArea[n].OpFmt & 0x00F0) >> 4;
        ap->HT_LUT = fb->SubArea[n].OpFmt & 0x000F;
        ap->QM = 0;
        }
    }

return 1;
}

/*-------------------------------------------------------------------------*/

void mk_ipb (struct FRMDEFB *fb, struct P1IPB *p1)
{
              int i;
unsigned long int evb;
unsigned      int evb_idx;
unsigned long int binning;
unsigned long int NPix;
         long int ExpT;
     unsigned int amp;


amp = cct.amp & 1;             // Currently selected amplifier

PageIndx = 1 - PageIndx;
p1->SPG = CamFrmPg[PageIndx];
for (i = 0; i < 4; i++) mp_hd2.b[i] = 0x40 | p1->SPG;
mp_hd2.pg = (p1->SPG) << 3;

p1->BPT = amp * 4;            // cct.amp has been updated by a call to mk_cct

p1->BPYO = cct.ofst;          // These are only valid for modes 4-7.
p1->BPYL = cct.len;

if (fb->CameraMode < 4) {
    p1->BPT += fb->CameraMode;
    p1->BPYL = 1024 / (fb->CameraMode + 1);
    }

i = AreaParams (&p1->FCP2P, fb, 0);
i = AreaParams (&p1->A1P2P, fb, 1);
i = AreaParams (&p1->A2P2P, fb, 2);

if (0 == fb->EvtDetectArea) {
    p1->P1SA = p1->FCP2P.SA;
    p1->P1RL = p1->FCP2P.RL;
    p1->P1NR = p1->FCP2P.NR;
    p1->P1NC = p1->FCP2P.NC;
    p1->P1BF = p1->FCP2P.BM;
    }
else {
    p1->P1SA = p1->A1P2P.SA;
    p1->P1RL = p1->A1P2P.RL;
    p1->P1NR = p1->A1P2P.NR;
    p1->P1NC = p1->A1P2P.NC;
    p1->P1BF = p1->A1P2P.BM;
    }

/*
evb_idx = (fb->EvtDetectArea ? fb->SubArea[0].Bin : fb->FullCamBin);
evb = 1 << evb_idx;
*/

evb = p1->P1BF;
if (0 == evb) evb = 1;

ExpT = extab[pic_idx].actual;

p1->SF   = fb->DetectSuFlr;
p1->SFHB = (((ULI) fb->SuFlrCntRate * ExpT * cct.xsum * cct.xsum) / 32768) +
           ((ADCoffset[amp][fb->CameraMode]) / 32);
if (p1->SFHB > 127) p1->SFHB = 127;

p1->SFHC = (fb->FlarePixCnt) /
           ((cct.xsum * cct.xsum) * (evb * evb));


p1->FF   = fb->DetectFlare;

p1->FHB  = (((ULI)fb->FlareCntRate * ExpT * cct.xsum * cct.xsum) / 32768) +
           ((ADCoffset[amp][fb->CameraMode]) / 32);

if (p1->FHB > 127) p1->FHB = 127;

p1->FHC  = (fb->FlarePixCnt) /
           ((cct.xsum * cct.xsum) * (evb * evb));

//CurrECW = fb->ExpCtrlWord;
p1->AECX = (fb->ExpCtrlWord & 0x1000) >> 12;
p1->AEHB = TS_AECT[AEC_indx].INH + (ADCoffset[amp][fb->CameraMode]/32);
if (p1->AEHB > 127) p1->AEHB = 127;
p1->AELB = TS_AECT[AEC_indx].INL + (ADCoffset[amp][fb->CameraMode]/32);

//*(SeqReg+20) = 3;
if (fb->EvtDetectArea == 0) {
    binning = 1 << fb->FullCamBin;
    NPix = (ULI) 1024 * ExtractSize * 64;
    }
else {
    binning = 1 << fb->SubArea[0].Bin;
    NPix = (ULI) RowBlks[0] * ColBlks[0] * 4096;
    }

p1->AELC = (NPix * TS_AECT[AEC_indx].PAL) / (100 * binning * binning);
p1->AEHC = (NPix * TS_AECT[AEC_indx].PAH) / (100 * binning * binning);

//*(SeqReg+20) = 4;

p1->TF = fb->DetectTrans;
p1->TMUL = fb->TransMult;
p1->TPC = fb->TransPixCnt;
p1->DT = fb->DarkTransient;
p1->TAI = fb->TimeAvgIntrvl; if (0 == p1->TAI) p1->TAI = 16;
p1->T0 = ((TASample == 1)? 1:0);
p1->IMX = fb->LocateImax;
p1->IMN = fb->LocateImin;

}
/*-------------------------------------------------------------------------*/


/*-----[SetupConfigParams]-------------------------------------------------*/
/* Decodes Frame Definition Block and Target Select tables to update       */
/* configuration tables;                                                   */
/*-------------------------------------------------------------------------*/
// This function decodes the Frame Definition Block CurrFDB to update the
// configuration tables. A telecommand to take a picture causes the
// command processor to copy the "default" FDB to CurrFDB and append the
// 'focus' and 'pzt_offset' parameters to the block. The sequence instruction
// 'FRAME' causes the FDB specified by the fid to be copied to CurFDB
// and also appends the PZT offset and focus information to the block.
// For the purposes of this function CurrFDB is treated as a 18 word block.
//
void SetupConfigParams (struct FRMDEFB *fb)         // int pindx, int fpos)
{
int i;
int wl_indx;

ExtractSize = (fb->ExtractSize ? fb->ExtractSize : 16);
RowBlks[0] = (fb->SubArea[0].RowBlks ? fb->SubArea[0].RowBlks : 16);
ColBlks[0] = (fb->SubArea[0].ColBlks ? fb->SubArea[0].ColBlks : 16);
RowBlks[1] = (fb->SubArea[1].RowBlks ? fb->SubArea[1].RowBlks : 16);
ColBlks[1] = (fb->SubArea[1].ColBlks ? fb->SubArea[1].ColBlks : 16);


/* DecFrame (fb); */

if (fb->DoTimeAvg) TASample++;

wl_indx = (fb->ExpCtrlWord & 0x0f80) >> 7;
FrmWLT = TS_WLT[wl_indx];
if (FocusPos) {
    FrmWLT.FMA += FocusPos;
    FocusPos = 0;
    }
pWLT = (unsigned int *) &FrmWLT;
for (i = 0; i < 4; i++) ocb[i] = *pWLT++;

set_exp (fb->ExpCtrlWord);

mk_cct (fb, &cct);
mk_ipb (fb, &DHCP1);

}

/*-----------------------------------------------------------------------*/

struct CCDLOC ccd_loc (unsigned long loc)
{
struct CCDLOC pos;
unsigned long bf2;

bf2 = 1 << DHCP1.P1BF;
bf2 = bf2 * bf2;

pos.Row = (((loc * bf2) / DHCP1.P1NC) +
                   ((DHCP1.P1SA - 1300) / DHCP1.P1RL)) * cct.xsum +
                         RefRow - (DHCP1.P1NR /2);
pos.Col = (((loc * bf2) % DHCP1.P1NC) +
                   ((DHCP1.P1SA - 1300)% DHCP1.P1RL)) * cct.ysum;

/* Invert row and column numbers if B amplifier used for the image */
if (cct.amp & 1) {
    pos.Row = 1024 - pos.Row;
    pos.Col = 1024 - pos.Col;
    }

return pos;
}

/*-----[ Frame ]---------------------------------------------------------*/
/*                                                                       */
/* Copy specified FDB to CurrFDB                                         */
/*-----------------------------------------------------------------------*/
// 

FRAME Instruction

struct ErrBlk FRAME (unsigned char **sp)
{
struct ErrBlk EB;
struct FRMDEFB *save_fdbp;
unsigned int fdbidx;


int i;
unsigned int numFDB;
char *sq_addr;
//int  sht_rdo_xx;

//sht_rdo_xx = 4;

EB.status = 0;
curr_instr_addr = *sp - 1;


switch (tapt_state) {
    case 1:
        for (i = 0; i < 3; i++) InstOp[i] = 0xFFFF;
        GetOperands (sp, InstOp, OpRegn);
        next_instr_addr = *sp;

        fdbidx = InstOp[0];
        if (InstOp[1] != 0xFFFF) PZTindx = InstOp[1];
        if (InstOp[2] != 0xFFFF) FocusPos = InstOp[2];

        //*(SeqReg+16) = 1;

        save_fdbp = 0;
        fdbp = FDBarray;
        while ((*fdbp).fid) {
            if (((*fdbp).fid & 0xFFF8) == (fdbidx & 0xFFF8)) save_fdbp = fdbp;
            fdbp -= 1;
            }
        if (save_fdbp != 0) fdbp = save_fdbp;
        if (save_fdbp != 0) {
            //CurrFDB = *fdbp;
            fdbp = save_fdbp;
            sa19.ksqfid = (*fdbp).fid;         //CurrFDB.fid;
            SetupConfigParams (fdbp);          //FDB gets decoded here
            req_ps1 = 1;
            tapt_state = 6;                    //It's a long story...
            *sp = curr_instr_addr;
            EB.status = 52;
            EB.TrSqState = SEQ_WAIT_DEV;
            //*(SeqReg+16) = 2;
            }
        else {
            fdbp = FDBarray;
            EB.status = UNDEFINED_FDB;
            EB.OpCode = TSRopcode;
            EB.param = (*fdbp).fid;            //CurrFDB.fid;
            EB.TrSqAddr = (int) *sp;
            *sp = next_instr_addr;
            EB.TrSqState = SEQ_RUN;
            //*(SeqReg+16) = 103;
            }

        break;
/*
    case 5:
        if (sht_rdo & 0x13) tapt_state = 6;    // Frame in progress
        *sp = curr_instr_addr;
        break;
*/
    case 6:
        if (DHCRes.NewRes) {
            DHCRes.NewRes = 0;
            tapt_state = 1;                    // INT 1 recieved from DHC
            *sp = next_instr_addr;
            bad_pic = 0;

            /* Frame Post Processing */

                 // If STOPSeq flag is set ABORT sequence
            if (DHCRes.STOPSeq) {
                EB.status = 512;
                EB.OpCode = **sp;
                EB.TrSqAddr = (int) *sp;
                EB.param = DHCRes.STOPSeq;
                return EB;
                }

                 // if MX set, Update IMAX location
            if ((fdbp->LocateImax) || (DHCRes.TransEvt)) {
                MaxLoc = ccd_loc (DHCRes.IMaxLoc);
                RBI_MXR = MaxLoc.Row;
                RBI_MXC = MaxLoc.Col;
                }

                 // if MN set, Update IMIN location
            if ((fdbp->LocateImin) || (DHCRes.TransEvt)) {
                MinLoc = ccd_loc (DHCRes.IMinLoc);
                RBI_MNR = MinLoc.Row;
                RBI_MNC = MinLoc.Col;
                }

                 // if AEC-ADJUST set, adjust AEC exposure
            switch (DHCRes.AECAdjust) {
                case 1:
                    TS_AECT[AEC_indx].CUR += TS_AECT[AEC_indx].SUP;
                    if (TS_AECT[AEC_indx].CUR > MAX_EXP_INDEX)
                        TS_AECT[AEC_indx].CUR = MAX_EXP_INDEX;
                    break;
                case -1:
                    if (TS_AECT[AEC_indx].CUR > TS_AECT[AEC_indx].SDN)
                        TS_AECT[AEC_indx].CUR -= TS_AECT[AEC_indx].SDN;
                    else TS_AECT[AEC_indx].CUR = 0;  // smallest possible
                    break;
                default:
                    break;
                }

                 // Update Event Flags (FLARE, SUPERFLARE and TRANSIENT)
            if (fdbp->DetectFlare) RBI_FEF = DHCRes.FlareEvt;
            if (fdbp->DetectSuFlr) RBI_SEF = DHCRes.SuFlareEvt;
            if (fdbp->DetectTrans) RBI_TEF = DHCRes.TransEvt;
            EB.status = 1;
            }

        else {
            *sp = curr_instr_addr;
            EB.status = 52;
            if (!(pic_stt & 0x000f)) {
                *sp = next_instr_addr;
                tapt_state = 1;
                EB.status = PIC_TIMEOUT;
                }
            }
        break;
    }

EB.OpCode = **sp;
EB.TrSqAddr = (int) *sp;

return EB;
}
/*-----[ TAPT ]------------------------------------------------------------*/
/*                                                                         */
/* Sends a request to the CC to take a picture                             */
/* Waits for Frame Gate Interrupt                                          */
/* Outputs DHC processing parameters to the Parameter Exchange Area        */
/* Waits for DHC phase 1 Completion interrupt                              */
/* Reads in the phase 1 processing results                                 */
/* Continues..                                                             */
/*.........................................................................*/
struct ErrBlk TAP (unsigned char **sp)
{
struct ErrBlk EB;
extern PXdone;

char *sq_addr;

sq_addr = *sp - 1;
switch (tapt_state) {
    case 1:
      req_ps1 = 1;
    	tapt_state = 6;
	   break;
    case 2:
   	break;
    case 3:
    	break;
    case 4:
   	break;
    case 5:
   	break;
    case 6:
   	//if (PXdone) {
	   //   PXdone = 0;
	      tapt_state = 1;
	   //   }
   	break;
    }
if (tapt_state != 1) *sp = sq_addr;  //

EB.status = 52;
EB.OpCode = 0x05;
EB.TrSqState = tapt_state+10;
EB.TrSqAddr = (int) *sp;

return EB;
}

/*-----[ SETTARG ]---------------------------------------------------------*

Argument:
    1. Target Index  Register or Immediate Value
/*.........................................................................*/


// 

STTG Instruction

struct ErrBlk STTG (unsigned char **sp)
{
void wedgeC(unsigned int *);

struct ErrBlk EB;
unsigned int wdgpos[2];
unsigned int rnum;
unsigned int TargetIDLo;
unsigned int TargetIDHi;
int          i;
unsigned int slewflag;

switch (STTG_state) {
    case 0:
        curr_instr_addr = *sp - 1;
        for (i = 0; i < 3; i++) InstOp[i] = 0xFFFF;
        GetOperands (sp, InstOp, OpRegn);
        TargIndx = InstOp[0];
        TargetIDLo = InstOp[0];
        //TargetIDHi = InstOp[1];
        next_instr_addr = *sp;

  //      *(SeqReg+18) = rnum;
  //      *(SeqReg+17) = TargIndx;

        TargIndx = 0;
        while ( (TargetIDLo != TS_PCT[TargIndx].TID_l)
                      &&
                (TargIndx < NUMPTG) ) TargIndx++;
        if (NUMPTG == TargIndx) {
            TargIndx = 0;
            EB.status = TARGET_NOT_FOUND;
            *sp = next_instr_addr;
            }
        else {
            FrmPCT = TS_PCT[TargIndx];
            wdgpos[0] = FrmPCT.W1;
            wdgpos[1] = FrmPCT.W2;
            sa19.ksqtarg = FrmPCT.TID_l;
            sa19.ksqtarg |= (unsigned long int) FrmPCT.TID_h << 16;
            RBI_TRC = FrmPCT.TC;
            wedgeC (wdgpos);

            STTG_state = 1;
            sttg_delay = slew_delay;

            *sp = curr_instr_addr;
            EB.status = 52;
            EB.TrSqState = SEQ_WAIT_DEV;
            EB.TrSqAddr = (int) *sp;
            }

        break;
    case 1:
        *sp = curr_instr_addr;
        EB.status = 52;
        EB.TrSqState = SEQ_WAIT_DEV;

        slewflag = sa1D.flag & 0x0200;
        if (slewflag == 0) STTG_state = 2;

        break;

    case 2:
        if (sttg_delay > 0) sttg_delay -= 1;

        if (sttg_delay == 0) {
            STTG_state = 0;
            *sp = next_instr_addr;
            EB.status = 0;
            EB.TrSqState = SEQ_RUN;
            }
        else {
            *sp = curr_instr_addr;
            EB.status = 52;
            EB.TrSqState = SEQ_WAIT_DEV;
            }

        break;
    }

EB.TrSqAddr = (int) *sp;
return EB;
}

/* Set readout amplifier and offset
   Call  SAMP amplifier(0|1)  offset(0-15)
   Opcodes - 91, 95, 99 and 9D
 */
// 

SAMP Instruction

struct ErrBlk SAMP (unsigned char **sp)
{
struct ErrBlk EB;

GetOperands (sp, InstOp, OpRegn);

if (InstOp[0] < 2) cct.amp = InstOp[0];
if (InstOp[1] < 16) cct.ofstab[cct.amp & 1] = InstOp[1] - 1;

EB.status = 0;

EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}


// 

CLL Instruction

struct ErrBlk CLL (unsigned char **sp)
{
unsigned char  *SqPtr (unsigned long id);
struct ErrBlk EB;
unsigned int CallAddr;
int          i;
int          *ptr;
unsigned long SqID;

    GetOperands (sp, InstOp, OpRegn);
    SqID = *( (unsigned long *) &InstOp[0]);
    CallAddr = (unsigned int) SqPtr (SqID);
    if (CallAddr == 0xFFFF) {
        EB.status = SEQ_NOT_FOUND;
        return EB;
        }

    if (CallDepth < MAX_CALL_DEPTH) {
        *SqCallStack++ = (int) *sp;                 /* save pc */
        ptr = (int *) &SeqID;
        *SqCallStack++ = *ptr++;                 /* save SID */
        *SqCallStack++ = *ptr;                   /* save SID */
        ptr = (int *) &TickCount;
        *SqCallStack++ = *ptr++;                 /* save SID */
        *SqCallStack++ = *ptr;                   /* save SID */
        ptr = (int *) &TRefSec;
        *SqCallStack++ = *ptr++;                 /* save SID */
        *SqCallStack++ = *ptr;                   /* save SID */

        CallDepth++;
        for (i = 0; i < NLCLREG; i++)
            *SqCallStack++ = *(SeqReg + i);         /* save local registers */
        *SqCallStack++ = BlkRptCount;

        *sp = seq + CallAddr; /* Set pc to call address */
        EB.status = 1;
        }
    else {
        EB.status = SEQ_STACK_DEPTH_EXCEEDED;
        EB.OpCode = **sp;
        EB.TrSqState = 0;
        EB.TrSqAddr = (int) *sp;
        TSSActive = 0;
        }

    EB.OpCode = TSRopcode;
    EB.TrSqAddr = (int) *sp;

    return EB;
    }

// 

RET Instruction

struct ErrBlk RET (unsigned char **sp)
{
struct ErrBlk EB;
int           i;
int           *ptr;

    if (CallDepth != 0) {
        BlkRptCount = *(--SqCallStack);
        for (i = NLCLREG-1; i >= 0; i--)
            *(SeqReg + i) = *(--SqCallStack);
        ptr = (int *) &TRefSec;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        ptr = (int *) &TickCount;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        ptr = (int *) &SeqID;
        ptr++;
        *ptr-- = *(--SqCallStack);
        *ptr   = *(--SqCallStack);
        *sp = (unsigned char *) *(--SqCallStack);
        CallDepth--;
        EB.status = 1;
        }
    else {
        EB.status = SEQ_EXIT;
        //SeqActive = 0;
        //EB.status = 100;
        EB.OpCode = **sp;
        EB.TrSqState = 0;
        EB.TrSqAddr = (int) *sp;
        TSSActive = 0;
        }

    EB.OpCode = TSRopcode;
    EB.TrSqAddr = (int) *sp;

    return EB;
    }

// 

SID Instruction

struct ErrBlk SID (unsigned char **sp)
{
struct ErrBlk EB;
int    i;

    GetOperands (sp, InstOp, OpRegn);
    //*(SeqReg + 23) = InstOp[0];
    //*(SeqReg + 24) = InstOp[1];

    SeqID = *((long *)(&InstOp[0]));
    EB.TrSqAddr = INT_OP;

    EB.status = 1;

    EB.OpCode = TSRopcode;
    EB.TrSqAddr = (int) *sp;

    return EB;
    }

// 

NOID Instruction

struct ErrBlk NOID (unsigned char **sp)
{
struct ErrBlk EB;
int    i;

    //GetOperands (sp, InstOp, OpRegn);
    //*(SeqReg + 23) = InstOp[0];
    //*(SeqReg + 24) = InstOp[1];

    //SeqID = *((long *)(&InstOp[0]));
    EB.TrSqAddr = INT_OP;
    EB.TrSqAddr = INT_OP;
    EB.TrSqAddr = INT_OP;

    EB.status = 1;

    EB.OpCode = TSRopcode;
    EB.TrSqAddr = (int) *sp;

    return EB;
    }

// 

TIMCHK Instruction

struct ErrBlk TIMCHK (unsigned char **sp) {
struct ErrBlk EB;

GetOperands (sp, InstOp, OpRegn);

if ((TRefSec + InstOp[0]) <  lulobt) *(SeqReg + OpRegn[1]) = -1;
if ((TRefSec + InstOp[0]) == lulobt) *(SeqReg + OpRegn[1]) =  0;
if ((TRefSec + InstOp[0]) >  lulobt) *(SeqReg + OpRegn[1]) =  1;

EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;

return EB;
}

// 

DEV Instruction

struct ErrBlk DEV (unsigned char **sp) {
struct ErrBlk EB;

EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

LOCKBUF Instruction

struct ErrBlk LOCKBUF (unsigned char **sp) {
struct ErrBlk EB;
int    nxtflb;

if (RBI_NBF) {
    EventsFile[RBI_CBF] = 1;        // Event File Locked;
    RBI_CBF = (RBI_CBF + 1) % 4;
    RBI_NBF -= 1;                   // This has to be reset
    EB.status = 1;
    }
else EB.status = 51;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

RESETAEC Instruction

struct ErrBlk RESETAEC (unsigned char **sp) {
struct ErrBlk EB;
int    i;

for (i = 0; i < 128; i++)
    TS_AECT[i].CUR = TS_AECT[i].DEF;

EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

STARTAVE Instruction

struct ErrBlk STARTAVE (unsigned char **sp) {
struct ErrBlk EB;
TASample = 0;
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

UPDIMX Instruction

struct ErrBlk UPDIMX (unsigned char **sp) {
struct ErrBlk EB;

if (DHCRes.IMaxValid) {
    MaxLoc = ccd_loc (DHCRes.IMaxLoc);
    RBI_MXR = MaxLoc.Row;
    RBI_MXC = MaxLoc.Col;
    }
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

NOOP Instruction

struct ErrBlk NOOP (unsigned char **sp) {
struct ErrBlk EB;
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

/* LDA - Load register from address
 */
// 

LDA Instruction

struct ErrBlk LDA (unsigned char **sp) {
struct ErrBlk EB;
int           numops;

GetOperands (sp, InstOp, OpRegn);
*(SeqReg + OpRegn[0]) = *(int *)InstOp[1];
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

/* LDR - Load register from register specified by source reg
 */
// 

LDR Instruction

struct ErrBlk LDR (unsigned char **sp) {
struct ErrBlk EB;
int           numops;
int           RNum;

GetOperands (sp, InstOp, OpRegn);
RNum = *(SeqReg + OpRegn[1]);
*(SeqReg + OpRegn[0]) = *(SeqReg + RNum++);
*(SeqReg + OpRegn[1]) = RNum;
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

/* SETREGS - Load a block of registers with immediate values */
// 

SETREGS Instruction

struct ErrBlk SETREGS (unsigned char **sp) {
struct ErrBlk EB;

unsigned int RNum;
unsigned int NumReg;
         int i;

GetOperands (sp, InstOp, OpRegn);
RNum = (OpRegn[0] == 0xFFFF ? InstOp[0] : OpRegn[0]);
//RNum = InstOp[0];
NumReg = InstOp[1];
for (i = 0; i < NumReg; i++)
    *(SeqReg + RNum++) = INT_OP;
EB.status = 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

RUNDHCP (B3, BB) Instruction

/* RQP - Runs a DHC Queue Program */
struct ErrBlk RUNDHCP(unsigned char **sp) {
struct ErrBlk EB;

GetOperands (sp, InstOp, OpRegn);
runmac (&InstOp[0]);
EB.status = SEQ_BREAK + 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

SETDHR (A2, A6, AA, AE) Instruction

/* SETDHR - Sets a DHC Regsiter to specified value */
struct ErrBlk SETDHCR (unsigned char **sp) {
struct ErrBlk EB;

GetOperands (sp, InstOp, OpRegn);
ipreg (&InstOp[0]);
EB.status = SEQ_BREAK + 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

OPENLOOP (ED) Instruction

/* OPENLOOP - Opens ISS Loop */
struct ErrBlk OPENLOOP (unsigned char **sp) {
struct ErrBlk EB;

opnLT (1);  // Opens loop, Lowers gains, no auto close
EB.status = SEQ_BREAK + 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}

// 

CLOSELOOP (EF) Instruction

/* SETDHR - Closes ISS Loop */
struct ErrBlk CLOSELOOP (unsigned char **sp) {
struct ErrBlk EB;

clsLT ();
EB.status = SEQ_BREAK + 1;
EB.OpCode = TSRopcode;
EB.TrSqAddr = (int) *sp;
return EB;
}




// 

Instructions

struct ErrBlk (*func[256])(unsigned char **) = {
BRANCHIF, ADD,     BRANCHIF,  ADD,      NOI____, ADD,       NOI____,  ADD,
//00        01        02        03        04        05        06        07
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____, NOI____,   NOI____,  NOI____,
//08        09        0a        0b        0c        0d        0e        0f
BRANCHIF, SUB,     BRANCHIF,  SUB,      NOI____, SUB,       NOI____,  SUB,
//10        11        12        13        14        15        16        17
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____, NOI____,   NOI____,  NOI____,
//18        19        1a        1b        1c        1d        1e        1f
BRANCHIF, MUL,     BRANCHIF,  MUL,      NOI____, MUL,       NOI____,  MUL,
//20        21        22        23        24        25        26        27
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____, NOI____,   NOI____,  NOI____,
//28        29        2a        2b        2c        2d        2e        2f
BRANCHIF, DIV,     BRANCHIF,  DIV,      NOI____, DIV,       NOI____,  DIV,
//30        31        32        33        34        35        36        37
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//38        39        3a        3b        3c        3d        3e        3f
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//40        41        42        43        44        45        46        47
BRANCHIF, NOI____, BRANCHIF,   NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//48        49        4a        4b        4c        4d        4e        4f
BRANCHIF, NOI____, BRANCHIF,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//50        51        52        53        54        55        56        57
BRANCHIF, NOI____, BRANCHIF,   NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//58        59        5a        5b        5c        5d        5e        5f
NOI____,  NOI____, NOI____,   NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//60        61        62        63        64        65        66        67
NOI____,  NOI____,  BRANCHIF, NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//68        69        6a        6b        6c        6d        6e        6f
FRAME,    NOI____,  FRAME,    NOI____,  FRAME,    NOI____,  FRAME,    NOI____,
//70        71        72        73        74        75        76        77
FRAME,    NOI____,  FRAME,    NOI____,  FRAME,    NOI____,  FRAME,    NOI____,
//78        79        7a        7b        7c        7d        7e        7f
SET,      CLL,      BRANCHIF, STTG,     SET,      CLL,      NOI____,  STTG,
//80        81        82        83        84        85        86        87
NOI____,  CLL,      BRANCHIF, STTG,     NOI____,  CLL,      NOI____,  STTG,
//88        89        8a        8b        8c        8d        8e        8f
BRANCHIF, SAMP,     TIMCHK,   SETREGS,  NOI____,  SAMP,     NOI____,  SETREGS,
//90        91        92        93        94        95        96        97
BRANCHIF, SAMP,     TIMCHK,   SETREGS,  NOI____,  SAMP,     NOI____,  SETREGS,
//98        99        9a        9b        9c        9d        9e        9f
SID,      LDA,      SETDHCR,  LDR,      SID,      LDA,      SETDHCR,  NOI____,
//a0        a1        a2        a3        a4        a5        a6        a7
SID,      NOI____,  SETDHCR,  NOI____,  SID,      NOI____,  SETDHCR,  NOI____,
//a8        a9        aa        ab        ac        ad        ae        af
TIM,      EXIT,     DELAY,    RUNDHCP,  WAIT,     NOI____,  STTG,     NOI____,
//b0        b1        b2        b3        b4        b5        b6        b7
TIM,      EXIT,     DELAY,    RUNDHCP,  WAIT,     NOI____,  STTG,     NOI____,
//b8        b9        ba        bb        bc        bd        be        bf
FRAME,    NOI____,  BRANCHIF, NOI____,  NOI____,  NOI____,  INC,      NOI____,
//c0        c1        c2        c3        c4        c5        c6        c7
FRAME,    NOI____,  BRANCHIF, NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//c8        c9        ca        cb        cc        cd        ce        cf
DEC,      NOI____,  SID,      NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//d0        d1        d2        d3        d4        d5        d6        d7
NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//d8        d9        da        db        dc        dd        de        df
RET,      NOID,     TERM,     NOI____,  SQABORT,  NOI____,  NOI____,  NOI____,
//e0        e1        e2        e3        e4        e5        e6        e7
SRT,      NOI____,  TAP,      NOI____,  LOCKBUF,  OPENLOOP, RESETAEC, CLOSELOOP,
//e8        e9        ea        eb        ec        ed        ee        ef
STARTAVE, NOI____,  UPDIMX,   NOI____,  NOI____,  NOI____,  NOI____,  NOI____,
//f0        f1        f2        f3        f4        f5        f6        f7
NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOI____,  NOOP};
//f8        f9        fa        fb        fc        fd        fe        ff

//