libbase: add progress bar (from Barebox).

This commit is contained in:
Florent Kermarrec 2020-06-09 20:00:05 +02:00
parent 32ebbc7761
commit 21b9239dc0
3 changed files with 132 additions and 1 deletions

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __PROGRSS_H
#define __PROGRSS_H
/* Initialize a progress bar. If max > 0 a one line progress
* bar is printed where 'max' corresponds to 100%. If max == 0
* a multi line progress bar is printed.
*/
void init_progression_bar(int max);
/* update a progress bar to a new value. If now < 0 then a
* spinner is printed.
*/
void show_progress(int now);
#endif /* __PROGRSS_H */

View File

@ -2,7 +2,8 @@ include ../include/generated/variables.mak
include $(SOC_DIRECTORY)/software/common.mak
OBJECTS = exception.o libc.o errno.o crc16.o crc32.o console.o \
system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o i2c.o
system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o i2c.o \
progress.o
all: crt0-ctr.o crt0-xip.o libbase.a libbase-nofloat.a

View File

@ -0,0 +1,114 @@
/*
* show_progress.c - simple progress bar functions
*
* Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <console.h>
#include <stdio.h>
#include <stdint.h>
#include <progress.h>
#define FILESIZE_MAX 100000000
#define HASHES_PER_LINE 65
static int printed;
static int progress_max;
static int spin;
uint32_t __div64_32(uint64_t *n, uint32_t base)
{
uint64_t rem = *n;
uint64_t b = base;
uint64_t res, d = 1;
uint32_t high = rem >> 32;
/* Reduce the thing a bit first */
res = 0;
if (high >= base) {
high /= base;
res = (uint64_t) high << 32;
rem -= (uint64_t) (high*base) << 32;
}
while ((int64_t)b > 0 && b < rem) {
b = b+b;
d = d+d;
}
do {
if (rem >= b) {
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);
*n = res;
return rem;
}
/* The unnecessary pointer compare is there
* to check for type safety (n must be 64bit)
*/
# define do_div(n,base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
if (((n) >> 32) == 0) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
} else \
__rem = __div64_32(&(n), __base); \
__rem; \
})
void show_progress(int now)
{
char spinchr[] = "\\|/-";
if (now < 0) {
printf("%c\b", spinchr[spin++ % (sizeof(spinchr) - 1)]);
return;
}
if (progress_max && progress_max != FILESIZE_MAX) {
uint64_t tmp = (int64_t)now * HASHES_PER_LINE;
do_div(tmp, progress_max);
now = tmp;
}
while (printed < now) {
if (!(printed % HASHES_PER_LINE) && printed)
printf("\n\t");
printf("#");
printed++;
}
}
void init_progression_bar(int max)
{
printed = 0;
progress_max = max;
spin = 0;
if (progress_max && progress_max != FILESIZE_MAX)
printf("\t[%*s]\r\t[", HASHES_PER_LINE, "");
else
printf("\t");
}