/*
* XGProcess.c
*
* This file does top-level processing of the incoming data. Most of it is specific to
* the XRS GSE. The function ProcessClump() is the top level entry point.
* Other useful functions are NewMainWaves() and SetupMainWaves(), which handle making
* the waves into which most incoming data goes.
*/
#include <stdio.h>
#include <IgorXOP.h>
#include <XOP.h>
#include <XOPSupport.h>
#include <fp.h>
#include "XGProcess.h"
#include "XGWaitReply.h"
#include "XGCommand.h"
#include "XGFilter.h"
#include "XGUtils.h"
#include "XOPUtils.h"
#include "XGDump.h"
#include "XGError.h"
#include "XGHKRates.h"
#include "handle_dt.h"
#include "XGMaster.h"
#include "XGCCSDS.h"
#include "XGCRC.h"
#include "XGCapTelem.h"
#include "XGNet.h"
long macTimeDiff = 0;
ccHdrInfo_t lastPacketHeader;
extern struct crnt_strct * crnt_ar[];
extern long scrLevel;
extern long msgLevel[kNumMsgSelectors];
extern long caughtUp;
const short kPutHeaderLevel = 4;
const char *cdpDFName = "cdp";
DataFolderHandle dfCDP = nil;
/* Types of the main waves. */
const short typesMain[kNMainWaves] =
{
kMainTypeGT,
kMainTypePix,
kMainTypeRT,
kMainTypeQual,
kMainTypePH,
kMainTypeTick,
kMainTypeVern,
kMainTypeSamp,
kMainTypeFlags,
kMainTypeUT
};
/* Names of the main waves */
char *namesMain[kNMainWaves] =
{
"SCTime",
"Pixel",
"Rt",
"Qual",
"Ph",
"Tick",
"Vern",
"Samp",
"Flags",
"UTime"
};
/* Info about the memory dump waves */
static waveHndl dpMemWave = nil;
static short dpMemType = dpmdNone;
static const short dpMemWaveType = NT_FP32; // Don't change this without fixing HandleCDPMemDumpPacket
static const long dpMemWaveLength = 65536;
static const char *dpMemCDPAWaveName = "memDumpCDPA";
static const char *dpMemCDPBWaveName = "memDumpCDPB";
static const char *dpMemAcheWaveName = "memDumpAche";
const short tcpFreeWaveType = NT_FP32;
const char *tcpFreeWaveName = "TCPFree";
const short tcpTimeWaveType = NT_FP64;
const char *tcpTimeWaveName = "TCPTime";
long tcpWaveInd;
extern long updateInterval;
extern long numPacketsLost;
long curPntMain;
long mainGrowPnts = 1000;
long hasDTLengths = 1;
waveHndl tcpFreeWave = nil;
waveHndl tcpTimeWave = nil;
waveHndl wavesMain[kNMainWaves] = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil};
static short modifiedMain = 0;
static unsigned long lastUpdate = 0;
static long scTimeDiff = 0;
//static unsigned long scTimeOffset = 0;
//static short sampRate = 12288;
extern long sampRate;
static const short kMaxPHAs = 5000;
static struct pha_struct *phaBuf = nil, *phaPtr, *phaBufEnd;
/*
* Set all wave handles to nil, because the experiment is new,
* so they all point to nowhere.
*/
void
NewMainWaves( void )
{
short i;
for(i=0; i curPntMain )
curPntMain = wPnts;
if( WaveType( wavesMain[i] ) != typesMain[i] )
{
dimSizes[0] = wPnts;
err = MDChangeWave( wavesMain[i], typesMain[i], dimSizes );
}
}
}
if( !err )
{
err = FetchOrMakeWaveInDF( nil, tcpFreeWaveName, tcpFreeWaveType, &tcpFreeWave,
0, &dfCDP );
wPnts = WavePoints( tcpFreeWave );
if( wPnts > tcpWaveInd )
tcpWaveInd = wPnts;
}
if( !err )
{
err = FetchOrMakeWaveInDF( nil, tcpTimeWaveName, tcpTimeWaveType, &tcpTimeWave,
0, &dfCDP );
wPnts = WavePoints( tcpTimeWave );
if( wPnts > tcpWaveInd )
tcpWaveInd = wPnts;
if( !err )
/* Make data units of time wave "dat", so it will display as time/date */
SetWaveUnits( tcpTimeWave, "", "dat" );
}
/*
* We don't have to make all the waves the same length, since
* the data-loading routines always check the length.
*/
return err;
}
void
LockMainWaves( int states[kNMainWaves], void *ptrs[kNMainWaves] )
{
int types[kNMainWaves];
int newStates[kNMainWaves];
long lengths[kNMainWaves];
short i;
GetWavesInfo( wavesMain, kNMainWaves, types, lengths, states, ptrs );
for( i=0; itick_cntr >= 12 )
nrolls = ( pp->scTime/4096 - scTimeDiff - 6 ) / 16;
else if( pp->tick_cntr < 4 )
nrolls = ( pp->scTime/4096 - scTimeDiff + 6 ) / 16;
else
nrolls = ( pp->scTime/4096 - scTimeDiff ) / 16;
return pp->tick_cntr + nrolls * 16;
}
static long
PHAParityOK( struct pha_struct *pp )
{
unsigned char *uc, accum;
short i, count;
uc = (unsigned char *)pp;
uc += sizeof(unsigned long); /* Don't forget to skip scTime field */
accum = 0;
for( i=0; i<8; i++ )
accum ^= *uc++;
count = 0;
for( i=0; i<8; i++ )
{
count ^= (accum & 1);
accum >>= 1;
}
return !count;
}
static void
HandlePHA( struct pha_struct *pp )
{
int err = 0;
DOUBLE dval[kNMainWaves];
short i;
if( !PHAParityOK( pp ) )
{
struct raw_struct *rs = (struct raw_struct *)pp;
PutMsg( mtErr, msDT, 9, "%02hd*(%lu) PHA PARITY ERR: %04X %04X %04X %04X",
pp->pixel, pp->scTime, rs->word0, rs->word1, rs->word2, rs->word3 );
return; // EARLY RETURN!
}
dval[wmPH] = pp->pulse_height;
if( pp->flag_baseline && ( dval[wmPH] > 16383 ) )
dval[wmPH] -= 32768;
dval[wmGT] = pp->scTime/4096.0;
dval[wmPix] = pp->pixel;
dval[wmRT] = pp->rise_time;
dval[wmQual] = pp->pulse_quality;
dval[wmTick] = pp->tick_cntr;
dval[wmVern] = pp->time_vernier;
dval[wmSamp] = pp->sample_count;
dval[wmUT] = CalcRealTime( pp );
dval[wmUT] += dval[wmSamp]/sampRate + dval[wmVern]/(sampRate*16.0);
dval[wmFlags] = pp->flag_secondary * (1<<0) + // 1
pp->flag_loRes * (1<<1) + // 2
pp->flag_noRes * (1<<2) + // 4
pp->flag_baseline * (1<<3) + // 8
pp->flag_antiCo * (1<<4) + // 16
pp->flag_clipped * (1<<5); // 32
for( i=0; i= phaBufEnd )
{
DoCDPUpdate();
if( phaPtr >= phaBufEnd )
{
numPacketsLost++;
PutMsg( mtErr, msGSE, 9, "Lost a packet (too many PHAs)" );
return;
}
}
*phaPtr++ = *phs;
}
/*
* Accumulate this channel's telemetry CRC, and increment its count
*/
static void
AccumTelemCRC( union dt_union *dup )
{
struct crnt_strct *crnt;
short pixel;
pixel = dup->pha.pixel;
crnt = crnt_ar[pixel];
if( crnt->tcrc_valid )
{
crnt->telem_count += 1;
crnt->telem_crc = crc_ary( crnt->telem_crc, 4, (unsigned short *)&(dup->raw.word0) );
}
}
static void
DTMessage( short level, union dt_union *dup, const char *typeStr )
{
PutMsg( mtInfo, msDT, level, "%02hd (%lu) %04X %04X %04X %04X %s",
dup->pha.pixel, dup->pha.scTime, dup->raw.word0,
dup->raw.word1, dup->raw.word2, dup->raw.word3, typeStr );
}
static void
HandleDT( union dt_union *dup )
{
short type;
if( 0 == (type = dup->pha.type) )
{
/* PHA block */
DTMessage( 2, dup, "(PHA)" );
StorePHA( &(dup->pha));
AccumTelemCRC( dup );
}
else if( 1 == type )
{
/* dump block */
DTMessage( 1, dup, "(dump)" );
HandleDump( dup );
AccumTelemCRC( dup );
}
else if( 3 == type )
{
/* rates, HK, reply or error */
if ( dup->rates.rates0.flag0 == 0 )
{
/* Rates */
/* (Don't accumulate telemCRC) */
DTMessage( 2, dup, "(Rates)" );
HandleRates( dup );
}
else
{
/* HK, reply or error */
if( dup->hk.hk0.blockcount == 3 )
{
/* Reply or error */
AccumTelemCRC( dup );
switch( dup->replyorerror.reply.flagrore)
{
case 0: /* reply */
DTMessage( 2, dup, "(reply)" );
HandleReply( dup );
break;
case 1: /* error */
DTMessage( 2, dup, "(error)" );
HandleError( dup );
break;
}
}
else
{
/* HK */
/* (Don't accumulate telemCRC) */
DTMessage( 2, dup, "(HK)" );
HandleHK( dup );
}
}
}
else
{
/* 2 == type */
DTMessage( 7, dup, "(unrecognized block type=2)" );
AccumTelemCRC( dup );
}
}
/*
* Transfer our local information about modified waves to Igor
*/
static void
UpdateIgor( void )
{
int i;
WaveHandleModified( tcpFreeWave );
WaveHandleModified( tcpTimeWave );
if( modifiedMain )
for( i=0; i kPutHeaderLevel) || force )
{
PutMsg( mtInfo, msCCSDS, sLevel, "CCSDS: %04hX %04hX %04hX %04hX %04hX:"
" inst=%hX, subsys=%hx, type=%hX, len=%hu, seqNum=%hu, time=%lu(%f)",
sp[0], sp[1], sp[2], sp[3], sp[4], ch->inst>>5, ch->subSys>>2, ch->dataType>>9,
ch->dataLength, ch->seqNum, ch->time, ch->time/4096.0 );
}
}
static unsigned short
BreakCCSDSHeader( unsigned char *p, ccHdrInfo_t *ch )
{
unsigned short w0, w1, inst, *sp;
sp = (unsigned short *)p;
w0 = *sp++;
w1 = *sp++;
inst = w0 & APID_instMask;
ch->inst = inst;
ch->subSys = w0 & APID_subSysMask;
ch->dataType = w0 & APID_typeMask;
ch->isTele = w0 & APID_teleMask;
ch->seqType = w1 & seqFlagMask;
ch->seqNum = w1 & seqCntMask;
ch->dataLength = *sp++ - 3;
// ch->time = *sp++ << 4;
// ch->time += *sp>>12;
ch->time = *sp++ * 65536.0;
ch->time += *sp;
lastPacketHeader = *ch;
PutCCSDSHeader( p, ch, kPutHeaderLevel, true );
return inst;
}
/*
* Looks at sp to see if it's a valid CCSDS header.
* If yes, returns the length of the data.
* If no, returns 0.
*/
static unsigned short
HeaderValid( unsigned short *sp )
{
unsigned short w0, w1;
unsigned short subSys, dataType, isTele, dataLength;
w0 = *sp++;
w1 = *sp++;
dataLength = *sp - 3;
subSys = w0 & APID_subSysMask;
dataType = w0 & APID_typeMask;
isTele = w0 & APID_teleMask;
/* Check the version, type and second header, plus instrument all at once */
if( ( w0 & (firstBitsMask|APID_instMask) ) == (firstBitsVal | APID_instXRS) )
{
/* Okay, the instrument field is okay. Check the subsys. */
if( APID_subSysCAPA == subSys || APID_subSysCAPB == subSys )
{
/* Looks like CAP data. Type must be HK (tele or auto) */
if( APID_typeHK != dataType )
return 0;
}
else if( APID_subSysCDPA == subSys || APID_subSysCDPB == subSys )
{
/* Looks like CDP data. Type must be HK (tele or auto), sci (auto) or mem (auto) */
if( APID_typeHK != dataType )
{
/* Not HK. If tele is on or it's not either sci or mem, it's bad. */
if( isTele || ( APID_typeMemDmp != dataType && APID_typeScience != dataType ) )
return 0;
}
}
else if( APID_subSysACHE == subSys )
{
/* ACHE. Better be hk (tele or auto) */
if( APID_typeHK != dataType )
return 0;
}
else
{
/* Bad instrument. */
return 0;
}
/*
* It's a valid instrument, subsystem and data type.
* Check sequence flag bits.
*/
if( (w1 & seqFlagMask) != seqFlagNoGroup )
return 0;
/* Make sure data length is even */
if( dataLength % 2 )
return 0;
/* Okay, it's a good header. */
return dataLength;
}
return 0;
}
/*
* Check whether we are at the start of a CCSDS packet. This is only
* called when we're trying to resync.
*
* Makes sure first 16 bits are a valid header, and checks for
* another valid header after the length of this packet.
* Returns ssUnknown if not good, ssResync if we have to wait to check.
*/
static short
PacketSync( unsigned char *p, long bytesLeft )
{
unsigned short dataLength, *sp;
sp = (unsigned short*)p;
dataLength = HeaderValid( sp );
if( dataLength )
{
/* Look for another good packet after this one */
if( dataLength < bytesLeft-20 )
{
dataLength = HeaderValid( sp + 5 + dataLength/2 );
if( dataLength )
return ssGood;
else
return ssUnknown;
}
else
{
/* This packet is incomplete. Wait a while */
return ssResync;
}
}
return ssUnknown;
}
/*
* Returns nonzero if it's an APID we care about (CDP or CAP)
* In fact it returns ssCDP or ssCAP respectively.
*
* Now does some sanity checking, and tries to resync if we're lost.
* skip tells the caller how many bytes to move ahead. Normally it's
* 10 for a good header.
*
* returns ssWait if we're still waiting for enough data to resync.
*
*/
static long
ReadCCSDSHeader( unsigned char *p, long bytesLeft, long *skip, ccHdrInfo_t *ch,
short state )
{
unsigned short inst, resyncState;
unsigned long timeout;
static short lostSync = false;
static unsigned long bytesLost;
long result = ssResync;
if( state != ssResync )
{
*skip = 10;
inst = BreakCCSDSHeader( p, ch );
bytesLost = 0;
if( APID_instXRS == inst )
{
/* ACHE packets */
lostSync = false;
if( ch->subSys == APID_subSysCDPA || ch->subSys == APID_subSysCDPB )
result = ssCDP;
else if( ch->subSys == APID_subSysCAPA || ch->subSys == APID_subSysCAPB )
result = ssCAP;
else if( ch->subSys == APID_subSysACHE )
{
short i, n;
char buf[256], *bp;
bp = buf;
bp += sprintf( bp, "ACHE: (%lu) %hd bytes: ", ch->time, ch->dataLength );
n = ch->dataLength;
if( n > 24 )
n = 24;
for( i=0; idataLength )
bp += sprintf( bp, "..." );
PutMsg( mtInfo, msACHE, 3, buf );
result = 0;
}
else
result = ssUnknown;
if( ssUnknown == result )
{
PutCCSDSHeader( p, ch, 9, false );
PutMsg( mtErr, msGSE, 9, " --> Unknown XRS subsystem %x", ch->subSys );
}
/* else
{
if( ch->dataLength > bytesLeft-10 )
{
*skip = 0;
result = ssWait;
}
}
return result;
*/
}
else if( APID_instFill == inst && APID_typeFill == ch->dataType )
{
/* Accept but ignore fill packets. */
result = 0;
}
else if( APID_instXIS == inst )
{
/* Accept but ignore XIS packets. */
result = 0;
}
else if( APID_instDP == inst )
{
if( scrLevel <= 1 )
{
/* Accept DP packets. */
char buf[256], *bp = buf;
short i, j, n;
bp += sprintf( bp, "DP: (%lu) %hd bytes:",ch->time, ch->dataLength );
n = ch->dataLength + 10;
if( n > bytesLeft )
n = bytesLeft;
//if( n > 30 )
// n = 30;
PutMsg( mtInfo, msDP, 3, buf );
for( i=0; idataLength > bytesLeft-10 )
{
*skip = 0;
result = ssWait;
}
else
{
result = ssDP;
}
*/
result = ssDP;
}
else if( APID_instHXD == inst )
{
/* Accept but ignore HXD packets. */
return 0;
}
else
{
/* Not an APID we know about -- Better resync. Start looking at next byte. */
*skip = 1;
p += 1;
bytesLost = 1;
bytesLeft -= 1;
if( !lostSync )
{
PutCCSDSHeader( p, ch, 9, false );
PutMsg( mtErr, msGSE, 9, " -->Lost Packet Sync (unknown system %x)", inst );
lostSync = true;
}
}
}
else
{
/* We were already trying to resync */
*skip = 0;
result = ssResync;
}
if( result != ssResync )
{
if( ch->dataLength > bytesLeft-10 )
{
*skip = 0;
return ssWait;
}
else
{
return result;
}
}
timeout = LMGetTicks() + 30;
while( LMGetTicks() < timeout && bytesLeft > 0 )
{
resyncState = PacketSync( p, bytesLeft );
if( ssResync == resyncState )
{
/* Not enough data to tell if it's a good packet */
return ssResync;
}
else if( ssUnknown != resyncState )
{
*skip += 10; /* skip over the good header */
inst = BreakCCSDSHeader( p, ch );
if( lostSync )
{
PutCCSDSHeader( p, ch, 9, false );
PutMsg( mtErr, msGSE, 9, "Back in Sync. Lost %lu bytes", bytesLost );
}
bytesLost = 0;
lostSync = false;
if( APID_instXRS == inst )
{
if( ch->subSys == APID_subSysCDPA || ch->subSys == APID_subSysCDPB )
return ssCDP;
if( ch->subSys == APID_subSysCAPA || ch->subSys == APID_subSysCAPB )
return ssCAP;
if( ch->subSys == APID_subSysACHE )
return 0; /* Accept but ignore ACHE packets */
}
}
p += 1;
bytesLost += 1;
bytesLeft -= 1;
*skip += 1;
}
/* Didn't manage to resync */
return ssResync;
}
static const long fileCreator = 'hDmp';
static const long fileType = 'BINA';
static long
OpenUniqueFile( const char *base, FSSpec *fssp, short *refNumP )
{
long err = 0;
short suffix;
char fName[64];
*refNumP = 0;
suffix = 0;
do
{
suffix += 1;
sprintf( fName, "%.25s %hd", base, suffix );
err = FSMakeFSSpec( 0, 0, CtoPstr( fName ), fssp );
} while( !err && suffix < 100 );
if( !err )
err = -1;
if( fnfErr == err )
err = 0;
if( !err )
{
err = FSpCreate( fssp, fileCreator, fileType, smSystemScript );
}
if( !err )
{
err = FSpOpenDF( fssp, fsWrPerm, refNumP );
}
return err;
}
/*
* We found a bad packet. Save it in the Igor application directory with
* a name like "CCSDS 1".
*/
static void
SaveCCSDSPacket( unsigned char *p, ccHdrInfo_t *ch )
{
long err = 0;
FSSpec fss;
short refNum;
long count;
err = OpenUniqueFile( "CCSDS ", &fss, &refNum );
if( err )
{
refNum = 0;
PutMsg( mtErr, msGSE, 9, "Couldn't open file to save bad packet (error %ld)", err );
}
else
{
count = sizeof( ccHdrInfo_t );
err = FSWrite( refNum, &count, ch );
}
if( !err )
{
count = ch->dataLength;
err = FSWrite( refNum, &count, p );
}
if( !err )
PutMsg( mtWarn, msGSE, 9, "Saved bad packet to file \"%#s\"", fss.name );
else
PutMsg( mtErr, msGSE, 9, "Error %ld saving bad packet to file \"%#s\"", fss.name );
if( refNum )
{
err = FSClose( refNum );
refNum = 0;
err = FlushVol( nil, fss.vRefNum );
}
}
static void
HandleCAPPacket( unsigned char *p, ccHdrInfo_t *ch )
{
short side;
if( APID_subSysCAPA == ch->subSys )
side = 0;
else
side = 1;
HandleCAPData( p, ch->dataLength, side, ch->time );
}
static void
HandleSciencePacket( unsigned char *p, ccHdrInfo_t *ch )
{
union dt_union du;
short more = true;
short blockBytes, length, toPrint, bytesLeft, i;
unsigned char *pp;
char *bp, buf[256];
/* No echo byte, just a bunch of dt blocks, with lengths */
/* If bad length, discard extra bytes */
if( hasDTLengths )
blockBytes = 9;
else
blockBytes = 8;
bytesLeft = ch->dataLength;
while( bytesLeft > 0 )
{
du.raw.scTime = ch->time;
if( hasDTLengths )
{
length = *p++;
bytesLeft--;
PutMsg( mtInfo, msDT, 3, "-----DT length 0x%02hX = %hdd (%.1f blocks)",
length, length, length/8.0 );
if( length % 8 )
{
PutMsg( mtErr, msDT, 9,
"DT contains %hu bytes (%hu left after %hu 8-byte blocks) at %hu bytes into",
length, length % 8, length / 8, ch->dataLength-bytesLeft );
PutCCSDSHeader( p, ch, 9, false );
toPrint = length;
pp = p;
while( toPrint > 0 )
{
bp = buf;
for( i=0; i<32&&toPrint>0; i++,toPrint-- )
bp += sprintf( bp, "%02hX ", *pp++ );
bp += sprintf( bp, "\r" );
PutMsg( mtErr, msDT, 5, buf );
}
/* Drop this DT, (and save the packet -- not implemented) */
SaveCCSDSPacket( p, ch );
bytesLeft = 0;
length = 0;
}
}
else
{
length = 8;
}
if( bytesLeft < length )
{
PutMsg( mtErr, msDT, 9, "DT length of %hd with %hd bytes remaining (total packet length = %hd)",
length, bytesLeft, ch->dataLength );
break;
}
while( length > 0 )
{
du.raw.word0 = *((short *)p); p += sizeof(short);
du.raw.word1 = *((short *)p); p += sizeof(short);
du.raw.word2 = *((short *)p); p += sizeof(short);
du.raw.word3 = *((short *)p); p += sizeof(short);
HandleDT( &du );
length -= 8;
bytesLeft -= 8;
}
}
}
static void
HandleHKPacket( unsigned char *p, ccHdrInfo_t *ch )
{
unsigned short mData[mcBufLength+1];
unsigned char echo;
long len, bytesLeft, i;
short side;
if( APID_subSysCDPA == ch->subSys )
side = 0;
else if ( APID_subSysCDPB == ch->subSys )
side = 1;
else
{
PutMsg( mtErr, msGSE, 9, "Oh crap! HandleHKPacket got a wrong subsys packet (%hu)", ch->subSys );
return;
}
bytesLeft = ch->dataLength;
while( bytesLeft > 0 )
{
len = *p++; bytesLeft--;
if( bytesLeft < len )
PutMsg( mtErr, msGSE, 9, "%d bytes missing from HK packet", len-bytesLeft );
echo = *p++; /* Get the echo byte from the master */
if( (echo & ECHO_TYPE_MASK) == ECHO_TYPE_MASTER )
{
short copyWords = (len-1) / 2;
if( copyWords > mcBufLength )
copyWords = mcBufLength;
for( i=0; itime, side, echo, mData, (len-1)/2, copyWords );
bytesLeft -= len;
} /* if echo is a master command */
else
{
/* echo is a channel or broadcast command */
PutMsg( mtInfo, msDT, 3, "(%c) @ %lu: Channel command %02X", side?'A':'B', ch->time, echo );
bytesLeft -= len;
p += len-1;
}
}
}
static void
PrepareDPMemDump( const char *dfName, const char *waveName, short type )
{
short err;
err = FetchOrMakeWaveInDF( dfName, waveName, dpMemWaveType, &dpMemWave,
dpMemWaveLength, nil );
if( err )
{
dpMemWave = nil;
dpMemType = dpmdNone;
}
else
{
dpMemType = type;
}
}
static void
HandleDPPacket( unsigned char *p, ccHdrInfo_t *ch )
{
unsigned char c;
/* we only handle hk */
if( APID_typeHK == ch->dataType )
{
/* all we care about are the mem dump bits */
c = p[dpHKMemDumpByte] & dpHKMemDumpBitMask;
switch( c )
{
case dpHKMemDumpBitCDPA:
PrepareDPMemDump( cdpDFName, dpMemCDPAWaveName, dpmdCDPA );
break;
case dpHKMemDumpBitCDPB:
PrepareDPMemDump( cdpDFName, dpMemCDPBWaveName, dpmdCDPB );
break;
case dpHKMemDumpBitAche:
PrepareDPMemDump( cdpDFName, dpMemAcheWaveName, dpmdAche );
break;
default:
dpMemWave = nil;
dpMemType = dpmdNone;
break;
}
}
}
/*
* CDP memory dump (from the DP)
* Format:
* 3 byte address (top byte always 0)
* 2 byte length
* 8 128-byte data blocks
*
* This puts it into a wave, in the correct place
*/
static void
HandleCDPMemDumpPacket( unsigned char *p, ccHdrInfo_t *ch )
{
long err = 0;
short i, hState;
short type;
long waveSize;
long dataOffset;
float *fp;
unsigned short addr, actLength, *dataP;
const unsigned short dpMemDumpBytes = 3 + 2 + 8 * 128;
if( GetScrLevel(msDP) <= 3 )
{
char buf[256], *bp;
bp = buf;
bp += sprintf( bp, "DP mem dump: " );
for( i=0; i<30; i++ )
bp += sprintf( bp, "%02hX", *(p+i) );
PutMsg( mtInfo, msDP, 3, buf );
}
if( ch->dataLength != dpMemDumpBytes )
{
PutMsg( mtErr, msDP, 9, "Mem Dump packet is %hu bytes, should be %hu", ch->dataLength,
dpMemDumpBytes );
return;
}
// err = FetchOrMakeWaveInDF( cdpDFName, dpMemWaveName, dpMemWaveType,
// &dpMemWave, dpMemWaveLength, nil );
if( !dpMemWave )
{
PutMsg( mtErr, msDP, 9, "Got a DP mem dump packet while DP is not dumping." );
return;
}
if( !err )
{
/*
* Put the data into the wave.
*/
type = WaveType( dpMemWave );
if( type != dpMemWaveType )
{
PutMsg( mtErr, msDP, 9, "Mem Dump wave is the wrong type" );
return;
}
waveSize = WavePoints( dpMemWave );
if( waveSize != dpMemWaveLength )
{
PutMsg( mtErr, msDP, 9, "Mem Dump wave is not %hu points long", dpMemWaveLength );
return;
}
err = MDAccessNumericWaveData( dpMemWave, kMDWaveAccessMode0, &dataOffset );
if( err )
{
PutMsg( mtErr, msDP, 9, "Can't access Mem Dump wave" );
IgorError( "Can't access Mem Dump wave", err );
return;
}
addr = p[1] * 256 + p[2];
actLength = p[3] * 256 + p[4];
if( actLength != ( 1024 ) )
{
PutMsg( mtErr, msDP, 9, "Mem Dump length is %hu, not %hu", actLength, dpMemDumpBytes );
return;
}
if( (addr + actLength) > dpMemWaveLength )
{
PutMsg( mtErr, msDP, 9, "Mem Dump will overflow wave!!" );
return;
}
hState = MoveLockHandle( dpMemWave );
fp = (float*)((char*)(*dpMemWave) + dataOffset);
fp += addr;
dataP = (unsigned short*)( p + 3 + 2 );
for( i=0; i 0 )
{
gotSome = true;
if( ssCDP == state )
{
switch( ch.dataType )
{
case APID_typeScience:
HandleSciencePacket( p, &ch );
break;
case APID_typeMemDmp:
HandleCDPMemDumpPacket( p, &ch );
break;
case APID_typeHK:
HandleHKPacket( p, &ch );
}
}
else if( ssCAP == state )
{
HandleCAPPacket( p, &ch );
}
else if( ssDP == state )
{
HandleDPPacket( p, &ch );
}
else
{
PutMsg( mtErr, msCCSDS, 9, "ReadCCSDSHeader returned unknown subsystem %d", state );
}
}
p += ch.dataLength;
bytesLeft -= ch.dataLength;
if( bytesLeft < 10 )
more = false;
}
if( bytesLeft < 0 )
{
PutCCSDSHeader( packetStart, &ch, 9, false );
PutMsg( mtErr, msCCSDS, 9, " -->Clump alignment error. Left with %ld bytes of %d, after using %d",
bytesLeft, totalBytes, packetStart-buf );
bytesLeft = 0;
}
GetDateTime( &now );
if( now >= (lastUpdate + updateInterval) && gotSome )
{
/*
* Time to actually deal with accumulated PHAs.
*/
DoCDPUpdate();
}
return bytesLeft;
}
/*
* Return 1 if we're using wave w, 0 otherwise.
*/
int
CheckWavePHA( waveHndl w )
{
short i;
for( i=0; i