/* Copyright 1997, 1998, 1999 University Corporation for Atmospheric Research This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Author: Louis H. Estey Date: July 1999 part of the BINEX source code release, see also: http://www.unavco.ucar.edu/software/binex */ #include "general.h" unsigned long read_ubnxi #if KR_C (file, rec, n) FILE_INFO *file; unsigned char *rec, *n; #else (FILE_INFO *file, unsigned char *rec, unsigned char *n) #endif { *n= 0x00; do { if ((size_t)fread((void *)&rec[*n], (size_t)1, (size_t)1, file->fp) < 1) { *n= 0x00; return(0L); } switch (++(*n)) { case 0x01: case 0x02: case 0x03: switch (rec[*n - 0x01] & 0x80) { case 0x80: break; default: return(ubnxi_to_uint4(rec, *n)); } break; } } while (*n < 0x04); *n= 0x00; return (0L); } /********************************************************************/ unsigned long ubnxi_to_uint4 #if KR_C (rec, n) unsigned char *rec, n; #else (unsigned char *rec, unsigned char n) #endif { unsigned char i; unsigned long ul; for (i= 0, ul= 0L; i < n; i++) switch (teq.tr.binex.little_endian_record) { case TRUE: ul|= (unsigned long)(rec[i] & (n < 0x03 ? 0x7f : 0xff)) << 7*i; break; case FALSE: ul|= (unsigned long)(rec[i] & (n < 0x03 ? 0x7f : 0xff)) << 7*(n-0x01-i); break; } return(ul); } /********************************************************************/ void binex_f_stx #if KR_C (_out) FILE *_out; #else (FILE *_out) #endif { unsigned char buff; static bool first_pass= (bool)TRUE; /* "forward-readable only" synchronization and endian byte: */ switch (teq.tr.little_endian) { case TRUE: /* little-endian processor/compiler: synchronization byte = 0xc2 */ buff= BINEX_F_stx_LE; break; case FALSE: /* big-endian processor/compiler: synchronization byte = 0xe2 */ buff= BINEX_F_stx_BE; break; } (void)fwrite((void *)&buff, 1, 1, _out); if (first_pass) { teq.tr.binex.bytes_reversed= (bool)FALSE; teq.tr.binex.little_endian_record= teq.tr.little_endian; first_pass= (bool)TRUE; } } /********************************************************************/ void binex_append_time #if KR_C (message, offset, sec_resolution) unsigned char *message; unsigned long *offset; unsigned char sec_resolution; #else (unsigned char *message, unsigned long *offset, unsigned char sec_resolution) #endif { unsigned char s; double frac; /* teqc epochs start at 1.0 Jan 1980, whereas GPS time starts at 6.0 Jan 1980, a difference of 5 days = 7200 minutes */ append_uint4(message, offset, (unsigned long)(obs.observation.epoch.minutes - 7200)); /* note: cases 0x05 and 0x06 need to be tested */ switch (sec_resolution) { case 0x00: /* resolution only to minutes */ break; case 0x01: /* resolution to 0.25 seconds */ append_uint1(message, offset, (unsigned char)floor(obs.observation.epoch.sec*4. + 0.5)); break; case 0x02: /* resolution to 0.001 seconds */ append_uint2(message, offset, (unsigned short)floor(obs.observation.epoch.sec*1000. + 0.5)); break; case 0x04: /* resolution to 20 nanoseconds */ append_uint4(message, offset, (unsigned long)floor(obs.observation.epoch.sec*50e6 + 0.5)); break; case 0x05: /* resolution to 0.1 nanoseconds: 6 bits used to store integer seconds; "1" = 1 second 34 bits used to store nearest fractional 0.1 nanoseconds; "1" = 0.1 nanosecond */ s= (unsigned char)floor(round(obs.observation.epoch.sec, 1e-10)); frac= floor((obs.observation.epoch.sec - (double)s)*1e10 + 0.5); switch (teq.tr.little_endian) { case TRUE: append_uint1(message, offset, s | (0xc0 & (unsigned char)fmod(frac, 4.) << 6)); append_uint4(message, offset, (unsigned long)(frac/4.)); break; case FALSE: append_uint1(message, offset, (s << 2) | (0x03 & (unsigned char)(frac/4294967296.))); append_uint4(message, offset, (unsigned long)fmod(frac, 4294967296.)); break; } break; case 0x06: /* resolution to 0.25 picoseconds: 6 bits used to store integer seconds; "1" = 1 second 42 bits used to store nearest fractional 0.25 picoseconds; "1" = 0.25 picosecond */ s= (unsigned char)floor(round(obs.observation.epoch.sec, 2.5e-13)); frac= floor((obs.observation.epoch.sec - (double)s)*4e12 + 0.5); switch (teq.tr.little_endian) { case TRUE: append_uint2(message, offset, (unsigned short)s | (0xffc0 & (unsigned short)fmod(frac, 1024.) << 6)); append_uint4(message, offset, (unsigned long)(frac/1024.)); break; case FALSE: append_uint2(message, offset, ((unsigned short)s << 10) | (0x03ff & (unsigned short)(frac/4294967296.))); append_uint4(message, offset, (unsigned long)fmod(frac, 4294967296.)); break; } break; case 0x08: /* 8-byte floating-point resolution */ append_real8(message, offset, obs.observation.epoch.sec); break; default: fprintf(stderr, "! Error ! binex_append_time(): case 0x%02 not found\n", (int)sec_resolution); exit(-1); } } /********************************************************************/ void binex_append_mGFZi #if KR_C (message, offset, delta, eight_byte) unsigned char *message; unsigned long *offset; double delta; bool eight_byte; #else (unsigned char *message, unsigned long *offset, double delta, bool eight_byte) #endif { /* value bits of leading byte ----- ----------------------- L -> M: big endian (absolute value is in the least significant bits) M <- L: little endian (absolute value is in the most significant bits) < 64 ....00: + 6-bit int ....10: - 6-bit int < 8254 ...001: + 13-bit int ...101: - 13-bit int < 268443709 ..0011: + 28-bit int ..1011: - 28-bit int else ..0111: + 60-bit int ..1111: - 60-bit int */ static double double_limit= MAXFLOAT/10.; double abs_delta; unsigned char sgn_delta; unsigned char uc; unsigned short us; unsigned long ul; if (delta > double_limit) { /* store in unsigned char: "-0" == 0x02 = 00000010; 0x40 = 01000000 */ switch (teq.tr.little_endian) { case TRUE: uc= 0x02; break; case FALSE: uc= 0x40; break; } append_uint1(message, offset, uc); return; } abs_delta= floor(fabs(delta) + 0.5); sgn_delta= delta < 0. ? 0x01 : 0x00; if (abs_delta < 64.) { /* 2^6 */ /* store in unsigned char: 0xfc = 11111100; 0x3f = 00111111 note: any "-0" representation is converted to the "+0" representation */ switch (teq.tr.little_endian) { case TRUE: uc= (sgn_delta << 1) | 0xfc & (unsigned char)abs_delta << 2; switch (uc) { case 0x02: uc= 0x00; break; } break; case FALSE: uc= (sgn_delta << 6) | 0x3f & (unsigned char)abs_delta; switch (uc) { case 0x40: uc= 0x00; break; } break; } append_uint1(message, offset, uc); } else if (abs_delta < 8254.) { /* 2^13 + 62 */ /* store in unsigned short: 0xf9 = 11111001; 0x9f = 10011111 */ abs_delta-= 62.; /* note: values of -1, -0, +0, and +1 are reserved for future use */ switch (teq.tr.little_endian) { case TRUE: us= ((unsigned short)sgn_delta << 2) | 0xfff9 & (0x0001 | (unsigned short)abs_delta << 3); break; case FALSE: us= ((unsigned short)sgn_delta << 13) | 0x9fff & (0x8000 | (unsigned short)abs_delta); break; } append_uint2(message, offset, us); } else if (abs_delta < 268443709.) { /* 2^28 + 8253 */ /* store in unsigned long: 0xf3 = 11110011; 0xcf = 11001111 */ abs_delta-= 8253.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff3 & (0x00000003 | (unsigned long)abs_delta << 4); break; case FALSE: ul= ((unsigned long)sgn_delta << 28) | 0xcfffffff & (0xc0000000 | (unsigned long)abs_delta); break; } append_uint4(message, offset, ul); } else { abs_delta-= 268443708.; switch (eight_byte) { case FALSE: /* store in an unsigned long and an unsigned short: 0xf7 = 11110111; 0xef = 11101111; 2^28 = 268435456; 2^16 = 65536 */ switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff7 & (0x00000007 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); us= (unsigned short)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 28) | 0xefffffff & (0xe0000000 | (unsigned long)(abs_delta/65536.)); append_uint4(message, offset, ul); us= (unsigned short)fmod(abs_delta, 65536.); break; } append_uint2(message, offset, us); break; case TRUE: /* store in two unsigned longs: 0xf7 = 11110111; 0xef = 11101111; 2^28 = 268435456; 2^32 = 4294967296 */ switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff7 & (0x00000007 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); ul= (unsigned long)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 28) | 0xefffffff & (0xe0000000 | (unsigned long)(abs_delta/4294967296.)); append_uint4(message, offset, ul); ul= (unsigned long)fmod(abs_delta, 4294967296.); break; } append_uint4(message, offset, ul); break; } } } /********************************************************************/ void binex_append_mGFZI #if KR_C (message, offset, delta) unsigned char *message; unsigned long *offset; double delta; #else (unsigned char *message, unsigned long *offset, double delta) #endif { /* value bits of leading byte ----- ----------------------- L -> M: big endian (absolute value is in the least significant bits) M <- L: little endian (absolute value is in the most significant bits) < 2^4 ....0000: + 4-bit int < 16 = 0x0000000000000010 (reserving -0) ....1000: - 4-bit int < ~2^12 ....0001: + 12-bit int < 4110 = 0x000000000000100e (reserving +-1, +-0) ....1001: - 12-bit int < ~2^20 ....0010: + 20-bit int < 1052685 = 0x000000000010100d (reserving -0) ....1010: - 20-bit int < ~2^28 ....0011: + 28-bit int < 269488140 = 0x000000001010100c (reserving -0) ....1011: - 28-bit int < ~2^36 ....0100: + 36-bit int < 68988964875 = 0x000000101010100b (reserving -0) ....1100: - 36-bit int < ~2^44 ....0101: + 44-bit int < 17661175009290 = 0x000010101010100a (reserving -0) ....1101: - 44-bit int < ~2^52 ....0110: + 52-bit int < 4521260802379785 = 0x0010101010101009 (reserving -0) ....1110: - 52-bit int < ~2^60 ....0111: + 60-bit int < 0x1010101010101008 (reserving -0) ....1111: - 60-bit int */ static double double_limit= MAXFLOAT/10.; double abs_delta; unsigned char sgn_delta; unsigned char uc; unsigned short us; unsigned long ul; if (delta > double_limit) { /* store in unsigned char: "-0" == 0x08 = 00001000; 0x80 = 10000000 */ switch (teq.tr.little_endian) { case TRUE: uc= 0x08; break; case FALSE: uc= 0x80; break; } append_uint1(message, offset, uc); return; } abs_delta= floor(fabs(delta) + 0.5); sgn_delta= delta < 0. ? 0x01 : 0x00; if (abs_delta < 16.) { /* store in unsigned char: 0xf0 = 11110000; 0x0f = 00001111 note: any "-0" representation is converted to the "+0" representation */ switch (teq.tr.little_endian) { case TRUE: uc= (sgn_delta << 3) | 0xf0 & (unsigned char)abs_delta << 4; switch (uc) { case 0x08: uc= 0x00; break; } break; case FALSE: uc= (sgn_delta << 7) | 0x0f & (unsigned char)abs_delta; switch (uc) { case 0x80: uc= 0x00; break; } break; } append_uint1(message, offset, uc); } else if (abs_delta < 4110.) { /* store in unsigned short: 0xf1 = 11110001; 0x1f = 00011111 */ abs_delta-= 14.; /* note: values of -1, -0, +0, and +1 are reserved for future use */ switch (teq.tr.little_endian) { case TRUE: us= ((unsigned short)sgn_delta << 3) | 0xfff1 & (0x0001 | (unsigned short)abs_delta << 4); break; case FALSE: us= ((unsigned short)sgn_delta << 15) | 0x1fff & (0x1000 | (unsigned short)abs_delta); break; } append_uint2(message, offset, us); } else if (abs_delta < 1052685.) { /* store in 3 bytes of unsigned long: 0xf2 = 11110010; 0x2f = 00101111 */ abs_delta-= 4109.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0x00fffff2 & (0x00000002 | (unsigned long)abs_delta << 4); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x2fffffff & (0x20000000 | (unsigned long)abs_delta << 8); break; } append_uint3(message, offset, ul); } else if (abs_delta < 269488140.) { /* store in unsigned long: 0xf3 = 11110011; 0x3f = 00111111 */ abs_delta-= 1052684.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff3 & (0x00000003 | (unsigned long)abs_delta << 4); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x3fffffff & (0x30000000 | (unsigned long)abs_delta); break; } append_uint4(message, offset, ul); } else if (abs_delta < 68988964875.) { /* store in an unsigned long and an unsigned char: 0xf4 = 11110100; 0x4f = 01001111; 2^28 = 268435456; 2^8 = 256 */ abs_delta-= 269488139.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff4 & (0x00000004 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); uc= (unsigned char)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x4fffffff & (0x40000000 | (unsigned long)(abs_delta/256.)); append_uint4(message, offset, ul); uc= (unsigned char)fmod(abs_delta, 256.); break; } append_uint1(message, offset, uc); } else if (abs_delta < 17661175009290.) { /* store in an unsigned long and an unsigned short: 0xf5 = 11110101; 0x5f = 01011111; 2^28 = 268435456; 2^16 = 65536 */ abs_delta-= 68988964874.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff5 & (0x00000005 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); us= (unsigned short)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x5fffffff & (0x50000000 | (unsigned long)(abs_delta/65536.)); append_uint4(message, offset, ul); us= (unsigned short)fmod(abs_delta, 65536.); break; } append_uint2(message, offset, us); } else if (abs_delta < 4521260802379785.) { /* store in an unsigned long and 3 bytes of unsigned long: 0xf6 = 11110110; 0x6f = 01101111; 2^28 = 268435456; 2^24 = 16777216 */ abs_delta-= 17661175009289.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff6 & (0x00000006 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); ul= (unsigned long)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x6fffffff & (0x60000000 | (unsigned long)(abs_delta/16777216.)); append_uint4(message, offset, ul); ul= (unsigned long)fmod(abs_delta, 16777216.) << 8; break; } append_uint3(message, offset, ul); } else { /* store in two unsigned longs: 0xf7 = 11110111; 0x7f = 01111111; 2^28 = 268435456; 2^32 = 4294967296 */ abs_delta-= 4521260802379784.; switch (teq.tr.little_endian) { case TRUE: ul= ((unsigned long)sgn_delta << 3) | 0xfffffff7 & (0x00000007 | (unsigned long)fmod(abs_delta, 268435456.) << 4); append_uint4(message, offset, ul); ul= (unsigned long)(abs_delta/268435456.); break; case FALSE: ul= ((unsigned long)sgn_delta << 31) | 0x7fffffff & (0x70000000 | (unsigned long)(abs_delta/4294967296.)); append_uint4(message, offset, ul); ul= (unsigned long)fmod(abs_delta, 4294967296.); break; } append_uint4(message, offset, ul); } } /********************************************************************/ double binex_extract_mGFZi #if KR_C (message, offset, valid, eight_byte) unsigned char *message; unsigned long *offset; bool *valid, eight_byte; #else (unsigned char *message, unsigned long *offset, bool *valid, bool eight_byte) #endif { static double abs_delta; unsigned char uc, i, flag; unsigned short us; unsigned long ul; short sgn_delta; switch (teq.tr.binex.little_endian_record) { case TRUE: flag= message[*offset] & 0x0f; break; case FALSE: /* rotate the 4 flag bits in the byte: */ for (uc= 0x01, i= 0x04, flag= 0x00; uc < 0x10; uc+= 0x02, i+= 0x01) flag|= (unsigned char)(((unsigned long)message[*offset] & (0x01 << i)) >> uc); break; } *valid= (bool)TRUE; sgn_delta= 1; abs_delta= 0.; switch (flag & 0x03) { case 0x02: sgn_delta= -1; /* no break */ case 0x00: /* use 1 byte: */ extract_uint1(message, offset, &uc); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)((unsigned long)uc >> 2); break; case 0x00: abs_delta= (double)((unsigned long)uc & 0x3f); break; } if (sgn_delta == -1 && abs_delta == 0.) { /* "-0" reserved for "no data" indicator */ *valid= (bool)FALSE; return(D_NO_DATA); } return((double)sgn_delta * abs_delta); default: switch (flag & 0x07) { case 0x05: sgn_delta= -1; /* no break */ case 0x01: /* use 2 bytes: */ extract_uint2(message, offset, &us); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)((unsigned long)us >> 3); break; case 0x00: abs_delta= (double)((unsigned long)us & 0x1fff); break; } return((double)sgn_delta * (62. + abs_delta)); default: switch (flag & 0x0f) { case 0x0b: sgn_delta= -1; /* no break */ case 0x03: /* use 4 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); break; case 0x00: abs_delta= (double)(ul & 0x0fffffff); break; } return((double)sgn_delta * (8253. + abs_delta)); case 0x0f: sgn_delta= -1; /* no break */ case 0x07: extract_uint4(message, offset, &ul); switch (eight_byte) { case FALSE: /* use 6 bytes: */ switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint2(message, offset, &us); abs_delta+= (double)us*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*65536.; extract_uint2(message, offset, &us); abs_delta+= (double)us; break; } break; case TRUE: /* use 8 bytes: */ switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint4(message, offset, &ul); abs_delta+= (double)ul*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*4294967296.; extract_uint4(message, offset, &ul); abs_delta+= (double)ul; break; } break; } return((double)sgn_delta * (268443708. + abs_delta)); default: /* something really screwed up! */ fprintf(stderr, "binex_extract_mGFZi(): leading byte = 0x%02\n", (int)uc); *valid= (bool)FALSE; return(0.); } } } } /********************************************************************/ double binex_extract_mGFZI #if KR_C (message, offset, valid) unsigned char *message; unsigned long *offset; bool *valid; #else (unsigned char *message, unsigned long *offset, bool *valid) #endif { static double abs_delta; unsigned char uc, i, flag; unsigned short us; unsigned long ul; short sgn_delta; switch (teq.tr.binex.little_endian_record) { case TRUE: flag= message[*offset] & 0x0f; break; case FALSE: flag= message[*offset] >> 4 & 0x0f; break; } *valid= (bool)TRUE; sgn_delta= 1; abs_delta= 0.; switch (flag) { case 0x08: sgn_delta= -1; /* no break */ case 0x00: /* use 1 byte: */ extract_uint1(message, offset, &uc); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)((unsigned long)uc >> 4); break; case 0x00: abs_delta= (double)((unsigned long)uc & 0x0f); break; } if (sgn_delta == -1 && abs_delta == 0.) { /* "-0" reserved for "no data" indicator */ *valid= (bool)FALSE; return(D_NO_DATA); } return((double)sgn_delta * abs_delta); case 0x09: sgn_delta= -1; /* no break */ case 0x01: /* use 2 bytes: */ extract_uint2(message, offset, &us); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)((unsigned long)us >> 4); break; case 0x00: abs_delta= (double)((unsigned long)us & 0x0fff); break; } return((double)sgn_delta * (14. + abs_delta)); case 0x0a: sgn_delta= -1; /* no break */ case 0x02: /* use 3 bytes: */ extract_uint3(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)((unsigned long)ul >> 4); break; case 0x00: abs_delta= (double)((unsigned long)ul >> 8 & 0x000fffff); break; } return((double)sgn_delta * (4109. + abs_delta)); case 0x0b: sgn_delta= -1; /* no break */ case 0x03: /* use 4 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); break; case 0x00: abs_delta= (double)(ul & 0x0fffffff); break; } return((double)sgn_delta * (1052684. + abs_delta)); case 0x0c: sgn_delta= -1; /* no break */ case 0x04: /* use 5 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint1(message, offset, &uc); abs_delta+= (double)uc*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*256.; extract_uint1(message, offset, &uc); abs_delta+= (double)uc; break; } return((double)sgn_delta * (269488139. + abs_delta)); case 0x0d: sgn_delta= -1; /* no break */ case 0x05: /* use 6 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint2(message, offset, &us); abs_delta+= (double)us*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*65536.; extract_uint2(message, offset, &us); abs_delta+= (double)us; break; } return((double)sgn_delta * (68988964874. + abs_delta)); case 0x0e: sgn_delta= -1; /* no break */ case 0x06: /* use 7 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint4(message, offset, &ul); abs_delta+= (double)ul*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*16777216.; extract_uint4(message, offset, &ul); abs_delta+= (double)(ul >> 8); break; } return((double)sgn_delta * (17661175009289. + abs_delta)); case 0x0f: sgn_delta= -1; /* no break */ case 0x07: /* use 8 bytes: */ extract_uint4(message, offset, &ul); switch (teq.tr.binex.bytes_reversed & 0x01 ^ teq.tr.little_endian & 0x01) { case 0x01: abs_delta= (double)(ul >> 4); extract_uint4(message, offset, &ul); abs_delta+= (double)ul*268435456.; break; case 0x00: abs_delta= (double)(ul & 0x0fffffff)*4294967296.; extract_uint4(message, offset, &ul); abs_delta+= (double)ul; break; } return((double)sgn_delta * (4521260802379784. + abs_delta)); default: /* something really screwed up! */ fprintf(stderr, "binex_extract_mGFZI(): leading byte = 0x%02\n", (int)uc); *valid= (bool)FALSE; return(0.); } } /********************************************************************/ void append_uint1 #if KR_C (buf, off, uc) unsigned char *buf; unsigned long *off; unsigned char uc; #else (unsigned char *buf, unsigned long *off, unsigned char uc) #endif { buf[*off]= uc; (*off)++; } /********************************************************************/ void append_uint2 #if KR_C (buf, off, us) unsigned char *buf; unsigned long *off; unsigned short us; #else (unsigned char *buf, unsigned long *off, unsigned short us) #endif { memcpy((void *)(buf + *off), (void *)&us, (size_t)2); (*off)+= 2; } /********************************************************************/ void append_sint2 #if KR_C (buf, off, s) unsigned char *buf; unsigned long *off; short s; #else (unsigned char *buf, unsigned long *off, short s) #endif { memcpy((void *)(buf + *off), (void *)&s, (size_t)2); (*off)+= 2; } /********************************************************************/ void append_uint3 #if KR_C (buf, off, ul) unsigned char *buf; unsigned long *off; unsigned long ul; #else (unsigned char *buf, unsigned long *off, unsigned long ul) #endif { memcpy((void *)(buf + *off), (void *)&ul, (size_t)3); (*off)+= 3; } /********************************************************************/ void append_uint4 #if KR_C (buf, off, ul) unsigned char *buf; unsigned long *off; unsigned long ul; #else (unsigned char *buf, unsigned long *off, unsigned long ul) #endif { memcpy((void *)(buf + *off), (void *)&ul, (size_t)4); (*off)+= 4; } /********************************************************************/ void append_sint4 #if KR_C (buf, off, sl) unsigned char *buf; unsigned long *off; long sl; #else (unsigned char *buf, unsigned long *off, long sl) #endif { memcpy((void *)(buf + *off), (void *)&sl, (size_t)4); (*off)+= 4; } /********************************************************************/ void append_real4 #if KR_C (buf, off, f) unsigned char *buf; unsigned long *off; float f; #else (unsigned char *buf, unsigned long *off, float f) #endif { memcpy((void *)(buf + *off), (void *)&f, (size_t)4); (*off)+= 4; } /********************************************************************/ void append_real8 #if KR_C (buf, off, d) unsigned char *buf; unsigned long *off; double d; #else (unsigned char *buf, unsigned long *off, double d) #endif { memcpy((void *)(buf + *off), (void *)&d, (size_t)8); (*off)+= 8; } /********************************************************************/ void extract_uint1 #if KR_C (buf, off, uc) unsigned char *buf; unsigned long *off; unsigned char *uc; #else (unsigned char *buf, unsigned long *off, unsigned char *uc) #endif { *uc= buf[*off]; (*off)++; } /********************************************************************/ void extract_uint2 #if KR_C (buf, off, us) unsigned char *buf; unsigned long *off; unsigned short *us; #else (unsigned char *buf, unsigned long *off, unsigned short *us) #endif { memcpy((void *)us, (void *)(buf + *off), (size_t)2); (*off)+= 2; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)us, 2); } /********************************************************************/ void extract_sint2 #if KR_C (buf, off, s) unsigned char *buf; unsigned long *off; short *s; #else (unsigned char *buf, unsigned long *off, short *s) #endif { memcpy((void *)s, (void *)(buf + *off), (size_t)2); (*off)+= 2; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)s, 2); } /********************************************************************/ void extract_uint3 #if KR_C (buf, off, ul) unsigned char *buf; unsigned long *off; unsigned long *ul; #else (unsigned char *buf, unsigned long *off, unsigned long *ul) #endif { *ul= 0L; memcpy((void *)ul, (void *)(buf + *off), (size_t)3); (*off)+= 3; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)ul, 4); } /********************************************************************/ void extract_uint4 #if KR_C (buf, off, ul) unsigned char *buf; unsigned long *off; unsigned long *ul; #else (unsigned char *buf, unsigned long *off, unsigned long *ul) #endif { memcpy((void *)ul, (void *)(buf + *off), (size_t)4); (*off)+= 4; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)ul, 4); } /********************************************************************/ void extract_sint4 #if KR_C (buf, off, l) unsigned char *buf; unsigned long *off; long *l; #else (unsigned char *buf, unsigned long *off, long *l) #endif { memcpy((void *)l, (void *)(buf + *off), (size_t)4); (*off)+= 4; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)l, 4); } /********************************************************************/ void extract_real4 #if KR_C (buf, off, f) unsigned char *buf; unsigned long *off; float *f; #else (unsigned char *buf, unsigned long *off, float *f) #endif { memcpy((void *)f, (void *)(buf + *off), (size_t)4); (*off)+= 4; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)f, 4); } /********************************************************************/ void extract_real8 #if KR_C (buf, off, d) unsigned char *buf; unsigned long *off; double *d; #else (unsigned char *buf, unsigned long *off, double *d) #endif { memcpy((void *)d, (void *)(buf + *off), (size_t)8); (*off)+= 8; if (teq.tr.binex.bytes_reversed) reverse_bytes((unsigned char *)d, 8); } /********************************************************************/ unsigned char binex_build_SV_id #if KR_C (system) SAT_ID *system; #else (SAT_ID *system) #endif { unsigned char id; if (0x00 < system->PRN && system->PRN < 0x21) /* number must be 1-32 only */ id= system->PRN - 0x01; else { fprintf(stderr, "! Error ! binex_build_SV_id(): invalid satellite number (%s)\n", SV_id(system)); exit(-1); } switch (system->sys) { case NNSS_Transit: fprintf(stderr, "! Error ! BINEX does not allow formatting of NNSS Transit data\n"); exit(-1); case NAVSTAR_GPS: id|= 0x00 << 5; break; case GLONASS: id|= 0x01 << 5; break; default: fprintf(stderr, "! Error ! binex_build_SV_id(): unknown satellite constellation (= 0x%02x)\n", (int)system->sys); exit(-1); } return(id); } /********************************************************************/ bool binex_extract_SV_id #if KR_C (id, system) unsigned char id; SAT_ID *system; #else (unsigned char id, SAT_ID *system) #endif { switch (id >> 5 & 0x03) { case 0x00: system->sys= (unsigned char)NAVSTAR_GPS; break; case 0x01: system->sys= (unsigned char)GLONASS; break; default: return ((bool)FALSE); } system->PRN= (id & 0x1f) + 0x01; return ((bool)TRUE); } /********************************************************************/ unsigned long uint4_to_ubnxi #if KR_C (buf, offset, value) unsigned char *buf; unsigned long *offset, value; #else (unsigned char *buf, unsigned long *offset, unsigned long value) #endif { /* convert an unsigned long which is < 536870912 (2^29) to the standard BINEX 1 to 4 byte sequence */ unsigned char uc; unsigned short us, us1; unsigned long ul, ul1, ul2, ul3, bytes; if (value < 128) { /* one byte needed: */ bytes= 1; uc= (unsigned char)value; memcpy((void *)(buf + *offset), (void *)&uc, (size_t)bytes); } else if (value < 16384) { /* two bytes needed: */ bytes= 2; us= (unsigned short)value; us1= 0x7f00 & us << 1; us&= 0x007f; us|= us1; switch (teq.tr.little_endian) { case TRUE: us|= 0x0080; break; case FALSE: us|= 0x8000; break; } memcpy((void *)(buf + *offset), (void *)&us, (size_t)bytes); } else if (value < 2097152) { /* three bytes needed: */ bytes= 3; ul= (unsigned long)value; ul2= 0x007f0000 & ul << 2; ul1= 0x00007f00 & ul << 1; ul&= 0x0000007f; ul|= ul1 | ul2; switch (teq.tr.little_endian) { case TRUE: ul|= 0x00008080; break; case FALSE: ul|= 0x00808000; ul<<= 8; break; } memcpy((void *)(buf + *offset), (void *)&ul, (size_t)bytes); } else if (value < 536870912) { /* four bytes needed: */ bytes= 4; ul= (unsigned long)value; ul3= 0xff000000 & ul << 3; ul2= 0x007f0000 & ul << 2; ul1= 0x00007f00 & ul << 1; ul&= 0x0000007f; ul|= ul1 | ul2 | ul3; switch (teq.tr.little_endian) { case TRUE: ul|= 0x00808080; break; case FALSE: ul|= 0x80808000; break; } memcpy((void *)(buf + *offset), (void *)&ul, (size_t)bytes); } else { bytes= 0; fprintf(stderr, "! Error ! uint4_to_ubnxi(): value is %d >= 536870912\n", value); exit(-1); } (*offset)+= bytes; return(bytes); } /********************************************************************/ void binex_crc #if KR_C (crc, buff, mess, crc_offset, buff_length, mess_length, reverse) unsigned char *crc, *buff, *mess; unsigned long *crc_offset, buff_length, mess_length; bool reverse; #else (unsigned char *crc, unsigned char *buff, unsigned char *mess, unsigned long *crc_offset, unsigned long buff_length, unsigned long mess_length, bool reverse) #endif { unsigned char uc, bytes; unsigned short us; unsigned long ul, length; /* compute BINEX CRC for this message length */ length= buff_length + mess_length; if (length < 128) { /* 1-byte checksum */ bytes= 1; uc= cks08(buff, mess, buff_length, mess_length); memcpy((void *)(crc + *crc_offset), (void *)&uc, (size_t)bytes); } else if (length < 4096) { /* 2-byte CRC */ bytes= 2; us= crc16(buff, mess, buff_length, mess_length); if (reverse) reverse_bytes((unsigned char *)&us, 2); memcpy((void *)(crc + *crc_offset), (void *)&us, (size_t)bytes); } else if (length < 1048576) { /* 4-byte CRC */ bytes= 4; ul= crc32(buff, mess, buff_length, mess_length); if (reverse) reverse_bytes((unsigned char *)&ul, 4); memcpy((void *)(crc + *crc_offset), (void *)&ul, (size_t)bytes); } else { /* 16-byte MD5 */ bytes= 16; /* code for md5() not yet complete; the next block is just a placeholder until md5() is finished */ fprintf(stderr, "binex_crc(): md5() not completed yet\n"); exit(-1); } (*crc_offset)+= (unsigned long)bytes; } /********************************************************************/ void reverse_bytes #if KR_C (rec, n) unsigned char *rec; int n; #else (unsigned char *rec, int n) #endif { switch (n) { case 2: swap_uc(&rec[0], &rec[1]); return; case 3: swap_uc(&rec[0], &rec[2]); return; case 4: swap_uc(&rec[0], &rec[3]); swap_uc(&rec[1], &rec[2]); return; case 6: swap_uc(&rec[0], &rec[1]); swap_uc(&rec[2], &rec[5]); swap_uc(&rec[3], &rec[4]); return; case 8: swap_uc(&rec[0], &rec[7]); swap_uc(&rec[1], &rec[6]); swap_uc(&rec[2], &rec[5]); swap_uc(&rec[3], &rec[4]); return; default: fprintf(stderr, "reverse_bytes(): uncoded case of %d bytes", n); exit(-1); } } /********************************************************************/ void swap_pp #if KR_C (a, b) void **a, **b; #else (void **a, void **b) #endif { void *tmp; tmp= *a; *a= *b; *b= tmp; } /********************************************************************/ void swap_c #if KR_C (a, b) char *a, *b; #else (char *a, char *b) #endif { char tmp; tmp= *a; *a= *b; *b= tmp; } /********************************************************************/ void swap_uc #if KR_C (a, b) unsigned char *a, *b; #else (unsigned char *a, unsigned char *b) #endif { unsigned char tmp; tmp= *a; *a= *b; *b= tmp; } /********************************************************************/ void swap_i #if KR_C (a, b) int *a, *b; #else (int *a, int *b) #endif { int tmp; tmp= *a; *a= *b; *b= tmp; } /********************************************************************/ void swap_d #if KR_C (a, b) double *a, *b; #else (double *a, double *b) #endif { double tmp; tmp= *a; *a= *b; *b= tmp; } /********************************************************************/