diff --git a/src/main/common/printf.c b/src/main/common/printf.c index ce40994d8c..fb8d2aac81 100644 --- a/src/main/common/printf.c +++ b/src/main/common/printf.c @@ -46,6 +46,8 @@ #ifdef REQUIRE_CC_ARM_PRINTF_SUPPORT +#define DEFAULT_FLOAT_PRECISION 6 + putcf stdout_putf; void *stdout_putp; @@ -68,10 +70,88 @@ static int putchw(void *putp, putcf putf, int n, char z, char *bf) return written; } -// retrun number of bytes written +// function to convert float to string +static void tfp_ftoa(double f, char *buf, int buf_size, int precision) { + int i = 0; + const double scales[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6 }; + + // Handle negative numbers + if (f < 0) { + buf[i++] = '-'; + f = -f; // Make f positive + } + + // Extract integer part + long int_part = (long)f; + + // Extract fractional part + double frac_part = f - (double)int_part; + + // Scale the fractional part for rounding + double scaled_frac_part = frac_part * scales[precision]; + + // Get the rounded fractional part + long rounded_frac = (long)(scaled_frac_part); + double last_digit = scaled_frac_part - rounded_frac; // Get last digit for rounding + + // Handle rounding based on the last digit + if (last_digit >= (double)0.5) { + rounded_frac++; // Round up if the last digit is 5 or more + } + + // Check for overflow in the fractional part + if (rounded_frac >= scales[precision]) { + rounded_frac = 0; + int_part++; // Increment the integer part if necessary + } + + // Convert the integer part to string + if (int_part == 0) { + buf[i++] = '0'; + } else { + long num = int_part; + int digits = 0; + + // Calculate the number of digits in the integer part + long temp = num; + while (temp > 0) { + temp /= 10; + digits++; + } + + // Write digits starting from the highest digit + for (int j = digits - 1; j >= 0; j--) { + if (i < buf_size - 1) { + buf[i + j] = (num % 10) + '0'; + num /= 10; + } + } + i += digits; + } + + // Add decimal point and fractional part if precision > 0 + if (precision > 0 && i < buf_size - 1) { + buf[i++] = '.'; + + // Convert the fractional part to string + for (int j = 0; j < precision && i < buf_size - 1; j++) { + rounded_frac *= 10; // Shift left + buf[i++] = (char)(rounded_frac / scales[precision]) + '0'; + rounded_frac %= (long)scales[precision]; + } + } + + if (i < buf_size) { + buf[i] = '\0'; + } else { + buf[buf_size - 1] = '\0'; + } +} + +// return number of bytes written int tfp_format(void *putp, putcf putf, const char *fmt, va_list va) { - char bf[12]; + char bf[32]; int written = 0; char ch; @@ -84,6 +164,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va) char lng = 0; #endif int w = 0; + int precision = DEFAULT_FLOAT_PRECISION; // Default float precision ch = *(fmt++); if (ch == '0') { ch = *(fmt++); @@ -92,6 +173,12 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va) if (ch >= '0' && ch <= '9') { ch = a2i(ch, &fmt, 10, &w); } + if (ch == '.') { + ch = *(fmt++); + if (ch >= '0' && ch <= '9') { + ch = a2i(ch, &fmt, 10, &precision); + } + } #ifdef REQUIRE_PRINTF_LONG_SUPPORT if (ch == 'l') { ch = *(fmt++); @@ -143,6 +230,13 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va) case 'n': *va_arg(va, int*) = written; break; + case 'f': { + double f = va_arg(va, double); + if (precision > DEFAULT_FLOAT_PRECISION) precision = DEFAULT_FLOAT_PRECISION; + tfp_ftoa(f, bf, sizeof(bf) - 1, precision); + written = putchw(putp, putf, w, lz, bf); + break; + } default: break; }