Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
aa7d527fbThis file is pinned to the selected release. Download the original to open it in your design tool.
/*
+=============================================================================+
| includes
+=============================================================================+
*/
#include <stdarg.h> // (...) parameter handling
#include <math.h>
#include "stm32_ub_usb_cdc.h"
#include "packet.h"
#include "printf.h"
#define PRINTF_BSIZE 128
#define PRINTF_FLENGTH 6
/*
+=============================================================================+
| local declarations
+=============================================================================+
*/
int vfprintf_(char *, const char *format, va_list arg); //generic print
/*
+=============================================================================+
| global functions
+=============================================================================+
*/
int printf_(const char *format, ...)
{
va_list arg;
char buffer[PRINTF_BSIZE];
int buffer_pos;
va_start(arg, format);
buffer_pos = vfprintf_(buffer, format, arg);
va_end(arg);
buffer[buffer_pos] = '\0';
struct packet p;
p.start = 255;
p.type = 1;
p.size = MIN(buffer_pos, 253);
p.txt = buffer;
buff_packet(&p);
UB_VCP_DataTx(p.start);
UB_VCP_DataTx(p.type);
UB_VCP_DataTx(p.size);
UB_VCP_DataTx(p.key);
UB_USB_CDC_SendData((char*)p.buf, p.size);
UB_USB_CDC_SendString(buffer, NONE);
return 0;
}
/*
+=============================================================================+
| local functions
+=============================================================================+
*/
/*--------------------------------------------------------------------------------+
* vfprintf_()
* Prints a string to buffer. Supports %s, %c, %d, %ld %ul %02d %i %x %lud and %%
* - partly supported: long long, float (%ll %f, %F, %2.2f)
* - not supported: double float and exponent (%e %g %p %o \t)
* returns length of string
* limits string length to PRINTF_BSIZE
*--------------------------------------------------------------------------------+
*/
int vfprintf_(char *buffer, const char* str, va_list arp){
int buffer_pos = 0; // position in output buffer
int input_pos = 0; // position in input buffer
int state = 0; // 0 = last char = normal char
// 1 = last char = '%'
// 2 = last char = '\'
int i = 0; // number to print
float f = 0; // float to print
char tmp[20]; // tmp string for numbers
int tmp_pos = 0; // pos in tmp
char *s = 0; // string to print
unsigned char float_length = PRINTF_FLENGTH;
while(str[input_pos] != '\0' && buffer_pos < PRINTF_BSIZE){
switch(state){
case 0: // last = normal
switch(str[input_pos]){
case '%':
state = 1;
break;
case '\'':
state = 2;
break;
default:
buffer[buffer_pos++] = str[input_pos];
}
input_pos++;
break;
case 1: // last = '%'
switch(str[input_pos++]){
case '%': // "%%"
buffer[buffer_pos++] = '%';
break;
case 'c': // "%c"
buffer[buffer_pos++] = (char)va_arg(arp, int);
break;
case 's': // "%s"
s = va_arg(arp, char*);
while(*s){
buffer[buffer_pos++] = *(s++);
}
break;
case 'i': // "%i"
tmp_pos = 0;
i = va_arg(arp, int);
if(i < 0){
buffer[buffer_pos++] = '-';
i *= -1;
}
do{
tmp[tmp_pos++] = i % 10 + '0';
i /= 10;
}
while(i > 0);
while(tmp_pos--){
buffer[buffer_pos++] = tmp[tmp_pos];
}
break;
case 'b': // "%b"
tmp_pos = 0;
i = va_arg(arp, int);
if(i < 0){
buffer[buffer_pos++] = '-';
i *= -1;
}
do{
tmp[tmp_pos++] = i % 2 + '0';
i /= 2;
}
while(i > 0);
buffer[buffer_pos++] = 'b';
while(tmp_pos--){
buffer[buffer_pos++] = tmp[tmp_pos];
}
break;
case 'h': // "%h"
tmp_pos = 0;
i = va_arg(arp, int);
if(i < 0){
buffer[buffer_pos++] = '-';
i *= -1;
}
do{
if(i % 16 < 10){
tmp[tmp_pos++] = i % 16 + '0';
}
else{
tmp[tmp_pos++] = i % 16 + 'A' - 10;
}
i /= 16;
}
while(i > 0);
buffer[buffer_pos++] = '0';
buffer[buffer_pos++] = 'x';
while(tmp_pos--){
buffer[buffer_pos++] = tmp[tmp_pos];
}
break;
case 'f': // "%f"
tmp_pos = 0;
f = va_arg(arp, double); // change to float for stm32
if(isnan(f) || f != f){
buffer[buffer_pos++] = 'N';
buffer[buffer_pos++] = 'a';
buffer[buffer_pos++] = 'N';
break;
}
if(f == INFINITY){
buffer[buffer_pos++] = '+';
buffer[buffer_pos++] = 'i';
buffer[buffer_pos++] = 'n';
buffer[buffer_pos++] = 'f';
break;
}
if(f == -INFINITY){
buffer[buffer_pos++] = '-';
buffer[buffer_pos++] = 'i';
buffer[buffer_pos++] = 'n';
buffer[buffer_pos++] = 'f';
break;
}
if(f < 0){
buffer[buffer_pos++] = '-';
f *= -1;
}
i = f;
do{
tmp[tmp_pos++] = i % 10 + '0';
i /= 10;
}
while(i > 0);
while(tmp_pos--){
buffer[buffer_pos++] = tmp[tmp_pos];
}
buffer[buffer_pos++] = '.';
f -= i;
tmp_pos = float_length - 1;
for(int j = 0; j < float_length; j++){
f *= 10;
tmp[tmp_pos--] = ((int)f) % 10 + '0';
}
tmp_pos = float_length;
while(tmp_pos--){
buffer[buffer_pos++] = tmp[tmp_pos];
}
break;
default:
break;
}
state = 0;
break;
case 2: // last = '\'
switch(str[input_pos++]){
case 'n': // "\n"
buffer[buffer_pos++] = '\n';
state = 0;
break;
case 't': // "\t"
buffer[buffer_pos++] = '\t';
state = 0;
break;
case 'r': // "\t"
buffer[buffer_pos++] = '\r';
state = 0;
break;
case '\'': // "\'"
buffer[buffer_pos++] = '\'';
state = 0;
break;
case '"': // "\""
buffer[buffer_pos++] = '\"';
state = 0;
break;
case '\\': // "\\"
buffer[buffer_pos++] = '\\';
state = 0;
break;
default:
break;
}
break;
}
}
return(buffer_pos);
}