DIY Logging Volt/Ampmeter
SEGGER_RTT_printf.c File Reference
#include "SEGGER_RTT.h"
#include "SEGGER_RTT_Conf.h"
#include <stdlib.h>
#include <stdarg.h>

Go to the source code of this file.

Data Structures

struct  SEGGER_RTT_PRINTF_DESC
 

Macros

#define FORMAT_FLAG_LEFT_JUSTIFY   (1u << 0)
 
#define FORMAT_FLAG_PAD_ZERO   (1u << 1)
 
#define FORMAT_FLAG_PRINT_SIGN   (1u << 2)
 
#define FORMAT_FLAG_ALTERNATE   (1u << 3)
 

Functions

static void _StoreChar (SEGGER_RTT_PRINTF_DESC *p, char c)
 
static void _PrintUnsigned (SEGGER_RTT_PRINTF_DESC *pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags)
 
static void _PrintInt (SEGGER_RTT_PRINTF_DESC *pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags)
 
int SEGGER_RTT_vprintf (unsigned BufferIndex, const char *sFormat, va_list *pParamList)
 
int SEGGER_RTT_printf (unsigned BufferIndex, const char *sFormat,...)
 

Macro Definition Documentation

◆ FORMAT_FLAG_ALTERNATE

#define FORMAT_FLAG_ALTERNATE   (1u << 3)

Definition at line 71 of file SEGGER_RTT_printf.c.

◆ FORMAT_FLAG_LEFT_JUSTIFY

#define FORMAT_FLAG_LEFT_JUSTIFY   (1u << 0)

Definition at line 68 of file SEGGER_RTT_printf.c.

◆ FORMAT_FLAG_PAD_ZERO

#define FORMAT_FLAG_PAD_ZERO   (1u << 1)

Definition at line 69 of file SEGGER_RTT_printf.c.

◆ FORMAT_FLAG_PRINT_SIGN

#define FORMAT_FLAG_PRINT_SIGN   (1u << 2)

Definition at line 70 of file SEGGER_RTT_printf.c.

Function Documentation

◆ _PrintInt()

static void _PrintInt ( SEGGER_RTT_PRINTF_DESC pBufferDesc,
int  v,
unsigned  Base,
unsigned  NumDigits,
unsigned  FieldWidth,
unsigned  FormatFlags 
)
static

Definition at line 222 of file SEGGER_RTT_printf.c.

222  {
223  unsigned Width;
224  int Number;
225 
226  Number = (v < 0) ? -v : v;
227 
228  //
229  // Get actual field width
230  //
231  Width = 1u;
232  while (Number >= (int)Base) {
233  Number = (Number / (int)Base);
234  Width++;
235  }
236  if (NumDigits > Width) {
237  Width = NumDigits;
238  }
239  if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
240  FieldWidth--;
241  }
242 
243  //
244  // Print leading spaces if necessary
245  //
246  if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
247  if (FieldWidth != 0u) {
248  while ((FieldWidth != 0u) && (Width < FieldWidth)) {
249  FieldWidth--;
250  _StoreChar(pBufferDesc, ' ');
251  if (pBufferDesc->ReturnValue < 0) {
252  break;
253  }
254  }
255  }
256  }
257  //
258  // Print sign if necessary
259  //
260  if (pBufferDesc->ReturnValue >= 0) {
261  if (v < 0) {
262  v = -v;
263  _StoreChar(pBufferDesc, '-');
264  } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
265  _StoreChar(pBufferDesc, '+');
266  } else {
267 
268  }
269  if (pBufferDesc->ReturnValue >= 0) {
270  //
271  // Print leading zeros if necessary
272  //
273  if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
274  if (FieldWidth != 0u) {
275  while ((FieldWidth != 0u) && (Width < FieldWidth)) {
276  FieldWidth--;
277  _StoreChar(pBufferDesc, '0');
278  if (pBufferDesc->ReturnValue < 0) {
279  break;
280  }
281  }
282  }
283  }
284  if (pBufferDesc->ReturnValue >= 0) {
285  //
286  // Print number without sign
287  //
288  _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
289  }
290  }
291  }
292 }

◆ _PrintUnsigned()

static void _PrintUnsigned ( SEGGER_RTT_PRINTF_DESC pBufferDesc,
unsigned  v,
unsigned  Base,
unsigned  NumDigits,
unsigned  FieldWidth,
unsigned  FormatFlags 
)
static

Definition at line 132 of file SEGGER_RTT_printf.c.

132  {
133  static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
134  unsigned Div;
135  unsigned Digit;
136  unsigned Number;
137  unsigned Width;
138  char c;
139 
140  Number = v;
141  Digit = 1u;
142  //
143  // Get actual field width
144  //
145  Width = 1u;
146  while (Number >= Base) {
147  Number = (Number / Base);
148  Width++;
149  }
150  if (NumDigits > Width) {
151  Width = NumDigits;
152  }
153  //
154  // Print leading chars if necessary
155  //
156  if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
157  if (FieldWidth != 0u) {
158  if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
159  c = '0';
160  } else {
161  c = ' ';
162  }
163  while ((FieldWidth != 0u) && (Width < FieldWidth)) {
164  FieldWidth--;
165  _StoreChar(pBufferDesc, c);
166  if (pBufferDesc->ReturnValue < 0) {
167  break;
168  }
169  }
170  }
171  }
172  if (pBufferDesc->ReturnValue >= 0) {
173  //
174  // Compute Digit.
175  // Loop until Digit has the value of the highest digit required.
176  // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
177  //
178  while (1) {
179  if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
180  NumDigits--;
181  } else {
182  Div = v / Digit;
183  if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
184  break;
185  }
186  }
187  Digit *= Base;
188  }
189  //
190  // Output digits
191  //
192  do {
193  Div = v / Digit;
194  v -= Div * Digit;
195  _StoreChar(pBufferDesc, _aV2C[Div]);
196  if (pBufferDesc->ReturnValue < 0) {
197  break;
198  }
199  Digit /= Base;
200  } while (Digit);
201  //
202  // Print trailing spaces if necessary
203  //
204  if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
205  if (FieldWidth != 0u) {
206  while ((FieldWidth != 0u) && (Width < FieldWidth)) {
207  FieldWidth--;
208  _StoreChar(pBufferDesc, ' ');
209  if (pBufferDesc->ReturnValue < 0) {
210  break;
211  }
212  }
213  }
214  }
215  }
216 }

◆ _StoreChar()

static void _StoreChar ( SEGGER_RTT_PRINTF_DESC p,
char  c 
)
static

Definition at line 107 of file SEGGER_RTT_printf.c.

107  {
108  unsigned Cnt;
109 
110  Cnt = p->Cnt;
111  if ((Cnt + 1u) <= p->BufferSize) {
112  *(p->pBuffer + Cnt) = c;
113  p->Cnt = Cnt + 1u;
114  p->ReturnValue++;
115  }
116  //
117  // Write part of string, when the buffer is full
118  //
119  if (p->Cnt == p->BufferSize) {
120  if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
121  p->ReturnValue = -1;
122  } else {
123  p->Cnt = 0u;
124  }
125  }
126 }

◆ SEGGER_RTT_printf()

int SEGGER_RTT_printf ( unsigned  BufferIndex,
const char *  sFormat,
  ... 
)

Definition at line 491 of file SEGGER_RTT_printf.c.

491  {
492  int r;
493  va_list ParamList;
494 
495  va_start(ParamList, sFormat);
496  r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
497  va_end(ParamList);
498  return r;
499 }

◆ SEGGER_RTT_vprintf()

int SEGGER_RTT_vprintf ( unsigned  BufferIndex,
const char *  sFormat,
va_list *  pParamList 
)

Definition at line 317 of file SEGGER_RTT_printf.c.

317  {
318  char c;
319  SEGGER_RTT_PRINTF_DESC BufferDesc;
320  int v;
321  unsigned NumDigits;
322  unsigned FormatFlags;
323  unsigned FieldWidth;
324  char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
325 
326  BufferDesc.pBuffer = acBuffer;
328  BufferDesc.Cnt = 0u;
329  BufferDesc.RTTBufferIndex = BufferIndex;
330  BufferDesc.ReturnValue = 0;
331 
332  do {
333  c = *sFormat;
334  sFormat++;
335  if (c == 0u) {
336  break;
337  }
338  if (c == '%') {
339  //
340  // Filter out flags
341  //
342  FormatFlags = 0u;
343  v = 1;
344  do {
345  c = *sFormat;
346  switch (c) {
347  case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
348  case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
349  case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
350  case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
351  default: v = 0; break;
352  }
353  } while (v);
354  //
355  // filter out field with
356  //
357  FieldWidth = 0u;
358  do {
359  c = *sFormat;
360  if ((c < '0') || (c > '9')) {
361  break;
362  }
363  sFormat++;
364  FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
365  } while (1);
366 
367  //
368  // Filter out precision (number of digits to display)
369  //
370  NumDigits = 0u;
371  c = *sFormat;
372  if (c == '.') {
373  sFormat++;
374  do {
375  c = *sFormat;
376  if ((c < '0') || (c > '9')) {
377  break;
378  }
379  sFormat++;
380  NumDigits = NumDigits * 10u + ((unsigned)c - '0');
381  } while (1);
382  }
383  //
384  // Filter out length modifier
385  //
386  c = *sFormat;
387  do {
388  if ((c == 'l') || (c == 'h')) {
389  sFormat++;
390  c = *sFormat;
391  } else {
392  break;
393  }
394  } while (1);
395  //
396  // Handle specifiers
397  //
398  switch (c) {
399  case 'c': {
400  char c0;
401  v = va_arg(*pParamList, int);
402  c0 = (char)v;
403  _StoreChar(&BufferDesc, c0);
404  break;
405  }
406  case 'd':
407  v = va_arg(*pParamList, int);
408  _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
409  break;
410  case 'u':
411  v = va_arg(*pParamList, int);
412  _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
413  break;
414  case 'x':
415  case 'X':
416  v = va_arg(*pParamList, int);
417  _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
418  break;
419  case 's':
420  {
421  const char * s = va_arg(*pParamList, const char *);
422  do {
423  c = *s;
424  s++;
425  if (c == '\0') {
426  break;
427  }
428  _StoreChar(&BufferDesc, c);
429  } while (BufferDesc.ReturnValue >= 0);
430  }
431  break;
432  case 'p':
433  v = va_arg(*pParamList, int);
434  _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
435  break;
436  case '%':
437  _StoreChar(&BufferDesc, '%');
438  break;
439  default:
440  break;
441  }
442  sFormat++;
443  } else {
444  _StoreChar(&BufferDesc, c);
445  }
446  } while (BufferDesc.ReturnValue >= 0);
447 
448  if (BufferDesc.ReturnValue > 0) {
449  //
450  // Write remaining data, if any
451  //
452  if (BufferDesc.Cnt != 0u) {
453  SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
454  }
455  BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
456  }
457  return BufferDesc.ReturnValue;
458 }
FORMAT_FLAG_PRINT_SIGN
#define FORMAT_FLAG_PRINT_SIGN
Definition: SEGGER_RTT_printf.c:70
_PrintInt
static void _PrintInt(SEGGER_RTT_PRINTF_DESC *pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags)
Definition: SEGGER_RTT_printf.c:222
_StoreChar
static void _StoreChar(SEGGER_RTT_PRINTF_DESC *p, char c)
Definition: SEGGER_RTT_printf.c:107
SEGGER_RTT_PRINTF_DESC::RTTBufferIndex
unsigned RTTBufferIndex
Definition: SEGGER_RTT_printf.c:92
FORMAT_FLAG_LEFT_JUSTIFY
#define FORMAT_FLAG_LEFT_JUSTIFY
Definition: SEGGER_RTT_printf.c:68
SEGGER_RTT_PRINTF_DESC::Cnt
unsigned Cnt
Definition: SEGGER_RTT_printf.c:88
SEGGER_RTT_PRINTF_BUFFER_SIZE
#define SEGGER_RTT_PRINTF_BUFFER_SIZE
Definition: SEGGER_RTT_Conf.h:98
SEGGER_RTT_PRINTF_DESC
Definition: SEGGER_RTT_printf.c:80
FORMAT_FLAG_ALTERNATE
#define FORMAT_FLAG_ALTERNATE
Definition: SEGGER_RTT_printf.c:71
FORMAT_FLAG_PAD_ZERO
#define FORMAT_FLAG_PAD_ZERO
Definition: SEGGER_RTT_printf.c:69
SEGGER_RTT_vprintf
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char *sFormat, va_list *pParamList)
Definition: SEGGER_RTT_printf.c:317
SEGGER_RTT_Write
unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void *pBuffer, unsigned NumBytes)
Definition: SEGGER_RTT.c:1185
SEGGER_RTT_PRINTF_DESC::BufferSize
unsigned BufferSize
Definition: SEGGER_RTT_printf.c:87
_PrintUnsigned
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC *pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags)
Definition: SEGGER_RTT_printf.c:132
SEGGER_RTT_PRINTF_DESC::pBuffer
char * pBuffer
Definition: SEGGER_RTT_printf.c:86
SEGGER_RTT_PRINTF_DESC::ReturnValue
int ReturnValue
Definition: SEGGER_RTT_printf.c:90