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:
commit
d6356bdc08
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
74
sys/fmt/table.c
Normal 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
56
sys/include/fmt_table.h
Normal 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 */
|
@ -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
|
||||
|
@ -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(<c4150, &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(<c4150, &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(<c4150, &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(<c4150, &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;
|
||||
|
Loading…
Reference in New Issue
Block a user