mirror of https://github.com/ArduPilot/ardupilot
AP_HAL: support %lld and %llu in internal printf
useful for log messages with 64 bit timestamps
This commit is contained in:
parent
8be9e99fad
commit
4705be97bf
|
@ -59,6 +59,7 @@
|
|||
#define FL_WIDTH 0x20
|
||||
#define FL_PREC 0x40
|
||||
#define FL_LONG 0x80
|
||||
#define FL_LONGLONG 0x100
|
||||
|
||||
#define FL_PGMSTRING FL_LONG
|
||||
#define FL_NEGATIVE FL_LONG
|
||||
|
@ -73,10 +74,10 @@
|
|||
void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt, va_list ap)
|
||||
{
|
||||
unsigned char c; /* holds a char from the format string */
|
||||
unsigned char flags;
|
||||
uint16_t flags;
|
||||
unsigned char width;
|
||||
unsigned char prec;
|
||||
unsigned char buf[13];
|
||||
unsigned char buf[23];
|
||||
|
||||
for (;;) {
|
||||
|
||||
|
@ -147,6 +148,9 @@ void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt,
|
|||
}
|
||||
if (c == 'h')
|
||||
continue;
|
||||
} else if ((flags & FL_LONG) && c == 'l') {
|
||||
flags |= FL_LONGLONG;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -279,22 +283,23 @@ void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt,
|
|||
if (flags & FL_FLTFIX) { /* 'f' format */
|
||||
|
||||
n = exp > 0 ? exp : 0; /* exponent of left digit */
|
||||
unsigned char v = 0;
|
||||
do {
|
||||
if (n == -1)
|
||||
s->write('.');
|
||||
flags = (n <= exp && n > exp - ndigs)
|
||||
v = (n <= exp && n > exp - ndigs)
|
||||
? buf[exp - n + 1] : '0';
|
||||
if (--n < -prec || flags == 0)
|
||||
if (--n < -prec || v == 0)
|
||||
break;
|
||||
s->write(flags);
|
||||
s->write(v);
|
||||
} while (1);
|
||||
if (n == exp
|
||||
&& (buf[1] > '5'
|
||||
|| (buf[1] == '5' && !(vtype & FTOA_CARRY))) )
|
||||
{
|
||||
flags = '1';
|
||||
v = '1';
|
||||
}
|
||||
if (flags) s->write(flags);
|
||||
if (v) s->write(v);
|
||||
|
||||
} else { /* 'e(E)' format */
|
||||
|
||||
|
@ -375,6 +380,15 @@ void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt,
|
|||
* Handle integer formats variations for d/i, u, o, p, x, X.
|
||||
*/
|
||||
if (c == 'd' || c == 'i') {
|
||||
if (flags & FL_LONGLONG) {
|
||||
int64_t x = va_arg(ap,long long);
|
||||
flags &= ~(FL_NEGATIVE | FL_ALT);
|
||||
if (x < 0) {
|
||||
x = -x;
|
||||
flags |= FL_NEGATIVE;
|
||||
}
|
||||
c = ulltoa_invert (x, (char *)buf, 10) - (char *)buf;
|
||||
} else {
|
||||
long x = (flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int);
|
||||
flags &= ~(FL_NEGATIVE | FL_ALT);
|
||||
if (x < 0) {
|
||||
|
@ -382,6 +396,7 @@ void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt,
|
|||
flags |= FL_NEGATIVE;
|
||||
}
|
||||
c = ultoa_invert (x, (char *)buf, 10) - (char *)buf;
|
||||
}
|
||||
|
||||
} else {
|
||||
int base;
|
||||
|
@ -411,10 +426,15 @@ void print_vprintf (AP_HAL::Print *s, unsigned char in_progmem, const char *fmt,
|
|||
flags |= (FL_ALTHEX | FL_ALTUPP);
|
||||
base = 16 | XTOA_UPPER;
|
||||
ultoa:
|
||||
if (flags & FL_LONGLONG) {
|
||||
c = ulltoa_invert (va_arg(ap, unsigned long long),
|
||||
(char *)buf, base) - (char *)buf;
|
||||
} else {
|
||||
c = ultoa_invert ((flags & FL_LONG)
|
||||
? va_arg(ap, unsigned long)
|
||||
: va_arg(ap, unsigned int),
|
||||
(char *)buf, base) - (char *)buf;
|
||||
}
|
||||
flags &= ~FL_NEGATIVE;
|
||||
break;
|
||||
|
||||
|
|
|
@ -75,3 +75,49 @@ char * ultoa_invert (uint32_t val, char *s, uint8_t base) {
|
|||
return s;
|
||||
}
|
||||
|
||||
|
||||
char * ulltoa_invert (uint64_t val, char *s, uint8_t base) {
|
||||
if (base == 8) {
|
||||
do {
|
||||
*s = '0' + (val & 0x7);
|
||||
val >>= 3;
|
||||
} while(val);
|
||||
return s;
|
||||
}
|
||||
|
||||
if (base == 16) {
|
||||
do {
|
||||
uint8_t digit = '0' + (val & 0xf);
|
||||
#if XTOA_UPPER == 0
|
||||
if (digit > '0' + 9)
|
||||
digit += ('a' - '0' - 10);
|
||||
#else
|
||||
if (digit > '0' + 9)
|
||||
digit += ('A' - '0' - 10);
|
||||
#endif
|
||||
*s++ = digit;
|
||||
val >>= 4;
|
||||
} while(val);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Every base which in not hex and not oct is considered decimal.
|
||||
|
||||
// 64 bits is not actually enough, we need 65, but it should
|
||||
// be good enough for the log dumping we're using this for
|
||||
uint64_t xval = val;
|
||||
do {
|
||||
uint8_t saved = xval;
|
||||
xval &= ~1;
|
||||
xval += 2;
|
||||
xval += xval >> 1; // *1.5
|
||||
xval += xval >> 4; // *1.0625
|
||||
xval += xval >> 8; // *1.00390625
|
||||
xval += xval >> 16; // *1.000015259
|
||||
xval += xval >> 32; // it all amounts to *1.6
|
||||
xval >>= 4; // /16 ... so *1.6/16 is /10, fraction truncated.
|
||||
*s++ = '0' + saved - 10 * (uint8_t)xval;
|
||||
} while (xval);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
/* Internal function for use from `printf'. */
|
||||
char *ultoa_invert (uint32_t val, char *s, uint8_t base);
|
||||
char *ulltoa_invert (uint64_t val, char *s, uint8_t base);
|
||||
|
||||
/* Next flags are to use with `base'. Unused fields are reserved. */
|
||||
#define XTOA_PREFIX 0x0100 /* put prefix for octal or hex */
|
||||
|
|
Loading…
Reference in New Issue