/* * Copyright(c) 1997, Space Science and Engineering Center, UW-Madison * Refer to "McIDAS Software Acquisition and Distribution Policies" * in the file mcidas/data/license.txt */ /**** $Id: GVAR.c,v 1.41 2021/01/29 21:58:38 daves Exp $ ****/ /* * GVAR.c * GVAR specific SDI routines * * GVAR data processing routines * LoadGvarLine load the next line of data into a buffer * CheckImgBounds check request extent against image extent * GetLineDoc get GVAR line documentation * GetBlockHeader get GVAR block header * FillBlock given word and bit offset, fill a buffer with raw data * GetNextBlock get next GVAR block of specified data type * GetGvarNavCod extract navigation codicil * GetGvarCards extract info for and create comment cards * GetGvarRes get resolution in km at a given image coordinate * GvarNavImgToEarth convert image coordinate to lat/lon pair * GvarNavEarthToImg convert lat/lon pair to image coordinates * GetGvarSSNum get sensor source number for current data * GetGvarCalCod extract calibration codicil * InitGvarAreaDir initialize a GVAR area directory * NearestDataLine return data for image line nearest that requested * * ADDE related routines * SendGvarCod transfer nav or cal codicil to client */ #include #include #include #include #include #include #include "crc16.h" #include "mcidas.h" #include "mcidasp.h" #include "AreaDir.h" #include "BitUtil.h" #include "GVAR.h" #include "SDIConv.h" #include "SDIUtil.h" #define MAX_CRC_TRY 1024 static int gvar_satid=0; /* *| Name: *| LoadGvarLine - Load the next line of data into a buffer. *| *| Interface: *| int *| LoadGvarLine ( *| FILE *ifp, *| idxinfo *idxInfo, *| reqinfo *reqInfo, *| int *areaDir, *| int reqImgLine, *| int band *| ) *| *| Input: *| ifp - index file pointer *| idxInfo - index file info struct pointer *| areaDir - area directory *| reqImgLine - image line number requested *| band - band number to locate data for *| *| Input and Output: *| reqInfo - request info struct, holds pointer to output data line *| *| Output: *| none *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int LoadGvarLine ( FILE *ifp, idxinfo *idxInfo, reqinfo *reqInfo, int *areaDir, int reqImgLine, int band ) { int rc; int gvarDataSize = GVAR_DATA_SIZE; int dummy; int dataType; sLog(SLOG_EE1, "\n -- LoadGvarLine in...\n"); sLog(SLOG_IMG, " loading req img line %d\n", reqImgLine); /* zero out the intermediate output line */ (void) memset(reqInfo->dstDataBuffer, 0, (unsigned int) (areaDir[NUM_ELEMENTS] * GVAR_DATA_SIZE)); /* zero out the input buffer */ (void) memset((void *) reqInfo->srcDataBuffer, 0, GVAR_MAX_BLOCK_SIZE); /* set data type flag */ if (band == 1) { dataType = DT_VIS; } else { dataType = DT_IR; } /* attempt to load the raw data block */ rc = GetNextBlock(ifp, idxInfo, reqInfo, reqInfo->srcDataBuffer, dataType, reqImgLine, band); if (rc < 0) return -1; /* extract the data needed for this line */ if (TenOff ( reqInfo->srcDataBuffer, idxInfo->bitOffset, (areaDir[ELEMENT_RES] / reqInfo->baseElemRes[band - 1]), 1, (reqInfo->dataElementCount[band - 1] / areaDir[ELEMENT_RES]), 32, (short *) (reqInfo->dstDataBuffer + ((reqInfo->elemSkipOut[band - 1] / areaDir[ELEMENT_RES]) * 2))) != 0) { return -1; } /* calibrate the data if needed */ if (strncmp((char *) &areaDir[CAL_TYPE], "RAW", 3) != 0) { sLog(SLOG_EE1, " calibrating, RAW to %4.4s\n", &areaDir[CAL_TYPE]); rc = kb1cal_(&dummy, areaDir, &areaDir[NUM_ELEMENTS], &band, reqInfo->dstDataBuffer); } else { sLog(SLOG_EE1, " no calibrating, just pack/crack\n"); sLog(SLOG_EE1, " %d to %d byte, %d elements\n", gvarDataSize, areaDir[BYTES_PER_PIX], areaDir[NUM_ELEMENTS]); mpixel_(&areaDir[NUM_ELEMENTS], &gvarDataSize, &areaDir[BYTES_PER_PIX], reqInfo->dstDataBuffer); } sLog(SLOG_EE1, " -- LoadGvarLine out (ok)...\n\n"); return 0; } /* *| Name: *| CheckImgBounds - Check request extent against image extent. *| *| Interface: *| int *| CheckImgBounds ( *| dscinfo *dscInfo, *| reqinfo *reqInfo, *| int *areaDir *| ) *| *| Input: *| dscInfo - descriptor file info struct pointer *| reqInfo - request info struct pointer *| areaDir - area directory *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| 0: some coverage exists *| -1: no coverage *| *| Remarks: *| *| Categories: *| ingest/decode */ int CheckImgBounds ( dscinfo *dscInfo, reqinfo *reqInfo, int *areaDir ) { int isl, iel; int ise, iee; int rsl, rel, rnl; int rse, ree, rne; int bandIdx; sLog(SLOG_EE1, "\n -- CheckImgBounds in...el=%d res=%d\n", areaDir[NUM_ELEMENTS],areaDir[ELEMENT_RES]); /* load image extent */ isl = dscInfo->sil; ise = dscInfo->sie; iel = dscInfo->eil; iee = dscInfo->eie; /* load request extent */ rsl = areaDir[START_LINE]; rse = areaDir[START_ELEMENT]; rnl = areaDir[NUM_LINES] * areaDir[LINE_RES]; rne = areaDir[NUM_ELEMENTS] * areaDir[ELEMENT_RES]; rel = rsl + rnl - 1; ree = rse + rne - 1; /* log image extent, request extent */ sLog(SLOG_IMG, " image extent: isl: %d, ise: %d, iel: %d, iee: %d\n", isl, ise, iel, iee); sLog(SLOG_IMG, " request extent: rsl: %d, rse: %d, rel: %d, ree: %d\n", rsl, rse, rel, ree); /* if request exceeds image in element extent, truncate request */ /* note this is new and some of the code below could probably be */ /* cleaned up or eliminated as a result, but I don't have time now! */ if (ree > iee) { areaDir[NUM_ELEMENTS] = areaDir[NUM_ELEMENTS] - ((ree - iee) / areaDir[ELEMENT_RES]); rne = areaDir[NUM_ELEMENTS] * areaDir[ELEMENT_RES]; ree = rse + rne - 1; areaDir[NUM_ELEMENTS] = (areaDir[NUM_ELEMENTS] + 3) / 4 * 4; } /* make sure there is some coverage, either line or element direction */ if ((rel < isl) || (iel < rsl)) { sLog(SLOG_EE1, " -- CheckImgBounds (failed) out...\n\n"); return -1; } if ((ree < ise) || (iee < rse)) { sLog(SLOG_EE1, " -- CheckImgBounds (failed) out...\n\n"); return -1; } for (bandIdx = 0; bandIdx < MAX_GVAR_BAND; bandIdx++) { { /* determine actual number of elements to move each line */ reqInfo->dataElementCount[bandIdx] = rne; /* number of elements to skip at beginning of each input line */ reqInfo->elemSkipIn[bandIdx] = 0; /* number of elements to skip at beginning of each output line */ reqInfo->elemSkipOut[bandIdx] = 0; /* if request starts before image starts */ if (rse < ise) { reqInfo->elemSkipOut[bandIdx] = ise - rse; reqInfo->dataElementCount[bandIdx] = reqInfo->dataElementCount[bandIdx] - reqInfo->elemSkipOut[bandIdx]; } /* if the image starts before the request starts */ if (ise < rse) { if (reqInfo->baseElemRes[bandIdx] != 0) { reqInfo->elemSkipIn[bandIdx] = (rse - ise) / reqInfo->baseElemRes[bandIdx]; } } /* if image ends before request ends */ if (ree > iee) { reqInfo->dataElementCount[bandIdx] = reqInfo->dataElementCount[bandIdx] - (ree - iee); } if ((reqInfo->dataElementCount[bandIdx] % areaDir[ELEMENT_RES]) != 0) { reqInfo->dataElementCount[bandIdx] += areaDir[ELEMENT_RES]; } sLog(SLOG_IMG, " skipping %d input elements\n", reqInfo->elemSkipIn[bandIdx]); sLog(SLOG_IMG, " skipping %d output elements\n", reqInfo->elemSkipOut[bandIdx]); sLog(SLOG_IMG, " dataElementCount=%d\n", reqInfo->dataElementCount[bandIdx]); } } /* if image line ends before request line ends, truncate request */ if (rel > iel) { areaDir[NUM_LINES] = areaDir[NUM_LINES] - ((rel - iel) / areaDir[LINE_RES]); } sLog(SLOG_EE1, " -- CheckImgBounds out...\n\n"); return 0; } /* *| Name: *| GetLineDoc - Get GVAR line documentation. *| *| Interface: *| int *| GetLineDoc ( *| idxinfo *idxInfo, *| short *lineDoc, *| int offset *| ) *| *| Input: *| idxInfo - index file info struct pointer *| offset - bit offset to line doc *| *| Input and Output: *| none *| *| Output: *| lineDoc - extracted GVAR line documentation *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetLineDoc ( idxinfo *idxInfo, short *lineDoc, int offset ) { /* a buffer of line doc size will work for reading raw bits */ char buffer[32]; int totalBits; int byteOffset; int bitOffset; int bytesRead; sLog(SLOG_EE2, "\n -- GetLineDoc in...\n"); /* calculate new byte and bit offsets specifically for reading doc */ totalBits = offset + idxInfo->bitOffset; byteOffset = idxInfo->wordOffset * sizeof(int); byteOffset = byteOffset + (totalBits / 8); bitOffset = totalBits % 8; /* set file pointer to the correct offset */ if (TrySeek(idxInfo->rdfFilePtr, byteOffset) != 0) { sLog(SLOG_EE2, " -- GetLineDoc out (TrySeek failure)...\n\n"); return -1; } /* attempt to read in the bytes */ bytesRead = TryRead(idxInfo->rdfFilePtr, buffer, sizeof(buffer)); if (bytesRead != sizeof(buffer)) { sLog(SLOG_EE2, " -- GetLineDoc out (RDF read failure)...\n\n"); return -1; } /* decode the line doc bits into shorts */ if (TenOff(buffer, bitOffset, 1, 1, 16, 1, lineDoc) != 0) { sLog(SLOG_EE2, " -- GetLineDoc out (TenOff failure)...\n\n"); return -1; } sLog(SLOG_EE2, " -- GetLineDoc out (ok)...\n\n"); return 0; } /* *| Name: *| GetBlockHeader - Get GVAR block header. *| *| Interface: *| int *| GetBlockHeader ( *| idxinfo *idxInfo, *| char *blockHeader *| ) *| *| Input: *| idxInfo - index file info struct pointer *| *| Input and Output: *| none *| *| Output: *| blockHeader - extracted GVAR block header *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetBlockHeader ( idxinfo *idxInfo, char *blockHeader ) { /* a buffer of block header size will work for reading raw bits */ char buffer[90 + 1]; unsigned char tmpHeader[90]; int i; int totalBits; int byteOffset; int bitOffset; int bytesRead; sLog(SLOG_EE2, "\n -- GetBlockHeader in...\n"); /* calculate new byte and bit offsets specifically for reading doc */ totalBits = idxInfo->bitOffset; byteOffset = idxInfo->wordOffset * sizeof(int); byteOffset = byteOffset + (totalBits / 8); bitOffset = totalBits % 8; /* set file pointer to the correct offset */ if (TrySeek(idxInfo->rdfFilePtr, byteOffset) != 0) { sLog(SLOG_EE2, " -- GetBlockHeader out (TrySeek failure)...\n\n"); return -1; } /* attempt to read in the bytes */ bytesRead = TryRead(idxInfo->rdfFilePtr, buffer, sizeof(buffer)); if (bytesRead != sizeof(buffer)) { sLog(SLOG_EE2, " -- GetBlockHeader out (RDF read failure)...\n\n"); return -1; } /* decode the line doc bits into shorts */ if (ByteOff(buffer, bitOffset, sizeof(tmpHeader), tmpHeader) != 0) { sLog(SLOG_EE2, " -- GetBlockHeader out (ByteOff failure)...\n\n"); return -1; } /* use majority vote to hopefully remove any noise */ for (i = 0; i < 30; ++i) blockHeader[i] = ((tmpHeader[i+30] | tmpHeader[i+60]) & tmpHeader[i] | tmpHeader[i+30] & tmpHeader[i+60]); sLog(SLOG_EE2, " -- GetBlockHeader out (ok)...\n\n"); return 0; } /* *| Name: *| FillBlock - Given word and bit offset, fill a buffer with raw data. *| *| Interface: *| int *| FillBlock ( *| FILE *rdf, *| void *dataBuffer, *| int wOffs, *| int bOffs, *| int eCount *| ) *| *| Input: *| rdf - raw data file pointer *| wOffs - word offset *| bOffs - bit offset *| eCount - number of data elements to extract *| *| Input and Output: *| none *| *| Output: *| dataBuffer - extracted GVAR image data *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int FillBlock ( FILE *rdf, void *dataBuffer, int wOffs, int bOffs, int eCount ) { unsigned int byteCount; int byteOffset; int bytesRead; sLog(SLOG_EE2, "\n -- FillBlock in...\n"); sLog(SLOG_EE2, " wOff: %d, bOff: %d, eCount: %d\n", wOffs, bOffs, eCount); /* compute offsets and counts */ byteOffset = (wOffs * sizeof(int)) + (bOffs / 8); byteCount = (eCount * 10) / 8; /* integer division in last two statements could require 2 more bytes read */ byteCount += 2; /* set file pointer to the correct offset */ if (TrySeek(rdf, byteOffset) != 0) { sLog(SLOG_ERR, " -- FillBlock out (TrySeek failed)...\n\n"); return -1; } /* attempt to read in the bytes */ sLog(SLOG_EE2, "trying to read %d bytes at offs %d\n", byteCount, byteOffset); bytesRead = TryRead(rdf, dataBuffer, byteCount); sLog(SLOG_EE2, "read %d bytes\n", bytesRead); if (bytesRead != byteCount) { /* should always be within four bytes */ if (bytesRead <= 0) { sLog(SLOG_EE2, " RDF read, wanted: %d, got: %d\n", byteCount, bytesRead); sLog(SLOG_ERR, " -- FillBlock out (failed)...\n\n"); return -1; } } sLog(SLOG_EE2, " -- FillBlock out (ok)...\n\n"); return 0; } /* *| Name: *| GetNextBlock - Get next GVAR block of specified data type. *| *| Interface: *| int *| GetNextBlock ( *| FILE *ifp, *| idxinfo *idxInfo, *| reqinfo *reqInfo, *| char *dataBuffer, *| int dataType, *| int reqLine, *| int band *| ) *| *| Input: *| ifp - index file pointer *| idxInfo - index file info struct pointer *| reqInfo - request info struct pointer *| dataType - an enum for visible or infrared, or other data *| reqLine - requested image line number *| band - band number requested *| *| Input and Output: *| none *| *| Output: *| dataBuffer - the extracted data *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetNextBlock ( FILE *ifp, idxinfo *idxInfo, reqinfo *reqInfo, char *dataBuffer, int dataType, int reqLine, int band ) { static int curImgLine = 1; static int prevBlock = -1; int found = 0; int rc; int ldo = GVAR_HDR_BITS; int tempOffs = 0; int dataOffs = 0; int nWords; int count = 0; short lineDoc[16]; char sadDoc[16]; char docSubset[sizeof(reqInfo->bufBlockZeroSubset) + 1]; int bytesRead; int byteOffset; int filePos; idxinfo tmpInfo = {0}; int imgLineError; /* * table mapping band ordering in goes 12&13 with respect to earlier satelites */ static int goes12_bands[] = { 0,1,4,5,2,3,3 }; sLog(SLOG_EE2, "\n -- GetNextBlock in,band %d\n",band); if(gvar_satid>11) band = goes12_bands[band]; sLog(SLOG_EE2, "\n -- GetNextBlock in,band %d\n",band); /* make sure the index file is valid and open */ if (ifp == NULL) return -1; /* if seek pointer is zero for index file, we are starting at beginning */ filePos = ftell(ifp); if (filePos == 0) { curImgLine = 1; prevBlock = -1; } /* look until we locate a matching block, or EOF encountered */ while (!found) { /* load IDX info for next block available */ rc = GetIdxInfo((enum SourceType) GVAR, ifp, idxInfo); if (rc < 0) return -1; /* gross error checking: did we miss a block 0? */ if ((prevBlock == BLOCKTYPE_10) && (idxInfo->blockType == BLOCKTYPE_1)) { /* to make sure we only missed one, we have to look at the next one */ sLog(SLOG_EE2, " -- ERROR: noticed missing block 0\n"); /* first, store current seek pointer */ filePos = ftell(ifp); tmpInfo.blockType = -1; while (tmpInfo.blockType != BLOCKTYPE_0) { rc = GetIdxInfo((enum SourceType) GVAR, ifp, &tmpInfo); if (rc < 0) break; } if (tmpInfo.rdfFilePtr != NULL) { (void) CloseRdfFile(tmpInfo.rdfFilePtr); tmpInfo.rdfFilePtr = NULL; } if (rc < 0) return -1; /* now we have a pointer to the next block 0, see if we only missed 1 */ if ((tmpInfo.imageLineNumber - curImgLine) == 16) { sLog(SLOG_EE2, " -- NOTE: recovered from missing block 0\n"); curImgLine += 8; } /* restore seek pointer from before we peeked ahead */ TrySeek(ifp, filePos); } /* always store a new seek pointer, new img line when a Block 0 is found */ if (idxInfo->blockType == BLOCKTYPE_0) { /* * error checking. this case is to adjust for a ground * station error where the signal has a break, and when it resumes * the image lines are offset by one from prior to the break */ if (curImgLine != 1) { if (((idxInfo->imageLineNumber - curImgLine) % 8) != 0) { sLog(SLOG_EE2, " -- ERROR: numbering break noticed at img line: %d\n", idxInfo->imageLineNumber); sLog(SLOG_EE2, " with current line of %d\n", curImgLine); imgLineError = (idxInfo->imageLineNumber - curImgLine) % 8; idxInfo->imageLineNumber = idxInfo->imageLineNumber - imgLineError; } } /* gross error checking: is image line reported valid? */ if ((idxInfo->imageLineNumber != (curImgLine + 8)) && (curImgLine != 1)) { /* we can correct this if next img line found verifies the error */ sLog(SLOG_EE2, " -- ERROR: noticed invalid image line: %d\n", idxInfo->imageLineNumber); /* first, store current seek pointer */ filePos = ftell(ifp); /* now, find next block 0 */ tmpInfo.blockType = -1; while (tmpInfo.blockType != BLOCKTYPE_0) { rc = GetIdxInfo((enum SourceType) GVAR, ifp, &tmpInfo); if (rc < 0) break; } if (tmpInfo.rdfFilePtr != NULL) { (void) CloseRdfFile(tmpInfo.rdfFilePtr); tmpInfo.rdfFilePtr = NULL; } if (rc < 0) return -1; /* see if we can correct */ if (tmpInfo.imageLineNumber == (curImgLine + 16)) { idxInfo->imageLineNumber = curImgLine + 8; sLog(SLOG_EE2, " -- NOTE: recovered from invalid image line\n"); } /* restore seek pointer from before we peeked ahead */ TrySeek(ifp, filePos); } idxInfo->filePos = ftell(ifp); curImgLine = idxInfo->imageLineNumber; /* if docFlag is set in request, must grab 1st 150 bytes for prefix */ if (reqInfo->docFlag == 1) { byteOffset = (idxInfo->wordOffset * sizeof(int) + (idxInfo->bitOffset + GVAR_HDR_BITS) / 8); rc = TrySeek(idxInfo->rdfFilePtr, byteOffset); bytesRead = TryRead(idxInfo->rdfFilePtr, docSubset, sizeof(docSubset)); if (bytesRead != sizeof(docSubset)) { sLog(SLOG_EE2, " -- GetNextBlock out (RDF read failure)...\n\n"); return -1; } if (rc == 0) { if (ByteOff(docSubset, ((idxInfo->bitOffset + GVAR_HDR_BITS) % 8), sizeof(reqInfo->bufBlockZeroSubset), (unsigned char *) reqInfo->bufBlockZeroSubset) != 0) { sLog(SLOG_EE2, " -- ERROR: ByteOff failure in GetNextBlock...\n"); } } } } /* look for a match base on type of data requested */ switch (dataType) { case DT_BLOCK11: found = 1; ldo = GVAR_HDR_BITS; if (GetSadDoc(idxInfo, (unsigned char *) sadDoc, ldo) < 0) { return -1; } nWords = (sadDoc[11] * 1024) + sadDoc[12]; sLog(SLOG_LDOC, "nWords: %d\n", nWords); idxInfo->blockType = sadDoc[2]; break; case DT_DOC: /* currently, request for DOC will match *any* Block 0 */ if (idxInfo->blockType == BLOCKTYPE_0) { found = 1; } break; case DT_VIS: if ((idxInfo->blockType >= BLOCKTYPE_3) || (idxInfo->blockType <= BLOCKTYPE_10)) { if (reqLine == (curImgLine + idxInfo->blockType - 3)) { found = 1; } /* if we requested data prior to current avail, hold seek pointer */ if (reqLine < (curImgLine + idxInfo->blockType - 3)) { TrySeek(ifp, idxInfo->filePos); return -1; } } break; case DT_IR: /* Block 1 will potentially match IR bands 4 and 5 */ if (idxInfo->blockType == BLOCKTYPE_1) { if ((band == 4) || (band == 5)) { if ((reqLine == curImgLine) || (reqLine == curImgLine + DETECTOR_OFFSET)) { found = 1; } } /* if we requested data prior to current avail, hold seek pointer */ if (reqLine < curImgLine) { TrySeek(ifp, idxInfo->filePos); return -1; } } /* Block 2 will potentially match IR bands 2 and 3 */ if (idxInfo->blockType == BLOCKTYPE_2) { if (band == 2) { if ((reqLine == curImgLine) || (reqLine == curImgLine + DETECTOR_OFFSET)) { found = 1; } } if (band == 3) { if ((reqLine == curImgLine) || (reqLine == curImgLine + DETECTOR_OFFSET)) { found = 1; } } /* if we requested data prior to current avail, hold seek pointer */ if (reqLine < curImgLine) { TrySeek(ifp, idxInfo->filePos); return -1; } } break; } /* determine offset to first data element */ if (found) { /* grab block header for data requests if docFlag is set */ if ((dataType == DT_VIS) || (dataType == DT_IR)) { if (reqInfo->docFlag == 1) { if (GetBlockHeader(idxInfo, reqInfo->bufBlockHeader) != 0) { sLog(SLOG_EE2, " -- ERROR: GetBlockHeader failure in GetNextBlock...\n"); } } } /* initialize data offset with req starting element offset */ if (dataType == DT_DOC) { dataOffs = 0; } else { dataOffs = GVAR_HDR_BITS + GVAR_LINEDOC_BITS + reqInfo->elemSkipIn[band - 1] * 10; } /* IR data may have an additional offset, gets a little complicated... */ if (dataType == DT_IR) { switch (band) { case 2: case 4: if (reqLine == curImgLine) { rc = TrySeek(ifp, idxInfo->filePos); ldo = GVAR_HDR_BITS; } if (reqLine == curImgLine + DETECTOR_OFFSET) { ldo = GVAR_HDR_BITS; if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; sLog(SLOG_LDOC, "case 2,4:nWords: %d\n", nWords); dataOffs += (nWords * 10); ldo = GVAR_HDR_BITS + (nWords * 10); } break; case 3: ldo = GVAR_HDR_BITS; if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; sLog(SLOG_LDOC, "case 3,call 1:nWords: %d\n", nWords); tempOffs = nWords * 10; ldo = ldo + (nWords * 10); if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; sLog(SLOG_LDOC, "case 3,call 2:nWords: %d\n", nWords); tempOffs = tempOffs + (nWords * 10); ldo = ldo + (nWords * 10); if( gvar_satid < 14) { dataOffs += tempOffs; } else { /* GOES-14, -15 have higher resolution band 6 */ if (reqLine == curImgLine) { dataOffs += tempOffs; rc = TrySeek(ifp, idxInfo->filePos); } if (reqLine == curImgLine + DETECTOR_OFFSET) { ldo = GVAR_HDR_BITS + tempOffs; if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; dataOffs += (tempOffs + (nWords * 10)); ldo = ldo + (nWords * 10); } } break; case 5: ldo = GVAR_HDR_BITS; if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; tempOffs = nWords * 10; ldo = ldo + (nWords * 10); if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; tempOffs = tempOffs + (nWords * 10); ldo = ldo + (nWords * 10); if (reqLine == curImgLine) { dataOffs += tempOffs; rc = TrySeek(ifp, idxInfo->filePos); } if (reqLine == curImgLine + DETECTOR_OFFSET) { ldo = GVAR_HDR_BITS + tempOffs; if (GetLineDoc(idxInfo, lineDoc, ldo) < 0) return -1; nWords = (lineDoc[11] * 1024) + lineDoc[12]; dataOffs += (tempOffs + (nWords * 10)); ldo = ldo + (nWords * 10); } break; } /* end switch */ } } /* always remember what the previous block type was */ prevBlock = idxInfo->blockType; } sLog(SLOG_LDOC, "done with case statement DT=%d\n",dataType); /* grab appropriate line doc if docFlag is set for the request */ if ((dataType == DT_VIS) || (dataType == DT_IR)) { if (reqInfo->docFlag == 1) { if (GetLineDoc(idxInfo, lineDoc, ldo) == 0) { (void) memcpy(reqInfo->bufLineDoc, lineDoc, 32); } } } sLog(SLOG_LDOC, "done with contingent linedoc call\n"); /* FillBlock wants a count of 10 bit elements, fake this for DOC */ if ((dataType == DT_DOC) || (dataType == DT_BLOCK11)) { count = BLOCK0_SIZE_BITS / 10; } else { count = reqInfo->dataElementCount[band-1] / reqInfo->baseElemRes[band - 1]; sLog(SLOG_LDOC, "%d %d\n",reqInfo->dataElementCount[band-1], reqInfo->baseElemRes[band-1]); } sLog(SLOG_LDOC, "count=%d\n",count); if(dataType == DT_BLOCK11) { sLog(SLOG_LDOC, "dataType=B11\n"); /* calculate new byte and bit offsets specifically for reading doc */ byteOffset = (idxInfo->wordOffset * sizeof(int)) +(idxInfo->bitOffset/8) + (GVAR_HDR_BITS/8); /* set file pointer to the correct offset */ rc = TrySeek(idxInfo->rdfFilePtr, byteOffset); /* attempt to read in the bytes */ bytesRead = TryRead(idxInfo->rdfFilePtr, dataBuffer, BLOCK11_SIZE_BYTES); if (bytesRead != BLOCK11_SIZE_BYTES) { sLog(SLOG_EE2, " -- GetNextBlock out (RDF read failure)...\n\n"); return -1; } return (0); } sLog(SLOG_LDOC, "about to call FillBlock\n"); rc = FillBlock(idxInfo->rdfFilePtr, dataBuffer, idxInfo->wordOffset, idxInfo->bitOffset + dataOffs, count); sLog(SLOG_LDOC, " FillBlock rc=%d\n",rc); if (rc < 0) return -1; /* at this point we modify the IDX bit offset to that of output buffer */ idxInfo->bitOffset = (idxInfo->bitOffset + dataOffs) % 8; /* also, we reset seek pointer to start of scan after each data access */ /* this allows multi-band requests to use the same API routines */ rc = TrySeek(ifp, idxInfo->filePos); /* we must also "pretend" last block seen was a block 0 */ prevBlock = BLOCKTYPE_0; sLog(SLOG_EE2, " -- GetNextBlock out (ok)...\n\n"); return 0; } /* *| Name: *| GetGvarNavCod - extract navigation codicil. *| *| Interface: *| int *| GetGvarNavCod ( *| FILE *ifp, *| int *cod, *| int *areaDir *| ) *| *| Input: *| ifp - index file pointer *| areaDir - area directory *| *| Input and Output: *| none *| *| Output: *| cod - navigation codicil *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetGvarNavCod ( FILE *ifp, int *cod, int *areaDir ) { int bitStart; int bitCount; u16 newcrc; char iofnc; int navWord; char iofec; short iofni; short iofei; int skipBits; int rc; unsigned char imcWord[4]; unsigned char yawWord[4]; char *bufBlock0; int navBlock[BLOCK0_SIZE_BYTES/4]; int loop; int one = 1; int offset; double dVal; int i; int try = 0; idxinfo idxInfo = {0}; reqinfo reqInfo = {0}; int *firstcod = NULL; static int sortcod[GVAR_NAV_SIZE_WORDS][MAX_CRC_TRY]; /* 2.5 MB */ int RELLST [31][2] = { { 4, 10}, { 13, 63}, { 65, 94}, { 98, 100}, {103, 105}, {108, 110}, {113, 115}, {116, 118}, {120, 149}, {153, 155}, {158, 160}, {163, 165}, {168, 170}, {171, 173}, {175, 204}, {208, 210}, {213, 215}, {218, 220}, {223, 225}, {226, 228}, {230, 259}, {263, 265}, {268, 270}, {273, 275}, {278, 283}, {285, 314}, {318, 320}, {323, 325}, {328, 330}, {333, 335}, { -1, -1}}; int INSLT [55] = { 0, 1, 11, 12, 64, 95, 96, 97, 101, 102, 106, 107, 111,112,119,150,151,152,156,157,161,162,166,167,174,205,206, 207,211,212,216,217,221,222,229,260,261,262,266,267,271,272, 276,277,284,315,316,317,321,322,326,327,331,332,-1 }; sLog(SLOG_EE1, "\n -- GetGvarNavCod in...\n"); /* first zero out the codicil */ (void) memset((void *) cod, 0, GVAR_NAV_SIZE); /* allocate space for a Block 0 */ bufBlock0 = (char *) malloc(BLOCK0_SIZE_BYTES); if (bufBlock0 == NULL) return -1; /* * try to get a valid block 0 buffer. since there is a chance * noisy data could be prevalent throughout the image, it makes * sense to try a certain number of times, and if that fails just * take the next block and hope it's good enough! */ /* create CRC table */ makecrc(); /* starting from the beginning */ fseek (ifp,0,SEEK_SET); /* make MAX_CRC_TRY attempts at finding a good block 0 */ for (try = 0; try < MAX_CRC_TRY; try++) { /* Do this every time through */ /* first zero out the codicil */ (void) memset((void *) cod, 0, GVAR_NAV_SIZE); sLog(SLOG_EE1, "\n -- GetGvarNavCod: try %d / %d\n", try+1, MAX_CRC_TRY); (void) updcrc(NULL, 0, 0); rc = GetNextBlock(ifp, &idxInfo, &reqInfo, bufBlock0, DT_DOC, 0, 1); if (rc < 0) { break; } bitStart = idxInfo.bitOffset; bitCount = idxInfo.bitCount; /* extract IMC bits field */ skipBits = bitStart + GVAR_HDR_BITS + (3 * 8); (void) memset(imcWord, 0, 4); if (ByteOff (bufBlock0, skipBits, 1, &imcWord[3]) != 0) { rc = -1; break; } /* extract next two bytes, mod to make yaw bit available, 26 Mar 98 */ (void) memset(yawWord, 0, sizeof(yawWord)); skipBits = bitStart + GVAR_HDR_BITS + (4 * 8); if (ByteOff (bufBlock0, skipBits, 2, &yawWord[2]) != 0) { rc = -1; break; } /* extract portion needed for nav codicil */ skipBits = bitStart + GVAR_HDR_BITS + (278 * 8); if (ByteOff (bufBlock0, skipBits, 1348, (unsigned char *) navBlock) != 0) { rc = -1; break; } /* convert Gould format floating point numbers to native format */ loop = 0; while (RELLST[loop][0] != -1) { offset = 1; if (RELLST[loop][0] > CUTOF1) offset = 13; if (RELLST[loop][0] > CUTOF2) offset = 31; for (i = RELLST[loop][0]; i <= RELLST[loop][1]; i++) { dVal = GouldToNative((unsigned char *) &navBlock[i]); dVal = dVal * 10000000.0; if ((i == 13) || (i == 60) || ((((i - 7) % 55) == 0) && (i != 7))) dVal = dVal / 100000; if (dVal > 0) dVal = dVal + 0.5; else if (dVal < 0) dVal = dVal - 0.5; * (cod + i + offset) = (int) dVal; } loop ++; } /* put text constants in place */ memcpy(cod + 127, "MORE", 4); memcpy(cod + 255, "MORE", 4); memcpy(cod + 383, "MORE", 4); memcpy(cod + 511, "MORE", 4); memcpy(cod + 0, "GVAR", 4); memcpy(cod + 128, "GVAR", 4); memcpy(cod + 256, "GVAR", 4); memcpy(cod + 384, "GVAR", 4); memcpy(cod + 512, "GVAR", 4); /* load int values from area directory */ * (cod + 367) = areaDir[YEAR_DAY]; * (cod + 368) = areaDir[ACTUAL_TIME] * 1000; * (cod + 369) = (areaDir[SENSOR_SOURCE] % 2) + 1; /* load IOFNC */ if (gvar_satid >= 14) skipBits = bitStart + GVAR_HDR_BITS + (8032 * 8); else skipBits = bitStart + GVAR_HDR_BITS + (6304 * 8); if (ByteOff(bufBlock0, skipBits, 1, (unsigned char *) &iofnc) != 0) { rc = -1; break; } /* load IOFEC */ if (gvar_satid >= 14) skipBits = bitStart + GVAR_HDR_BITS + (8033 * 8); else skipBits = bitStart + GVAR_HDR_BITS + (6305 * 8); if (ByteOff(bufBlock0, skipBits, 1, (unsigned char *) &iofec) != 0) { rc = -1; break; } /* load IOFNI */ if (gvar_satid >= 14) skipBits = bitStart + GVAR_HDR_BITS + (8034 * 8); else skipBits = bitStart + GVAR_HDR_BITS + (6306 * 8); if (ByteOff(bufBlock0, skipBits, 2, (unsigned char *) &iofni) != 0) { rc = -1; break; } swbyt2_(&iofni, &one); /* load IOFEI */ if (gvar_satid >= 14) skipBits = bitStart + GVAR_HDR_BITS + (8036 * 8); else skipBits = bitStart + GVAR_HDR_BITS + (6308 * 8); if (ByteOff(bufBlock0, skipBits, 2, (unsigned char *) &iofei) != 0) { rc = -1; break; } swbyt2_(&iofei, &one); /* load default values for GOES-14 if any of these are not set */ if (gvar_satid == 14 && (iofnc == 0 || iofec == 0 || iofni == 0 || iofei == 0)) { iofnc = 4; iofec = 2; if (!(yawWord[2] & 0x80)) { sLog(SLOG_EE1, " -- Using GOES-14 default upright nadir position\n"); iofni = 3013; iofei = 3192; } else { sLog(SLOG_EE1, " -- Using GOES-14 default inverted nadir position\n"); iofni = 3123; iofei = 2944; } } /* store IOFNC, IOFEC, IOFNI, and IOFEI into the codicil */ * (cod + 379) = (int) iofnc; * (cod + 380) = (int) iofec; * (cod + 381) = (int) iofni; * (cod + 382) = (int) iofei; /* these values are just copied straight into the codicil */ loop = 0; while(INSLT[loop] != -1) { offset = 1; if (INSLT[loop] > CUTOF1) offset = 13; if (INSLT[loop] > CUTOF2) offset = 31; navWord = navBlock[INSLT[loop]]; M0swbyt4(&navWord, 1); * (cod + INSLT[loop] + offset) = navWord; loop ++; } /* On little Endian architectures, bits for IMC and */ /* Yaw, get flipped in SendGvarCod */ /* so they are flipped here first, so they are returned*/ /* to Network byte order in SendGvarCod. */ /* IMC bits need to go in low order byte of word 3 */ (void) memcpy(&navWord, &imcWord[0], sizeof(imcWord)); M0swbyt4(&navWord, 1); * (cod + 2) = navWord; /* copy over next two bytes of status info */ (void) memcpy(&navWord, &yawWord[0], sizeof(yawWord)); M0swbyt4(&navWord, 1); * (cod + 3) = navWord; /* save the first codicil we run into... in case we need it later */ if (firstcod == NULL) { firstcod = (int *) malloc(GVAR_NAV_SIZE); (void) memcpy(firstcod, cod, GVAR_NAV_SIZE); } /* now we have a complete McIDAS nav block */ /* decide if we want to use it or not */ newcrc = updcrc ( (unsigned char *) bufBlock0, bitStart + GVAR_HDR_BITS, bitCount - GVAR_HDR_BITS ); /* If we encounter a good CRC, use this nav */ if (newcrc == CRC_GOOD) { sLog(SLOG_EE1, " -- CRC check succeeded on attempt %d\n", try+1); break; } /* Else look for three consecutive similar nav blocks */ /* Do a nav transform and see how close they are... */ sLog(SLOG_EE1, " -- CRC check failed on attempt %d\n", try+1); /* save this nav block in the sort array */ for (i = 0; i < GVAR_NAV_SIZE_WORDS; ++i) { int j; for (j = try; j > 0; --j) { if (sortcod[i][j-1] <= cod[i]) break; sortcod[i][j] = sortcod[i][j-1]; } sortcod[i][j] = cod[i]; } /* try is odd and at least 5 (zero-based) */ if (!(try & 1) && (try >= 4)) { int count = try + 1; int need = try / 2; /* look for over 50% matching values at every index */ for (i = 0; i < GVAR_NAV_SIZE_WORDS; ++i) { int j, k, l; j = need; l = sortcod[i][0]; /* (k <= j) so (j < count) implies (k < count) */ for (k = 1; j < count; ++k) { if (sortcod[i][k] != l) { j = k + need; l = sortcod[i][k]; } else if (k >= j) break; /* here (k < j) so next iteration (k <= j) */ } /* (j >= count) means not enough matching values */ if (j >= count) rc = -1; else firstcod[i] = l; } /* (rc >= 0) means success at every index */ if (rc >= 0) { rc = -1; break; } } } /* end try for loop */ /* close the RDF we opened to get the nav block */ if (idxInfo.rdfFilePtr != NULL) { (void) CloseRdfFile(idxInfo.rdfFilePtr); idxInfo.rdfFilePtr = NULL; } free(bufBlock0); if (firstcod == NULL) return -1; if (rc < 0) { (void) memcpy(cod, firstcod, GVAR_NAV_SIZE); sLog(SLOG_EE1, " -- GetGvarNavCod out (no good codicils, using first)...\n\n"); } else { sLog(SLOG_EE1, " -- GetGvarNavCod out (ok)...\n\n"); } free(firstcod); return 0; } /* *| Name: *| GetGvarCards - Extract info for and create comment cards. *| *| Interface: *| int *| GetGvarCards ( *| int *navCod, *| int *areaDir, *| int *cards, *| int auxFlag *| ) *| *| Input: *| navCod - navigation codicil *| areaDir - area directory *| auxFlag - auxilliary flag, indicates cal cards are needed *| *| Input and Output: *| none *| *| Output: *| cards - the assembled comment cards *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetGvarCards ( int *navCod, int *areaDir, int *cards, int auxFlag ) { int rc; float line; float elem; float lat; float lon; float resx; float resy; float cresx; float cresy; int numCards = 0; int band; char card[MAX_CARD_LEN]; sLog(SLOG_EE1, "\n -- GetGvarCards in...\n"); /* load center line/elem */ line = areaDir[START_LINE] + ((areaDir[NUM_LINES] * areaDir[LINE_RES]) / 2.0); elem = areaDir[START_ELEMENT] + ((areaDir[NUM_ELEMENTS] * areaDir[ELEMENT_RES]) / 2.0); /* get center lat/lon */ rc = GvarNavImgToEarth(navCod, line, elem, &lat, &lon); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarCards out (GvarNavImgToEarth failure)...\n\n"); return -1; } /* build cards for center point */ (void) sprintf(card, CEN_LAT_CARD, lat); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; (void) sprintf(card, CEN_LON_CARD, lon); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; rc = GetGvarRes(navCod, line, elem, &resx, &resy, &cresx, &cresy); (void) sprintf(card, COMP_LAT_CARD, (cresx * areaDir[LINE_RES])); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; (void) sprintf(card, RES_LAT_CARD, (int) ((resx * areaDir[LINE_RES]) + 0.5)); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; (void) sprintf(card, COMP_LON_CARD, (cresy * areaDir[ELEMENT_RES])); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; (void) sprintf(card, RES_LON_CARD, (int) ((resy * areaDir[ELEMENT_RES]) + 0.5)); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* aux cal cards if needed */ if (auxFlag) { /* handle visible band separately */ band = 1; /* raw card */ (void) sprintf(card, CAL_CARD, band, "RAW ", "RAW"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* albedo card */ (void) sprintf(card, CAL_CARD, band, "ALB ", "ALBEDO"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* brightness card */ (void) sprintf(card, CAL_CARD, band, "BRIT", "BRIGHTNESS"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* handle ir bands together */ for (band = 2; band <= 5; band++) { if(band==5&&gvar_satid>11) band=6; /* raw card */ (void) sprintf(card, CAL_CARD, band, "RAW ", "RAW"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* radiance card */ (void) sprintf(card, CAL_CARD, band, "RAD ", "RADIANCE"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* temperature card */ (void) sprintf(card, CAL_CARD, band, "TEMP", "TEMPERATURE"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; /* brightness card */ (void) sprintf(card, CAL_CARD, band, "BRIT", "BRIGHTNESS"); sLog(SLOG_EE1, "\n -- new card: %s\n", card); rc = AddCard(card, (char *) cards, MAX_CARD_LEN, numCards); numCards++; } } /* update area directory */ areaDir[COMMENT_CARDS] = areaDir[COMMENT_CARDS] + numCards; sLog(SLOG_EE1, " -- GetGvarCards out (ok)...\n\n"); return 0; } /* *| Name: *| GetGvarRes - Get resolution in km at a given image coordinate. *| *| Interface: *| int *| GetGvarRes ( *| int *navCod, *| float line, *| float elem, *| float *resx, *| float *resy, *| float *cresx, *| float *cresy *| ) *| *| Input: *| navCod - navigation codicil *| line - image line *| elem - image element *| *| Input and Output: *| none *| *| Output: *| resx - x-resolution at center of image (km) *| resy - y-resolution at center of image (km) *| cresx - computed x-resolution at center of image (km) *| cresy - computed y-resolution at center of image (km) *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetGvarRes ( int *navCod, float line, float elem, float *resx, float *resy, float *cresx, float *cresy ) { int rc; int latLonFlag; double range1; /* range from center down */ double range2; /* range from down 1 line to over 1 element */ float dum; /* dummy variable */ float elem_p1; /* element plus one */ float lat; /* lat to measure distance */ float lat2; /* lat to measure distance */ float line_p1; /* line plus one */ float lon; /* lon to measure distance */ float lon2; /* lon to measure distance */ int one=1; /* the number one (1) */ int two=2; /* the number two (2) */ sLog(SLOG_EE1, "\n -- GetGvarRes in...\n"); sLog(SLOG_EE1, " inp line: %f, elem: %f\n", line, elem); /* initialize McIDAS nav transforms */ rc = nvprep_(&one, navCod); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (nvprep failure: %d)...\n\n",rc); return -1; } /* need text LL in a variable for Fortran call */ memcpy(&latLonFlag, "LL ", sizeof(int)); rc = nv1ini_(&two, &latLonFlag); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (nv1ini failure: %d)...\n\n",rc); return -1; } rc = nv1sae_(&line, &elem, &dum, &lat, &lon, &dum); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (nv1sae failure: %d)...\n\n",rc); return -1; } sLog(SLOG_EE1, " 1st lat/lon: %f,%f\n", lat, lon); /* * move down one line and find the lat/lon */ line_p1 = line + 1.0; rc = nv1sae_(&line_p1, &elem, &dum, &lat2, &lon2, &dum); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (nv1sae failure: %d)...\n\n",rc); return -1; } sLog(SLOG_EE1, " 2nd lat/lon: %f,%f\n", lat2, lon2); /* * find range from center to down one line */ range1 = LatLonToDistance(lat, lon, lat2, lon2); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (LatLonToDistance fail)...\n\n"); return -1; } /* * move over one element and find the lat/lon */ lat = lat2; lon = lon2; elem_p1 = elem + 1.0; rc = nv1sae_(&line_p1, &elem_p1, &dum, &lat2, &lon2, &dum); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (nv1sae failure: %d)...\n\n",rc); return -1; } /* * find range from center to down one line */ range2 = LatLonToDistance(lat, lon, lat2, lon2); if (rc < 0) { sLog(SLOG_EE1, " -- GetGvarRes out (LatLonToDistance fail)...\n\n"); return -1; } /* * res is average of the 2 ranges (resx = resy) */ *resy = (float) (range1 + range2) / 2.0; *resx = *resy; *cresy = (float) range2; *cresx = (float) range1; sLog(SLOG_EE1, " -- GetGvarRes out (ok)...\n\n"); return 0; } /* *| Name: *| GvarNavImgToEarth - Convert image coordinate to lat/lon pair. *| *| Interface: *| int *| GvarNavImgToEarth ( *| int *navCod, *| float line, *| float elem, *| float *lat, *| float *lon *| ) *| *| Input: *| navCod - navigation codicil *| line - image line *| elem - image element *| *| Input and Output: *| none *| *| Output: *| lat - latitude of input coordinate *| lon - longitude of input coordinate *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GvarNavImgToEarth ( int *navCod, float line, float elem, float *lat, float *lon ) { int rc; int one = 1; int two = 2; int latLonFlag; float dum; sLog(SLOG_EE1, "\n -- GvarNavImgToEarth in, line: %f, elem: %f\n", line, elem); /* initialize McIDAS nav transforms */ rc = nvprep_(&one, navCod); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavImgToEarth out (nvprep failure: %d)...\n\n",rc); return -1; } /* need text LL in a variable for Fortran call */ memcpy(&latLonFlag, "LL ", sizeof(int)); rc = nv1ini_(&two, &latLonFlag); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavImgToEarth out (nv1ini failure: %d)...\n\n",rc); return -1; } rc = nv1sae_(&line, &elem, &dum, lat, lon, &dum); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavImgToEarth out (nv1sae failure: %d)...\n\n",rc); return -1; } sLog(SLOG_EE1, " -- GvarNavImgToEarth out (ok)...\n\n"); return 0; } /* *| Name: *| GvarNavEarthToImg - Convert lat/lon pair to image coordinates. *| *| Interface: *| int *| GvarNavEarthToImg ( *| int *navCod, *| float lat, *| float lon, *| float *line, *| float *elem *| ) *| *| Input: *| navCod - navigation codicil *| lat - latitude of input coordinate *| lon - longitude of input coordinate *| *| Input and Output: *| none *| *| Output: *| line - image line of input coordinate *| elem - image element of input coordinate *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GvarNavEarthToImg ( int *navCod, float lat, float lon, float *line, float *elem ) { int rc; int one = 1; int two = 2; int latLonFlag; float dum; sLog(SLOG_EE1, "\n -- GvarNavEarthToImg in...\n"); sLog(SLOG_EE1, " lat: %f, lon: %f\n", lat, lon); /* initialize McIDAS nav transforms */ rc = nvprep_(&one, navCod); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavEarthToImg out (nvprep failure: %d)...\n\n",rc); return -1; } /* need text LL in a variable for Fortran call */ memcpy(&latLonFlag, "LL ", sizeof(int)); rc = nv1ini_(&two, &latLonFlag); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavEarthToImg out (nv1ini failure: %d)...\n\n",rc); return -1; } rc = nv1eas_(&lat, &lon, &dum, line, elem, &dum); if (rc < 0) { sLog(SLOG_EE1, " -- GvarNavEarthToImg out (nv1eas failure: %d)...\n\n",rc); return -1; } sLog(SLOG_EE1, " -- GvarNavEarthToImg out (ok)...\n\n"); return 0; } /* *| Name: *| GetGvarSSNum - Get sensor source number for current data. *| *| Interface: *| int *| GetGvarSSNum ( *| FILE *ifp *| ) *| *| Input: *| ifp - index file pointer *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| sensor source number input data originated from *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ int GetGvarSSNum ( FILE *ifp ) { int ssNum; int bitStart; int bitCount; u16 newcrc; int skipBits; int timeBits; int rc; int try = 0; char *bufBlock0; unsigned char satIdBuf[1]; unsigned char SPS_Time[8]; reqinfo reqInfo = {0}; idxinfo idxInfo = {0}; /* For triplicate ss num checking */ int ss3 = 0; int ssCheck0 = -1; int ssCheck1 = -1; int ssCheck2 = -1; int ssCheck3 = -1; int yjCheck0 = -1; int yjCheck1 = -1; int yjCheck2 = -1; int yjCheck3 = -1; int offset; sLog(SLOG_EE1, "\n -- GetGvarSSNum in...\n"); ssNum = -1; /* allocate space for a Block 0 */ bufBlock0 = (char *) malloc(BLOCK0_SIZE_BYTES); if (bufBlock0 == NULL) return -1; /* * try to get a valid block 0 buffer. since there is a chance * noisy data could be prevalent throughout the image, it makes * sense to try a certain number of times, and if that fails just * take the next block and hope it's good enough! */ /* create CRC table */ makecrc(); /* starting from the beginning */ fseek (ifp,0,SEEK_SET); /* make MAX_CRC_TRY attempts at finding a good block 0 */ for (try = 0; try < MAX_CRC_TRY; try++) { sLog(SLOG_EE1, "\n -- GetGvarSSNum: try %d / %d\n", try+1, MAX_CRC_TRY); (void) updcrc(NULL, 0, 0); rc = GetNextBlock(ifp, &idxInfo, &reqInfo, bufBlock0, DT_DOC, 0, 1); if (rc < 0) { break; } bitStart = idxInfo.bitOffset; bitCount = idxInfo.bitCount; ss3 = 0; for (offset = 0; offset < GVAR_HDR_BITS; offset += GVAR_HDR_BITS / 3) { /* first grab the sat id, needed for SS num */ skipBits = bitStart + offset + 11 * 8; timeBits = bitStart + offset + 16 * 8; if ((ByteOff(bufBlock0, skipBits, sizeof(satIdBuf), satIdBuf) != 0) || (ByteOff(bufBlock0, timeBits, sizeof(SPS_Time), SPS_Time) != 0)) { rc = -1; break; } satIdBuf[0] >>= 4; (void) updcrc(NULL, 0, 0); newcrc = updcrc ( (unsigned char *) bufBlock0, bitStart + offset, GVAR_HDR_BITS / 3 ); /* If we encounter a good CRC, use this ss */ if (newcrc == CRC_GOOD) { sLog(SLOG_EE1, " -- CRC check succeeded on attempt %d\n", try+1); break; } /* Else look for three consecutive same ss nums */ sLog(SLOG_EE1, " -- CRC check failed on attempt %d\n", try+1); ss3++; ssCheck0 = satIdBuf[0]; yjCheck0 = ntohl(*(int *)SPS_Time); ssCheck1 = ssCheck2; ssCheck2 = ssCheck3; ssCheck3 = ssCheck0; yjCheck1 = yjCheck2; yjCheck2 = yjCheck3; yjCheck3 = yjCheck0; sLog(SLOG_EE1, " -- SS num read attempt %d: %d\n", ss3, ssCheck0); if (ss3 >= 3 && ssCheck1 == ssCheck2 && ssCheck2 == ssCheck3 && yjCheck1 == yjCheck2 && yjCheck2 == yjCheck3) { sLog(SLOG_EE1, " -- SS num triple check succeeded on attempt %d\n",ss3); break; } sLog(SLOG_EE1, " -- SS num triple check failed on attempt %d\n", ss3); } if (offset < GVAR_HDR_BITS) break; rc = -1; /* in case try >= MAX_CRC_TRY */ } free(bufBlock0); /* free here before any return statements */ /* close the RDF we opened to get the Block 0 needed */ if (idxInfo.rdfFilePtr != NULL) { (void) CloseRdfFile(idxInfo.rdfFilePtr); idxInfo.rdfFilePtr = NULL; } if (rc < 0) return -1; sLog(SLOG_EE1, " found satid %d\n", satIdBuf[0]); gvar_satid = satIdBuf[0]; /* save in local static for use in other functions*/ ssNum = 54 + 2 * satIdBuf[0]; /* goes08-12 = 70, 72, 74, 76, 78 */ ssNum += (satIdBuf[0] > 12) * 100; /* goes13-15 = 180, 182, 184 */ switch (satIdBuf[0]) { case 13: /* date -d"September 8, 2020" +0x%Y%j0 -> 0x20202520 (BCD YYYYJJJ0) */ if (ntohl(*(int *)SPS_Time) >= 0x20202520) ssNum = 174; break; case 14: if (0) ssNum = 176; break; case 15: if (0) ssNum = 178; break; } sLog(SLOG_EE1, " -- GetGvarSSNum out (ok)...\n\n"); return ssNum; } /* *| Name: *| GetGvarCalCod - Extract calibration codicil. *| *| Interface: *| int *| GetGvarCalCod ( *| FILE *ifp, *| void *cod, *| reqinfo *reqInfo *| ) *| *| Input: *| ifp - index file pointer *| reqInfo - request info struct pointer *| *| Input and Output: *| none *| *| Output: *| cod - calibration codicil *| *| Return values: *| 0: success *| -1: failure *| *| Remarks: *| *| Categories: *| ingest/decode */ static unsigned char cal_cod_8[41 * 4] = { 0xbe, 0x09, 0x6a, 0x16, /* -15.4116 */ 0xbe, 0x0b, 0x21, 0x2d, /* -15.3044 */ 0xbe, 0x09, 0xc6, 0xa8, /* -15.389 */ 0xbe, 0x0b, 0xb4, 0xa2, /* -15.2684 */ 0xbe, 0x0b, 0x05, 0xbc, /* -15.3111 */ 0xbe, 0x0b, 0xa1, 0xcb, /* -15.273 */ 0xbe, 0x0a, 0x58, 0x79, /* -15.3534 */ 0xbe, 0x0a, 0xb8, 0x52, /* -15.33 */ 0x40, 0x8d, 0x84, 0xce, /* 0.5528077 */ 0x40, 0x8c, 0xd9, 0x13, /* 0.5501873 */ 0x40, 0x8d, 0xd1, 0x46, /* 0.5539745 */ 0x40, 0x8d, 0x03, 0x63, /* 0.550833 */ 0x40, 0x8d, 0x0a, 0xc4, /* 0.5509456 */ 0x40, 0x8d, 0x5c, 0x51, /* 0.5521899 */ 0x40, 0x8c, 0xea, 0xe2, /* 0.5504591 */ 0x40, 0x8c, 0xfc, 0x84, /* 0.5507281 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x7e, 0x78, 0x81, /* 0.00192979 */ 0x41, 0xfa, 0xf7, 0x66, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xca, /* 15.3332 */ 0x42, 0x44, 0x37, 0x7a, /* 68.21671 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x66, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xca, /* 15.3332 */ 0x42, 0x44, 0x37, 0x7a, /* 68.21671 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0x53, 0xa7, 0xf0, /* 5.228501 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8f, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9b, /* 38.8383 */ 0x41, 0x53, 0xa7, 0xf0, /* 5.228501 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8f, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9b, /* 38.8383 */ }; static unsigned char cal_cod_9[41 * 4] = { 0xbd, 0xef, 0xc7, 0x4c, /* -16.2215 */ 0xbd, 0xef, 0xb1, 0x5b, /* -16.30721 */ 0xbd, 0xef, 0xc4, 0x74, /* -16.23261 */ 0xbd, 0xef, 0x36, 0xdc, /* -16.78571 */ 0xbd, 0xef, 0x84, 0x12, /* -16.4841 */ 0xbd, 0xef, 0xd5, 0x5a, /* -16.1666 */ 0xbd, 0xef, 0xe5, 0x25, /* -16.10491 */ 0xbd, 0xef, 0x53, 0x61, /* -16.6743 */ 0x40, 0x8e, 0x11, 0x6f, /* 0.5549535 */ 0x40, 0x8e, 0xc4, 0x19, /* 0.5576797 */ 0x40, 0x8c, 0x9a, 0xbd, /* 0.5492362 */ 0x40, 0x90, 0x4b, 0xa8, /* 0.5636545 */ 0x40, 0x8e, 0xb9, 0xb1, /* 0.557521 */ 0x40, 0x8d, 0x25, 0x5a, /* 0.5513512 */ 0x40, 0x8e, 0x5c, 0x3e, /* 0.556095 */ 0x40, 0x8f, 0x76, 0xe9, /* 0.5604082 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x7f, 0x41, 0xff, /* 0.0019418 */ 0x41, 0xfa, 0xf7, 0x66, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xca, /* 15.3332 */ 0x42, 0x44, 0x37, 0x7a, /* 68.21671 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x66, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xca, /* 15.3332 */ 0x42, 0x44, 0x37, 0x7a, /* 68.21671 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0x53, 0xa7, 0xf0, /* 5.228501 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8f, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9b, /* 38.8383 */ 0x41, 0x53, 0xa7, 0xf0, /* 5.228501 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8f, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9b, /* 38.8383 */ }; static unsigned char cal_cod_10[41 * 4] = { 0xbd, 0xef, 0xa2, 0x62, /* -16.36569 */ 0xbd, 0xef, 0xb2, 0xa4, /* -16.30219 */ 0xbd, 0xef, 0xaa, 0x37, /* -16.3351 */ 0xbd, 0xef, 0x90, 0xa4, /* -16.435 */ 0xbd, 0xef, 0xaa, 0x10, /* -16.33569 */ 0xbd, 0xef, 0xb0, 0x07, /* -16.31239 */ 0xbd, 0xef, 0x9f, 0x70, /* -16.3772 */ 0xbd, 0xee, 0xfd, 0xf4, /* -17.008 */ 0x40, 0x8f, 0x80, 0xdf, /* 0.5605602 */ 0x40, 0x8e, 0x6d, 0x24, /* 0.5563529 */ 0x40, 0x8e, 0x81, 0x19, /* 0.5566574 */ 0x40, 0x8e, 0xe7, 0x34, /* 0.5582154 */ 0x40, 0x8e, 0xef, 0x1d, /* 0.5583361 */ 0x40, 0x8e, 0xa2, 0xed, /* 0.5571736 */ 0x40, 0x8e, 0x6a, 0x8f, /* 0.5563135 */ 0x40, 0x8f, 0xb4, 0xde, /* 0.5613536 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x82, 0x4a, 0x72, /* 0.00198808 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xc9, /* 15.3332 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xc9, /* 15.3332 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ }; static unsigned char cal_cod_11[41 * 4] = { 0xbe, 0x00, 0x26, 0x81, /* -15.9906 */ 0xbe, 0x01, 0x58, 0xe3, /* -15.9158 */ 0xbd, 0xef, 0xf9, 0x86, /* -16.0253 */ 0xbd, 0xef, 0xe2, 0x89, /* -16.1151 */ 0xbe, 0x00, 0x57, 0x3f, /* -15.9787 */ 0xbd, 0xef, 0xe7, 0x59, /* -16.0963 */ 0xbd, 0xef, 0xec, 0x8c, /* -16.07599 */ 0xbe, 0x00, 0x3f, 0xe6, /* -15.9844 */ 0x40, 0x8e, 0x60, 0x4a, /* 0.5561568 */ 0x40, 0x8e, 0x28, 0x00, /* 0.5552979 */ 0x40, 0x8e, 0x4f, 0x56, /* 0.5558981 */ 0x40, 0x8e, 0xc9, 0x89, /* 0.5577627 */ 0x40, 0x8e, 0x43, 0xea, /* 0.5557238 */ 0x40, 0x8f, 0x0d, 0x5f, /* 0.5587978 */ 0x40, 0x8f, 0x03, 0xe2, /* 0.558653 */ 0x40, 0x8d, 0x8a, 0xaa, /* 0.5528971 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x84, 0x12, 0x1d, /* 0.00201524 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xc9, /* 15.3332 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x41, 0xf5, 0x54, 0xc9, /* 15.3332 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x50, 0x6f, 0xd2, /* 5.0273 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ }; static unsigned char cal_cod_12[41 * 4] = { 0xbd, 0xef, 0x8b, 0x3e, /* -16.45609 */ 0xbd, 0xef, 0x8e, 0xf4, /* -16.44159 */ 0xbd, 0xef, 0x8d, 0xe7, /* -16.44569 */ 0xbd, 0xef, 0x80, 0x69, /* -16.4984 */ 0xbd, 0xef, 0x97, 0x4c, /* -16.409 */ 0xbd, 0xef, 0xa1, 0xa4, /* -16.36859 */ 0xbd, 0xef, 0x9b, 0x03, /* -16.39449 */ 0xbd, 0xef, 0x99, 0xc1, /* -16.3994 */ 0x40, 0x93, 0xbd, 0x05, /* 0.577103 */ 0x40, 0x93, 0x80, 0x4b, /* 0.5761764 */ 0x40, 0x93, 0xdc, 0x72, /* 0.5775825 */ 0x40, 0x94, 0x3d, 0xec, /* 0.5790699 */ 0x40, 0x94, 0x26, 0x04, /* 0.5787051 */ 0x40, 0x93, 0x5a, 0x51, /* 0.5755969 */ 0x40, 0x93, 0x4d, 0x3c, /* 0.5753973 */ 0x40, 0x93, 0x40, 0xf4, /* 0.5752099 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x81, 0x89, 0x82, /* 0.00197658 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ }; static unsigned char cal_cod_13[41 * 4] = { 0xbd, 0xec, 0x66, 0x7b, /* -19.59969 */ 0xbd, 0xec, 0x7f, 0x07, /* -19.5038 */ 0xbd, 0xec, 0x95, 0x9c, /* -19.41559 */ 0xbd, 0xec, 0xae, 0xd3, /* -19.31709 */ 0xbd, 0xec, 0x73, 0x89, /* -19.54869 */ 0xbd, 0xec, 0x6e, 0x98, /* -19.56799 */ 0xbd, 0xec, 0x7e, 0x57, /* -19.50649 */ 0xbd, 0xec, 0xa2, 0xb7, /* -19.3644 */ 0x40, 0x9c, 0xad, 0x51, /* 0.6120196 */ 0x40, 0x9c, 0xa2, 0x3a, /* 0.6118504 */ 0x40, 0x9c, 0x11, 0x1a, /* 0.609636 */ 0x40, 0x9b, 0xd4, 0x1f, /* 0.6087055 */ 0x40, 0x9d, 0x00, 0x4f, /* 0.613286 */ 0x40, 0x9c, 0xa0, 0x49, /* 0.6118208 */ 0x40, 0x9c, 0xbb, 0x26, /* 0.6122307 */ 0x40, 0x9b, 0x50, 0x7b, /* 0.6066968 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x7c, 0x38, 0x34, /* 0.00189544 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ }; static unsigned char cal_cod_14[41 * 4] = { 0xbe, 0x02, 0x52, 0x55, /* -15.8549 */ 0xbe, 0x01, 0x96, 0x53, /* -15.9008 */ 0xbe, 0x05, 0xd0, 0x14, /* -15.6367 */ 0xbe, 0x00, 0x50, 0x49, /* -15.9804 */ 0xbd, 0xef, 0xeb, 0x4b, /* -16.08089 */ 0xbe, 0x01, 0x8b, 0x44, /* -15.9035 */ 0xbe, 0x00, 0x3c, 0x37, /* -15.9853 */ 0xbd, 0xef, 0xd5, 0xe4, /* -16.16449 */ 0x40, 0x96, 0x64, 0x63, /* 0.5874693 */ 0x40, 0x96, 0x27, 0x44, /* 0.5865367 */ 0x40, 0x96, 0x16, 0x7d, /* 0.5862807 */ 0x40, 0x96, 0x1e, 0xdf, /* 0.5864086 */ 0x40, 0x95, 0xf1, 0x64, /* 0.5857146 */ 0x40, 0x95, 0xcf, 0xb1, /* 0.5852004 */ 0x40, 0x96, 0x09, 0x6e, /* 0.5860814 */ 0x40, 0x95, 0x8c, 0x25, /* 0.5841697 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x7b, 0xb6, 0xb2, /* 0.00188772 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ }; static unsigned char cal_cod_15[41 * 4] = { 0xbd, 0xef, 0xae, 0xcc, /* -16.3172 */ 0xbd, 0xef, 0x6d, 0x5d, /* -16.5728 */ 0xbd, 0xef, 0x82, 0x20, /* -16.4917 */ 0xbd, 0xef, 0xbf, 0x8b, /* -16.25179 */ 0xbd, 0xef, 0xa3, 0x41, /* -16.36229 */ 0xbd, 0xef, 0xf0, 0x70, /* -16.06079 */ 0xbd, 0xef, 0x8c, 0x09, /* -16.45299 */ 0xbd, 0xef, 0x94, 0x26, /* -16.4213 */ 0x40, 0x95, 0xcf, 0x71, /* 0.5851966 */ 0x40, 0x96, 0x85, 0xac, /* 0.5879772 */ 0x40, 0x95, 0xef, 0x14, /* 0.5856793 */ 0x40, 0x95, 0xde, 0x69, /* 0.585425 */ 0x40, 0x96, 0x31, 0xeb, /* 0.5866992 */ 0x40, 0x95, 0x68, 0x63, /* 0.5836241 */ 0x40, 0x95, 0xab, 0xfb, /* 0.5846555 */ 0x40, 0x95, 0x99, 0x9e, /* 0.5843753 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x00, 0x00, 0x00, 0x00, /* 0 */ 0x3e, 0x7b, 0xc4, 0x25, /* 0.00188852 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0x44, 0x37, 0x79, /* 68.21669 */ 0x42, 0x1d, 0x20, 0xf2, /* 29.12869 */ 0x41, 0xfa, 0xf7, 0x65, /* 15.6854 */ 0x42, 0x10, 0x96, 0xd5, /* 16.58919 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ 0x42, 0xe3, 0x63, 0x8e, /* 227.3889 */ 0x42, 0x26, 0xd6, 0x9a, /* 38.83829 */ 0x41, 0x53, 0xa7, 0xef, /* 5.2285 */ 0x41, 0x58, 0x79, 0xa6, /* 5.5297 */ }; int GetGvarCalCod ( FILE *ifp, void *cod, reqinfo *reqInfo ) { int numWords; int bitStart; char *bufBlock0; int skipBits; idxinfo idxInfo = {0}; /* return code holder */ int rc; u16 newcrc; unsigned char rangeWord[1]; unsigned char satId; sLog(SLOG_EE1, "\n -- GetGvarCalCod in [static table]...\n"); /* first zero out the codicil */ (void) memset((void *) cod, 0, GVAR_CAL_SIZE); /* allocate space for a Block 0 */ bufBlock0 = (char *) malloc(BLOCK0_SIZE_BYTES); if (bufBlock0 == NULL) return -1; /* get a block 0 data buffer */ rc = GetNextBlock(ifp, &idxInfo, reqInfo, bufBlock0, DT_DOC, 0, 1); if (idxInfo.rdfFilePtr != NULL) { (void) CloseRdfFile(idxInfo.rdfFilePtr); idxInfo.rdfFilePtr = NULL; } if (rc < 0) { free(bufBlock0); return -1; } bitStart = idxInfo.bitOffset; makecrc(); for (skipBits = 0; skipBits < GVAR_HDR_BITS; skipBits += GVAR_HDR_BITS / 3) { (void) updcrc(NULL, 0, 0); newcrc = updcrc ((unsigned char *) bufBlock0, bitStart + skipBits, GVAR_HDR_BITS / 3); if (newcrc == CRC_GOOD) break; } if (skipBits >= GVAR_HDR_BITS) { free(bufBlock0); return -1; } if ((rc = ByteOff(bufBlock0 + 11, bitStart + skipBits, 1, rangeWord)) != 0) { free(bufBlock0); return -1; } satId = rangeWord[0] >> 4; switch (satId) { case 8: memcpy(cod, cal_cod_8, sizeof(cal_cod_8)); break; case 9: memcpy(cod, cal_cod_9, sizeof(cal_cod_9)); break; case 10: memcpy(cod, cal_cod_10, sizeof(cal_cod_10)); break; case 11: memcpy(cod, cal_cod_11, sizeof(cal_cod_11)); break; case 12: memcpy(cod, cal_cod_12, sizeof(cal_cod_12)); break; case 13: memcpy(cod, cal_cod_13, sizeof(cal_cod_13)); break; case 14: memcpy(cod, cal_cod_14, sizeof(cal_cod_14)); break; case 15: memcpy(cod, cal_cod_15, sizeof(cal_cod_15)); break; } /* byte flip words to obtain arch specific format */ numWords = GVAR_CAL_SIZE / 4; M0swbyt4((int *) cod, numWords); free(bufBlock0); sLog(SLOG_EE1, " -- GetGvarCalCod out (ok)...\n\n"); return 0; } /* *| Name: *| InitGvarAreaDir - Initialize a GVAR area directory. *| *| Interface: *| int *| InitGvarAreaDir ( *| FILE *ifp, *| int *areaDir, *| dscinfo dscInfo, *| reqinfo reqInfo, *| int posNum, *| int spacing, *| const char *cUnits *| ) *| *| Input: *| ifp - index file pointer *| dscInfo - descriptor file info struct *| reqInfo - request info struct *| posNum - position number *| spacing - number of bytes per data element *| cUnits - calibration units *| *| Input and Output: *| none *| *| Output: *| areaDir - area directory *| *| Return values: *| always returns 0 *| *| Remarks: *| *| Categories: *| ingest/decode */ int InitGvarAreaDir ( FILE *ifp, int *areaDir, dscinfo dscInfo, reqinfo reqInfo, int posNum, int spacing, const char *cUnits ) { int srcType; int calType; int bandIdx; sLog(SLOG_EE1, "\n -- InitGvarAreaDir in...\n"); /* current version number is 4 */ areaDir[VERSION] = 4; /* ADDE dataset position number is 1st word in directory */ areaDir[0] = posNum; /* * fill in readily available fields in area directory */ areaDir[VIS_LIN_OFFSET] = 0; areaDir[VIS_ELE_OFFSET] = 0; areaDir[AMIP_PACE_LINE] = -1; areaDir[AREA_NUM] = 1; /* * line/elem res get overridden later by user supplied keywords, * but initialize to defaults so directory server is satisfied. */ for (bandIdx = 0; bandIdx < MAX_GVAR_BAND; bandIdx++) { if (reqInfo.bands[bandIdx] > 0) { if (reqInfo.bands[bandIdx] == 1) { areaDir[LINE_RES] = BASE_VIS_RES; areaDir[ELEMENT_RES] = BASE_VIS_RES; } else { areaDir[LINE_RES] = BASE_IR_RES; areaDir[ELEMENT_RES] = BASE_IR_RES; } break; } } /* creation date and time should be same as image date and time */ areaDir[CREATION_DATE] = ((dscInfo.yyyy % 1900) * 1000) + dscInfo.ddd; areaDir[CREATION_TIME] = dscInfo.hh * 10000 + dscInfo.mm * 100 + dscInfo.ss; /* McIDAS sensor source number - a bunch of hooey */ areaDir[SENSOR_SOURCE] = GetGvarSSNum(ifp); /* image date and time */ areaDir[YEAR_DAY] = ((dscInfo.yyyy % 1900) * 1000) + dscInfo.ddd; areaDir[IMAGE_TIME] = dscInfo.hhmmss; areaDir[ACTUAL_YYDDD] = areaDir[YEAR_DAY]; areaDir[ACTUAL_TIME] = (dscInfo.hh * 10000) + (dscInfo.mm * 100) + dscInfo.ss; /* filter map is a 32 bit vector, bit 0 is for band 1 */ for (bandIdx = 0; bandIdx < MAX_GVAR_BAND; bandIdx++) { if (reqInfo.bands[bandIdx] > 0) { int b = bandIdx; if(b==4 && gvar_satid>11) b=5; areaDir[NUM_BANDS] = areaDir[NUM_BANDS] + 1; areaDir[FILTER_MAP] = areaDir[FILTER_MAP] | 0x01 << b; } } /* size of output data is determined by user keyword specification */ areaDir[BYTES_PER_PIX] = spacing; /* memo field */ memcpy(&areaDir[COMMENTS], "RT GVAR", sizeof("RT GVAR")); /* * we load line doc and fill in the validity code section * if the doc flag is set (meaning the user requested * it with the DOC= keyword). * length is determined by: * - 14 bytes of historical block 0 fields * - line doc and block header section for each band in output * - a block zero subset, the first 150 bytes */ if (reqInfo.docFlag == 1) { areaDir[DOC_LENGTH] = 14 + (areaDir[NUM_BANDS] * 62) + 150; areaDir[VALIDITY_CODE] = areaDir[IMAGE_TIME] + ((areaDir[YEAR_DAY] % 1000) * 1000000); } /* use validity code on multibanded requests too */ if (areaDir[NUM_BANDS] > 1) { areaDir[VALIDITY_CODE] = areaDir[IMAGE_TIME] + ((areaDir[YEAR_DAY] % 1000) * 1000000); } /* round to nearest 4 byte boundary */ if ((areaDir[DOC_LENGTH] % 4) != 0) { areaDir[DOC_LENGTH] = areaDir[DOC_LENGTH] + 4 - (areaDir[DOC_LENGTH] % 4); } /* line by line cal always zero */ areaDir[CAL_LENGTH] = 0; /* * level length: one byte for each band in image, but - * round field width to nearest 4 byte boundary * BUT! - only use the level field on multi-banded output! */ if (areaDir[NUM_BANDS] > 1) { if ((areaDir[NUM_BANDS] % 4) != 0) { areaDir[LEVEL_LENGTH] = areaDir[NUM_BANDS] + 4 - (areaDir[NUM_BANDS] % 4); } else { areaDir[LEVEL_LENGTH] = areaDir[NUM_BANDS]; } } /* prefix: doc + cal + lev */ areaDir[PREFIX_SIZE] = areaDir[DOC_LENGTH] + areaDir[CAL_LENGTH] + areaDir[LEVEL_LENGTH]; /* and an extra 4 bytes if the val code is used */ if (areaDir[VALIDITY_CODE] != 0) { areaDir[PREFIX_SIZE] += 4; } /* starting element comes from descriptor info structure */ areaDir[START_ELEMENT] = dscInfo.sie; areaDir[START_LINE] = dscInfo.sil; areaDir[NUM_LINES] = (dscInfo.eil - dscInfo.sil + 1) / areaDir[LINE_RES]; areaDir[NUM_ELEMENTS] = (dscInfo.eie - dscInfo.sie + 1) / areaDir[ELEMENT_RES]; areaDir[STARTING_SCAN] = ((dscInfo.sil - 1) / 8) + 1; areaDir[NAV_OFFSET] = AREA_DIR_SIZE * sizeof(int); /* no cal block if VISR (1 byte) data */ if (areaDir[BYTES_PER_PIX] == 1) { areaDir[CAL_OFFSET] = 0; areaDir[DATA_OFFSET] = areaDir[NAV_OFFSET] + GVAR_NAV_SIZE; } else { areaDir[CAL_OFFSET] = areaDir[NAV_OFFSET] + GVAR_NAV_SIZE; areaDir[DATA_OFFSET] = areaDir[CAL_OFFSET] + GVAR_CAL_SIZE; } /* McIDAS source type */ if (areaDir[BYTES_PER_PIX] == 1) { memcpy(&srcType, "GVAR", sizeof(int)); areaDir[ORIG_SOURCE] = srcType; memcpy(&srcType, "VISR", sizeof(int)); } else { memcpy(&srcType, "GVAR", sizeof(int)); } areaDir[SOURCE_TYPE] = srcType; /* McIDAS cal type */ memcpy(&calType, " ", sizeof(int)); memcpy(&calType, cUnits, strlen(cUnits)); areaDir[CAL_TYPE] = calType; /* averaged or sampled data flag - 0 = averaged, 1 = sampled, 2 = neither */ areaDir[AVG_SAMP_FLAG] = 2; sLog(SLOG_EE1, " -- InitGvarAreaDir out (OK)...\n\n"); return (0); } /* *| Name: *| NearestDataLine - Return data for image line nearest that requested. *| *| Interface: *| int *| NearestDataLine ( *| int startingImgLine, *| int inputImgLine, *| int baseLineRes *| ) *| *| Input: *| startingImgLine - first image line in the image *| inputImgLine - target image line *| baseLineRes - base line resolution of the image *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| always returns nearest data line to the input image line *| *| Remarks: *| *| Categories: *| ingest/decode */ int NearestDataLine ( int startingImgLine, int inputImgLine, int baseLineRes ) { int result; int relImgLine; int resMod; relImgLine = inputImgLine - startingImgLine; if (relImgLine < 0) { return (startingImgLine); } if ((relImgLine % baseLineRes) == 0) { result = inputImgLine; } else { resMod = relImgLine % baseLineRes; if (resMod <= (baseLineRes / 2)) { result = inputImgLine - resMod; } else { result = inputImgLine + (baseLineRes - resMod); } } return (result); } /* *| Name: *| SendGvarCod - Transfer nav or cal codicil to client. *| *| Interface: *| int *| SendGvarCod ( *| char *cod, *| int length, *| int codType *| ) *| *| Input: *| cod - data codicil to send *| length - number of bytes to send *| codType - codicil type, navigation or calibration *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| always returns 0 *| *| Remarks: *| *| Categories: *| ingest/decode */ int SendGvarCod ( char *cod, int length, int codType ) { int i; int num_words; int * icod; /* Integer array of cod */ sLog(SLOG_EE1, "\n -- SendGvarCod in...\n"); num_words = length / 4; icod = (int * ) cod ; /* cal codicil */ if (codType == CAL_COD) { M0swbyt4(icod, num_words); M0sxsend(length, (void *) cod); } /* nav codicil */ if (codType == NAV_COD) { /* Don't flip bytes every 128 words */ for (i = 1; i < num_words; i+=128) { M0swbyt4(&icod[i], 128-2); } M0sxsend(length, (void *) cod ); } sLog(SLOG_EE1, " -- SendGvarCod out...\n\n"); return 0; }