(test->master) rs41 aux: xdata decoding for ID=0x01 and ID=0x05, no O3-P calculation

pull/47/head
Zilog80 2022-02-06 20:26:03 +01:00
rodzic 6ac06d552b
commit 716496dd7b
1 zmienionych plików z 239 dodań i 2 usunięć

Wyświetl plik

@ -60,6 +60,7 @@ typedef struct {
i8_t sat; // GPS sat data
i8_t ptu; // PTU: temperature humidity (pressure)
i8_t dwp; // PTU derived: dew point
i8_t aux; // decode xdata
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
@ -1063,12 +1064,217 @@ static int get_GPS3(gpx_t *gpx, int ofs) {
return err;
}
static int hex2uint(char *str, int nibs) {
int i;
int erg = 0;
int h = 0;
if (nibs > 7) return -2;
for (i = 0; i < nibs; i++) { // MSB i.e. most significant nibble first
if (str[i] >= '0' && str[i] <= '9') h = str[i]-'0';
else if (str[i] >= 'a' && str[i] <= 'f') h = str[i]-'a'+0xA;
else if (str[i] >= 'A' && str[i] <= 'F') h = str[i]-'A'+0xA;
else return -1;
erg = (erg << 4) | (h & 0xF);
}
return erg;
}
static int prn_aux_IDx01(char *xdata) {
// V7 ECC (Electrochemical Concentration Cell) Ozonesonde
// https://gml.noaa.gov/aftp/user/jordan/iMet%20Radiosonde%20Protocol.pdf
// https://harbor.weber.edu/Hardware/Ozonesonde/ECC_Ozonesonde-1.pdf
// ID=0x01: ECC Ozonesonde
// N=2*8 nibs (1byte = 2nibs) (MSB)
// 0 2 u8 Instrument_type = 0x01 (ID)
// 2 2 u8 Instrument_number
// 4 4 u16 Icell, uA (I = n/1000)
// 8 4 i16 Tpump, C (T = n/100)
// 12 2 u8 Ipump, mA
// 14 2 u8 Vbat, (V = n/10)
//
int val;
i16_t Tpump;
ui16_t Icell;
ui8_t InstrNum, Ipump, Vbat;
char *px = xdata;
int N = 2*8;
if (*px) {
if (strncmp(px, "01", 2) != 0) {
px = strstr(xdata, "#01");
if (px == NULL) return -1;
else px += 1;
}
if (strlen(px) < N) return -1;
fprintf(stdout, " ID=0x01 ECC ");
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
InstrNum = val & 0xFF;
val = hex2uint(px+ 4, 4); if (val < 0) return -1;
Icell = val & 0xFFFF; // u16
val = hex2uint(px+ 8, 4); if (val < 0) return -1;
Tpump = val & 0xFFFF; // i16
val = hex2uint(px+12, 2); if (val < 0) return -1;
Ipump = val & 0xFF; // u8
val = hex2uint(px+14, 2); if (val < 0) return -1;
Vbat = val & 0xFF; // u8
fprintf(stdout, " No.%d ", InstrNum);
fprintf(stdout, " Icell:%.3fuA ", Icell/1000.0);
fprintf(stdout, " Tpump:%.2fC ", Tpump/100.0);
fprintf(stdout, " Ipump:%dmA ", Ipump);
fprintf(stdout, " Vbat:%.1fV ", Vbat/10.0);
}
else {
return -2;
}
return 0;
}
static int prn_aux_IDx05(char *xdata) {
// OIF411
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide M211486EN
//
// ID=0x05: OIF411
// pos nibs (MSB)
// 0 2 u8 Instrument_type = 0x05 (ID)
// 2 2 u8 Instrument_number
// Measurement Data, N=2*10
// 4 4 i16 Tpump, C (T = n/100)
// 8 5 u20 Icell, uA (I = n/10000)
// 13 2 u8 Vbat, (V = n/10)
// 15 3 u12 Ipump, mA
// 18 2 u8 Vext, (V = n/10)
// ID Data, N=2*10+1
// 4 8 char OIF411 Serial
// 12 4 u16 Diagnostics Word
// 16 2?4 u16? SW version (n/100)
// 20 1 char I
//
char *px = xdata;
int N = 2*10;
int val;
ui8_t InstrNum;
if (*px) {
if (strncmp(px, "05", 2) != 0) {
px = strstr(xdata, "#05");
if (px == NULL) return -1;
else px += 1;
}
if (strlen(px) < N) return -1;
fprintf(stdout, " ID=0x05 OIF411 ");
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
InstrNum = val & 0xFF;
fprintf(stdout, " No.%d ", InstrNum);
if (px[N] == 'I') {
ui16_t dw;
ui16_t sw;
char sn[9];
// 5.2 ID Data
//
N += 1;
strncpy(sn, px+4, 8); sn[8] = '\0';
val = hex2uint(px+12, 4); if (val < 0) return -1;
dw = val & 0xFFFF; // i16
val = hex2uint(px+16, 4); if (val < 0) return -1;
sw = val & 0xFFFF; // u8
fprintf(stdout, " SN:%s ", sn);
fprintf(stdout, " DW:%04X ", dw);
fprintf(stdout, " SW:%.2f ", sw/100.0);
// Diagnostics Word dw
// 0000 = "Default value, no diagnostics bits active"
// 0004 = "Ozone pump temperature below -5C"
// 0400 = "Ozone pump battery voltage (+VBatt) is not connected to OIF411"
// 0404 = 0004 | 0400
}
else {
ui32_t Icell;
ui16_t Ipump;
i16_t Tpump;
ui8_t InstrNum, Vbat, Vext;
// 5.1 Measurement Data
//
val = hex2uint(px+ 4, 4); if (val < 0) return -1;
Tpump = val & 0xFFFF; // i16
val = hex2uint(px+ 8, 5); if (val < 0) return -1;
Icell = val & 0xFFFFF; // u20
val = hex2uint(px+13, 2); if (val < 0) return -1;
Vbat = val & 0xFF; // u8
val = hex2uint(px+15, 3); if (val < 0) return -1;
Ipump = val & 0xFFF; // u12
val = hex2uint(px+18, 2); if (val < 0) return -1;
Vext = val & 0xFF; // u8
fprintf(stdout, " Tpump:%.2fC ", Tpump/100.0);
fprintf(stdout, " Icell:%.4fuA ", Icell/10000.0);
fprintf(stdout, " Vbat:%.1fV ", Vbat/10.0);
fprintf(stdout, " Ipump:%dmA ", Ipump);
fprintf(stdout, " Vext:%.1fV ", Vext/10.0);
}
}
else {
return -2;
}
return 0;
}
static int prn_aux_IDx08(char *xdata) {
// CFH Cryogenic Frost Point Hygrometer
// ID=0x08: CFH
// N=2*12 nibs
// 0 2 u8 Instrument_type = 0x08 (ID)
// 2 2 u8 Instrument_number
// 4 6 Tmir, Mirror Temperature
// 10 6 Vopt, Optics Voltage
// 16 4 Topt, Optics Temperature
// 20 4 Vbat, CFH Battery
//
char *px = xdata;
int N = 2*12;
int val;
ui8_t InstrNum;
if (*px) {
if (strncmp(px, "08", 2) != 0) {
px = strstr(xdata, "#08");
if (px == NULL) return -1;
else px += 1;
}
if (strlen(px) < N) return -1;
fprintf(stdout, " ID=0x08 CFH ");
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
InstrNum = val & 0xFF;
fprintf(stdout, " No.%d ", InstrNum);
fprintf(stdout, " Tmir:0x%.6s ", px+4);
fprintf(stdout, " Vopt:0x%.6s ", px+10);
fprintf(stdout, " Topt:0x%.4s ", px+16);
fprintf(stdout, " Vbat:0x%.4s ", px+20);
}
else {
return -2;
}
return 0;
}
static int get_Aux(gpx_t *gpx, int out, int pos) {
//
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide M211486EN
//
int auxlen, auxcrc, count7E, pos7E;
int i, n;
char *paux;
n = 0;
count7E = 0;
@ -1113,6 +1319,34 @@ static int get_Aux(gpx_t *gpx, int out, int pos) {
}
gpx->xdata[n] = '\0';
// decode OIF411 xdata
paux = gpx->xdata;
if (out && gpx->option.aux && *paux)
{
int val;
ui8_t ID;
for (i = 0; i < count7E; i++) {
if (paux > gpx->xdata) {
//while (paux < (gpx->xdata)+n && *paux != '#') paux++;
while (*paux && *paux != '#') paux++;
paux++;
}
if (strlen(paux) > 2) {
val = hex2uint(paux, 2);
if (val < 0) { paux += 2; continue; }
ID = val & 0xFF;
switch (ID) {
case 0x01: fprintf(stdout, "\n"); prn_aux_IDx01(paux); break;
case 0x05: fprintf(stdout, "\n"); prn_aux_IDx05(paux); break;
case 0x08: fprintf(stdout, "\n"); prn_aux_IDx08(paux); break;
}
paux++;
}
else break;
}
if ( !gpx->option.jsn ) fprintf(stdout, "\n");
}
i = check_CRC(gpx, pos, pck_ZERO); // 0x76xx: 00-padding block
if (i) gpx->crc |= crc_ZERO;
@ -2095,9 +2329,10 @@ int main(int argc, char *argv[]) {
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
gpx.option.vbs = 1;
}
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; }
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; } // xdata
else if (strcmp(*argv, "-vv") == 0) { gpx.option.vbs = 3; }
//else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
else if (strcmp(*argv, "--aux") == 0) { gpx.option.aux = 1; }
else if (strcmp(*argv, "--crc") == 0) { gpx.option.crc = 1; }
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
gpx.option.raw = 1;
@ -2221,6 +2456,8 @@ int main(int argc, char *argv[]) {
rs_init_RS255(&gpx.RS); // RS, GF
}
if (gpx.option.aux) gpx.option.vbs = 2;
// init gpx
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes