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);
|
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)
|
String create_lat_aprs(RawDegrees lat)
|
||||||
{
|
{
|
||||||
char str[20];
|
char str[20];
|
||||||
|
@ -394,7 +414,9 @@ String create_lat_aprs(RawDegrees lat)
|
||||||
{
|
{
|
||||||
n_s = 'S';
|
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);
|
String lat_str(str);
|
||||||
return lat_str;
|
return lat_str;
|
||||||
}
|
}
|
||||||
|
@ -408,9 +430,10 @@ String create_lat_aprs_dao(RawDegrees lat)
|
||||||
{
|
{
|
||||||
n_s = 'S';
|
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);
|
String lat_str(str);
|
||||||
lat_str.remove(7,2);
|
|
||||||
return lat_str;
|
return lat_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +445,7 @@ String create_long_aprs(RawDegrees lng)
|
||||||
{
|
{
|
||||||
e_w = 'W';
|
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);
|
String lng_str(str);
|
||||||
return lng_str;
|
return lng_str;
|
||||||
}
|
}
|
||||||
|
@ -436,36 +459,22 @@ String create_long_aprs_dao(RawDegrees lng)
|
||||||
{
|
{
|
||||||
e_w = 'W';
|
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);
|
String lng_str(str);
|
||||||
lng_str.remove(8,2);
|
|
||||||
return lng_str;
|
return lng_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
String create_dao_aprs(RawDegrees lat, RawDegrees lng)
|
String create_dao_aprs(RawDegrees lat, RawDegrees lng)
|
||||||
{
|
{
|
||||||
// !DAO! extension, use Base91 format for best precision
|
// !DAO! extension, use Base91 format for best precision
|
||||||
// /1.1 : scale from 0-99 to 0-90 for base91, int(... + 0.5): round to nearest integer
|
// /1.1 : scale from 0-99 to 0-90 for base91, int(... + 0.5): round to nearest integer
|
||||||
// https://metacpan.org/dist/Ham-APRS-FAP/source/FAP.pm
|
// https://metacpan.org/dist/Ham-APRS-FAP/source/FAP.pm
|
||||||
// http://www.aprs.org/aprs12/datum.txt
|
// http://www.aprs.org/aprs12/datum.txt
|
||||||
//
|
//
|
||||||
// TODO: optimize ugly float to char to string to int conversion?
|
|
||||||
|
|
||||||
char str[10];
|
char str[10];
|
||||||
char lat_str[10];
|
sprintf(str, "!w%s", s_min_nn(lat.billionths, 2));
|
||||||
char lng_str[10];
|
sprintf(str+3, "%s!", s_min_nn(lng.billionths, 2));
|
||||||
|
|
||||||
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);
|
|
||||||
String dao_str(str);
|
String dao_str(str);
|
||||||
return dao_str;
|
return dao_str;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue