rs41_sgm.c -> (new) rs41mod.c

pull/18/head
Zilog80 2019-05-23 18:21:14 +02:00
rodzic be7f11f694
commit 4daffacf29
2 zmienionych plików z 692 dodań i 691 usunięć

Wyświetl plik

@ -51,6 +51,7 @@ typedef struct {
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
i8_t slt; // silent
} option_t;
typedef struct {
@ -96,11 +97,12 @@ typedef struct {
float ptu_calT2[3]; // calibration T2-Hum
float ptu_calH[2]; // calibration Hum
ui32_t freq; // freq/kHz
float batt; // battery voltage (V)
ui16_t conf_fw; // firmware
ui16_t conf_kt; // kill timer (sec)
ui16_t conf_bt; // burst timer (sec)
ui8_t conf_bk; // burst kill
ui16_t conf_cd; // kill countdown (sec) (kt or bt)
ui8_t conf_bk; // burst kill
char rstyp[9]; // RS41-SG, RS41-SGP
int aux;
char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ...
@ -278,6 +280,7 @@ GPS chip: ublox UBX-G6010-ST
#define pck_FRAME 0x7928
#define pos_FRAME 0x039
#define pos_FrameNb 0x03B // 2 byte
#define pos_BattVolts 0x045 // 2 byte
#define pos_SondeID 0x03D // 8 byte
#define pos_CalData 0x052 // 1 byte, counter 0x00..0x32
#define pos_Calfreq 0x055 // 2 byte, calfr 0x00
@ -328,7 +331,8 @@ GPS chip: ublox UBX-G6010-ST
#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux
#define pos_ZEROstd 0x12B // pos_AUX(0)
#define pck_ENCRYPTED 0x8000 // Packet type for an Encrypted payload
#define pck_SGM_xTU 0x7F1B // temperature/humidity
#define pck_SGM_CRYPT 0x80A7 // Packet type for an Encrypted payload
/*
frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320)
@ -344,14 +348,14 @@ static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4
return ft;
}
static int get_FrameNb(gpx_t *gpx) {
static int get_FrameNb(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t frnr_bytes[2];
int frnr;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_FrameNb + i];
byte = gpx->frame[pos_FrameNb+ofs + i];
frnr_bytes[i] = byte;
}
@ -361,21 +365,38 @@ static int get_FrameNb(gpx_t *gpx) {
return 0;
}
static int get_SondeID(gpx_t *gpx, int crc) {
static int get_BattVolts(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t batt_bytes[2];
float batt_volts;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_BattVolts+ofs + i];
batt_bytes[i] = byte;
}
batt_volts = (float)(batt_bytes[0] + (batt_bytes[1] << 8));
gpx->batt = batt_volts/10.0;
return 0;
}
static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
int i;
unsigned byte;
char sondeid_bytes[9];
if (crc == 0) {
for (i = 0; i < 8; i++) {
byte = gpx->frame[pos_SondeID + i];
byte = gpx->frame[pos_SondeID+ofs + i];
//if ((byte < 0x20) || (byte > 0x7E)) return -1;
sondeid_bytes[i] = byte;
}
sondeid_bytes[8] = '\0';
if ( strncmp(gpx->id, sondeid_bytes, 8) != 0 ) {
//for (i = 0; i < 51; i++) gpx->calfrchk[i] = 0;
memset(gpx->calfrchk, 0, 51);
memset(gpx->calfrchk, 0, 51); // 0x00..0x32
// reset conf data
memset(gpx->rstyp, 0, 9);
gpx->freq = 0;
@ -385,8 +406,8 @@ static int get_SondeID(gpx_t *gpx, int crc) {
gpx->conf_cd = -1;
gpx->conf_kt = -1;
// don't reset gpx->frame[] !
// gpx->T = -273.15;
// gpx->RH = -1.0;
gpx->T = -273.15;
gpx->RH = -1.0;
// new ID:
memcpy(gpx->id, sondeid_bytes, 8);
gpx->id[8] = '\0';
@ -396,24 +417,25 @@ static int get_SondeID(gpx_t *gpx, int crc) {
return 0;
}
static int get_FrameConf(gpx_t *gpx) {
static int get_FrameConf(gpx_t *gpx, int ofs) {
int crc, err;
ui8_t calfr;
int i;
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
crc = check_CRC(gpx, pos_FRAME+ofs, pck_FRAME);
if (crc) gpx->crc |= crc_FRAME;
err = crc;
err |= get_SondeID(gpx, crc);
err |= get_FrameNb(gpx);
err |= get_SondeID(gpx, crc, ofs);
err |= get_FrameNb(gpx, ofs);
err |= get_BattVolts(gpx, ofs);
if (crc == 0) {
calfr = gpx->frame[pos_CalData];
calfr = gpx->frame[pos_CalData+ofs];
if (gpx->calfrchk[calfr] == 0) // const?
{ // 0x32 not constant
for (i = 0; i < 16; i++) {
gpx->calibytes[calfr*16 + i] = gpx->frame[pos_CalData+1+i];
gpx->calibytes[calfr*16 + i] = gpx->frame[pos_CalData+ofs+1+i];
}
gpx->calfrchk[calfr] = 1;
}
@ -512,7 +534,7 @@ static float get_RH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T) {
return rh;
}
static int get_PTU(gpx_t *gpx) {
static int get_PTU(gpx_t *gpx, int ofs, int pck) {
int err=0, i;
int bR, bc1, bT1,
bc2, bT2;
@ -524,14 +546,15 @@ static int get_PTU(gpx_t *gpx) {
get_CalData(gpx);
err = check_CRC(gpx, pos_PTU, pck_PTU);
err = check_CRC(gpx, pos_PTU+ofs, pck);
if (err) gpx->crc |= crc_PTU;
if (err == 0)
{
// 0x7A2A: 16 byte (P)TU
// 0x7F1B: 12 byte _TU
for (i = 0; i < 12; i++) {
meas[i] = u3(gpx->frame+pos_PTU+2+3*i);
meas[i] = u3(gpx->frame+pos_PTU+ofs+2+3*i);
}
bR = gpx->calfrchk[0x03] && gpx->calfrchk[0x04];
@ -596,89 +619,14 @@ static int get_PTU(gpx_t *gpx) {
}
const double c = 299.792458e6;
const double L1 = 1575.42e6;
static int get_SatData(gpx_t *gpx) {
int i, n;
int sv;
ui32_t minPR;
int numSV;
double pDOP, sAcc;
int err = 0;
if ( ((gpx->frame[pos_GPS1]<<8) | gpx->frame[pos_GPS1+1]) != pck_GPS1 ) return -1;
if ( ((gpx->frame[pos_GPS2]<<8) | gpx->frame[pos_GPS2+1]) != pck_GPS2 ) return -2;
if ( ((gpx->frame[pos_GPS3]<<8) | gpx->frame[pos_GPS3+1]) != pck_GPS3 ) return -3;
err = get_FrameConf(gpx);
if (!err) {
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, "(%s) ", gpx->id);
fprintf(stdout, "\n");
}
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW));
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek));
fprintf(stdout, "\n");
minPR = u4(gpx->frame+pos_minPR);
fprintf(stdout, "minPR: %d", minPR);
fprintf(stdout, "\n");
for (i = 0; i < 12; i++) {
n = i*7;
sv = gpx->frame[pos_satsN+2*i];
if (sv == 0xFF) break;
fprintf(stdout, " SV: %2d ", sv);
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
fprintf(stdout, "# ");
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+n)/100.0 + minPR);
fprintf(stdout, " ");
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+n+4)/100.0*L1/c);
fprintf(stdout, "\n");
}
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
(i32_t)u4(gpx->frame+pos_GPSecefX),
(i32_t)u4(gpx->frame+pos_GPSecefY),
(i32_t)u4(gpx->frame+pos_GPSecefZ));
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
(i16_t)u2(gpx->frame+pos_GPSecefV+0),
(i16_t)u2(gpx->frame+pos_GPSecefV+2),
(i16_t)u2(gpx->frame+pos_GPSecefV+4));
numSV = gpx->frame[pos_numSats];
sAcc = gpx->frame[pos_sAcc]/10.0; if (gpx->frame[pos_sAcc] == 0xFF) sAcc = -1.0;
pDOP = gpx->frame[pos_pDOP]/10.0; if (gpx->frame[pos_pDOP] == 0xFF) pDOP = -1.0;
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
fprintf(stdout, "CRC: ");
fprintf(stdout, " %04X", pck_GPS1);
if (check_CRC(gpx, pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
fprintf(stdout, " %04X", pck_GPS2);
if (check_CRC(gpx, pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
fprintf(stdout, " %04X", pck_GPS3);
if (check_CRC(gpx, pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
fprintf(stdout, "\n");
fprintf(stdout, "\n");
return 0;
}
static int get_GPSweek(gpx_t *gpx) {
static int get_GPSweek(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t gpsweek_bytes[2];
int gpsweek;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_GPSweek + i];
byte = gpx->frame[pos_GPSweek+ofs + i];
gpsweek_bytes[i] = byte;
}
@ -692,7 +640,7 @@ static int get_GPSweek(gpx_t *gpx) {
//char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
static char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static int get_GPStime(gpx_t *gpx) {
static int get_GPStime(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t gpstime_bytes[4];
@ -701,7 +649,7 @@ static int get_GPStime(gpx_t *gpx) {
int ms;
for (i = 0; i < 4; i++) {
byte = gpx->frame[pos_GPSiTOW + i];
byte = gpx->frame[pos_GPSiTOW+ofs + i];
gpstime_bytes[i] = byte;
}
@ -725,11 +673,11 @@ static int get_GPStime(gpx_t *gpx) {
return 0;
}
static int get_GPS1(gpx_t *gpx) {
static int get_GPS1(gpx_t *gpx, int ofs) {
int err=0;
// gpx->frame[pos_GPS1+1] != (pck_GPS1 & 0xFF) ?
err = check_CRC(gpx, pos_GPS1, pck_GPS1);
err = check_CRC(gpx, pos_GPS1+ofs, pck_GPS1);
if (err) {
gpx->crc |= crc_GPS1;
// reset GPS1-data (json)
@ -738,17 +686,17 @@ static int get_GPS1(gpx_t *gpx) {
return -1;
}
err |= get_GPSweek(gpx); // no plausibility-check
err |= get_GPStime(gpx); // no plausibility-check
err |= get_GPSweek(gpx, ofs); // no plausibility-check
err |= get_GPStime(gpx, ofs); // no plausibility-check
return err;
}
static int get_GPS2(gpx_t *gpx) {
static int get_GPS2(gpx_t *gpx, int ofs) {
int err=0;
// gpx->frame[pos_GPS2+1] != (pck_GPS2 & 0xFF) ?
err = check_CRC(gpx, pos_GPS2, pck_GPS2);
err = check_CRC(gpx, pos_GPS2+ofs, pck_GPS2);
if (err) gpx->crc |= crc_GPS2;
return err;
@ -783,7 +731,7 @@ static void ecef2elli(double X[], double *lat, double *lon, double *alt) {
*lon = lam*180/M_PI;
}
static int get_GPSkoord(gpx_t *gpx) {
static int get_GPSkoord(gpx_t *gpx, int ofs) {
int i, k;
unsigned byte;
ui8_t XYZ_bytes[4];
@ -799,14 +747,14 @@ static int get_GPSkoord(gpx_t *gpx) {
for (k = 0; k < 3; k++) {
for (i = 0; i < 4; i++) {
byte = gpx->frame[pos_GPSecefX + 4*k + i];
byte = gpx->frame[pos_GPSecefX+ofs + 4*k + i];
XYZ_bytes[i] = byte;
}
memcpy(&XYZ, XYZ_bytes, 4);
X[k] = XYZ / 100.0;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_GPSecefV + 2*k + i];
byte = gpx->frame[pos_GPSecefV+ofs + 2*k + i];
gpsVel_bytes[i] = byte;
}
vel16 = gpsVel_bytes[0] | gpsVel_bytes[1] << 8;
@ -846,16 +794,16 @@ static int get_GPSkoord(gpx_t *gpx) {
gpx->vV = vU;
gpx->numSV = gpx->frame[pos_numSats];
gpx->numSV = gpx->frame[pos_numSats+ofs];
return 0;
}
static int get_GPS3(gpx_t *gpx) {
static int get_GPS3(gpx_t *gpx, int ofs) {
int err=0;
// gpx->frame[pos_GPS3+1] != (pck_GPS3 & 0xFF) ?
err = check_CRC(gpx, pos_GPS3, pck_GPS3);
err = check_CRC(gpx, pos_GPS3+ofs, pck_GPS3);
if (err) {
gpx->crc |= crc_GPS3;
// reset GPS3-data (json)
@ -865,12 +813,12 @@ static int get_GPS3(gpx_t *gpx) {
return -1;
}
err |= get_GPSkoord(gpx); // plausibility-check: altitude, if ecef=(0,0,0)
err |= get_GPSkoord(gpx, ofs); // plausibility-check: altitude, if ecef=(0,0,0)
return err;
}
static int get_Aux(gpx_t *gpx) {
static int get_Aux(gpx_t *gpx, int out, int pos) {
//
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide
//
@ -879,47 +827,54 @@ static int get_Aux(gpx_t *gpx) {
n = 0;
count7E = 0;
pos7E = pos_AUX;
pos7E = 0;
//if (pos != pos_AUX) ;
gpx->xdata[0] = '\0';
if (frametype(gpx) <= 0) // pos7E == pos7611, 0x7E^0x76=0x08 ...
{
// 7Exx: xdata
while ( pos7E < FRAME_LEN && gpx->frame[pos7E] == 0x7E ) {
while ( pos < FRAME_LEN && gpx->frame[pos] == 0x7E ) {
auxlen = gpx->frame[pos7E+1];
auxcrc = gpx->frame[pos7E+2+auxlen] | (gpx->frame[pos7E+2+auxlen+1]<<8);
auxlen = gpx->frame[pos+1];
auxcrc = gpx->frame[pos+2+auxlen] | (gpx->frame[pos+2+auxlen+1]<<8);
if ( auxcrc == crc16(gpx, pos7E+2, auxlen) ) {
if (count7E == 0) fprintf(stdout, "\n # xdata = ");
else { fprintf(stdout, " # "); gpx->xdata[n++] = '#'; } // aux separator
if ( auxcrc == crc16(gpx, pos+2, auxlen) ) {
if (count7E == 0) {
if (out) fprintf(stdout, "\n # xdata = ");
}
else {
if (out) fprintf(stdout, " # ");
gpx->xdata[n++] = '#'; // aux separator
}
//fprintf(stdout, " # %02x : ", gpx->frame[pos7E+2]);
for (i = 1; i < auxlen; i++) {
ui8_t c = gpx->frame[pos7E+2+i]; // (char) or better < 0x7F
ui8_t c = gpx->frame[pos+2+i]; // (char) or better < 0x7F
if (c > 0x1E && c < 0x7F) { // ASCII-only
fprintf(stdout, "%c", c);
if (out) fprintf(stdout, "%c", c);
gpx->xdata[n++] = c;
}
}
count7E++;
pos7E += 2+auxlen+2;
pos7E = pos;
pos += 2+auxlen+2;
}
else {
pos7E = FRAME_LEN;
pos = FRAME_LEN;
gpx->crc |= crc_AUX;
}
}
}
gpx->xdata[n] = '\0';
i = check_CRC(gpx, pos7E, pck_ZERO); // 0x76xx: 00-padding block
i = check_CRC(gpx, pos, pck_ZERO); // 0x76xx: 00-padding block
if (i) gpx->crc |= crc_ZERO;
return count7E;
return pos7E; // count7E
}
static int get_Calconf(gpx_t *gpx, int out) {
static int get_Calconf(gpx_t *gpx, int out, int ofs) {
int i;
unsigned byte;
ui8_t calfr = 0;
@ -928,29 +883,31 @@ static int get_Calconf(gpx_t *gpx, int out) {
char sondetyp[9];
int err = 0;
byte = gpx->frame[pos_CalData];
byte = gpx->frame[pos_CalData+ofs];
calfr = byte;
err = check_CRC(gpx, pos_FRAME, pck_FRAME);
err = check_CRC(gpx, pos_FRAME+ofs, pck_FRAME);
if (gpx->option.vbs == 3) {
if (out && gpx->option.vbs == 3) {
fprintf(stdout, "\n"); // fflush(stdout);
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, " 0x%02x: ", calfr);
for (i = 0; i < 16; i++) {
byte = gpx->frame[pos_CalData+1+i];
byte = gpx->frame[pos_CalData+ofs+1+i];
fprintf(stdout, "%02x ", byte);
}
/*
if (err == 0) fprintf(stdout, "[OK]");
else fprintf(stdout, "[NO]");
*/
fprintf(stdout, " ");
}
if (err == 0)
{
if (calfr == 0x00) {
byte = gpx->frame[pos_Calfreq] & 0xC0; // erstmal nur oberste beiden bits
byte = gpx->frame[pos_Calfreq+ofs] & 0xC0; // erstmal nur oberste beiden bits
f0 = (byte * 10) / 64; // 0x80 -> 1/2, 0x40 -> 1/4 ; dann mal 40
byte = gpx->frame[pos_Calfreq+1];
byte = gpx->frame[pos_Calfreq+ofs+1];
f1 = 40 * byte;
freq = 400000 + f1+f0; // kHz;
if (out && gpx->option.vbs) fprintf(stdout, ": fq %d ", freq);
@ -958,14 +915,14 @@ static int get_Calconf(gpx_t *gpx, int out) {
}
if (calfr == 0x01) {
fw = gpx->frame[pos_CalData+6] | (gpx->frame[pos_CalData+7]<<8);
fw = gpx->frame[pos_CalData+ofs+6] | (gpx->frame[pos_CalData+ofs+7]<<8);
if (out && gpx->option.vbs) fprintf(stdout, ": fw 0x%04x ", fw);
gpx->conf_fw = fw;
}
if (calfr == 0x02) { // 0x5E, 0x5A..0x5B
ui8_t bk = gpx->frame[pos_Calburst]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[pos_CalData+8] + (gpx->frame[pos_CalData+9] << 8); // killtimer (short?)
ui8_t bk = gpx->frame[pos_Calburst+ofs]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[pos_CalData+ofs+8] + (gpx->frame[pos_CalData+ofs+9] << 8); // killtimer (short?)
if (out && gpx->option.vbs) fprintf(stdout, ": BK %02X ", bk);
if (out && gpx->option.vbs && kt != 0xFFFF ) fprintf(stdout, ": kt %.1fmin ", kt/60.0);
gpx->conf_bk = bk;
@ -973,7 +930,7 @@ static int get_Calconf(gpx_t *gpx, int out) {
}
if (calfr == 0x31) { // 0x59..0x5A
ui16_t bt = gpx->frame[pos_CalData+7] + (gpx->frame[pos_CalData+8] << 8); // burst timer (short?)
ui16_t bt = gpx->frame[pos_CalData+ofs+7] + (gpx->frame[pos_CalData+ofs+8] << 8); // burst timer (short?)
// fw >= 0x4ef5: default=[88 77]=0x7788sec=510min
if (out && bt != 0x0000 &&
(gpx->option.vbs == 3 || gpx->option.vbs && gpx->conf_bk)
@ -982,17 +939,17 @@ static int get_Calconf(gpx_t *gpx, int out) {
}
if (calfr == 0x32) {
ui16_t cd = gpx->frame[pos_CalData+1] + (gpx->frame[pos_CalData+2] << 8); // countdown (bt or kt) (short?)
ui16_t cd = gpx->frame[pos_CalData+ofs+1] + (gpx->frame[pos_CalData+ofs+2] << 8); // countdown (bt or kt) (short?)
if (out && cd != 0xFFFF &&
(gpx->option.vbs == 3 || gpx->option.vbs && (gpx->conf_bk || gpx->conf_kt != 0xFFFF))
) fprintf(stdout, ": cd %.1fmin ", cd/60.0);
gpx->conf_cd = cd;
gpx->conf_cd = cd; // (short/i16_t) ?
}
if (calfr == 0x21) { // ... eventuell noch 2 bytes in 0x22
for (i = 0; i < 9; i++) sondetyp[i] = 0;
for (i = 0; i < 8; i++) {
byte = gpx->frame[pos_CalRSTyp + i];
byte = gpx->frame[pos_CalRSTyp+ofs + i];
if ((byte >= 0x20) && (byte < 0x7F)) sondetyp[i] = byte;
else if (byte == 0x00) sondetyp[i] = '\0';
}
@ -1101,120 +1058,267 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
/* ------------------------------------------------------------------------------------ */
static int print_position(gpx_t *gpx, int ec) {
int i;
int err, err0, err1, err2, err3;
int output, out_mask;
int encrypted = 0;
gpx->out = 0;
gpx->aux = 0;
// Quick check for an encrypted packet (RS41-SGM)
// These sondes have a type 0x80 packet in place of the regular PTU packet.
if (check_CRC(gpx, pos_PTU, pck_ENCRYPTED)==0) { // frame[pos_PTU] == pck_ENCRYPTED>>8
encrypted = 1; // and CRC-OK
// Continue with the rest of the extraction
}
err = get_FrameConf(gpx);
err1 = get_GPS1(gpx);
err2 = get_GPS2(gpx);
err3 = get_GPS3(gpx);
err0 = get_PTU(gpx);
out_mask = crc_FRAME|crc_GPS1|crc_GPS3;
output = ((gpx->crc & out_mask) != out_mask); // (!err || !err1 || !err3);
if (output) {
gpx->out = 1; // cf. gpx->crc
if (!err && gpx->option.aut && gpx->option.vbs == 3) fprintf(stdout, "<%c> ", gpx->option.inv?'-':'+');
if (!err) {
static int prn_frm(gpx_t *gpx) {
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, "(%s) ", gpx->id);
}
if (encrypted) { // e.g. 0x80A7-pck
fprintf(stdout, " (RS41-SGM: %02X%02X) ", gpx->frame[pos_PTU], gpx->frame[pos_PTU+1]);
}
if (!err1) {
if (gpx->option.vbs == 3) fprintf(stdout, "(%.1f V) ", gpx->batt);
fprintf(stdout, " ");
return 0;
}
static int prn_ptu(gpx_t *gpx) {
fprintf(stdout, " ");
if (gpx->T > -273.0) fprintf(stdout, " T=%.1fC ", gpx->T);
if (gpx->RH > -0.5) fprintf(stdout, " RH=%.0f%% ", gpx->RH);
return 0;
}
static int prn_gpstime(gpx_t *gpx) {
Gps2Date(gpx);
fprintf(stdout, "%s ", weekday[gpx->wday]);
fprintf(stdout, "%04d-%02d-%02d %02d:%02d:%06.3f",
gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek);
if (gpx->option.vbs == 3) fprintf(stdout, " (W %d)", gpx->week);
}
if (!err3) {
fprintf(stdout, " ");
return 0;
}
static int prn_gpspos(gpx_t *gpx) {
//fprintf(stdout, " ");
fprintf(stdout, " lat: %.5f ", gpx->lat);
fprintf(stdout, " lon: %.5f ", gpx->lon);
fprintf(stdout, " alt: %.2f ", gpx->alt);
//if (gpx->option.vbs)
{
//fprintf(stdout, " (%.1f %.1f %.1f) ", gpx->vN, gpx->vE, gpx->vU);
fprintf(stdout," vH: %4.1f D: %5.1f vV: %3.1f ", gpx->vH, gpx->vD, gpx->vV);
if (gpx->option.vbs == 3) fprintf(stdout," sats: %02d ", gpx->numSV);
}
}
if (gpx->option.ptu && !err0) {
fprintf(stderr, " ");
if (gpx->T > -273.0) fprintf(stderr, " T=%.1fC ", gpx->T);
if (gpx->RH > -0.5) fprintf(stderr, " RH=%.0f%% ", gpx->RH);
return 0;
}
static int prn_sat1(gpx_t *gpx, int ofs) {
fprintf(stdout, "\n");
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW+ofs));
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek+ofs));
return 0;
}
const double c = 299.792458e6;
const double L1 = 1575.42e6;
static int prn_sat2(gpx_t *gpx, int ofs) {
int i, n;
int sv;
ui32_t minPR;
fprintf(stdout, "\n");
minPR = u4(gpx->frame+pos_minPR+ofs);
fprintf(stdout, "minPR: %d", minPR);
fprintf(stdout, "\n");
for (i = 0; i < 12; i++) {
n = i*7;
sv = gpx->frame[pos_satsN+ofs+2*i];
if (sv == 0xFF) break;
fprintf(stdout, " SV: %2d ", sv);
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
fprintf(stdout, "# ");
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+ofs+n)/100.0 + minPR);
fprintf(stdout, " ");
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+ofs+n+4)/100.0*L1/c);
fprintf(stdout, "\n");
}
return 0;
}
static int prn_sat3(gpx_t *gpx, int ofs) {
int numSV;
double pDOP, sAcc;
if (gpx->option.crc) {
fprintf(stdout, " # ");
if (gpx->option.ecc && ec >= 0 && (gpx->crc & 0x1F) != 0) {
int pos, blk, len, crc; // unexpected blocks
fprintf(stdout, "\n");
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
(i32_t)u4(gpx->frame+pos_GPSecefX+ofs),
(i32_t)u4(gpx->frame+pos_GPSecefY+ofs),
(i32_t)u4(gpx->frame+pos_GPSecefZ+ofs));
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+0),
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+2),
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+4));
numSV = gpx->frame[pos_numSats+ofs];
sAcc = gpx->frame[pos_sAcc+ofs]/10.0; if (gpx->frame[pos_sAcc+ofs] == 0xFF) sAcc = -1.0;
pDOP = gpx->frame[pos_pDOP+ofs]/10.0; if (gpx->frame[pos_pDOP+ofs] == 0xFF) pDOP = -1.0;
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
/*
fprintf(stdout, "CRC: ");
fprintf(stdout, " %04X", pck_GPS1);
if (check_CRC(gpx, pos_GPS1+ofs, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
fprintf(stdout, " %04X", pck_GPS2);
if (check_CRC(gpx, pos_GPS2+ofs, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
fprintf(stdout, " %04X", pck_GPS3);
if (check_CRC(gpx, pos_GPS3+ofs, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
fprintf(stdout, "\n");
*/
return 0;
}
static int print_position(gpx_t *gpx, int ec) {
int i, j;
int err, err0, err1, err2, err3;
//int output, out_mask;
int encrypted = 0;
int unexp = 0;
int out = 1;
int sat = 0;
int pos_aux = 0, cnt_aux = 0;
//gpx->out = 0;
gpx->aux = 0;
if (gpx->option.sat) sat = 1;
if (gpx->option.slt) out = 0; else out = 1;
if ( ec >= 0 )
{
int pos, blk, len, crc, pck;
int flen = NDATA_LEN;
int ofs_cal = 0;
int frm_end = NDATA_LEN-2;
if (frametype(gpx) < 0) flen += XDATA_LEN;
switch (gpx->frame[pos_PTU]) {
case 0x7A: // 0x7A2A
frm_end = flen-2;
break;
case 0x7F: // 0x7F1B
frm_end = pos_ZEROstd + 0x1B-0x2A - 2;
break;
case 0x80: // 0x80A7
frm_end = pos_PTU + 2 + 0xA7;
break;
}
pos = pos_FRAME;
while (pos < flen-1) { // e.g.
blk = gpx->frame[pos]; // 0x80xx: encrypted block
len = gpx->frame[pos+1]; // 0x76xx: 00-padding block
gpx->crc = 0;
while (pos < flen-1) {
blk = gpx->frame[pos];
len = gpx->frame[pos+1];
crc = check_CRC(gpx, pos, blk<<8);
fprintf(stdout, " %02X%02X", gpx->frame[pos], gpx->frame[pos+1]);
fprintf(stdout, "[%d]", crc&1);
pos = pos+2+len+2;
pck = (blk<<8) | len;
if ( crc == 0 ) // ecc-OK -> crc-OK
{
int ofs = 0;
switch (pck)
{
case pck_FRAME: // 0x7928
ofs = pos - pos_FRAME;
ofs_cal = ofs;
err = get_FrameConf(gpx, ofs);
if ( !err ) {
if (out || sat) prn_frm(gpx);
}
break;
case pck_PTU: // 0x7A2A
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck_PTU);
if ( 0 && !err0 && gpx->option.ptu ) {
prn_ptu(gpx);
}
else {
fprintf(stdout, "[");
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx->crc>>i)&1);
fprintf(stdout, "]");
break;
case pck_GPS1: // 0x7C1E
ofs = pos - pos_GPS1;
err1 = get_GPS1(gpx, ofs);
if ( !err1 ) {
if (out) prn_gpstime(gpx);
if (sat) prn_sat1(gpx, ofs);
}
if (gpx->option.ecc == 2) {
if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)");
else if (ec == -2) fprintf(stdout, " (+-)");
else /*ec == -3*/ fprintf(stdout, " (--)");
break;
case pck_GPS2: // 0x7D59
ofs = pos - pos_GPS2;
err2 = get_GPS2(gpx, ofs);
if ( !err2 ) {
if (sat) prn_sat2(gpx, ofs);
}
break;
case pck_GPS3: // 0x7B15
ofs = pos - pos_GPS3;
err3 = get_GPS3(gpx, ofs);
if ( !err3 ) {
if (out) prn_gpspos(gpx);
if (sat) prn_sat3(gpx, ofs);
}
break;
case pck_SGM_xTU: // 0x7F1B
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck);
break;
case pck_SGM_CRYPT: // 0x80A7
encrypted = 1;
if (out) fprintf(stdout, " [%04X] (RS41-SGM) ", pck_SGM_CRYPT);
break;
default:
if (blk == 0x7E) {
if (pos_aux == 0) pos_aux = pos; // pos == pos_AUX ?
cnt_aux += 1;
}
if (blk == 0x76) {
// ZERO-Padding pck
}
get_Calconf(gpx, output);
if (gpx->option.vbs > 1 || gpx->option.jsn) {
gpx->aux = get_Aux(gpx);
//if (gpx->aux) fprintf(stdout, "\n%d: %s", gpx->aux, gpx->xdata);
if (blk != 0x76 && blk != 0x7E) {
if (out) fprintf(stdout, " [%04X] ", pck);
unexp = 1;
}
}
}
else { // CRC-ERROR (ECC-OK)
fprintf(stdout, " [ERROR]\n");
break;
}
fprintf(stdout, "\n"); // fflush(stdout);
pos += 2+len+2; // next pck
if ( pos > frm_end ) // end of (sub)frame
{
if (gpx->option.ptu && out && !sat && !err0 && !encrypted) {
prn_ptu(gpx);
}
get_Calconf(gpx, out, ofs_cal);
if (out && ec > 0 && pos > flen-1) fprintf(stdout, " (%d)", ec);
if (pos_aux) gpx->aux = get_Aux(gpx, out && gpx->option.vbs > 1, pos_aux);
gpx->crc = 0;
frm_end = FRAME_LEN-2;
if (out || sat) fprintf(stdout, "\n");
if (gpx->option.jsn) {
// Print out telemetry data as JSON
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
// eigentlich GPS, d.h. UTC = GPS - 18sec (ab 1.1.2017)
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d",
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd );
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
}
@ -1224,19 +1328,85 @@ static int print_position(gpx_t *gpx, int ec) {
if (gpx->aux) { // <=> gpx->xdata[0]!='\0'
fprintf(stdout, ", \"aux\": \"%s\"", gpx->xdata );
}
if (encrypted){
fprintf(stderr, ", \"encrypted\": true");
if (encrypted) {
fprintf(stdout, ", \"subtype\": \"RS41-SGM\", \"encrypted\": true");
} else {
fprintf(stdout, ", \"subtype\": \"%s\"", *gpx->rstyp ? gpx->rstyp : "RS41" ); // RS41-SG(P/M)
if (strncmp(gpx->rstyp, "RS41-SGM", 8) == 0) {
fprintf(stdout, ", \"encrypted\": false");
}
}
fprintf(stdout, " }\n");
fprintf(stdout, "\n");
}
}
}
}
}
// else
if (ec < 0 && (out || sat /*|| gpx->option.jsn*/)) {
//
// crc-OK pcks ?
//
int pck, ofs;
int output = 0, out_mask;
gpx->crc = 0;
out_mask = crc_FRAME|crc_GPS1|crc_GPS3;
if (gpx->option.ptu) out_mask |= crc_PTU;
err = get_FrameConf(gpx, 0);
if (out && !err) prn_frm(gpx);
pck = (gpx->frame[pos_PTU]<<8) | gpx->frame[pos_PTU+1];
ofs = 0;
if (pck < 0x8000) {
err0 = get_PTU(gpx, 0, pck);
if (pck == pck_PTU) ofs = 0;
else if (pck == pck_SGM_xTU) ofs = 0x1B-0x2A;
err1 = get_GPS1(gpx, ofs);
err2 = get_GPS2(gpx, ofs);
err3 = get_GPS3(gpx, ofs);
if (out) {
if (!err1) prn_gpstime(gpx);
if (!err3) prn_gpspos(gpx);
if (!err0) prn_ptu(gpx);
if (0 && !err) get_Calconf(gpx, out, 0); // only if ecc-OK
output = ((gpx->crc & out_mask) != out_mask);
if (output) {
fprintf(stdout, " ");
fprintf(stdout, "[");
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx->crc>>i)&1);
fprintf(stdout, "]");
}
}
}
else if (pck == pck_SGM_CRYPT) {
if (out && !err) {
fprintf(stdout, " [%04X] (RS41-SGM) ", pck_SGM_CRYPT);
//fprintf(stdout, "[%d] ", check_CRC(gpx, pos_PTU, pck_SGM_CRYPT));
output = 1;
}
}
err |= err1 | err3;
if (out && output)
{
if (ec == -1) fprintf(stdout, " (-+)");
else if (ec == -2) fprintf(stdout, " (+-)");
else /*ec == -3*/ fprintf(stdout, " (--)");
return err;
fprintf(stdout, "\n"); // fflush(stdout);
}
}
return 0;
}
static void print_frame(gpx_t *gpx, int len) {
@ -1267,7 +1437,7 @@ static void print_frame(gpx_t *gpx, int len) {
}
if (gpx->option.ecc) {
if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
if (gpx->option.ecc == 2) {
if (gpx->option.ecc /*== 2*/) {
if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)");
@ -1278,9 +1448,6 @@ static void print_frame(gpx_t *gpx, int len) {
}
fprintf(stdout, "\n");
}
else if (gpx->option.sat) {
get_SatData(gpx);
}
else {
print_position(gpx, ec);
}
@ -1406,8 +1573,8 @@ int main(int argc, char *argv[]) {
fprintf(stderr, " -v, -vx, -vv (info, aux, info/conf)\n");
fprintf(stderr, " -r, --raw\n");
fprintf(stderr, " -i, --invert\n");
fprintf(stderr, " --crc (check CRC)\n");
fprintf(stderr, " --ecc2 (Reed-Solomon 2-pass)\n");
//fprintf(stderr, " --crc (check CRC)\n");
//fprintf(stderr, " --ecc2 (Reed-Solomon )\n");
fprintf(stderr, " --ths <x> (peak threshold; default=%.1f)\n", thres);
fprintf(stderr, " --iq0,2,3 (IQ data)\n");
return 0;
@ -1417,7 +1584,7 @@ int main(int argc, char *argv[]) {
}
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; }
else if (strcmp(*argv, "-vv") == 0) { gpx.option.vbs = 3; }
else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
//else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
else if (strcmp(*argv, "--crc") == 0) { gpx.option.crc = 1; }
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
gpx.option.raw = 1;
@ -1429,6 +1596,7 @@ int main(int argc, char *argv[]) {
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; }
else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; }
else if (strcmp(*argv, "--json") == 0) {
gpx.option.jsn = 1;
gpx.option.ecc = 2;

Wyświetl plik

@ -51,7 +51,6 @@ typedef struct {
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
i8_t slt; // silent
} option_t;
typedef struct {
@ -97,12 +96,11 @@ typedef struct {
float ptu_calT2[3]; // calibration T2-Hum
float ptu_calH[2]; // calibration Hum
ui32_t freq; // freq/kHz
float batt; // battery voltage (V)
ui16_t conf_fw; // firmware
ui16_t conf_kt; // kill timer (sec)
ui16_t conf_bt; // burst timer (sec)
ui16_t conf_cd; // kill countdown (sec) (kt or bt)
ui8_t conf_bk; // burst kill
ui16_t conf_cd; // kill countdown (sec) (kt or bt)
char rstyp[9]; // RS41-SG, RS41-SGP
int aux;
char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ...
@ -280,7 +278,6 @@ GPS chip: ublox UBX-G6010-ST
#define pck_FRAME 0x7928
#define pos_FRAME 0x039
#define pos_FrameNb 0x03B // 2 byte
#define pos_BattVolts 0x045 // 2 byte
#define pos_SondeID 0x03D // 8 byte
#define pos_CalData 0x052 // 1 byte, counter 0x00..0x32
#define pos_Calfreq 0x055 // 2 byte, calfr 0x00
@ -331,8 +328,7 @@ GPS chip: ublox UBX-G6010-ST
#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux
#define pos_ZEROstd 0x12B // pos_AUX(0)
#define pck_SGM_xTU 0x7F1B // temperature/humidity
#define pck_SGM_CRYPT 0x80A7 // Packet type for an Encrypted payload
#define pck_ENCRYPTED 0x8000 // Packet type for an Encrypted payload
/*
frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320)
@ -348,14 +344,14 @@ static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4
return ft;
}
static int get_FrameNb(gpx_t *gpx, int ofs) {
static int get_FrameNb(gpx_t *gpx) {
int i;
unsigned byte;
ui8_t frnr_bytes[2];
int frnr;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_FrameNb+ofs + i];
byte = gpx->frame[pos_FrameNb + i];
frnr_bytes[i] = byte;
}
@ -365,38 +361,21 @@ static int get_FrameNb(gpx_t *gpx, int ofs) {
return 0;
}
static int get_BattVolts(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t batt_bytes[2];
float batt_volts;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_BattVolts+ofs + i];
batt_bytes[i] = byte;
}
batt_volts = (float)(batt_bytes[0] + (batt_bytes[1] << 8));
gpx->batt = batt_volts/10.0;
return 0;
}
static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
static int get_SondeID(gpx_t *gpx, int crc) {
int i;
unsigned byte;
char sondeid_bytes[9];
if (crc == 0) {
for (i = 0; i < 8; i++) {
byte = gpx->frame[pos_SondeID+ofs + i];
byte = gpx->frame[pos_SondeID + i];
//if ((byte < 0x20) || (byte > 0x7E)) return -1;
sondeid_bytes[i] = byte;
}
sondeid_bytes[8] = '\0';
if ( strncmp(gpx->id, sondeid_bytes, 8) != 0 ) {
//for (i = 0; i < 51; i++) gpx->calfrchk[i] = 0;
memset(gpx->calfrchk, 0, 51); // 0x00..0x32
memset(gpx->calfrchk, 0, 51);
// reset conf data
memset(gpx->rstyp, 0, 9);
gpx->freq = 0;
@ -406,8 +385,8 @@ static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
gpx->conf_cd = -1;
gpx->conf_kt = -1;
// don't reset gpx->frame[] !
gpx->T = -273.15;
gpx->RH = -1.0;
// gpx->T = -273.15;
// gpx->RH = -1.0;
// new ID:
memcpy(gpx->id, sondeid_bytes, 8);
gpx->id[8] = '\0';
@ -417,25 +396,24 @@ static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
return 0;
}
static int get_FrameConf(gpx_t *gpx, int ofs) {
static int get_FrameConf(gpx_t *gpx) {
int crc, err;
ui8_t calfr;
int i;
crc = check_CRC(gpx, pos_FRAME+ofs, pck_FRAME);
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
if (crc) gpx->crc |= crc_FRAME;
err = crc;
err |= get_SondeID(gpx, crc, ofs);
err |= get_FrameNb(gpx, ofs);
err |= get_BattVolts(gpx, ofs);
err |= get_SondeID(gpx, crc);
err |= get_FrameNb(gpx);
if (crc == 0) {
calfr = gpx->frame[pos_CalData+ofs];
calfr = gpx->frame[pos_CalData];
if (gpx->calfrchk[calfr] == 0) // const?
{ // 0x32 not constant
for (i = 0; i < 16; i++) {
gpx->calibytes[calfr*16 + i] = gpx->frame[pos_CalData+ofs+1+i];
gpx->calibytes[calfr*16 + i] = gpx->frame[pos_CalData+1+i];
}
gpx->calfrchk[calfr] = 1;
}
@ -534,7 +512,7 @@ static float get_RH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T) {
return rh;
}
static int get_PTU(gpx_t *gpx, int ofs, int pck) {
static int get_PTU(gpx_t *gpx) {
int err=0, i;
int bR, bc1, bT1,
bc2, bT2;
@ -546,15 +524,14 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
get_CalData(gpx);
err = check_CRC(gpx, pos_PTU+ofs, pck);
err = check_CRC(gpx, pos_PTU, pck_PTU);
if (err) gpx->crc |= crc_PTU;
if (err == 0)
{
// 0x7A2A: 16 byte (P)TU
// 0x7F1B: 12 byte _TU
for (i = 0; i < 12; i++) {
meas[i] = u3(gpx->frame+pos_PTU+ofs+2+3*i);
meas[i] = u3(gpx->frame+pos_PTU+2+3*i);
}
bR = gpx->calfrchk[0x03] && gpx->calfrchk[0x04];
@ -619,14 +596,89 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
}
static int get_GPSweek(gpx_t *gpx, int ofs) {
const double c = 299.792458e6;
const double L1 = 1575.42e6;
static int get_SatData(gpx_t *gpx) {
int i, n;
int sv;
ui32_t minPR;
int numSV;
double pDOP, sAcc;
int err = 0;
if ( ((gpx->frame[pos_GPS1]<<8) | gpx->frame[pos_GPS1+1]) != pck_GPS1 ) return -1;
if ( ((gpx->frame[pos_GPS2]<<8) | gpx->frame[pos_GPS2+1]) != pck_GPS2 ) return -2;
if ( ((gpx->frame[pos_GPS3]<<8) | gpx->frame[pos_GPS3+1]) != pck_GPS3 ) return -3;
err = get_FrameConf(gpx);
if (!err) {
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, "(%s) ", gpx->id);
fprintf(stdout, "\n");
}
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW));
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek));
fprintf(stdout, "\n");
minPR = u4(gpx->frame+pos_minPR);
fprintf(stdout, "minPR: %d", minPR);
fprintf(stdout, "\n");
for (i = 0; i < 12; i++) {
n = i*7;
sv = gpx->frame[pos_satsN+2*i];
if (sv == 0xFF) break;
fprintf(stdout, " SV: %2d ", sv);
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
fprintf(stdout, "# ");
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+n)/100.0 + minPR);
fprintf(stdout, " ");
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+n+4)/100.0*L1/c);
fprintf(stdout, "\n");
}
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
(i32_t)u4(gpx->frame+pos_GPSecefX),
(i32_t)u4(gpx->frame+pos_GPSecefY),
(i32_t)u4(gpx->frame+pos_GPSecefZ));
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
(i16_t)u2(gpx->frame+pos_GPSecefV+0),
(i16_t)u2(gpx->frame+pos_GPSecefV+2),
(i16_t)u2(gpx->frame+pos_GPSecefV+4));
numSV = gpx->frame[pos_numSats];
sAcc = gpx->frame[pos_sAcc]/10.0; if (gpx->frame[pos_sAcc] == 0xFF) sAcc = -1.0;
pDOP = gpx->frame[pos_pDOP]/10.0; if (gpx->frame[pos_pDOP] == 0xFF) pDOP = -1.0;
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
fprintf(stdout, "CRC: ");
fprintf(stdout, " %04X", pck_GPS1);
if (check_CRC(gpx, pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
fprintf(stdout, " %04X", pck_GPS2);
if (check_CRC(gpx, pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
fprintf(stdout, " %04X", pck_GPS3);
if (check_CRC(gpx, pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
fprintf(stdout, "\n");
fprintf(stdout, "\n");
return 0;
}
static int get_GPSweek(gpx_t *gpx) {
int i;
unsigned byte;
ui8_t gpsweek_bytes[2];
int gpsweek;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_GPSweek+ofs + i];
byte = gpx->frame[pos_GPSweek + i];
gpsweek_bytes[i] = byte;
}
@ -640,7 +692,7 @@ static int get_GPSweek(gpx_t *gpx, int ofs) {
//char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
static char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static int get_GPStime(gpx_t *gpx, int ofs) {
static int get_GPStime(gpx_t *gpx) {
int i;
unsigned byte;
ui8_t gpstime_bytes[4];
@ -649,7 +701,7 @@ static int get_GPStime(gpx_t *gpx, int ofs) {
int ms;
for (i = 0; i < 4; i++) {
byte = gpx->frame[pos_GPSiTOW+ofs + i];
byte = gpx->frame[pos_GPSiTOW + i];
gpstime_bytes[i] = byte;
}
@ -673,11 +725,11 @@ static int get_GPStime(gpx_t *gpx, int ofs) {
return 0;
}
static int get_GPS1(gpx_t *gpx, int ofs) {
static int get_GPS1(gpx_t *gpx) {
int err=0;
// gpx->frame[pos_GPS1+1] != (pck_GPS1 & 0xFF) ?
err = check_CRC(gpx, pos_GPS1+ofs, pck_GPS1);
err = check_CRC(gpx, pos_GPS1, pck_GPS1);
if (err) {
gpx->crc |= crc_GPS1;
// reset GPS1-data (json)
@ -686,17 +738,17 @@ static int get_GPS1(gpx_t *gpx, int ofs) {
return -1;
}
err |= get_GPSweek(gpx, ofs); // no plausibility-check
err |= get_GPStime(gpx, ofs); // no plausibility-check
err |= get_GPSweek(gpx); // no plausibility-check
err |= get_GPStime(gpx); // no plausibility-check
return err;
}
static int get_GPS2(gpx_t *gpx, int ofs) {
static int get_GPS2(gpx_t *gpx) {
int err=0;
// gpx->frame[pos_GPS2+1] != (pck_GPS2 & 0xFF) ?
err = check_CRC(gpx, pos_GPS2+ofs, pck_GPS2);
err = check_CRC(gpx, pos_GPS2, pck_GPS2);
if (err) gpx->crc |= crc_GPS2;
return err;
@ -731,7 +783,7 @@ static void ecef2elli(double X[], double *lat, double *lon, double *alt) {
*lon = lam*180/M_PI;
}
static int get_GPSkoord(gpx_t *gpx, int ofs) {
static int get_GPSkoord(gpx_t *gpx) {
int i, k;
unsigned byte;
ui8_t XYZ_bytes[4];
@ -747,14 +799,14 @@ static int get_GPSkoord(gpx_t *gpx, int ofs) {
for (k = 0; k < 3; k++) {
for (i = 0; i < 4; i++) {
byte = gpx->frame[pos_GPSecefX+ofs + 4*k + i];
byte = gpx->frame[pos_GPSecefX + 4*k + i];
XYZ_bytes[i] = byte;
}
memcpy(&XYZ, XYZ_bytes, 4);
X[k] = XYZ / 100.0;
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_GPSecefV+ofs + 2*k + i];
byte = gpx->frame[pos_GPSecefV + 2*k + i];
gpsVel_bytes[i] = byte;
}
vel16 = gpsVel_bytes[0] | gpsVel_bytes[1] << 8;
@ -794,16 +846,16 @@ static int get_GPSkoord(gpx_t *gpx, int ofs) {
gpx->vV = vU;
gpx->numSV = gpx->frame[pos_numSats+ofs];
gpx->numSV = gpx->frame[pos_numSats];
return 0;
}
static int get_GPS3(gpx_t *gpx, int ofs) {
static int get_GPS3(gpx_t *gpx) {
int err=0;
// gpx->frame[pos_GPS3+1] != (pck_GPS3 & 0xFF) ?
err = check_CRC(gpx, pos_GPS3+ofs, pck_GPS3);
err = check_CRC(gpx, pos_GPS3, pck_GPS3);
if (err) {
gpx->crc |= crc_GPS3;
// reset GPS3-data (json)
@ -813,12 +865,12 @@ static int get_GPS3(gpx_t *gpx, int ofs) {
return -1;
}
err |= get_GPSkoord(gpx, ofs); // plausibility-check: altitude, if ecef=(0,0,0)
err |= get_GPSkoord(gpx); // plausibility-check: altitude, if ecef=(0,0,0)
return err;
}
static int get_Aux(gpx_t *gpx, int out, int pos) {
static int get_Aux(gpx_t *gpx) {
//
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide
//
@ -827,54 +879,47 @@ static int get_Aux(gpx_t *gpx, int out, int pos) {
n = 0;
count7E = 0;
pos7E = 0;
//if (pos != pos_AUX) ;
pos7E = pos_AUX;
gpx->xdata[0] = '\0';
if (frametype(gpx) <= 0) // pos7E == pos7611, 0x7E^0x76=0x08 ...
{
// 7Exx: xdata
while ( pos < FRAME_LEN && gpx->frame[pos] == 0x7E ) {
while ( pos7E < FRAME_LEN && gpx->frame[pos7E] == 0x7E ) {
auxlen = gpx->frame[pos+1];
auxcrc = gpx->frame[pos+2+auxlen] | (gpx->frame[pos+2+auxlen+1]<<8);
auxlen = gpx->frame[pos7E+1];
auxcrc = gpx->frame[pos7E+2+auxlen] | (gpx->frame[pos7E+2+auxlen+1]<<8);
if ( auxcrc == crc16(gpx, pos+2, auxlen) ) {
if (count7E == 0) {
if (out) fprintf(stdout, "\n # xdata = ");
}
else {
if (out) fprintf(stdout, " # ");
gpx->xdata[n++] = '#'; // aux separator
}
if ( auxcrc == crc16(gpx, pos7E+2, auxlen) ) {
if (count7E == 0) fprintf(stdout, "\n # xdata = ");
else { fprintf(stdout, " # "); gpx->xdata[n++] = '#'; } // aux separator
//fprintf(stdout, " # %02x : ", gpx->frame[pos7E+2]);
for (i = 1; i < auxlen; i++) {
ui8_t c = gpx->frame[pos+2+i]; // (char) or better < 0x7F
ui8_t c = gpx->frame[pos7E+2+i]; // (char) or better < 0x7F
if (c > 0x1E && c < 0x7F) { // ASCII-only
if (out) fprintf(stdout, "%c", c);
fprintf(stdout, "%c", c);
gpx->xdata[n++] = c;
}
}
count7E++;
pos7E = pos;
pos += 2+auxlen+2;
pos7E += 2+auxlen+2;
}
else {
pos = FRAME_LEN;
pos7E = FRAME_LEN;
gpx->crc |= crc_AUX;
}
}
}
gpx->xdata[n] = '\0';
i = check_CRC(gpx, pos, pck_ZERO); // 0x76xx: 00-padding block
i = check_CRC(gpx, pos7E, pck_ZERO); // 0x76xx: 00-padding block
if (i) gpx->crc |= crc_ZERO;
return pos7E; // count7E
return count7E;
}
static int get_Calconf(gpx_t *gpx, int out, int ofs) {
static int get_Calconf(gpx_t *gpx, int out) {
int i;
unsigned byte;
ui8_t calfr = 0;
@ -883,31 +928,29 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
char sondetyp[9];
int err = 0;
byte = gpx->frame[pos_CalData+ofs];
byte = gpx->frame[pos_CalData];
calfr = byte;
err = check_CRC(gpx, pos_FRAME+ofs, pck_FRAME);
err = check_CRC(gpx, pos_FRAME, pck_FRAME);
if (out && gpx->option.vbs == 3) {
if (gpx->option.vbs == 3) {
fprintf(stdout, "\n"); // fflush(stdout);
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, " 0x%02x: ", calfr);
for (i = 0; i < 16; i++) {
byte = gpx->frame[pos_CalData+ofs+1+i];
byte = gpx->frame[pos_CalData+1+i];
fprintf(stdout, "%02x ", byte);
}
/*
if (err == 0) fprintf(stdout, "[OK]");
else fprintf(stdout, "[NO]");
*/
fprintf(stdout, " ");
}
if (err == 0)
{
if (calfr == 0x00) {
byte = gpx->frame[pos_Calfreq+ofs] & 0xC0; // erstmal nur oberste beiden bits
byte = gpx->frame[pos_Calfreq] & 0xC0; // erstmal nur oberste beiden bits
f0 = (byte * 10) / 64; // 0x80 -> 1/2, 0x40 -> 1/4 ; dann mal 40
byte = gpx->frame[pos_Calfreq+ofs+1];
byte = gpx->frame[pos_Calfreq+1];
f1 = 40 * byte;
freq = 400000 + f1+f0; // kHz;
if (out && gpx->option.vbs) fprintf(stdout, ": fq %d ", freq);
@ -915,14 +958,14 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
}
if (calfr == 0x01) {
fw = gpx->frame[pos_CalData+ofs+6] | (gpx->frame[pos_CalData+ofs+7]<<8);
fw = gpx->frame[pos_CalData+6] | (gpx->frame[pos_CalData+7]<<8);
if (out && gpx->option.vbs) fprintf(stdout, ": fw 0x%04x ", fw);
gpx->conf_fw = fw;
}
if (calfr == 0x02) { // 0x5E, 0x5A..0x5B
ui8_t bk = gpx->frame[pos_Calburst+ofs]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[pos_CalData+ofs+8] + (gpx->frame[pos_CalData+ofs+9] << 8); // killtimer (short?)
ui8_t bk = gpx->frame[pos_Calburst]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[pos_CalData+8] + (gpx->frame[pos_CalData+9] << 8); // killtimer (short?)
if (out && gpx->option.vbs) fprintf(stdout, ": BK %02X ", bk);
if (out && gpx->option.vbs && kt != 0xFFFF ) fprintf(stdout, ": kt %.1fmin ", kt/60.0);
gpx->conf_bk = bk;
@ -930,7 +973,7 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
}
if (calfr == 0x31) { // 0x59..0x5A
ui16_t bt = gpx->frame[pos_CalData+ofs+7] + (gpx->frame[pos_CalData+ofs+8] << 8); // burst timer (short?)
ui16_t bt = gpx->frame[pos_CalData+7] + (gpx->frame[pos_CalData+8] << 8); // burst timer (short?)
// fw >= 0x4ef5: default=[88 77]=0x7788sec=510min
if (out && bt != 0x0000 &&
(gpx->option.vbs == 3 || gpx->option.vbs && gpx->conf_bk)
@ -939,17 +982,17 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
}
if (calfr == 0x32) {
ui16_t cd = gpx->frame[pos_CalData+ofs+1] + (gpx->frame[pos_CalData+ofs+2] << 8); // countdown (bt or kt) (short?)
ui16_t cd = gpx->frame[pos_CalData+1] + (gpx->frame[pos_CalData+2] << 8); // countdown (bt or kt) (short?)
if (out && cd != 0xFFFF &&
(gpx->option.vbs == 3 || gpx->option.vbs && (gpx->conf_bk || gpx->conf_kt != 0xFFFF))
) fprintf(stdout, ": cd %.1fmin ", cd/60.0);
gpx->conf_cd = cd; // (short/i16_t) ?
gpx->conf_cd = cd;
}
if (calfr == 0x21) { // ... eventuell noch 2 bytes in 0x22
for (i = 0; i < 9; i++) sondetyp[i] = 0;
for (i = 0; i < 8; i++) {
byte = gpx->frame[pos_CalRSTyp+ofs + i];
byte = gpx->frame[pos_CalRSTyp + i];
if ((byte >= 0x20) && (byte < 0x7F)) sondetyp[i] = byte;
else if (byte == 0x00) sondetyp[i] = '\0';
}
@ -1058,266 +1101,120 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
/* ------------------------------------------------------------------------------------ */
static int prn_frm(gpx_t *gpx) {
static int print_position(gpx_t *gpx, int ec) {
int i;
int err, err0, err1, err2, err3;
int output, out_mask;
int encrypted = 0;
gpx->out = 0;
gpx->aux = 0;
// Quick check for an encrypted packet (RS41-SGM)
// These sondes have a type 0x80 packet in place of the regular PTU packet.
if (check_CRC(gpx, pos_PTU, pck_ENCRYPTED)==0) { // frame[pos_PTU] == pck_ENCRYPTED>>8
encrypted = 1; // and CRC-OK
// Continue with the rest of the extraction
}
err = get_FrameConf(gpx);
err1 = get_GPS1(gpx);
err2 = get_GPS2(gpx);
err3 = get_GPS3(gpx);
err0 = get_PTU(gpx);
out_mask = crc_FRAME|crc_GPS1|crc_GPS3;
output = ((gpx->crc & out_mask) != out_mask); // (!err || !err1 || !err3);
if (output) {
gpx->out = 1; // cf. gpx->crc
if (!err && gpx->option.aut && gpx->option.vbs == 3) fprintf(stdout, "<%c> ", gpx->option.inv?'-':'+');
if (!err) {
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, "(%s) ", gpx->id);
fprintf(stdout, " (%.1f V) ", gpx->batt);
return 0;
}
static int prn_ptu(gpx_t *gpx) {
fprintf(stdout, " ");
if (gpx->T > -273.0) fprintf(stdout, " T=%.1fC ", gpx->T);
if (gpx->RH > -0.5) fprintf(stdout, " RH=%.0f%% ", gpx->RH);
return 0;
}
static int prn_gpstime(gpx_t *gpx) {
}
if (encrypted) { // e.g. 0x80A7-pck
fprintf(stdout, " (RS41-SGM: %02X%02X) ", gpx->frame[pos_PTU], gpx->frame[pos_PTU+1]);
}
if (!err1) {
Gps2Date(gpx);
fprintf(stdout, "%s ", weekday[gpx->wday]);
fprintf(stdout, "%04d-%02d-%02d %02d:%02d:%06.3f",
gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek);
if (gpx->option.vbs == 3) fprintf(stdout, " (W %d)", gpx->week);
}
if (!err3) {
fprintf(stdout, " ");
return 0;
}
static int prn_gpspos(gpx_t *gpx) {
//fprintf(stdout, " ");
fprintf(stdout, " lat: %.5f ", gpx->lat);
fprintf(stdout, " lon: %.5f ", gpx->lon);
fprintf(stdout, " alt: %.2f ", gpx->alt);
//if (gpx->option.vbs)
{
//fprintf(stdout, " (%.1f %.1f %.1f) ", gpx->vN, gpx->vE, gpx->vU);
fprintf(stdout," vH: %4.1f D: %5.1f vV: %3.1f ", gpx->vH, gpx->vD, gpx->vV);
if (gpx->option.vbs == 3) fprintf(stdout," sats: %02d ", gpx->numSV);
return 0;
}
static int prn_sat1(gpx_t *gpx, int ofs) {
fprintf(stdout, "\n");
fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW+ofs));
fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek+ofs));
return 0;
}
const double c = 299.792458e6;
const double L1 = 1575.42e6;
static int prn_sat2(gpx_t *gpx, int ofs) {
int i, n;
int sv;
ui32_t minPR;
fprintf(stdout, "\n");
minPR = u4(gpx->frame+pos_minPR+ofs);
fprintf(stdout, "minPR: %d", minPR);
fprintf(stdout, "\n");
for (i = 0; i < 12; i++) {
n = i*7;
sv = gpx->frame[pos_satsN+ofs+2*i];
if (sv == 0xFF) break;
fprintf(stdout, " SV: %2d ", sv);
//fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]);
fprintf(stdout, "# ");
fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+ofs+n)/100.0 + minPR);
fprintf(stdout, " ");
fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+ofs+n+4)/100.0*L1/c);
fprintf(stdout, "\n");
}
}
if (gpx->option.ptu && !err0) {
fprintf(stderr, " ");
if (gpx->T > -273.0) fprintf(stderr, " T=%.1fC ", gpx->T);
if (gpx->RH > -0.5) fprintf(stderr, " RH=%.0f%% ", gpx->RH);
}
return 0;
}
static int prn_sat3(gpx_t *gpx, int ofs) {
int numSV;
double pDOP, sAcc;
fprintf(stdout, "\n");
fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n",
(i32_t)u4(gpx->frame+pos_GPSecefX+ofs),
(i32_t)u4(gpx->frame+pos_GPSecefY+ofs),
(i32_t)u4(gpx->frame+pos_GPSecefZ+ofs));
fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n",
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+0),
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+2),
(i16_t)u2(gpx->frame+pos_GPSecefV+ofs+4));
numSV = gpx->frame[pos_numSats+ofs];
sAcc = gpx->frame[pos_sAcc+ofs]/10.0; if (gpx->frame[pos_sAcc+ofs] == 0xFF) sAcc = -1.0;
pDOP = gpx->frame[pos_pDOP+ofs]/10.0; if (gpx->frame[pos_pDOP+ofs] == 0xFF) pDOP = -1.0;
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
/*
fprintf(stdout, "CRC: ");
fprintf(stdout, " %04X", pck_GPS1);
if (check_CRC(gpx, pos_GPS1+ofs, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1));
fprintf(stdout, " %04X", pck_GPS2);
if (check_CRC(gpx, pos_GPS2+ofs, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2));
fprintf(stdout, " %04X", pck_GPS3);
if (check_CRC(gpx, pos_GPS3+ofs, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
fprintf(stdout, "\n");
*/
return 0;
}
static int print_position(gpx_t *gpx, int ec) {
int i, j;
int err, err0, err1, err2, err3;
//int output, out_mask;
int encrypted = 0;
int unexp = 0;
int out = 1;
int sat = 0;
int pos_aux = 0, cnt_aux = 0;
//gpx->out = 0;
gpx->aux = 0;
if (gpx->option.sat) sat = 1;
if (gpx->option.slt) out = 0; else out = 1;
if ( ec >= 0 )
{
int pos, blk, len, crc, pck;
if (gpx->option.crc) {
fprintf(stdout, " # ");
if (gpx->option.ecc && ec >= 0 && (gpx->crc & 0x1F) != 0) {
int pos, blk, len, crc; // unexpected blocks
int flen = NDATA_LEN;
int ofs_cal = 0;
int frm_end = NDATA_LEN-2;
if (frametype(gpx) < 0) flen += XDATA_LEN;
switch (gpx->frame[pos_PTU]) {
case 0x7A: // 0x7A2A
frm_end = flen-2;
break;
case 0x7F: // 0x7F1B
frm_end = pos_ZEROstd + 0x1B-0x2A - 2;
break;
case 0x80: // 0x80A7
frm_end = pos_PTU + 2 + 0xA7;
break;
}
pos = pos_FRAME;
gpx->crc = 0;
while (pos < flen-1) {
blk = gpx->frame[pos];
len = gpx->frame[pos+1];
while (pos < flen-1) { // e.g.
blk = gpx->frame[pos]; // 0x80xx: encrypted block
len = gpx->frame[pos+1]; // 0x76xx: 00-padding block
crc = check_CRC(gpx, pos, blk<<8);
pck = (blk<<8) | len;
if ( crc == 0 ) // ecc-OK -> crc-OK
{
int ofs = 0;
switch (pck)
{
case pck_FRAME: // 0x7928
ofs = pos - pos_FRAME;
ofs_cal = ofs;
err = get_FrameConf(gpx, ofs);
if ( !err ) {
if (out || sat) prn_frm(gpx);
fprintf(stdout, " %02X%02X", gpx->frame[pos], gpx->frame[pos+1]);
fprintf(stdout, "[%d]", crc&1);
pos = pos+2+len+2;
}
break;
case pck_PTU: // 0x7A2A
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck_PTU);
if ( 0 && !err0 && gpx->option.ptu ) {
prn_ptu(gpx);
}
break;
case pck_GPS1: // 0x7C1E
ofs = pos - pos_GPS1;
err1 = get_GPS1(gpx, ofs);
if ( !err1 ) {
if (out) prn_gpstime(gpx);
if (sat) prn_sat1(gpx, ofs);
else {
fprintf(stdout, "[");
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx->crc>>i)&1);
fprintf(stdout, "]");
}
break;
case pck_GPS2: // 0x7D59
ofs = pos - pos_GPS2;
err2 = get_GPS2(gpx, ofs);
if ( !err2 ) {
if (sat) prn_sat2(gpx, ofs);
}
break;
case pck_GPS3: // 0x7B15
ofs = pos - pos_GPS3;
err3 = get_GPS3(gpx, ofs);
if ( !err3 ) {
if (out) prn_gpspos(gpx);
if (sat) prn_sat3(gpx, ofs);
}
break;
case pck_SGM_xTU: // 0x7F1B
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck);
break;
case pck_SGM_CRYPT: // 0x80A7
encrypted = 1;
if (out) fprintf(stdout, " [%04X] (RS41-SGM) ", pck_SGM_CRYPT);
break;
default:
if (blk == 0x7E) {
if (pos_aux == 0) pos_aux = pos; // pos == pos_AUX ?
cnt_aux += 1;
}
if (blk == 0x76) {
// ZERO-Padding pck
}
if (blk != 0x76 && blk != 0x7E) {
if (out) fprintf(stdout, " [%04X] ", pck);
unexp = 1;
if (gpx->option.ecc == 2) {
if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)");
else if (ec == -2) fprintf(stdout, " (+-)");
else /*ec == -3*/ fprintf(stdout, " (--)");
}
}
}
else { // CRC-ERROR (ECC-OK)
fprintf(stdout, " [ERROR]\n");
break;
get_Calconf(gpx, output);
if (gpx->option.vbs > 1 || gpx->option.jsn) {
gpx->aux = get_Aux(gpx);
//if (gpx->aux) fprintf(stdout, "\n%d: %s", gpx->aux, gpx->xdata);
}
pos += 2+len+2; // next pck
if ( pos > frm_end ) // end of (sub)frame
{
if (gpx->option.ptu && out && !sat && !err0 && !encrypted) {
prn_ptu(gpx);
}
get_Calconf(gpx, out, ofs_cal);
if (out && ec > 0 && pos > flen-1) fprintf(stdout, " (%d)", ec);
if (pos_aux) gpx->aux = get_Aux(gpx, out && gpx->option.vbs > 1, pos_aux);
gpx->crc = 0;
frm_end = FRAME_LEN-2;
if (out || sat) fprintf(stdout, "\n");
fprintf(stdout, "\n"); // fflush(stdout);
if (gpx->option.jsn) {
// Print out telemetry data as JSON
if ((!err && !err1 && !err3) || (!err && encrypted)) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed
// eigentlich GPS, d.h. UTC = GPS - 18sec (ab 1.1.2017)
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
fprintf(stdout, "{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d",
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd );
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
}
@ -1327,85 +1224,19 @@ static int print_position(gpx_t *gpx, int ec) {
if (gpx->aux) { // <=> gpx->xdata[0]!='\0'
fprintf(stdout, ", \"aux\": \"%s\"", gpx->xdata );
}
if (encrypted) {
fprintf(stdout, ", \"subtype\": \"RS41-SGM\", \"encrypted\": true");
} else {
fprintf(stdout, ", \"subtype\": \"%s\"", *gpx->rstyp ? gpx->rstyp : "RS41" ); // RS41-SG(P/M)
if (strncmp(gpx->rstyp, "RS41-SGM", 8) == 0) {
fprintf(stdout, ", \"encrypted\": false");
}
if (encrypted){
fprintf(stderr, ", \"encrypted\": true");
}
fprintf(stdout, " }\n");
fprintf(stdout, "\n");
}
}
}
}
}
// else
if (ec < 0 && (out || sat /*|| gpx->option.jsn*/)) {
//
// crc-OK pcks ?
//
int pck, ofs;
int output = 0, out_mask;
gpx->crc = 0;
out_mask = crc_FRAME|crc_GPS1|crc_GPS3;
if (gpx->option.ptu) out_mask |= crc_PTU;
err = get_FrameConf(gpx, 0);
if (out && !err) prn_frm(gpx);
pck = (gpx->frame[pos_PTU]<<8) | gpx->frame[pos_PTU+1];
ofs = 0;
if (pck < 0x8000) {
err0 = get_PTU(gpx, 0, pck);
if (pck == pck_PTU) ofs = 0;
else if (pck == pck_SGM_xTU) ofs = 0x1B-0x2A;
err1 = get_GPS1(gpx, ofs);
err2 = get_GPS2(gpx, ofs);
err3 = get_GPS3(gpx, ofs);
if (out) {
if (!err1) prn_gpstime(gpx);
if (!err3) prn_gpspos(gpx);
if (!err0) prn_ptu(gpx);
if (0 && !err) get_Calconf(gpx, out, 0); // only if ecc-OK
output = ((gpx->crc & out_mask) != out_mask);
if (output) {
fprintf(stdout, " ");
fprintf(stdout, "[");
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx->crc>>i)&1);
fprintf(stdout, "]");
}
}
}
else if (pck == pck_SGM_CRYPT) {
if (out && !err) {
fprintf(stdout, " [%04X] (RS41-SGM) ", pck_SGM_CRYPT);
//fprintf(stdout, "[%d] ", check_CRC(gpx, pos_PTU, pck_SGM_CRYPT));
output = 1;
}
}
if (out && output)
{
if (ec == -1) fprintf(stdout, " (-+)");
else if (ec == -2) fprintf(stdout, " (+-)");
else /*ec == -3*/ fprintf(stdout, " (--)");
err |= err1 | err3;
fprintf(stdout, "\n"); // fflush(stdout);
}
}
return 0;
return err;
}
static void print_frame(gpx_t *gpx, int len) {
@ -1436,7 +1267,7 @@ static void print_frame(gpx_t *gpx, int len) {
}
if (gpx->option.ecc) {
if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
if (gpx->option.ecc /*== 2*/) {
if (gpx->option.ecc == 2) {
if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)");
@ -1447,6 +1278,9 @@ static void print_frame(gpx_t *gpx, int len) {
}
fprintf(stdout, "\n");
}
else if (gpx->option.sat) {
get_SatData(gpx);
}
else {
print_position(gpx, ec);
}
@ -1572,8 +1406,8 @@ int main(int argc, char *argv[]) {
fprintf(stderr, " -v, -vx, -vv (info, aux, info/conf)\n");
fprintf(stderr, " -r, --raw\n");
fprintf(stderr, " -i, --invert\n");
//fprintf(stderr, " --crc (check CRC)\n");
//fprintf(stderr, " --ecc2 (Reed-Solomon )\n");
fprintf(stderr, " --crc (check CRC)\n");
fprintf(stderr, " --ecc2 (Reed-Solomon 2-pass)\n");
fprintf(stderr, " --ths <x> (peak threshold; default=%.1f)\n", thres);
fprintf(stderr, " --iq0,2,3 (IQ data)\n");
return 0;
@ -1583,7 +1417,7 @@ int main(int argc, char *argv[]) {
}
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; }
else if (strcmp(*argv, "-vv") == 0) { gpx.option.vbs = 3; }
//else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
else if (strcmp(*argv, "--crc") == 0) { gpx.option.crc = 1; }
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
gpx.option.raw = 1;
@ -1595,7 +1429,6 @@ int main(int argc, char *argv[]) {
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; }
else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; }
else if (strcmp(*argv, "--json") == 0) {
gpx.option.jsn = 1;
gpx.option.ecc = 2;