libbase: add progress bar (from Barebox).
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 9 Jun 2020 18:00:05 +0000 (20:00 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 9 Jun 2020 18:00:05 +0000 (20:00 +0200)
litex/soc/software/include/base/progress.h [new file with mode: 0644]
litex/soc/software/libbase/Makefile
litex/soc/software/libbase/progress.c [new file with mode: 0644]

diff --git a/litex/soc/software/include/base/progress.h b/litex/soc/software/include/base/progress.h
new file mode 100644 (file)
index 0000000..75aa9c4
--- /dev/null
@@ -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 */
index dff9f7188115cccab90b5e31f0b241e406120ed4..107c8736466ad0861b8dcd8538739e5b586b004f 100755 (executable)
@@ -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
 
diff --git a/litex/soc/software/libbase/progress.c b/litex/soc/software/libbase/progress.c
new file mode 100644 (file)
index 0000000..c13b2da
--- /dev/null
@@ -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");
+}