sprintf("%f", ... rounds up.
In the special case of minute of position > 59.9990 the result is 60.0. This results in a wrong APRS position location (i.e. 53.60.00N). This patch also makes create_dao_aprs() nicer and fixes "TODO: optimize ugly float to char to string to int conversion?". I tested the patch, and the author of the dao_aprs extension, dj1an, has confirmed everythin is still ok.
This commit is contained in:
parent
5a28898255
commit
cfa6c4f203
1 changed files with 31 additions and 22 deletions
|
@ -386,6 +386,26 @@ void setup_gps()
|
|||
ss.begin(9600, SERIAL_8N1, GPS_TX, GPS_RX);
|
||||
}
|
||||
|
||||
char *s_min_nn(uint32_t min_nnnnn, int high_precision)
|
||||
{
|
||||
/* min_nnnnn: RawDegrees billionths is uint32_t by definition and is n'telth degree (-> *= 6 -> nn.mmmmmm minutes)
|
||||
* high_precision: 0: round at decimal position 2. 1: round at decimal position 4. 2: return decimal position 3-4 as base91 encoded char
|
||||
*/
|
||||
|
||||
static char buf[6];
|
||||
min_nnnnn = min_nnnnn * 0.006;
|
||||
if ( ((min_nnnnn / (high_precision ? 1 : 100)) % 10) >= 5 && min_nnnnn < (6000000 - ((high_precision ? 1 : 100)*5)) ) {
|
||||
// round up. Avoid overflow (59.999999 should never become 60.0 or more)
|
||||
min_nnnnn = min_nnnnn + (high_precision ? 1 : 100)*5;
|
||||
}
|
||||
if (high_precision < 2)
|
||||
sprintf(buf, "%02u.%02u", (unsigned int ) ((min_nnnnn / 100000) % 100), (unsigned int ) ((min_nnnnn / 1000) % 100));
|
||||
else
|
||||
sprintf(buf, "%c", (char) ((min_nnnnn % 1000) / 11) + 33);
|
||||
// Like to verify? type in python for i.e. RawDegrees billions 566688333: i = 566688333; "%c" % (int(((i*.0006+0.5) % 100)/1.1) +33)
|
||||
return buf;
|
||||
}
|
||||
|
||||
String create_lat_aprs(RawDegrees lat)
|
||||
{
|
||||
char str[20];
|
||||
|
@ -394,7 +414,9 @@ String create_lat_aprs(RawDegrees lat)
|
|||
{
|
||||
n_s = 'S';
|
||||
}
|
||||
sprintf(str, "%02d%05.2f%c", lat.deg, lat.billionths / 1000000000.0 * 60.0, n_s);
|
||||
// we like sprintf's float up-rounding.
|
||||
// but sprintf % may round to 60.00 -> 5360.00 (53° 60min is a wrong notation ;)
|
||||
sprintf(str, "%02d%s%c", lat.deg, s_min_nn(lat.billionths, 0), n_s);
|
||||
String lat_str(str);
|
||||
return lat_str;
|
||||
}
|
||||
|
@ -408,9 +430,10 @@ String create_lat_aprs_dao(RawDegrees lat)
|
|||
{
|
||||
n_s = 'S';
|
||||
}
|
||||
sprintf(str, "%02d%07.4f%c", lat.deg, lat.billionths / 1000000000.0 * 60.0, n_s);
|
||||
// we need sprintf's float up-rounding. Must be the same principle as in aprs_dao(). We cut off the string to two decimals afterwards.
|
||||
// but sprintf % may round to 60.0000 -> 5360.0000 (53° 60min is a wrong notation ;)
|
||||
sprintf(str, "%02d%s%c", lat.deg, s_min_nn(lat.billionths, 1 /* high precision */), n_s);
|
||||
String lat_str(str);
|
||||
lat_str.remove(7,2);
|
||||
return lat_str;
|
||||
}
|
||||
|
||||
|
@ -422,7 +445,7 @@ String create_long_aprs(RawDegrees lng)
|
|||
{
|
||||
e_w = 'W';
|
||||
}
|
||||
sprintf(str, "%03d%05.2f%c", lng.deg, lng.billionths / 1000000000.0 * 60.0, e_w);
|
||||
sprintf(str, "%03d%s%c", lng.deg, s_min_nn(lng.billionths, 0), e_w);
|
||||
String lng_str(str);
|
||||
return lng_str;
|
||||
}
|
||||
|
@ -436,9 +459,8 @@ String create_long_aprs_dao(RawDegrees lng)
|
|||
{
|
||||
e_w = 'W';
|
||||
}
|
||||
sprintf(str, "%03d%07.4f%c", lng.deg, lng.billionths / 1000000000.0 * 60.0, e_w);
|
||||
sprintf(str, "%03d%s%c", lng.deg, s_min_nn(lng.billionths, 1 /* high precision */), e_w);
|
||||
String lng_str(str);
|
||||
lng_str.remove(8,2);
|
||||
return lng_str;
|
||||
}
|
||||
|
||||
|
@ -449,23 +471,10 @@ String create_dao_aprs(RawDegrees lat, RawDegrees lng)
|
|||
// https://metacpan.org/dist/Ham-APRS-FAP/source/FAP.pm
|
||||
// http://www.aprs.org/aprs12/datum.txt
|
||||
//
|
||||
// TODO: optimize ugly float to char to string to int conversion?
|
||||
|
||||
char str[10];
|
||||
char lat_str[10];
|
||||
char lng_str[10];
|
||||
|
||||
sprintf(lat_str, "%07.4f", lat.billionths / 1000000000.0 * 60.0);
|
||||
sprintf(lng_str, "%07.4f", lng.billionths / 1000000000.0 * 60.0);
|
||||
|
||||
String lat_dao(lat_str);
|
||||
String lng_dao(lng_str);
|
||||
int lat_int = lat_dao.substring(5,7).toInt();
|
||||
int lng_int = lng_dao.substring(5,7).toInt();
|
||||
char lat_char = char(int((lat_int/1.1 + 0.5) + 33));
|
||||
char lng_char = char(int((lng_int/1.1 + 0.5) + 33));
|
||||
|
||||
sprintf(str, "!w%c%c!", lat_char, lng_char);
|
||||
sprintf(str, "!w%s", s_min_nn(lat.billionths, 2));
|
||||
sprintf(str+3, "%s!", s_min_nn(lng.billionths, 2));
|
||||
String dao_str(str);
|
||||
return dao_str;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue