Ais27::Ais27(const char *nmea_payload, const size_t pad) { assert(nmea_payload); assert(0==pad); init(); const size_t num_bits = strlen(nmea_payload) * 6 - pad; assert(96==num_bits); if (96 != num_bits) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<96> bs; status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (27 != message_id) {status = AIS_ERR_WRONG_MSG_TYPE; return;} repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); position_accuracy = bs[38]; raim = bs[39]; nav_status = ubits(bs, 40, 4); x = sbits(bs, 44, 18) / 600.; y = sbits(bs, 62, 17) / 600.; sog = ubits(bs,79,6); cog = ubits(bs,85,9); gnss = !bs[94]; spare = bs[95]; }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf Ais8_200_40::Ais8_200_40(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 40); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 168) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } x = (float)(sbits(bs, 56, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, 84, 27) / 600000.0);//Crouse:Added typecasting form = ubits(bs, 111, 4); dir = ubits(bs, 115, 9); // degrees stream_dir = ubits(bs, 124, 3); status_raw = ubits(bs, 127, 30); // TODO(schwehr): status[ ] = bite me; spare2 = ubits(bs, 157, 11); status = AIS_OK; }
Ais8_366_22_Sector::Ais8_366_22_Sector(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; radius_m = ubits(bs,offset+5+28+27,12) * scale_multipliers[scale_factor]; left_bound_deg = ubits(bs, offset+5+28+27+12, 9); right_bound_deg = ubits(bs, offset+5+28+27+12+9, 9); }
Ais8_366_22_Circle::Ais8_366_22_Circle(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; // TODO: precision? And bit counts for radius and spare? radius_m = ubits(bs,offset+5+28+27,12) * scale_multipliers[scale_factor]; spare = ubits(bs,offset+5+28+27+12,16); }
Ais8_366_22_Sector::Ais8_366_22_Sector(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = (float)(sbits(bs, offset + 5, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 33, 27) / 600000.0);//Crouse:Added typecasting radius_m = ubits(bs, offset + 60, 12) * scale_multipliers[scale_factor]; left_bound_deg = ubits(bs, offset + 72, 9); right_bound_deg = ubits(bs, offset + 81, 9); }
Ais8_1_26_Location::Ais8_1_26_Location(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { x = (float)(sbits(bs, offset, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 28, 27) / 600000.0);//Crouse:Added typecasting z = (float)(ubits(bs, offset + 55, 11) / 10.0);//Crouse:Added typecasting owner = ubits(bs, offset + 66, 4); timeout = ubits(bs, offset + 70, 3); spare = ubits(bs, offset + 73, 12); }
Ais8_366_22_Rect::Ais8_366_22_Rect(const std::bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs,offset+3,2); x = sbits(bs, offset+5, 28) / 600000.; y = sbits(bs, offset+5+28, 27) / 600000.; e_dim_m = ubits(bs, offset+5+28+27, 8) * scale_multipliers[scale_factor]; n_dim_m = ubits(bs, offset+5+28+27+8, 8) * scale_multipliers[scale_factor]; orient_deg = ubits(bs, offset+5+28+27+8+8, 9); spare = ubits(bs, offset+5+28+27+8+8+9, 5); }
Ais21::Ais21(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 21); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // TODO(schwehr): make this more careful than 272-360 if (num_bits < 272 || num_bits > 360) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<360> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } aton_type = ubits(bs, 38, 5); name = ais_str(bs, 43, 120); position_accuracy = bs[163]; x = sbits(bs, 164, 28) / 600000.; y = sbits(bs, 192, 27) / 600000.; dim_a = ubits(bs, 219, 9); dim_b = ubits(bs, 228, 9); dim_c = ubits(bs, 237, 6); dim_d = ubits(bs, 243, 6); fix_type = ubits(bs, 249, 4); timestamp = ubits(bs, 253, 6); off_pos = bs[259]; aton_status = ubits(bs, 260, 8); raim = bs[268]; virtual_aton = bs[269]; assigned_mode = bs[270]; spare = bs[271]; const size_t extra_total_bits = num_bits - 272; const size_t extra_chars = extra_total_bits / 6; const size_t extra_char_bits = extra_chars * 6; const size_t extra_bits = extra_total_bits % 6; if (extra_chars > 0) { name += ais_str(bs, 272, extra_char_bits); } if (extra_bits > 0) { spare2 = ubits(bs, 272 + extra_char_bits, extra_bits); } else { spare2 = 0; } status = AIS_OK; }
Ais8_366_22_Rect::Ais8_366_22_Rect(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = (float)(sbits(bs, offset + 5, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, offset + 33, 27) / 600000.0);//Crouse:Added typecasting e_dim_m = ubits(bs, offset + 60, 8) * scale_multipliers[scale_factor]; n_dim_m = ubits(bs, offset + 68, 8) * scale_multipliers[scale_factor]; orient_deg = ubits(bs, offset + 76, 9); spare = ubits(bs, offset + 85, 5); }
Ais8_366_22_Circle::Ais8_366_22_Circle(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { const int scale_factor = ubits(bs, offset + 3, 2); x = sbits(bs, offset + 5, 28) / 600000.; y = sbits(bs, offset + 33, 27) / 600000.; // TODO(schwehr): precision? And bit counts for radius and spare? // TODO(schwehr): collapse these numbers radius_m = ubits(bs, offset + 60, 12) * scale_multipliers[scale_factor]; spare = ubits(bs, offset + 72, 16); }
Ais21::Ais21(const char *nmea_payload, const int pad) { assert(nmea_payload); init(); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // 272-360 - FIX: make this more careful if (272 > num_bits || num_bits > 360) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<360> bs; // 360 % 6 == 0 -> 60 NMEA characters exactly status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (message_id != 21) {status = AIS_ERR_WRONG_MSG_TYPE; return;} repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); aton_type = ubits(bs,38,5); name = ais_str(bs, 43, 120); position_accuracy = bs[163]; x = sbits(bs, 164, 28) / 600000.; y = sbits(bs, 192, 27) / 600000.; dim_a = ubits(bs, 219, 9); dim_b = ubits(bs, 228, 9); dim_c = ubits(bs, 237, 6); dim_d = ubits(bs, 243, 6); fix_type = ubits(bs, 249, 4); timestamp = ubits(bs, 253, 6); off_pos = bool(bs[259]); aton_status = ubits(bs, 260, 8); raim = bool(bs[268]); virtual_aton = bool(bs[269]); assigned_mode = bool(bs[270]); spare = bs[271]; const size_t extra_total_bits = num_bits - 272; const size_t extra_chars = extra_total_bits / 6; const size_t extra_char_bits = extra_chars * 6; const size_t extra_bits = extra_total_bits % 6; if (extra_chars > 0) { name += ais_str(bs,272,extra_char_bits); } if (extra_bits > 0) { spare2 = ubits(bs,272+extra_char_bits, extra_bits); } else { spare2 = 0; } }
Ais8_1_26_Wx::Ais8_1_26_Wx(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { air_temp = (float)(sbits(bs, offset, 11) / 10.0);//Crouse:Added typecasting air_temp_sensor_type = ubits(bs, offset + 11, 3); precip = ubits(bs, offset + 14, 2); horz_vis = (float)(ubits(bs, offset + 16, 8) / 10.0);//Crouse:Added typecasting dew_point = (float)(sbits(bs, offset + 24, 10) / 10.0);//Crouse:Added typecasting dew_point_type = ubits(bs, offset + 34, 3); air_pressure = ubits(bs, offset + 37, 9)+799;//Crouse: added the +800 to put it into hectoPascals air_pressure_trend = ubits(bs, offset + 46, 2); air_pressor_type = ubits(bs, offset + 48, 3); salinity = (float)(ubits(bs, offset + 51, 9) / 10.0);//Crouse:Added typecasting spare = ubits(bs, offset + 60, 25); }
// TODO: pad Ais22::Ais22(const char *nmea_payload) { assert(nmea_payload); init(); const int num_char = std::strlen(nmea_payload); if (28 != num_char) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<168> bs; status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (message_id != 22) { status = AIS_ERR_WRONG_MSG_TYPE; return; } repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); spare = ubits(bs,38,2); chan_a = ubits(bs,40,12); chan_b = ubits(bs,52,12); txrx_mode = ubits(bs, 64, 4); power_low = bs[68]; // WARNING: OUT OF ORDER DECODE bool addressed = bs[139]; if (not(addressed)) { // geographic position pos_valid = true; dest_valid = false; x1 = sbits(bs, 69, 28) / 600000.; y1 = sbits(bs, 87, 27) / 600000.; x2 = sbits(bs, 104, 28) / 600000.; y2 = sbits(bs, 122, 27) / 600000.; } else { pos_valid = false; dest_valid = true; dest_mmsi_1 = ubits(bs, 69, 30); // TODO: save the 5 spare bits dest_mmsi_2 = ubits(bs, 104, 30); // TODO: save the 5 spare bits } // OUT OF ORDER: addressed is before chan_a_bandwidth = bs[140]; chan_b_bandwidth = bs[141]; zone_size = ubits(bs, 142, 3); spare2 = ubits(bs, 145, 23); }
Ais8_1_26_WaterLevel::Ais8_1_26_WaterLevel(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { type = bs[offset]; level = (float)(sbits(bs, offset + 1, 16) / 100.0);//Crouse:Added typecasting trend = ubits(bs, offset + 17, 2); vdatum = ubits(bs, offset + 19, 5); sensor_type = ubits(bs, offset + 24, 3); forcast_type = bs[offset + 27]; level_forcast = (float)(sbits(bs, offset + 28, 16) / 100.0);//Crouse:Added typecasting utc_day_forcast = ubits(bs, offset + 44, 5); utc_hour_forcast = ubits(bs, offset + 49, 5); utc_min_forcast = ubits(bs, offset + 54, 6); duration = ubits(bs, offset + 60, 8); spare = ubits(bs, offset + 68, 17); }
// River Information Systems ECE-TRANS-SC3-2006-10r-RIS.pdf Ais8_200_23::Ais8_200_23(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 200); assert(fi == 23); const size_t num_bits = strlen(nmea_payload) * 6 - pad; if (num_bits != 256) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<256> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } utc_year_start = ubits(bs, 56, 9); utc_month_start = ubits(bs, 65, 4); utc_day_start = ubits(bs, 69, 4); // ERROR: not enough bits to cover 1-31 utc_year_end = ubits(bs, 73, 9); utc_month_end = ubits(bs, 82, 4); utc_day_end = ubits(bs, 86, 4); // ERROR: not enough bits to cover 1-31 utc_hour_start = ubits(bs, 90, 5); utc_min_start = ubits(bs, 95, 6); utc_hour_end = ubits(bs, 101, 5); utc_min_end = ubits(bs, 106, 6); x1 = (float)(sbits(bs, 112, 28) / 600000.0);//Crouse:Added typecasting y1 = (float)(sbits(bs, 140, 27) / 600000.0);//Crouse:Added typecasting x2 = (float)(sbits(bs, 167, 28) / 600000.0);//Crouse:Added typecasting y2 = (float)(sbits(bs, 195, 27) / 600000.0);//Crouse:Added typecasting type = ubits(bs, 222, 4); min = ubits(bs, 226, 9); max = ubits(bs, 235, 9); classification = ubits(bs, 244, 2); wind_dir = ubits(bs, 246, 4); spare2 = ubits(bs, 250, 6); status = AIS_OK; }
int fetchrq(tchar *tp) { if (ismot(tp[0]) || !isxfunc(tp[0], RQ)) return 0; return sbits(tp[0]); }
// IMO Circ 289 - Route information // See also Circ 236 Ais8_1_27::Ais8_1_27(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 27); const size_t num_bits = strlen(nmea_payload) * 6 - pad; const size_t num_waypoints = (num_bits - 117) / 55; const size_t extra_bits = (num_bits - 117) % 55; if (extra_bits || num_waypoints > 16) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<997> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } link_id = ubits(bs, 56, 10); sender_type = ubits(bs, 66, 3); route_type = ubits(bs, 69, 5); utc_month = ubits(bs, 74, 4); utc_day = ubits(bs, 78, 5); utc_hour = ubits(bs, 83, 5); utc_min = ubits(bs, 88, 6); duration = ubits(bs, 94, 18); // TODO(schwehr): manage the case where num_waypoints does not match // const size_t num_waypoints_stated = ubits(bs, 112, 5); for (size_t waypoint_num = 0; waypoint_num < num_waypoints; waypoint_num++) { AisPoint pt; const size_t start = 117 + 55*waypoint_num; pt.x = (float)(sbits(bs, start, 28) / 600000.0);//Crouse: Added typecasting pt.y = (float)(sbits(bs, start + 28, 27) / 600000.0);//Crouse: Added typecasting waypoints.push_back(pt); } status = AIS_OK; }
// TODO: pad Ais19::Ais19(const char *nmea_payload) { assert(nmea_payload); init(); if (strlen(nmea_payload) != 52) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<312> bs; status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (19 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return; } repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); spare = ubits(bs,38,8); sog = ubits(bs,46,10) / 10.; position_accuracy = bs[56]; x = sbits(bs, 57, 28) / 600000.; y = sbits(bs, 85, 27) / 600000.; cog = ubits(bs, 112, 12) / 10.; true_heading = ubits(bs, 124, 9); timestamp = ubits(bs, 133, 6); spare2 = ubits(bs, 139, 4); name = ais_str(bs, 143, 120); type_and_cargo = ubits(bs, 263, 8); dim_a = ubits(bs, 271, 9); dim_b = ubits(bs, 280, 9); dim_c = ubits(bs, 289, 6); dim_d = ubits(bs, 295, 6); fix_type = ubits(bs, 301, 4); raim = bs[305]; dte = bs[306]; assigned_mode = bs[307]; spare3 = ubits(bs,308,4); }
// IMO Circ 289 - Marine traffic signal Ais8_1_19::Ais8_1_19(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 19); const size_t num_bits = strlen(nmea_payload) * 6 - pad; // Some people transmit without the idiodic spare padding if (num_bits != 258 && num_bits != 360) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<360> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } link_id = ubits(bs, 56, 10); name = ais_str(bs, 66, 120); x = (float)(sbits(bs, 186, 25) / 60000.0);//Crouse: Added typecasting y = (float)(sbits(bs, 211, 24) / 60000.0);//Crouse: Added typecasting status = ubits(bs, 235, 2); signal = ubits(bs, 237, 5); utc_hour_next = ubits(bs, 242, 5); utc_min_next = ubits(bs, 247, 6); next_signal = ubits(bs, 253, 5); if (num_bits != 360) return; spare2[0] = ubits(bs, 258, 32); spare2[1] = ubits(bs, 290, 32); spare2[2] = ubits(bs, 322, 32); spare2[3] = ubits(bs, 354, 6); status = AIS_OK; }
// IMO Circ 289 - VTS Generated/Synthetic Targets // See also Circ 236 Ais8_1_17::Ais8_1_17(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 17); const size_t num_bits = strlen(nmea_payload) * 6 - pad; const size_t num_targets = (num_bits - 56) / 120; const size_t extra_bits = (num_bits - 56) % 120; if (extra_bits || num_targets > 4) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<536> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } for (size_t target_num = 0; target_num < num_targets; target_num++) { Ais8_1_17_Target target; const size_t start = 56 + (120 * target_num); target.type = ubits(bs, start, 2); target.id = ais_str(bs, start + 2, 42); target.spare = ubits(bs, start + 44, 4); target.y = (float)(sbits(bs, start + 48, 24) / 60000.0); // booo - lat, lon //Crouse: Added typecasting target.x = (float)(sbits(bs, start + 72, 25) / 60000.0);//Crouse: Added typecasting target.cog = ubits(bs, start + 97, 9); target.timestamp = ubits(bs, start + 106, 6); target.sog = ubits(bs, start + 112, 8); } status = AIS_OK; }
Ais8_1_26_SeaState::Ais8_1_26_SeaState(const bitset<AIS8_MAX_BITS> &bs, const size_t offset) { swell_height = (float)(ubits(bs, offset, 8) / 10.0);//Crouse:Added typecasting swell_period = ubits(bs, offset + 8, 6); swell_dir = ubits(bs, offset + 14, 9); sea_state = ubits(bs, offset + 23, 4); swell_sensor_type = ubits(bs, offset + 27, 3); water_temp = (float)(sbits(bs, offset + 30, 10) / 10.0);//Crouse:Added typecasting water_temp_depth = (float)(ubits(bs, offset + 40, 7) / 10.0);//Crouse:Added typecasting water_sensor_type = ubits(bs, offset + 47, 3); wave_height = (float)(ubits(bs, offset + 50, 8) / 10.0);//Crouse:Added typecasting wave_period = ubits(bs, offset + 58, 6); wave_dir = ubits(bs, offset + 64, 9); wave_sensor_type = ubits(bs, offset + 73, 3); salinity = (float)(ubits(bs, offset + 76, 9) / 10.0);//Crouse:Added typecasting }
void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, unsigned char *cpack, g2int *lcpack) /*$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: misspack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2000-06-21 // // ABSTRACT: This subroutine packs up a data field using a complex // packing algorithm as defined in the GRIB2 documention. It // supports GRIB2 complex packing templates with or without // spatial differences (i.e. DRTs 5.2 and 5.3). // It also fills in GRIB2 Data Representation Template 5.2 or 5.3 // with the appropriate values. // This version assumes that Missing Value Management is being used and that // 1 or 2 missing values appear in the data. // // PROGRAM HISTORY LOG: // 2000-06-21 Gilbert // // USAGE: misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, // unsigned char *cpack, g2int *lcpack) // INPUT ARGUMENT LIST: // fld[] - Contains the data values to pack // ndpts - The number of data values in array fld[] // idrsnum - Data Representation Template number 5.N // Must equal 2 or 3. // idrstmpl - Contains the array of values for Data Representation // Template 5.2 or 5.3 // [0] = Reference value - ignored on input // [1] = Binary Scale Factor // [2] = Decimal Scale Factor // . // . // [6] = Missing value management // [7] = Primary missing value // [8] = Secondary missing value // . // . // [16] = Order of Spatial Differencing ( 1 or 2 ) // . // . // // OUTPUT ARGUMENT LIST: // idrstmpl - Contains the array of values for Data Representation // Template 5.3 // [0] = Reference value - set by misspack routine. // [1] = Binary Scale Factor - unchanged from input // [2] = Decimal Scale Factor - unchanged from input // . // . // cpack - The packed data field (character*1 array) // *lcpack - length of packed field cpack(). // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$*/ { g2int *ifld, *ifldmiss, *jfld; g2int *jmin, *jmax, *lbit; static g2int zero=0; g2int *gref, *gwidth, *glen; g2int glength, grpwidth; g2int i, n, iofst, imin, ival1, ival2, isd, minsd, nbitsd; g2int nbitsgref, left, iwmax, ngwidthref, nbitsgwidth, ilmax; g2int nglenref, nglenlast, nbitsglen, ij; g2int j, missopt, nonmiss, itemp, maxorig, nbitorig, miss1, miss2; g2int ngroups, ng, num0, num1, num2; g2int imax, lg, mtemp, ier, igmax; g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref; g2float rmissp, rmisss, bscale, dscale, rmin, temp; static g2int simple_alg = 0; static g2float alog2=0.69314718; /* ln(2.0) */ static g2int one=1; bscale=int_power(2.0,-idrstmpl[1]); dscale=int_power(10.0,idrstmpl[2]); missopt=idrstmpl[6]; if ( missopt != 1 && missopt != 2 ) { printf("misspack: Unrecognized option.\n"); *lcpack=-1; return; } else { /* Get missing values */ g2_rdieee(idrstmpl+7,&rmissp,1); if (missopt == 2) g2_rdieee(idrstmpl+8,&rmisss,1); } /* // Find min value of non-missing values in the data, // AND set up missing value mapping of the field. */ ifldmiss = calloc(ndpts,sizeof(g2int)); rmin=1E+37; if ( missopt == 1 ) { /* Primary missing value only */ for ( j=0; j<ndpts; j++) { if (fld[j] == rmissp) { ifldmiss[j]=1; } else { ifldmiss[j]=0; if (fld[j] < rmin) rmin=fld[j]; } } } if ( missopt == 2 ) { /* Primary and secondary missing values */ for ( j=0; j<ndpts; j++ ) { if (fld[j] == rmissp) { ifldmiss[j]=1; } else if (fld[j] == rmisss) { ifldmiss[j]=2; } else { ifldmiss[j]=0; if (fld[j] < rmin) rmin=fld[j]; } } } /* // Allocate work arrays: // Note: -ifldmiss[j],j=0,ndpts-1 is a map of original field indicating // which of the original data values // are primary missing (1), sencondary missing (2) or non-missing (0). // -jfld[j],j=0,nonmiss-1 is a subarray of just the non-missing values // from the original field. */ /*if (rmin != rmax) { */ iofst=0; ifld = calloc(ndpts,sizeof(g2int)); jfld = calloc(ndpts,sizeof(g2int)); gref = calloc(ndpts,sizeof(g2int)); gwidth = calloc(ndpts,sizeof(g2int)); glen = calloc(ndpts,sizeof(g2int)); /* // Scale original data */ nonmiss=0; if (idrstmpl[1] == 0) { /* No binary scaling */ imin=(g2int)rint(rmin*dscale); /*imax=(g2int)rint(rmax*dscale); */ rmin=(g2float)imin; for ( j=0; j<ndpts; j++) { if (ifldmiss[j] == 0) { jfld[nonmiss]=(g2int)rint(fld[j]*dscale)-imin; nonmiss++; } } } else { /* Use binary scaling factor */ rmin=rmin*dscale; /*rmax=rmax*dscale; */ for ( j=0; j<ndpts; j++ ) { if (ifldmiss[j] == 0) { jfld[nonmiss]=(g2int)rint(((fld[j]*dscale)-rmin)*bscale); nonmiss++; } } } /* // Calculate Spatial differences, if using DRS Template 5.3 */ if (idrsnum == 3) { /* spatial differences */ if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=2; if (idrstmpl[16] == 1) { /* first order */ ival1=jfld[0]; for ( j=nonmiss-1; j>0; j--) jfld[j]=jfld[j]-jfld[j-1]; jfld[0]=0; } else if (idrstmpl[16] == 2) { /* second order */ ival1=jfld[0]; ival2=jfld[1]; for ( j=nonmiss-1; j>1; j--) jfld[j]=jfld[j]-(2*jfld[j-1])+jfld[j-2]; jfld[0]=0; jfld[1]=0; } /* // subtract min value from spatial diff field */ isd=idrstmpl[16]; minsd=jfld[isd]; for ( j=isd; j<nonmiss; j++ ) if ( jfld[j] < minsd ) minsd=jfld[j]; for ( j=isd; j<nonmiss; j++ ) jfld[j]=jfld[j]-minsd; /* // find num of bits need to store minsd and add 1 extra bit // to indicate sign */ temp=log((double)(abs(minsd)+1))/alog2; nbitsd=(g2int)ceil(temp)+1; /* // find num of bits need to store ifld[0] ( and ifld[1] // if using 2nd order differencing ) */ maxorig=ival1; if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2; temp=log((double)(maxorig+1))/alog2; nbitorig=(g2int)ceil(temp)+1; if (nbitorig > nbitsd) nbitsd=nbitorig; /* increase number of bits to even multiple of 8 ( octet ) */ if ( (nbitsd%8) != 0) nbitsd=nbitsd+(8-(nbitsd%8)); /* // Store extra spatial differencing info into the packed // data section. */ if (nbitsd != 0) { /* pack first original value */ if (ival1 >= 0) { sbit(cpack,&ival1,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival1); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } if (idrstmpl[16] == 2) { /* pack second original value */ if (ival2 >= 0) { sbit(cpack,&ival2,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival2); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } /* pack overall min of spatial differences */ if (minsd >= 0) { sbit(cpack,&minsd,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(minsd); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } /*print *,'SDp ',ival1,ival2,minsd,nbitsd*/ } /* end of spatial diff section */ /* // Expand non-missing data values to original grid. */ miss1=jfld[0]; for ( j=0; j<nonmiss; j++) if (jfld[j] < miss1) miss1 = jfld[j]; miss1--; miss2=miss1-1; n=0; for ( j=0; j<ndpts; j++) { if ( ifldmiss[j] == 0 ) { ifld[j]=jfld[n]; n++; } else if ( ifldmiss[j] == 1 ) { ifld[j]=miss1; } else if ( ifldmiss[j] == 2 ) { ifld[j]=miss2; } } /* // Determine Groups to be used. */ if ( simple_alg == 1 ) { /* set group length to 10 : calculate number of groups */ /* and length of last group */ ngroups=ndpts/10; for (j=0;j<ngroups;j++) glen[j]=10; itemp=ndpts%10; if (itemp != 0) { ngroups++; glen[ngroups-1]=itemp; } } else { /* Use Dr. Glahn's algorithm for determining grouping. */ kfildo=6; minpk=10; inc=1; maxgrps=(ndpts/minpk)+1; jmin = calloc(maxgrps,sizeof(g2int)); jmax = calloc(maxgrps,sizeof(g2int)); lbit = calloc(maxgrps,sizeof(g2int)); g2_pack_gp(&kfildo,ifld,&ndpts,&missopt,&minpk,&inc,&miss1,&miss2, jmin,jmax,lbit,glen,&maxgrps,&ngroups,&ibit,&jbit, &kbit,&novref,&lbitref,&ier); /*printf("SAGier = %d %d %d %d %d %d\n",ier,ibit,jbit,kbit,novref,lbitref);*/ for ( ng=0; ng<ngroups; ng++) glen[ng]=glen[ng]+novref; free(jmin); free(jmax); free(lbit); } /* // For each group, find the group's reference value (min) // and the number of bits needed to hold the remaining values */ n=0; for ( ng=0; ng<ngroups; ng++) { /* how many of each type? */ num0=num1=num2=0; for (j=n; j<n+glen[ng]; j++) { if (ifldmiss[j] == 0 ) num0++; if (ifldmiss[j] == 1 ) num1++; if (ifldmiss[j] == 2 ) num2++; } if ( num0 == 0 ) { /* all missing values */ if ( num1 == 0 ) { /* all secondary missing */ gref[ng]=-2; gwidth[ng]=0; } else if ( num2 == 0 ) { /* all primary missing */ gref[ng]=-1; gwidth[ng]=0; } else { /* both primary and secondary */ gref[ng]=0; gwidth[ng]=1; } } else { /* contains some non-missing data */ /* find max and min values of group */ gref[ng]=2147483647; imax=-2147483647; j=n; for ( lg=0; lg<glen[ng]; lg++ ) { if ( ifldmiss[j] == 0 ) { if (ifld[j] < gref[ng]) gref[ng]=ifld[j]; if (ifld[j] > imax) imax=ifld[j]; } j++; } if (missopt == 1) imax=imax+1; if (missopt == 2) imax=imax+2; /* calc num of bits needed to hold data */ if ( gref[ng] != imax ) { temp=log((double)(imax-gref[ng]+1))/alog2; gwidth[ng]=(g2int)ceil(temp); } else { gwidth[ng]=0; } } /* Subtract min from data */ j=n; mtemp=(g2int)int_power(2.,gwidth[ng]); for ( lg=0; lg<glen[ng]; lg++ ) { if (ifldmiss[j] == 0) /* non-missing */ ifld[j]=ifld[j]-gref[ng]; else if (ifldmiss[j] == 1) /* primary missing */ ifld[j]=mtemp-1; else if (ifldmiss[j] == 2) /* secondary missing */ ifld[j]=mtemp-2; j++; } /* increment fld array counter */ n=n+glen[ng]; } /* // Find max of the group references and calc num of bits needed // to pack each groups reference value, then // pack up group reference values */ /*printf(" GREFS: "); */ /*for (j=0;j<ngroups;j++) printf(" %d",gref[j]); printf("\n"); */ igmax=gref[0]; for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j]; if (missopt == 1) igmax=igmax+1; if (missopt == 2) igmax=igmax+2; if (igmax != 0) { temp=log((double)(igmax+1))/alog2; nbitsgref=(g2int)ceil(temp); /* reset the ref values of any "missing only" groups. */ mtemp=(g2int)int_power(2.,nbitsgref); for ( j=0; j<ngroups; j++ ) { if (gref[j] == -1) gref[j]=mtemp-1; if (gref[j] == -2) gref[j]=mtemp-2; } sbits(cpack,gref,iofst,nbitsgref,0,ngroups); itemp=nbitsgref*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary, */ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsgref=0; } /* // Find max/min of the group widths and calc num of bits needed // to pack each groups width value, then // pack up group width values */ /*write(77,*)'GWIDTHS: ',(gwidth(j),j=1,ngroups)*/ iwmax=gwidth[0]; ngwidthref=gwidth[0]; for (j=1;j<ngroups;j++) { if (gwidth[j] > iwmax) iwmax=gwidth[j]; if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j]; } if (iwmax != ngwidthref) { temp=log((double)(iwmax-ngwidthref+1))/alog2; nbitsgwidth=(g2int)ceil(temp); for ( i=0; i<ngroups; i++) gwidth[i]=gwidth[i]-ngwidthref; sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups); itemp=nbitsgwidth*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary,*/ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsgwidth=0; for (i=0;i<ngroups;i++) gwidth[i]=0; } /* // Find max/min of the group lengths and calc num of bits needed // to pack each groups length value, then // pack up group length values */ /*printf(" GLENS: ");*/ /*for (j=0;j<ngroups;j++) printf(" %d",glen[j]); printf("\n");*/ ilmax=glen[0]; nglenref=glen[0]; for (j=1;j<ngroups-1;j++) { if (glen[j] > ilmax) ilmax=glen[j]; if (glen[j] < nglenref) nglenref=glen[j]; } nglenlast=glen[ngroups-1]; if (ilmax != nglenref) { temp=log((double)(ilmax-nglenref+1))/alog2; nbitsglen=(g2int)ceil(temp); for ( i=0; i<ngroups-1; i++) glen[i]=glen[i]-nglenref; sbits(cpack,glen,iofst,nbitsglen,0,ngroups); itemp=nbitsglen*ngroups; iofst=iofst+itemp; /* Pad last octet with Zeros, if necessary,*/ if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsglen=0; for (i=0;i<ngroups;i++) glen[i]=0; } /* // For each group, pack data values */ /*write(77,*)'IFLDS: ',(ifld(j),j=1,ndpts)*/ n=0; ij=0; for ( ng=0; ng<ngroups; ng++) { glength=glen[ng]+nglenref; if (ng == (ngroups-1) ) glength=nglenlast; grpwidth=gwidth[ng]+ngwidthref; /*write(77,*)'NGP ',ng,grpwidth,glength,gref(ng)*/ if ( grpwidth != 0 ) { sbits(cpack,ifld+n,iofst,grpwidth,0,glength); iofst=iofst+(grpwidth*glength); } /* do kk=1,glength*/ /* ij=ij+1*/ /*write(77,*)'SAG ',ij,fld(ij),ifld(ij),gref(ng),bscale,rmin,dscale*/ /* enddo*/ n=n+glength; } /* Pad last octet with Zeros, if necessary,*/ if ( (iofst%8) != 0) { left=8-(iofst%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } *lcpack=iofst/8; if ( ifld != 0 ) free(ifld); free(jfld); if ( ifldmiss != 0 ) free(ifldmiss); free(gref); free(gwidth); free(glen); /*} //else { // Constant field ( max = min ) // nbits=0; // *lcpack=0; // nbitsgref=0; // ngroups=0; }*/ /* // Fill in ref value and number of bits in Template 5.2 */ mkieee(&rmin,idrstmpl+0,1); /* ensure reference value is IEEE format*/ idrstmpl[3]=nbitsgref; idrstmpl[4]=0; /* original data were reals*/ idrstmpl[5]=1; /* general group splitting*/ idrstmpl[9]=ngroups; /* Number of groups*/ idrstmpl[10]=ngwidthref; /* reference for group widths*/ idrstmpl[11]=nbitsgwidth; /* num bits used for group widths*/ idrstmpl[12]=nglenref; /* Reference for group lengths*/ idrstmpl[13]=1; /* length increment for group lengths*/ idrstmpl[14]=nglenlast; /* True length of last group*/ idrstmpl[15]=nbitsglen; /* num bits used for group lengths*/ if (idrsnum == 3) { idrstmpl[17]=nbitsd/8; /* num bits used for extra spatial*/ /* differencing values*/ } }
Ais18::Ais18(const char *nmea_payload) { assert(nmea_payload); init(); if (strlen(nmea_payload) != 168/6) { status = AIS_ERR_BAD_BIT_COUNT; return; } std::bitset<168> bs; // 1 slot status = aivdm_to_bits(bs, nmea_payload); if (had_error()) return; message_id = ubits(bs, 0, 6); if (18 != message_id) { status = AIS_ERR_WRONG_MSG_TYPE; return; } repeat_indicator = ubits(bs,6,2); mmsi = ubits(bs,8,30); spare = ubits(bs,38,8); sog = ubits(bs,46,10) / 10.; position_accuracy = ubits(bs,56,1); x = sbits(bs, 57, 28) / 600000.; y = sbits(bs, 85, 27) / 600000.; cog = ubits(bs, 112, 12) / 10.; true_heading = ubits(bs, 124, 9); timestamp = ubits(bs, 133, 6); spare2 = ubits(bs, 139, 2); unit_flag = bs[141]; display_flag = bs[142]; dsc_flag = bs[143]; band_flag = bs[144]; m22_flag = bs[145]; mode_flag = bs[146]; raim = bool(bs[147]); commstate_flag = bs[148]; // 0 SOTDMA, 1 ITDMA // FIX: set all to -1 and set valids to NOT! if (1 == unit_flag) { // CS - carrier sense - fixed commstate payload of 1100000000000000110 int commstate = ubits(bs,149, 19); //std::cout << "\tcs commstate: " << commstate << std::endl; if (393222 != commstate) { // FIX: is this the right value? // FIX: return an error? } } else { sync_state = ubits(bs, 149, 2); if (0 == commstate_flag) { // SOTDMA slot_timeout = ubits(bs,151,3); switch (slot_timeout) { case 0: slot_offset = ubits(bs, 154, 14); slot_offset_valid = true; break; case 1: utc_hour = ubits(bs, 154, 5); utc_min = ubits(bs, 159, 7); utc_spare = ubits(bs, 166, 2); utc_valid = true; break; case 2: // FALLTHROUGH case 4: // FALLTHROUGH case 6: slot_number = ubits(bs, 154, 14); slot_number_valid = true; break; case 3: // FALLTHROUGH case 5: // FALLTHROUGH case 7: received_stations = ubits(bs, 154, 14); received_stations_valid = true; break; default: assert (false); } } else { // ITDMA slot_increment = ubits(bs, 151, 13); slot_increment_valid = true; slots_to_allocate = ubits(bs, 164, 3); slots_to_allocate_valid = true; keep_flag = bool(bs[167]); keep_flag_valid = true; } } }
void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl, unsigned char *cpack,g2int *lcpack) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: compack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-07 // // ABSTRACT: This subroutine packs up a data field using a complex // packing algorithm as defined in the GRIB2 documentation. It // supports GRIB2 complex packing templates with or without // spatial differences (i.e. DRTs 5.2 and 5.3). // It also fills in GRIB2 Data Representation Template 5.2 or 5.3 // with the appropriate values. // // PROGRAM HISTORY LOG: // 2002-11-07 Gilbert // // USAGE: void compack(g2float *fld,g2int ndpts,g2int idrsnum, // g2int *idrstmpl,unsigned char *cpack,g2int *lcpack) // // INPUT ARGUMENTS: // fld[] - Contains the data values to pack // ndpts - The number of data values in array fld[] // idrsnum - Data Representation Template number 5.N // Must equal 2 or 3. // idrstmpl - Contains the array of values for Data Representation // Template 5.2 or 5.3 // [0] = Reference value - ignored on input // [1] = Binary Scale Factor // [2] = Decimal Scale Factor // . // . // [6] = Missing value management // [7] = Primary missing value // [8] = Secondary missing value // . // . // [16] = Order of Spatial Differencing ( 1 or 2 ) // . // . // // OUTPUT ARGUMENTS: // idrstmpl - Contains the array of values for Data Representation // Template 5.3 // [0] = Reference value - set by compack routine. // [1] = Binary Scale Factor - unchanged from input // [2] = Decimal Scale Factor - unchanged from input // . // . // cpack - The packed data field // lcpack - length of packed field cpack. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$ { const g2int zero=0; g2int *ifld,*gref,*glen,*gwidth; g2int *jmin, *jmax, *lbit; g2int i,j,n, /* nbits, */ imin,imax,left; g2int isd,itemp,ilmax,ngwidthref=0,nbitsgwidth=0; g2int nglenref=0,nglenlast=0,iofst,ival1,ival2; g2int minsd,nbitsd=0,maxorig,nbitorig,ngroups; g2int lg,ng,igmax,iwmax,nbitsgref; g2int glength,grpwidth,nbitsglen=0; g2int kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref; g2int missopt, miss1, miss2, ier; g2float bscale,dscale,rmax,rmin,temp; const g2int simple_alg = 0; const g2float alog2=0.69314718f; // ln(2.0) const g2int one=1; bscale=(float)int_power(2.0,-idrstmpl[1]); dscale=(float)int_power(10.0,idrstmpl[2]); // // Find max and min values in the data // rmax=fld[0]; rmin=fld[0]; for (j=1;j<ndpts;j++) { if (fld[j] > rmax) rmax=fld[j]; if (fld[j] < rmin) rmin=fld[j]; } // // If max and min values are not equal, pack up field. // If they are equal, we have a constant field, and the reference // value (rmin) is the value for each point in the field and // set nbits to 0. // if (rmin != rmax) { iofst=0; ifld=calloc(ndpts,sizeof(g2int)); gref=calloc(ndpts,sizeof(g2int)); gwidth=calloc(ndpts,sizeof(g2int)); glen=calloc(ndpts,sizeof(g2int)); // // Scale original data // if (idrstmpl[1] == 0) { // No binary scaling imin=(g2int)RINT(rmin*dscale); //imax=(g2int)rint(rmax*dscale); rmin=(g2float)imin; for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(fld[j]*dscale)-imin; } else { // Use binary scaling factor rmin=rmin*dscale; //rmax=rmax*dscale; for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); } // // Calculate spatial differences, if using DRS Template 5.3. // if (idrsnum == 3) { // spatial differences if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=1; if (idrstmpl[16] == 1) { // first order ival1=ifld[0]; for (j=ndpts-1;j>0;j--) ifld[j]=ifld[j]-ifld[j-1]; ifld[0]=0; } else if (idrstmpl[16] == 2) { // second order ival1=ifld[0]; ival2=ifld[1]; for (j=ndpts-1;j>1;j--) ifld[j]=ifld[j]-(2*ifld[j-1])+ifld[j-2]; ifld[0]=0; ifld[1]=0; } // // subtract min value from spatial diff field // isd=idrstmpl[16]; minsd=ifld[isd]; for (j=isd;j<ndpts;j++) if ( ifld[j] < minsd ) minsd=ifld[j]; for (j=isd;j<ndpts;j++) ifld[j]=ifld[j]-minsd; // // find num of bits need to store minsd and add 1 extra bit // to indicate sign // temp=(float)(log((double)(abs(minsd)+1))/alog2); nbitsd=(g2int)ceil(temp)+1; // // find num of bits need to store ifld[0] ( and ifld[1] // if using 2nd order differencing ) // maxorig=ival1; if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2; temp=(float)(log((double)(maxorig+1))/alog2); nbitorig=(g2int)ceil(temp)+1; if (nbitorig > nbitsd) nbitsd=nbitorig; // increase number of bits to even multiple of 8 ( octet ) if ( (nbitsd%8) != 0) nbitsd=nbitsd+(8-(nbitsd%8)); // // Store extra spatial differencing info into the packed // data section. // if (nbitsd != 0) { // pack first original value if (ival1 >= 0) { sbit(cpack,&ival1,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival1); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } if (idrstmpl[16] == 2) { // pack second original value if (ival2 >= 0) { sbit(cpack,&ival2,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(ival2); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } // pack overall min of spatial differences if (minsd >= 0) { sbit(cpack,&minsd,iofst,nbitsd); iofst=iofst+nbitsd; } else { sbit(cpack,&one,iofst,1); iofst=iofst+1; itemp=abs(minsd); sbit(cpack,&itemp,iofst,nbitsd-1); iofst=iofst+nbitsd-1; } } //printf("SDp %ld %ld %ld %ld\n",ival1,ival2,minsd,nbitsd); } // end of spatial diff section // // Determine Groups to be used. // if ( simple_alg == 1 ) { // set group length to 10; calculate number of groups // and length of last group ngroups=ndpts/10; for (j=0;j<ngroups;j++) glen[j]=10; itemp=ndpts%10; if (itemp != 0) { ngroups=ngroups+1; glen[ngroups-1]=itemp; } } else { // Use Dr. Glahn's algorithm for determining grouping. // kfildo=6; minpk=10; inc=1; maxgrps=(ndpts/minpk)+1; jmin = calloc(maxgrps,sizeof(g2int)); jmax = calloc(maxgrps,sizeof(g2int)); lbit = calloc(maxgrps,sizeof(g2int)); missopt=0; pack_gp(&kfildo,ifld,&ndpts,&missopt,&minpk,&inc,&miss1,&miss2, jmin,jmax,lbit,glen,&maxgrps,&ngroups,&ibit,&jbit, &kbit,&novref,&lbitref,&ier); //print *,'SAGier = ',ier,ibit,jbit,kbit,novref,lbitref for ( ng=0; ng<ngroups; ng++) glen[ng]=glen[ng]+novref; free(jmin); free(jmax); free(lbit); } // // For each group, find the group's reference value // and the number of bits needed to hold the remaining values // n=0; for (ng=0;ng<ngroups;ng++) { // find max and min values of group gref[ng]=ifld[n]; imax=ifld[n]; j=n+1; for (lg=1;lg<glen[ng];lg++) { if (ifld[j] < gref[ng]) gref[ng]=ifld[j]; if (ifld[j] > imax) imax=ifld[j]; j++; } // calc num of bits needed to hold data if ( gref[ng] != imax ) { temp=(float)(log((double)(imax-gref[ng]+1))/alog2); gwidth[ng]=(g2int)ceil(temp); } else gwidth[ng]=0; // Subtract min from data j=n; for (lg=0;lg<glen[ng];lg++) { ifld[j]=ifld[j]-gref[ng]; j++; } // increment fld array counter n=n+glen[ng]; } // // Find max of the group references and calc num of bits needed // to pack each groups reference value, then // pack up group reference values // igmax=gref[0]; for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j]; if (igmax != 0) { temp=(float)(log((double)(igmax+1))/alog2); nbitsgref=(g2int)ceil(temp); sbits(cpack,gref,iofst,nbitsgref,0,ngroups); itemp=nbitsgref*ngroups; iofst=iofst+itemp; // Pad last octet with Zeros, if necessary, if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else nbitsgref=0; // // Find max/min of the group widths and calc num of bits needed // to pack each groups width value, then // pack up group width values // iwmax=gwidth[0]; ngwidthref=gwidth[0]; for (j=1;j<ngroups;j++) { if (gwidth[j] > iwmax) iwmax=gwidth[j]; if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j]; } if (iwmax != ngwidthref) { temp=(float)(log((double)(iwmax-ngwidthref+1))/alog2); nbitsgwidth=(g2int)ceil(temp); for (i=0;i<ngroups;i++) gwidth[i]=gwidth[i]-ngwidthref; sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups); itemp=nbitsgwidth*ngroups; iofst=iofst+itemp; // Pad last octet with Zeros, if necessary, if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsgwidth=0; for (i=0;i<ngroups;i++) gwidth[i]=0; } // // Find max/min of the group lengths and calc num of bits needed // to pack each groups length value, then // pack up group length values // //write(77,*)'GLENS: ',(glen(j),j=1,ngroups) ilmax=glen[0]; nglenref=glen[0]; for (j=1;j<ngroups-1;j++) { if (glen[j] > ilmax) ilmax=glen[j]; if (glen[j] < nglenref) nglenref=glen[j]; } nglenlast=glen[ngroups-1]; if (ilmax != nglenref) { temp=(float)(log((double)(ilmax-nglenref+1))/alog2); nbitsglen=(g2int)ceil(temp); for (i=0;i<ngroups-1;i++) glen[i]=glen[i]-nglenref; sbits(cpack,glen,iofst,nbitsglen,0,ngroups); itemp=nbitsglen*ngroups; iofst=iofst+itemp; // Pad last octet with Zeros, if necessary, if ( (itemp%8) != 0) { left=8-(itemp%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } } else { nbitsglen=0; for (i=0;i<ngroups;i++) glen[i]=0; } // // For each group, pack data values // n=0; for (ng=0;ng<ngroups;ng++) { glength=glen[ng]+nglenref; if (ng == (ngroups-1) ) glength=nglenlast; grpwidth=gwidth[ng]+ngwidthref; if ( grpwidth != 0 ) { sbits(cpack,ifld+n,iofst,grpwidth,0,glength); iofst=iofst+(grpwidth*glength); } n=n+glength; } // Pad last octet with Zeros, if necessary, if ( (iofst%8) != 0) { left=8-(iofst%8); sbit(cpack,&zero,iofst,left); iofst=iofst+left; } *lcpack=iofst/8; // if ( ifld!=0 ) free(ifld); if ( gref!=0 ) free(gref); if ( gwidth!=0 ) free(gwidth); if ( glen!=0 ) free(glen); } else { // Constant field ( max = min ) /* nbits=0; */ *lcpack=0; nbitsgref=0; ngroups=0; } // // Fill in ref value and number of bits in Template 5.2 // mkieee(&rmin,idrstmpl+0,1); // ensure reference value is IEEE format idrstmpl[3]=nbitsgref; idrstmpl[4]=0; // original data were reals idrstmpl[5]=1; // general group splitting idrstmpl[6]=0; // No internal missing values idrstmpl[7]=0; // Primary missing value idrstmpl[8]=0; // secondary missing value idrstmpl[9]=ngroups; // Number of groups idrstmpl[10]=ngwidthref; // reference for group widths idrstmpl[11]=nbitsgwidth; // num bits used for group widths idrstmpl[12]=nglenref; // Reference for group lengths idrstmpl[13]=1; // length increment for group lengths idrstmpl[14]=nglenlast; // True length of last group idrstmpl[15]=nbitsglen; // num bits used for group lengths if (idrsnum == 3) { idrstmpl[17]=nbitsd/8; // num bits used for extra spatial // differencing values } }
void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int *lcpack) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: simpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-06 // // ABSTRACT: This subroutine packs up a data field using the simple // packing algorithm as defined in the GRIB2 documentation. It // also fills in GRIB2 Data Representation Template 5.0 with the // appropriate values. // // PROGRAM HISTORY LOG: // 2002-11-06 Gilbert // // USAGE: CALL simpack(fld,ndpts,idrstmpl,cpack,lcpack) // INPUT ARGUMENT LIST: // fld[] - Contains the data values to pack // ndpts - The number of data values in array fld[] // idrstmpl - Contains the array of values for Data Representation // Template 5.0 // [0] = Reference value - ignored on input // [1] = Binary Scale Factor // [2] = Decimal Scale Factor // [3] = Number of bits used to pack data, if value is // > 0 and <= 31. // If this input value is 0 or outside above range // then the num of bits is calculated based on given // data and scale factors. // [4] = Original field type - currently ignored on input // Data values assumed to be reals. // // OUTPUT ARGUMENT LIST: // idrstmpl - Contains the array of values for Data Representation // Template 5.0 // [0] = Reference value - set by simpack routine. // [1] = Binary Scale Factor - unchanged from input // [2] = Decimal Scale Factor - unchanged from input // [3] = Number of bits used to pack data, unchanged from // input if value is between 0 and 31. // If this input value is 0 or outside above range // then the num of bits is calculated based on given // data and scale factors. // [4] = Original field type - currently set = 0 on output. // Data values assumed to be reals. // cpack - The packed data field // lcpack - length of packed field starting at cpack. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$ { const g2int zero=0; g2int *ifld; g2int j,nbits,imin,imax,maxdif,nbittot,left; g2float bscale,dscale,rmax,rmin,temp; double maxnum; const g2float alog2=0.69314718f; // ln(2.0) bscale=(float)int_power(2.0,-idrstmpl[1]); dscale=(float)int_power(10.0,idrstmpl[2]); if (idrstmpl[3] <= 0 || idrstmpl[3] > 31) nbits=0; else nbits=idrstmpl[3]; // // Find max and min values in the data // rmax=fld[0]; rmin=fld[0]; for (j=1;j<ndpts;j++) { if (fld[j] > rmax) rmax=fld[j]; if (fld[j] < rmin) rmin=fld[j]; } ifld=calloc(ndpts,sizeof(g2int)); // // If max and min values are not equal, pack up field. // If they are equal, we have a constant field, and the reference // value (rmin) is the value for each point in the field and // set nbits to 0. // if (rmin != rmax) { // // Determine which algorithm to use based on user-supplied // binary scale factor and number of bits. // if (nbits==0 && idrstmpl[1]==0) { // // No binary scaling and calculate minimum number of // bits in which the data will fit. // imin=(g2int)RINT(rmin*dscale); imax=(g2int)RINT(rmax*dscale); maxdif=imax-imin; temp=(float)(log((double)(maxdif+1))/alog2); nbits=(g2int)ceil(temp); rmin=(g2float)imin; // scale data for(j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(fld[j]*dscale)-imin; } else if (nbits!=0 && idrstmpl[1]==0) { // // Use minimum number of bits specified by user and // adjust binary scaling factor to accommodate data. // rmin=rmin*dscale; rmax=rmax*dscale; maxnum=int_power(2.0,nbits)-1; temp=(float)(log(maxnum/(rmax-rmin))/alog2); idrstmpl[1]=(g2int)ceil(-1.0*temp); bscale=(float)int_power(2.0,-idrstmpl[1]); // scale data for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); } else if (nbits==0 && idrstmpl[1]!=0) { // // Use binary scaling factor and calculate minimum number of // bits in which the data will fit. // rmin=rmin*dscale; rmax=rmax*dscale; maxdif=(g2int)RINT((rmax-rmin)*bscale); temp=(float)(log((double)(maxdif+1))/alog2); nbits=(g2int)ceil(temp); // scale data for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); } else if (nbits!=0 && idrstmpl[1]!=0) { // // Use binary scaling factor and use minimum number of // bits specified by user. Dangerous - may loose // information if binary scale factor and nbits not set // properly by user. // rmin=rmin*dscale; // scale data for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); } // // Pack data, Pad last octet with Zeros, if necessary, // and calculate the length of the packed data in bytes // sbits(cpack,ifld+0,0,nbits,0,ndpts); nbittot=nbits*ndpts; left=8-(nbittot%8); if (left != 8) { sbit(cpack,&zero,nbittot,left); // Pad with zeros to fill Octet nbittot=nbittot+left; } *lcpack=nbittot/8; } else { nbits=0; *lcpack=0; } // // Fill in ref value and number of bits in Template 5.0 // //printf("SAGmkieee %f\n",rmin); mkieee(&rmin,idrstmpl+0,1); // ensure reference value is IEEE format //printf("SAGmkieee %ld\n",idrstmpl[0]); idrstmpl[3]=nbits; idrstmpl[4]=0; // original data were reals free(ifld); }
g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflist,g2int idefnum) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: g2_addgrid // PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-11-01 // // ABSTRACT: This routine packs up a Grid Definition Section (Section 3) // and adds it to a GRIB2 message. It is used with routines "g2_create", // "g2_addlocal", "g2_addfield", // and "g2_gribend" to create a complete GRIB2 message. // g2_create must be called first to initialize a new GRIB2 message. // // PROGRAM HISTORY LOG: // 2002-11-01 Gilbert // 2009-01-14 Vuong Changed structure name template to gtemplate // // USAGE: int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl, // g2int *ideflist,g2int idefnum) // INPUT ARGUMENTS: // cgrib - Char array that contains the GRIB2 message to which // section should be added. // igds - Contains information needed for GRIB Grid Definition Section 3 // Must be dimensioned >= 5. // igds[0]=Source of grid definition (see Code Table 3.0) // igds[1]=Number of grid points in the defined grid. // igds[2]=Number of octets needed for each // additional grid points definition. // Used to define number of // points in each row ( or column ) for // non-regular grids. // = 0, if using regular grid. // igds[3]=Interpretation of list for optional points // definition. (Code Table 3.11) // igds[4]=Grid Definition Template Number (Code Table 3.1) // igdstmpl - Contains the data values for the specified Grid Definition // Template ( NN=igds[4] ). Each element of this integer // array contains an entry (in the order specified) of Grid // Defintion Template 3.NN // ideflist - (Used if igds[2] != 0) This array contains the // number of grid points contained in each row ( or column ) // idefnum - (Used if igds[2] != 0) The number of entries // in array ideflist. i.e. number of rows ( or columns ) // for which optional grid points are defined. // // OUTPUT ARGUMENTS: // cgrib - Char array to contain the updated GRIB2 message. // Must be allocated large enough to store the entire // GRIB2 message. // // RETURN VALUES: // ierr - Return code. // > 0 = Current size of updated GRIB2 message // -1 = GRIB message was not initialized. Need to call // routine gribcreate first. // -2 = GRIB message already complete. Cannot add new section. // -3 = Sum of Section byte counts doesn't add to total byte count // -4 = Previous Section was not 1, 2 or 7. // -5 = Could not find requested Grid Definition Template. // // REMARKS: Note that the Grid Def Section ( Section 3 ) can only follow // Section 1, 2 or Section 7 in a GRIB2 message. // // ATTRIBUTES: // LANGUAGE: C // MACHINE: // //$$$ { g2int ierr; static unsigned char G=0x47; // 'G' static unsigned char R=0x52; // 'R' static unsigned char I=0x49; // 'I' static unsigned char B=0x42; // 'B' static unsigned char seven=0x37; // '7' static g2int one=1,three=3,miss=65535; g2int lensec3,iofst,ibeg,lencurr,len; g2int i,j,temp,ilen,isecnum,nbits; gtemplate *mapgrid=0; ierr=0; // // Check to see if beginning of GRIB message exists // if ( cgrib[0]!=G || cgrib[1]!=R || cgrib[2]!=I || cgrib[3]!=B ) { // printf("g2_addgrid: GRIB not found in given message.\n"); // printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB messge.\n"); ierr=-1; return(ierr); } // // Get current length of GRIB message // gbit(cgrib,&lencurr,96,32); // // Check to see if GRIB message is already complete // if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven && cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) { // printf("g2_addgrid: GRIB message already complete. Cannot add new section.\n"); ierr=-2; return(ierr); } // // Loop through all current sections of the GRIB message to // find the last section number. // len=16; // length of Section 0 for (;;) { // Get section number and length of next section iofst=len*8; gbit(cgrib,&ilen,iofst,32); iofst=iofst+32; gbit(cgrib,&isecnum,iofst,8); len=len+ilen; // Exit loop if last section reached if ( len == lencurr ) break; // If byte count for each section doesn't match current // total length, then there is a problem. if ( len > lencurr ) { // printf("g2_addgrid: Section byte counts don''t add to total.\n"); // printf("g2_addgrid: Sum of section byte counts = %ld\n",len); // printf("g2_addgrid: Total byte count in Section 0 = %ld\n",lencurr); ierr=-3; return(ierr); } } // // Section 3 can only be added after sections 1, 2 and 7. // if ( (isecnum!=1) && (isecnum!=2) && (isecnum!=7) ) { // printf("g2_addgrid: Section 3 can only be added after Section 1, 2 or 7.\n"); // printf("g2_addgrid: Section ',isecnum,' was the last found in given GRIB message.\n"); ierr=-4; return(ierr); } // // Add Section 3 - Grid Definition Section // ibeg=lencurr*8; // Calculate offset for beginning of section 3 iofst=ibeg+32; // leave space for length of section sbit(cgrib,&three,iofst,8); // Store section number ( 3 ) iofst=iofst+8; sbit(cgrib,igds+0,iofst,8); // Store source of Grid def. iofst=iofst+8; sbit(cgrib,igds+1,iofst,32); // Store number of data pts. iofst=iofst+32; sbit(cgrib,igds+2,iofst,8); // Store number of extra octets. iofst=iofst+8; sbit(cgrib,igds+3,iofst,8); // Store interp. of extra octets. iofst=iofst+8; // if Octet 6 is not equal to zero, Grid Definition Template may // not be supplied. if ( igds[0] == 0 ) sbit(cgrib,igds+4,iofst,16); // Store Grid Def Template num. else sbit(cgrib,&miss,iofst,16); // Store missing value as Grid Def Template num. iofst=iofst+16; // // Get Grid Definition Template // if (igds[0] == 0) { mapgrid=getgridtemplate(igds[4]); if (mapgrid == 0) { // undefined template ierr=-5; return(ierr); } // // Extend the Grid Definition Template, if necessary. // The number of values in a specific template may vary // depending on data specified in the "static" part of the // template. // if ( mapgrid->needext ) { free(mapgrid); mapgrid=extgridtemplate(igds[4],igdstmpl); } } // // Pack up each input value in array igdstmpl into the // the appropriate number of octets, which are specified in // corresponding entries in array mapgrid. // for (i=0;i<mapgrid->maplen;i++) { nbits=abs(mapgrid->map[i])*8; if ( (mapgrid->map[i] >= 0) || (igdstmpl[i] >= 0) ) sbit(cgrib,igdstmpl+i,iofst,nbits); else { sbit(cgrib,&one,iofst,1); temp=abs(igdstmpl[i]); sbit(cgrib,&temp,iofst+1,nbits-1); } iofst=iofst+nbits; } // Pack template extension, if appropriate j=mapgrid->maplen; if ( mapgrid->needext && (mapgrid->extlen > 0) ) { for (i=0;i<mapgrid->extlen;i++) { nbits=abs(mapgrid->ext[i])*8; if ( (mapgrid->ext[i] >= 0) || (igdstmpl[j] >= 0) ) sbit(cgrib,igdstmpl+j,iofst,nbits); else { sbit(cgrib,&one,iofst,1); temp=abs(igdstmpl[j]); sbit(cgrib,&temp,iofst+1,nbits-1); } iofst=iofst+nbits; j++; } } free(mapgrid); // // If requested, // Insert optional list of numbers defining number of points // in each row or column. This is used for non regular // grids. // if ( igds[2] != 0 ) { nbits=igds[2]*8; sbits(cgrib,ideflist,iofst,nbits,0,idefnum); iofst=iofst+(nbits*idefnum); } // // Calculate length of section 3 and store it in octets // 1-4 of section 3. // lensec3=(iofst-ibeg)/8; sbit(cgrib,&lensec3,ibeg,32); // // Update current byte total of message in Section 0 // lencurr+=lensec3; sbit(cgrib,&lencurr,96,32); return(lencurr); }
void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl, unsigned char *cpack,g2int *lcpack) //$$$ SUBPROGRAM DOCUMENTATION BLOCK // . . . . // SUBPROGRAM: pngpack // PRGMMR: Gilbert ORG: W/NP11 DATE: 2003-08-27 // // ABSTRACT: This subroutine packs up a data field into PNG image format. // After the data field is scaled, and the reference value is subtracted out, // it is treated as a grayscale image and passed to a PNG encoder. // It also fills in GRIB2 Data Representation Template 5.41 or 5.40010 with // the appropriate values. // // PROGRAM HISTORY LOG: // 2003-08-27 Gilbert // // USAGE: pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl, // unsigned char *cpack,g2int *lcpack); // INPUT ARGUMENT LIST: // fld[] - Contains the data values to pack // width - number of points in the x direction // height - number of points in the y direction // idrstmpl - Contains the array of values for Data Representation // Template 5.41 or 5.40010 // [0] = Reference value - ignored on input // [1] = Binary Scale Factor // [2] = Decimal Scale Factor // [3] = number of bits for each data value - ignored on input // [4] = Original field type - currently ignored on input // Data values assumed to be reals. // // OUTPUT ARGUMENT LIST: // idrstmpl - Contains the array of values for Data Representation // Template 5.41 or 5.40010 // [0] = Reference value - set by pngpack routine. // [1] = Binary Scale Factor - unchanged from input // [2] = Decimal Scale Factor - unchanged from input // [3] = Number of bits containing each grayscale pixel value // [4] = Original field type - currently set = 0 on output. // Data values assumed to be reals. // cpack - The packed data field // lcpack - length of packed field cpack. // // REMARKS: None // // ATTRIBUTES: // LANGUAGE: C // MACHINE: IBM SP // //$$$ { g2int *ifld; const g2float alog2=0.69314718f; // ln(2.0) g2int j,nbits,imin,imax,maxdif; g2int ndpts,nbytes; g2float bscale,dscale,rmax,rmin,temp; unsigned char *ctemp; ifld=0; ndpts=width*height; bscale=(g2float)int_power(2.0,-idrstmpl[1]); dscale=(g2float)int_power(10.0,idrstmpl[2]); // // Find max and min values in the data // rmax=fld[0]; rmin=fld[0]; for (j=1;j<ndpts;j++) { if (fld[j] > rmax) rmax=fld[j]; if (fld[j] < rmin) rmin=fld[j]; } maxdif = (g2int)RINT( (rmax-rmin)*dscale*bscale ); // // If max and min values are not equal, pack up field. // If they are equal, we have a constant field, and the reference // value (rmin) is the value for each point in the field and // set nbits to 0. // if (rmin != rmax && maxdif != 0 ) { ifld=(g2int *)malloc(ndpts*sizeof(g2int)); // // Determine which algorithm to use based on user-supplied // binary scale factor and number of bits. // if (idrstmpl[1] == 0) { // // No binary scaling and calculate minimum number of // bits in which the data will fit. // imin=(g2int)RINT(rmin*dscale); imax=(g2int)RINT(rmax*dscale); maxdif=imax-imin; temp=(g2float)log((double)(maxdif+1))/alog2; nbits=(g2int)ceil(temp); rmin=(g2float)imin; // scale data for(j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(fld[j]*dscale)-imin; } else { // // Use binary scaling factor and calculate minimum number of // bits in which the data will fit. // rmin=rmin*dscale; rmax=rmax*dscale; maxdif=(g2int)RINT((rmax-rmin)*bscale); temp=(g2float)log((double)(maxdif+1))/alog2; nbits=(g2int)ceil(temp); // scale data for (j=0;j<ndpts;j++) ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale); } // // Pack data into full octets, then do PNG encode. // and calculate the length of the packed data in bytes // if (nbits <= 8) { nbits=8; } else if (nbits <= 16) { nbits=16; } else if (nbits <= 24) { nbits=24; } else { nbits=32; } nbytes=(nbits/8)*ndpts; ctemp=calloc(nbytes,1); sbits(ctemp,ifld,0,nbits,0,ndpts); // // Encode data into PNG Format. // *lcpack=(g2int)enc_png((char *)ctemp,width,height,nbits,(char *)cpack); if (*lcpack <= 0) { printf("pngpack: ERROR Packing PNG = %d\n",(int)*lcpack); } free(ctemp); } else { nbits=0; *lcpack=0; } // // Fill in ref value and number of bits in Template 5.0 // mkieee(&rmin,idrstmpl+0,1); // ensure reference value is IEEE format idrstmpl[3]=nbits; idrstmpl[4]=0; // original data were reals if (ifld != 0) free(ifld); }
Ais9::Ais9(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 9); if (pad != 0 || strlen(nmea_payload) != 28) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } alt = ubits(bs, 38, 12); sog = (float)(ubits(bs, 50, 10) / 10.0);//Crouse:Added typecasting position_accuracy = bs[60]; x = (float)(sbits(bs, 61, 28) / 600000.0);//Crouse:Added typecasting y = (float)(sbits(bs, 89, 27) / 600000.0);//Crouse:Added typecasting cog = (float)(ubits(bs, 116, 12) / 10.0);//Crouse:Added typecasting timestamp = ubits(bs, 128, 6); alt_sensor = bs[134]; spare = ubits(bs, 135, 7); dte = bs[142]; spare2 = ubits(bs, 143, 3); assigned_mode = bs[146]; raim = bs[147]; commstate_flag = bs[148]; // 0 SOTDMA, 1 ITDMA sync_state = ubits(bs, 149, 2); #ifndef NDEBUG slot_timeout = -1; received_stations = slot_number = utc_hour = utc_min = utc_spare -1; slot_offset = slot_increment = slots_to_allocate = -1; keep_flag = false; #endif slot_timeout_valid = false; received_stations_valid = false; slot_number_valid = false; utc_valid = false; slot_offset_valid = false; slot_increment_valid = false; slots_to_allocate_valid = false; keep_flag_valid = false; if (0 == commstate_flag) { // SOTDMA slot_timeout = ubits(bs, 151, 3); slot_timeout_valid = true; switch (slot_timeout) { case 0: slot_offset = ubits(bs, 154, 14); slot_offset_valid = true; break; case 1: utc_hour = ubits(bs, 154, 5); utc_min = ubits(bs, 159, 7); utc_spare = ubits(bs, 166, 2); utc_valid = true; break; case 2: // FALLTHROUGH case 4: // FALLTHROUGH case 6: slot_number = ubits(bs, 154, 14); slot_number_valid = true; break; case 3: // FALLTHROUGH case 5: // FALLTHROUGH case 7: received_stations = ubits(bs, 154, 14); received_stations_valid = true; break; default: assert(false); } } else { // ITDMA slot_increment = ubits(bs, 151, 13); slot_increment_valid = true; slots_to_allocate = ubits(bs, 164, 3); slots_to_allocate_valid = true; keep_flag = bs[167]; keep_flag_valid = true; } status = AIS_OK; }
Ais18::Ais18(const char *nmea_payload, const size_t pad) : AisMsg(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(message_id == 18); if (pad != 0 || std::strlen(nmea_payload) != 28) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<168> bs; const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } spare = ubits(bs, 38, 8); sog = ubits(bs, 46, 10) / 10.; position_accuracy = bs[56]; x = sbits(bs, 57, 28) / 600000.; y = sbits(bs, 85, 27) / 600000.; cog = ubits(bs, 112, 12) / 10.; true_heading = ubits(bs, 124, 9); timestamp = ubits(bs, 133, 6); spare2 = ubits(bs, 139, 2); unit_flag = bs[141]; display_flag = bs[142]; dsc_flag = bs[143]; band_flag = bs[144]; m22_flag = bs[145]; mode_flag = bs[146]; raim = bs[147]; commstate_flag = bs[148]; // 0 SOTDMA, 1 ITDMA received_stations_valid = slot_number_valid = utc_valid = false; slot_offset_valid = slot_increment_valid = slots_to_allocate_valid = false; keep_flag = false; // if unit_flag is 1: // CS - carrier sense - fixed commstate payload of 1100000000000000110 // TODO(schwehr): What if commstate is not 393222? // commstate = ubits(bs, 149, 19); if (unit_flag == 1) { status = AIS_OK; return; } // unit_flag is 0 sync_state = ubits(bs, 149, 2); if (0 == commstate_flag) { // SOTDMA slot_timeout = ubits(bs, 151, 3); switch (slot_timeout) { case 0: slot_offset = ubits(bs, 154, 14); slot_offset_valid = true; break; case 1: utc_hour = ubits(bs, 154, 5); utc_min = ubits(bs, 159, 7); utc_spare = ubits(bs, 166, 2); utc_valid = true; break; case 2: // FALLTHROUGH case 4: // FALLTHROUGH case 6: slot_number = ubits(bs, 154, 14); slot_number_valid = true; break; case 3: // FALLTHROUGH case 5: // FALLTHROUGH case 7: received_stations = ubits(bs, 154, 14); received_stations_valid = true; break; default: assert(false); } } else { // ITDMA slot_increment = ubits(bs, 151, 13); slot_increment_valid = true; slots_to_allocate = ubits(bs, 164, 3); slots_to_allocate_valid = true; keep_flag = bs[167]; keep_flag_valid = true; } status = AIS_OK; }
Ais8_1_11::Ais8_1_11(const char *nmea_payload, const size_t pad) : Ais8(nmea_payload, pad) { if (status != AIS_UNINITIALIZED) return; assert(dac == 1); assert(fi == 11); if (strlen(nmea_payload) != 59) { status = AIS_ERR_BAD_BIT_COUNT; return; } bitset<354> bs; // 352 + 2 spares to be 6 bit aligned const AIS_STATUS r = aivdm_to_bits(bs, nmea_payload); if (r != AIS_OK) { status = r; return; } y = (float)(sbits(bs, 56, 24) / 60000.0);//Crouse: Added typecasting x = (float)(sbits(bs, 80, 25) / 60000.0);//Crouse: Added typecasting day = ubits(bs, 105, 5); hour = ubits(bs, 110, 5); minute = ubits(bs, 115, 6); wind_ave = ubits(bs, 121, 7); wind_gust = ubits(bs, 128, 7); wind_dir = ubits(bs, 135, 9); wind_gust_dir = ubits(bs, 144, 9); air_temp = (float)(ubits(bs, 153, 11) / 10.0 - 60);//Crouse: Added typecasting rel_humid = ubits(bs, 164, 7); dew_point = (float)(ubits(bs, 171, 10) / 10.0 - 20); // TODO(schwehr): verify //Crouse: Added typecasting air_pres = (float)ubits(bs, 181, 9) + (float)800.0; air_pres_trend = ubits(bs, 190, 2); horz_vis = (float)(ubits(bs, 192, 8) / 10.0);//Crouse: Added typecasting // TODO(schwehr): verify for -10.0 to 30.0 water_level = (float)(ubits(bs, 200, 9) / 10.0 - 10);//Crouse: Added typecasting water_level_trend = ubits(bs, 209, 2); surf_cur_speed = (float)(ubits(bs, 211, 8) / 10.0);//Crouse: Added typecasting surf_cur_dir = ubits(bs, 219, 9); cur_speed_2 = (float)(ubits(bs, 228, 8) / 10.0);//Crouse: Added typecasting cur_dir_2 = ubits(bs, 236, 9); cur_depth_2 = ubits(bs, 245, 5); cur_speed_3 = (float)(ubits(bs, 250, 8) / 10.0);//Crouse: Added typecasting cur_dir_3 = ubits(bs, 258, 9); cur_depth_3 = ubits(bs, 267, 5); wave_height = (float)(ubits(bs, 272, 8) / 10.0);//Crouse: Added typecasting wave_period = ubits(bs, 280, 6); wave_dir = ubits(bs, 286, 9); swell_height = (float)(ubits(bs, 295, 8) / 10.0);//Crouse: Added typecasting swell_period = ubits(bs, 303, 6); swell_dir = ubits(bs, 309, 9); sea_state = ubits(bs, 318, 4); // TODO(schwehr): verify for -10.0 to +50.0 water_temp = (float)(ubits(bs, 322, 10) / 10.0 - 10);//Crouse: Added typecasting precip_type = ubits(bs, 332, 3); salinity = (float)(ubits(bs, 335, 9)/10.0);//Crouse: Corrected to divide by 10.0 and added typecasting ice = ubits(bs, 344, 2); // There is no way to know which meaning to attach to the following 6 bits // TODO(schwehr): how to treat this spare vrs water level? spare2 = ubits(bs, 346, 6); extended_water_level = ubits(bs, 346, 6); status = AIS_OK; }