rusefi 2017-04-07 16:06:29 -04:00
parent 9913d7306e
commit 849a645b5f
4 changed files with 133 additions and 500 deletions

View File

@ -1,5 +1,5 @@
/* /*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -27,15 +27,16 @@
* @{ * @{
*/ */
#include "ch.h" #include "hal.h"
#include "chprintf.h" #include "chprintf.h"
#include "memstreams.h"
//#include "error_handling.h"
#define MAX_FILLER 11 #define MAX_FILLER 11
/** #define FLOAT_PRECISION 9
* That's out default %f precision here. Two digits should be fine?
* That's important on the lcd screen int getRemainingStack(thread_t *otp);
*/
#define FLOAT_PRECISION 100
static char *long_to_string_with_divisor(char *p, static char *long_to_string_with_divisor(char *p,
long num, long num,
unsigned radix, unsigned radix,
@ -69,28 +70,22 @@ static char *long_to_string_with_divisor(char *p,
return p; return p;
} }
// custom_ name in order to avoid method signature conflict with standard libraries static char *ch_ltoa(char *p, long num, unsigned radix) {
static char *custom_ltoa(char *p, long num, unsigned radix) {
return long_to_string_with_divisor(p, num, radix, 0); return long_to_string_with_divisor(p, num, radix, 0);
} }
#if CHPRINTF_USE_FLOAT #if CHPRINTF_USE_FLOAT
char *ftoa(char *p, double num, unsigned long precision) { static const long pow10[FLOAT_PRECISION] = {
if (num < 0) { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
*p++ = '-'; };
return ftoa(p, -num, precision);
}
long l;
if (isnan(num)) {
*p++ = 'N';
*p++ = 'a';
*p++ = 'N';
return p;
}
if (precision == 0) static char *ftoa(char *p, double num, unsigned long precision) {
long l;
if ((precision == 0) || (precision > FLOAT_PRECISION))
precision = FLOAT_PRECISION; precision = FLOAT_PRECISION;
precision = pow10[precision - 1];
l = (long)num; l = (long)num;
p = long_to_string_with_divisor(p, l, 10, 0); p = long_to_string_with_divisor(p, l, 10, 0);
@ -100,9 +95,6 @@ char *ftoa(char *p, double num, unsigned long precision) {
} }
#endif #endif
#include "error_handling.h"
int getRemainingStack(thread_t *otp);
/** /**
* @brief System formatted output function. * @brief System formatted output function.
* @details This function implements a minimal @p vprintf()-like functionality * @details This function implements a minimal @p vprintf()-like functionality
@ -124,12 +116,15 @@ int getRemainingStack(thread_t *otp);
* @param[in] chp pointer to a @p BaseSequentialStream implementing object * @param[in] chp pointer to a @p BaseSequentialStream implementing object
* @param[in] fmt formatting string * @param[in] fmt formatting string
* @param[in] ap list of parameters * @param[in] ap list of parameters
* @return The number of bytes that would have been
* written to @p chp if no stream error occurs
* *
* @api * @api
*/ */
void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) { int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
char *p, *s, c, filler; char *p, *s, c, filler;
int i, precision, width; int i, precision, width;
int n = 0;
bool is_long, left_align; bool is_long, left_align;
long l; long l;
#if CHPRINTF_USE_FLOAT #if CHPRINTF_USE_FLOAT
@ -139,18 +134,17 @@ void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
char tmpbuf[MAX_FILLER + 1]; char tmpbuf[MAX_FILLER + 1];
#endif #endif
efiAssertVoid(getRemainingStack(chThdGetSelfX()) > 64, "lowstck#1c"); // efiAssert(getRemainingStack(chThdGetSelfX()) > 128, "lowstck#1c", 0);
while (true) {
while (TRUE) {
c = *fmt++; c = *fmt++;
if (c == 0) if (c == 0)
return; return n;
if (c != '%') { if (c != '%') {
chSequentialStreamPut(chp, (uint8_t)c); streamPut(chp, (uint8_t)c);
n++;
continue; continue;
} }
// we are here if c == '%' meaning we have a control sequence
p = tmpbuf; p = tmpbuf;
s = tmpbuf; s = tmpbuf;
left_align = FALSE; left_align = FALSE;
@ -159,7 +153,7 @@ void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
left_align = TRUE; left_align = TRUE;
} }
filler = ' '; filler = ' ';
if ((*fmt == '.') || (*fmt == '0')) { if (*fmt == '0') {
fmt++; fmt++;
filler = '0'; filler = '0';
} }
@ -224,7 +218,7 @@ void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
*p++ = '-'; *p++ = '-';
l = -l; l = -l;
} }
p = custom_ltoa(p, l, 10); p = ch_ltoa(p, l, 10);
break; break;
#if CHPRINTF_USE_FLOAT #if CHPRINTF_USE_FLOAT
case 'f': case 'f':
@ -252,7 +246,7 @@ unsigned_common:
l = va_arg(ap, unsigned long); l = va_arg(ap, unsigned long);
else else
l = va_arg(ap, unsigned int); l = va_arg(ap, unsigned int);
p = custom_ltoa(p, l, c); p = ch_ltoa(p, l, c);
break; break;
default: default:
*p++ = c; *p++ = c;
@ -265,23 +259,117 @@ unsigned_common:
width = -width; width = -width;
if (width < 0) { if (width < 0) {
if (*s == '-' && filler == '0') { if (*s == '-' && filler == '0') {
chSequentialStreamPut(chp, (uint8_t)*s++); streamPut(chp, (uint8_t)*s++);
n++;
i--; i--;
} }
do { do {
chSequentialStreamPut(chp, (uint8_t)filler); streamPut(chp, (uint8_t)filler);
n++;
} while (++width != 0); } while (++width != 0);
} }
if (i > 0) { while (--i >= 0) {
chSequentialStreamWrite(chp, (uint8_t*)s, i); streamPut(chp, (uint8_t)*s++);
n++;
} }
s += i;
while (width) { while (width) {
chSequentialStreamPut(chp, (uint8_t)filler); streamPut(chp, (uint8_t)filler);
n++;
width--; width--;
} }
} }
} }
/**
* @brief System formatted output function.
* @details This function implements a minimal @p printf() like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
* @param[in] fmt formatting string
*
* @api
*/
int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
va_list ap;
int formatted_bytes;
va_start(ap, fmt);
formatted_bytes = chvprintf(chp, fmt, ap);
va_end(ap);
return formatted_bytes;
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p snprintf()-like functionality.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
* @post @p str is NUL-terminated, unless @p size is 0.
*
* @param[in] str pointer to a buffer
* @param[in] size maximum size of the buffer
* @param[in] fmt formatting string
* @return The number of characters (excluding the
* terminating NUL byte) that would have been
* stored in @p str if there was room.
*
* @api
*/
int chsnprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
MemoryStream ms;
BaseSequentialStream *chp;
size_t size_wo_nul;
int retval;
if (size > 0)
size_wo_nul = size - 1;
else
size_wo_nul = 0;
/* Memory stream object to be used as a string writer, reserving one
byte for the final zero.*/
msObjectInit(&ms, (uint8_t *)str, size_wo_nul, 0);
/* Performing the print operation using the common code.*/
chp = (BaseSequentialStream *)(void *)&ms;
va_start(ap, fmt);
retval = chvprintf(chp, fmt, ap);
va_end(ap);
/* Terminate with a zero, unless size==0.*/
if (ms.eos < size)
str[ms.eos] = 0;
/* Return number of bytes that would have been written.*/
return retval;
}
/** @} */ /** @} */

View File

@ -1,375 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Concepts and parts of this file have been contributed by Fabio Utzig,
chvprintf() added by Brent Roman.
*/
/**
* @file chprintf.c
* @brief Mini printf-like functionality.
*
* @addtogroup chprintf
* @{
*/
#include "hal.h"
#include "chprintf.h"
#include "memstreams.h"
//#include "error_handling.h"
#define MAX_FILLER 11
#define FLOAT_PRECISION 9
int getRemainingStack(thread_t *otp);
static char *long_to_string_with_divisor(char *p,
long num,
unsigned radix,
long divisor) {
int i;
char *q;
long l, ll;
l = num;
if (divisor == 0) {
ll = num;
} else {
ll = divisor;
}
q = p + MAX_FILLER;
do {
i = (int)(l % radix);
i += '0';
if (i > '9')
i += 'A' - '0' - 10;
*--q = i;
l /= radix;
} while ((ll /= radix) != 0);
i = (int)(p + MAX_FILLER - q);
do
*p++ = *q++;
while (--i);
return p;
}
static char *ch_ltoa(char *p, long num, unsigned radix) {
return long_to_string_with_divisor(p, num, radix, 0);
}
#if CHPRINTF_USE_FLOAT
static const long pow10[FLOAT_PRECISION] = {
10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
};
static char *ftoa(char *p, double num, unsigned long precision) {
long l;
if ((precision == 0) || (precision > FLOAT_PRECISION))
precision = FLOAT_PRECISION;
precision = pow10[precision - 1];
l = (long)num;
p = long_to_string_with_divisor(p, l, 10, 0);
*p++ = '.';
l = (long)((num - l) * precision);
return long_to_string_with_divisor(p, l, 10, precision / 10);
}
#endif
/**
* @brief System formatted output function.
* @details This function implements a minimal @p vprintf()-like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
* @param[in] fmt formatting string
* @param[in] ap list of parameters
* @return The number of bytes that would have been
* written to @p chp if no stream error occurs
*
* @api
*/
int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
char *p, *s, c, filler;
int i, precision, width;
int n = 0;
bool is_long, left_align;
long l;
#if CHPRINTF_USE_FLOAT
float f;
char tmpbuf[2*MAX_FILLER + 1];
#else
char tmpbuf[MAX_FILLER + 1];
#endif
// efiAssert(getRemainingStack(chThdGetSelfX()) > 128, "lowstck#1c", 0);
while (true) {
c = *fmt++;
if (c == 0)
return n;
if (c != '%') {
streamPut(chp, (uint8_t)c);
n++;
continue;
}
p = tmpbuf;
s = tmpbuf;
left_align = FALSE;
if (*fmt == '-') {
fmt++;
left_align = TRUE;
}
filler = ' ';
if (*fmt == '0') {
fmt++;
filler = '0';
}
width = 0;
while (TRUE) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = va_arg(ap, int);
else
break;
width = width * 10 + c;
}
precision = 0;
if (c == '.') {
while (TRUE) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = va_arg(ap, int);
else
break;
precision *= 10;
precision += c;
}
}
/* Long modifier.*/
if (c == 'l' || c == 'L') {
is_long = TRUE;
if (*fmt)
c = *fmt++;
}
else
is_long = (c >= 'A') && (c <= 'Z');
/* Command decoding.*/
switch (c) {
case 'c':
filler = ' ';
*p++ = va_arg(ap, int);
break;
case 's':
filler = ' ';
if ((s = va_arg(ap, char *)) == 0)
s = "(null)";
if (precision == 0)
precision = 32767;
for (p = s; *p && (--precision >= 0); p++)
;
break;
case 'D':
case 'd':
case 'I':
case 'i':
if (is_long)
l = va_arg(ap, long);
else
l = va_arg(ap, int);
if (l < 0) {
*p++ = '-';
l = -l;
}
p = ch_ltoa(p, l, 10);
break;
#if CHPRINTF_USE_FLOAT
case 'f':
f = (float) va_arg(ap, double);
if (f < 0) {
*p++ = '-';
f = -f;
}
p = ftoa(p, f, precision);
break;
#endif
case 'X':
case 'x':
c = 16;
goto unsigned_common;
case 'U':
case 'u':
c = 10;
goto unsigned_common;
case 'O':
case 'o':
c = 8;
unsigned_common:
if (is_long)
l = va_arg(ap, unsigned long);
else
l = va_arg(ap, unsigned int);
p = ch_ltoa(p, l, c);
break;
default:
*p++ = c;
break;
}
i = (int)(p - s);
if ((width -= i) < 0)
width = 0;
if (left_align == FALSE)
width = -width;
if (width < 0) {
if (*s == '-' && filler == '0') {
streamPut(chp, (uint8_t)*s++);
n++;
i--;
}
do {
streamPut(chp, (uint8_t)filler);
n++;
} while (++width != 0);
}
while (--i >= 0) {
streamPut(chp, (uint8_t)*s++);
n++;
}
while (width) {
streamPut(chp, (uint8_t)filler);
n++;
width--;
}
}
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p printf() like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
* @param[in] fmt formatting string
*
* @api
*/
int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
va_list ap;
int formatted_bytes;
va_start(ap, fmt);
formatted_bytes = chvprintf(chp, fmt, ap);
va_end(ap);
return formatted_bytes;
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p snprintf()-like functionality.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
* @post @p str is NUL-terminated, unless @p size is 0.
*
* @param[in] str pointer to a buffer
* @param[in] size maximum size of the buffer
* @param[in] fmt formatting string
* @return The number of characters (excluding the
* terminating NUL byte) that would have been
* stored in @p str if there was room.
*
* @api
*/
int chsnprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
MemoryStream ms;
BaseSequentialStream *chp;
size_t size_wo_nul;
int retval;
if (size > 0)
size_wo_nul = size - 1;
else
size_wo_nul = 0;
/* Memory stream object to be used as a string writer, reserving one
byte for the final zero.*/
msObjectInit(&ms, (uint8_t *)str, size_wo_nul, 0);
/* Performing the print operation using the common code.*/
chp = (BaseSequentialStream *)(void *)&ms;
va_start(ap, fmt);
retval = chvprintf(chp, fmt, ap);
va_end(ap);
/* Terminate with a zero, unless size==0.*/
if (ms.eos < size)
str[ms.eos] = 0;
/* Return number of bytes that would have been written.*/
return retval;
}
/** @} */

View File

@ -1,5 +1,5 @@
/* /*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -26,7 +26,6 @@
#define _CHPRINTF_H_ #define _CHPRINTF_H_
#include <stdarg.h> #include <stdarg.h>
#include <math.h>
/** /**
* @brief Float type support. * @brief Float type support.
@ -38,43 +37,13 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap); int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap);
char *ftoa(char *p, double num, unsigned long precision); int chprintf(BaseSequentialStream *chp, const char *fmt, ...);
int chsnprintf(char *str, size_t size, const char *fmt, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/**
* @brief System formatted output function.
* @details This function implements a minimal @p printf() like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] chp pointer to a @p BaseSequentialStream implementing object
* @param[in] fmt formatting string
*
* @api
*/
static inline void chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
chvprintf(chp, fmt, ap);
va_end(ap);
}
#endif /* _CHPRINTF_H_ */ #endif /* _CHPRINTF_H_ */
/** @} */ /** @} */

View File

@ -1,49 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file chprintf.h
* @brief Mini printf-like functionality.
*
* @addtogroup chprintf
* @{
*/
#ifndef _CHPRINTF_H_
#define _CHPRINTF_H_
#include <stdarg.h>
/**
* @brief Float type support.
*/
#if !defined(CHPRINTF_USE_FLOAT) || defined(__DOXYGEN__)
#define CHPRINTF_USE_FLOAT FALSE
#endif
#ifdef __cplusplus
extern "C" {
#endif
int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap);
int chprintf(BaseSequentialStream *chp, const char *fmt, ...);
int chsnprintf(char *str, size_t size, const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif /* _CHPRINTF_H_ */
/** @} */