1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #11692 from maribu/fmt_table

sys/fmt: Added submodule fmt_table for printing tables
This commit is contained in:
Kaspar Schleiser 2019-08-20 22:18:54 +02:00 committed by GitHub
commit d6356bdc08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 193 additions and 125 deletions

View File

@ -13,6 +13,7 @@ PSEUDOMODULES += devfs_%
PSEUDOMODULES += ecc_%
PSEUDOMODULES += emb6_router
PSEUDOMODULES += event_%
PSEUDOMODULES += fmt_%
PSEUDOMODULES += gnrc_ipv6_default
PSEUDOMODULES += gnrc_ipv6_router
PSEUDOMODULES += gnrc_ipv6_router_default

View File

@ -2,6 +2,10 @@ ifneq (,$(filter eepreg,$(USEMODULE)))
FEATURES_REQUIRED += periph_eeprom
endif
ifneq (,$(filter fmt_table,$(USEMODULE)))
USEMODULE += fmt
endif
ifneq (,$(filter i2c_scan,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c
endif

View File

@ -1 +1,7 @@
# exclude submodule sources from *.c wildcard source selection
SRC := $(filter-out table.c,$(wildcard *.c))
# enable submodules
SUBMODULES := 1
include $(RIOTBASE)/Makefile.base

74
sys/fmt/table.c Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright 2019 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_fmt_table
* @{
*
* @file
* @brief Implementation of the table extensions of the string formatting
* library
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @}
*/
#include <assert.h>
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include "fmt.h"
static const char fmt_table_spaces[16] = " ";
/**
* @brief Prints @p fill_size bytes of the given pattern, repeating the
* pattern if needed
* @param pat Pattern to print
* @param pat_size Size of the pattern in bytes
* @param fill_size Number of bytes to print (if bigger than @p pat_size, the
* pattern will be repeated)
*
* E.g. `print_pattern("ab", 2, 5);` will print `ababa` to the console.
* This can be used to fill table columns with spaces, draw lines, etc.
*/
static void print_pattern(const char *pat, size_t pat_size, size_t fill_size)
{
while (fill_size > pat_size) {
print(pat, pat_size);
}
print(pat, fill_size);
}
void print_col_u32_dec(uint32_t number, size_t width)
{
char sbuf[10]; /* "4294967295" */
size_t slen;
slen = fmt_u32_dec(sbuf, number);
if (width > slen) {
print_pattern(fmt_table_spaces, sizeof(fmt_table_spaces), width - slen);
}
print(sbuf, slen);
}
void print_col_s32_dec(int32_t number, size_t width)
{
char sbuf[11]; /* "-2147483648" */
size_t slen;
slen = fmt_s32_dec(sbuf, number);
if (width > slen) {
print_pattern(fmt_table_spaces, sizeof(fmt_table_spaces), width - slen);
}
print(sbuf, slen);
}

56
sys/include/fmt_table.h Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright 2019 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_fmt_table Table extension of the string formatting API (fmt_table)
* @ingroup sys_fmt
* @brief Provides utilities to print tables.
*
* \note The print functions in this library do not buffer any output.
* Mixing calls to standard @c printf from stdio.h with the @c print_xxx
* functions in fmt, especially on the same output line, may cause garbled
* output.
*
* @{
*
* @file
* @brief Table extension of the string formatting API
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#ifndef FMT_TABLE_H
#define FMT_TABLE_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Print a table column with the given number as decimal
* @param number Number to print in the column
* @param width Width of the column
*/
void print_col_u32_dec(uint32_t number, size_t width);
/**
* @brief Print a table column with the given number as decimal
* @param number Number to print in the column
* @param width Width of the column
*/
void print_col_s32_dec(int32_t number, size_t width);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* FMT_TABLE_H */

View File

@ -4,7 +4,7 @@ BOARD_INSUFFICIENT_MEMORY += arduino-duemilanove arduino-leonardo arduino-nano \
arduino-uno
BOARD ?= msba2
USEMODULE += fmt
USEMODULE += fmt_table
USEMODULE += ltc4150
include $(RIOTBASE)/Makefile.include

View File

@ -19,9 +19,9 @@
*/
#include <errno.h>
#include <stdio.h>
#include "fmt.h"
#include "fmt_table.h"
#include "led.h"
#include "ltc4150.h"
#include "thread.h"
@ -62,22 +62,6 @@ static void *recorder_data[] = {
#include "ltc4150_params.h"
/**
* @brief Like `puts()`, but do not append a newline
*
* Normally I would just use `fputs(str, stdout)` directly, but the msp430
* toolchain lacks `fputs()`. This wrapper allows to add a less efficient
* fallback to printf()
*/
static inline void puts_no_nl(const char *s)
{
#ifndef NO_FPUTS
fputs(s, stdout);
#else
printf("%s", s);
#endif
}
/**
* @brief Callback function to reset/initialize the recorder data
*/
@ -151,62 +135,6 @@ static void *busy_thread(void *arg)
return NULL;
}
/**
* @brief Print the given number of spaces
*/
static void print_spaces(size_t number)
{
static const char *spaces = " ";
while (number > 16) {
puts_no_nl(spaces);
number -= 16;
}
puts_no_nl(spaces + 16 - number);
}
/**
* @brief Print a table column with the given number as decimal
* @param number Number to print in the column
* @param width Width of the column
*/
static void print_col_u32(uint32_t number, size_t width)
{
char sbuf[32];
size_t slen;
slen = fmt_u32_dec(sbuf, number);
sbuf[slen] = '\0';
if (width > slen) {
print_spaces(width - slen);
}
puts_no_nl(sbuf);
}
/**
* @brief Print a table column with the given number as decimal
* @param number Number to print in the column
* @param width Width of the column
*/
static void print_col_i32(int32_t number, size_t width)
{
char sbuf[32];
size_t slen;
char *pos = sbuf;
if (number < 0) {
*pos++ = '-';
number = -number;
width--;
}
slen = fmt_u32_dec(sbuf, (uint32_t)number);
sbuf[slen] = '\0';
if (width > slen) {
print_spaces(width - slen);
}
puts_no_nl(sbuf);
}
/**
* @brief Print a table column with the given current as E-01
* @param current Value to print in the column (as E-01)
@ -214,13 +142,12 @@ static void print_col_i32(int32_t number, size_t width)
*/
static void print_current(int32_t current, size_t width)
{
char sbuf[3];
char sbuf[2];
print_col_i32(current/10, width - 2);
print_col_s32_dec(current/10, width - 2);
sbuf[0] = '.';
sbuf[1] = '0' + current % 10;
sbuf[2] = '\0';
puts_no_nl(sbuf);
print(sbuf, 2);
}
int main(void)
@ -236,16 +163,16 @@ int main(void)
ltc4150_pulses2c(&ltc4150, &ten_uc_per_pulse, NULL, 10000, 0);
if (retval) {
puts_no_nl("Failed to initialize LTC4150 driver:");
print_str("Failed to initialize LTC4150 driver:");
switch (retval) {
case -EINVAL:
puts("Invalid parameter");
print_str("Invalid parameter\n");
break;
case -EIO:
puts("GPIO or interrupt configuration failed");
print_str("GPIO or interrupt configuration failed\n");
break;
default:
puts("Unknown (should no happen, file a bug)");
print_str("Unknown (should no happen, file a bug)\n");
break;
}
return -1;
@ -256,39 +183,39 @@ int main(void)
THREAD_PRIORITY_MAIN + 1, THREAD_CREATE_STACKTEST,
busy_thread, NULL, "busy_thread");
puts("This test will put three levels of load on the MCU:\n"
" 1. One minute of little to no load (LEDs(*) off)\n"
" 2. One minute of about 50% CPU load (LEDs(*) blinking)\n"
" 3. One minute of 100% CPU load (LEDs(*) constantly on)\n"
"\n"
" (*) LED0 and LED1, if present on your board\n"
"\n"
"During this time the charge drawn is measured and printed on every\n"
"pulse the LTC4150 generates. A horizontal line in the table\n"
"separates values of different load levels. On the MSB-A2 the\n"
"expected result per column is:\n"
"\n"
" Charging: Should remain zero\n"
" Discharging: Should increase for every pulse\n"
" Average: Should be something between 60mA to 80mA\n"
" Last Minute: Starts with 0 at boot up and is updated every 10s.\n"
" Should be higher for higher system load when looking\n"
" at the last update for each load level.\n"
" (Note: Not synchronized with load levels!)\n"
" Currently: Should be higher for higher system load. Might be\n"
" \"jumpy\" on 50% load, as this implemented by having\n"
" one second of 100% load and one second of ~0% load\n"
" in turns.\n"
"\n"
"Hint: You'll want to look mostly at the rightmost column.\n"
"Note: The test will repeat endlessly.");
print_str("This test will put three levels of load on the MCU:\n"
" 1. One minute of little to no load (LEDs(*) off)\n"
" 2. One minute of about 50% CPU load (LEDs(*) blinking)\n"
" 3. One minute of 100% CPU load (LEDs(*) constantly on)\n"
"\n"
" (*) LED0 and LED1, if present on your board\n"
"\n"
"During this time the charge drawn is measured and printed on every\n"
"pulse the LTC4150 generates. A horizontal line in the table\n"
"separates values of different load levels. On the MSB-A2 the\n"
"expected result per column is:\n"
"\n"
" Charging: Should remain zero\n"
" Discharging: Should increase for every pulse\n"
" Average: Should be something between 60mA to 80mA\n"
" Last Minute: Starts with 0 at boot up and is updated every 10s.\n"
" Should be higher for higher system load when looking\n"
" at the last update for each load level.\n"
" (Note: Not synchronized with load levels!)\n"
" Currently: Should be higher for higher system load. Might be\n"
" \"jumpy\" on 50% load, as this implemented by having\n"
" one second of 100% load and one second of ~0% load\n"
" in turns.\n"
"\n"
"Hint: You'll want to look mostly at the rightmost column.\n"
"Note: The test will repeat endlessly.\n");
LED0_OFF;
puts("+-------------------------------+-----------------------------------+\n"
"| Total Transferred Charge [mC] | Current from Power Supply [mA] |\n"
"| Charging | Discharging | Average | Last Minute | Currently |\n"
"+---------------+---------------+---------+-------------+-----------+");
print_str("+-------------------------------+-----------------------------------+\n"
"| Total Transferred Charge [mC] | Current from Power Supply [mA] |\n"
"| Charging | Discharging | Average | Last Minute | Currently |\n"
"+---------------+---------------+---------+-------------+-----------+\n");
while (1) {
/* Wait for the next pulse of the LTC4150 */
@ -298,40 +225,40 @@ int main(void)
int32_t current;
if (change_of_load_level) {
puts("+---------------+---------------+---------+-------------+-----------+");
print_str("+---------------+---------------+---------+-------------+-----------+\n");
change_of_load_level = 0;
}
/* Get & print total charge transferred */
if (ltc4150_charge(&ltc4150, &charged, &discharged)) {
puts("ltc4150_charge() failed!");
print_str("ltc4150_charge() failed!\n");
return -1;
}
puts_no_nl("| ");
print_col_u32(charged, 13);
puts_no_nl(" | ");
print_col_u32(discharged, 13);
puts_no_nl(" | ");
print_str("| ");
print_col_u32_dec(charged, 13);
print_str(" | ");
print_col_u32_dec(discharged, 13);
print_str(" | ");
/* Get & print avg current */
if (ltc4150_avg_current(&ltc4150, &avg_current)) {
puts("ltc4150_avg_current() failed!");
print_str("ltc4150_avg_current() failed!\n");
return -1;
}
print_current(avg_current, 7);
puts_no_nl(" | ");
print_str(" | ");
/* Get & print last minute current */
if (ltc4150_last_minute_charge(&ltc4150, &last_minute_data,
&charged, &discharged)
) {
puts("ltc4150_last_minute_charge() failed!");
print_str("ltc4150_last_minute_charge() failed!\n");
return -1;
}
current = (int32_t)discharged - (int32_t)charged;
current /= 60;
print_col_i32(current, 11);
puts_no_nl(" | ");
print_col_s32_dec(current, 11);
print_str(" | ");
/* Calculate & print the current between the last two pulses */
current = (int32_t)((test_data.now_usec - test_data.last_usec) / MS_PER_SEC);
@ -340,7 +267,7 @@ int main(void)
current = -current;
}
print_current(current, 9);
puts(" |");
print_str(" |\n");
}
return 0;