From 5df5c67397e2800182e5016ab89bbd17e4e67a5b Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 19 Apr 2018 13:14:39 -0400 Subject: [PATCH] better text managment --- Makefile | 2 +- include/display_draw.h | 29 +------ include/display_text.h | 13 ++++ initrd/init | 4 +- src/display_draw.c | 65 +++------------- src/display_text.c | 168 +++++++++++++++++++++++++++++++++++++++++ src/fat32.c | 23 +++--- src/main.c | 10 ++- src/script.c | 59 +++++++++------ 9 files changed, 253 insertions(+), 120 deletions(-) create mode 100644 include/display_text.h create mode 100644 src/display_text.c diff --git a/Makefile b/Makefile index 595694a..07af411 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ STRIP = strip MCUFLAGS = -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 AFLAGS = $(MCUFLAGS) -CFLAGS = $(MCUFLAGS) -ggdb \ +CFLAGS = $(MCUFLAGS) -O2 \ -Iinclude -Iinclude/cmsis \ -fno-builtin -fsigned-char -ffreestanding \ -Wall -Werror -Wextra -pedantic \ diff --git a/include/display_draw.h b/include/display_draw.h index 1057a1c..ece280d 100644 --- a/include/display_draw.h +++ b/include/display_draw.h @@ -23,6 +23,9 @@ #include +#define C_WIDTH 12 +#define C_HEIGHT 16 + /** * Starts the task for a blinking text cursor. */ @@ -56,30 +59,6 @@ void dsp_line(int x, int y, int i, int j, uint16_t color); */ void dsp_rect(int x, int y, int w, int h, uint16_t color); -/** - * Sets the text cursor's position, in characters NOT pixels. - * @param x text column to move to - * @param y text row to move to - */ -void dsp_cpos(int x, int y); - -/* - * Shifts the cursor the given amount of characters. - */ -void dsp_spos(int x, int y); - -/** - * Sets the pixel offset of the text cursor. - * @param x x-pixel offset from (0, 0) - * @param y y-pixel offset from (0, 0) - */ -void dsp_coff(int x, int y); - -/** - * Puts a string to the screen. Text position if kept track of internally, so - * multiple calls will print the strings in one line. - * @param s the string to print - */ -void dsp_puts(const char *s); +void dsp_putchar(int c, unsigned int xpos, unsigned int ypos); #endif // DISPLAY_DRAW_H_ diff --git a/include/display_text.h b/include/display_text.h new file mode 100644 index 0000000..de7ebce --- /dev/null +++ b/include/display_text.h @@ -0,0 +1,13 @@ +#ifndef DISPLAY_TEXT_H_ +#define DISPLAY_TEXT_H_ + +void text_init(void); +void text_switch(unsigned int i); +void text_puts(const char *s); + +void text_clear(void); + +void text_setpos(uint8_t x, uint8_t y); +void text_relpos(int8_t x, int8_t y); + +#endif // DISPLAY_TEXT_H_ diff --git a/initrd/init b/initrd/init index 68ef07d..7592b4a 100644 --- a/initrd/init +++ b/initrd/init @@ -1,10 +1,8 @@ while (1) { - rect(0, 0, 480, 300, 0) - ppos(0, 0) - print("Free mem: ") print(freemem()) print("\n") choice = filemenu() program(choice) + clear() } diff --git a/src/display_draw.c b/src/display_draw.c index 97ee386..ff58c27 100644 --- a/src/display_draw.c +++ b/src/display_draw.c @@ -25,44 +25,22 @@ #include #include -#define C_WIDTH 12 -#define C_HEIGHT 16 -#define S_WIDTH 40 -#define S_HEIGHT 18 - volatile uint8_t lock = 0; #define LOCK while (lock) { delay(5); } task_hold(1); lock = 1 #define UNLOCK task_hold(0); lock = 0 -static unsigned int curx = 0; -static unsigned int cury = 0; -static unsigned int curxo = 0; -static unsigned int curyo = 0; static unsigned char *font; -void task_cursor(void) -{ - while (1) { - int x = curxo + curx * C_WIDTH; - int y = curyo + cury * C_HEIGHT; - dsp_rect(x, y + C_HEIGHT, C_WIDTH, 1, 0xFFFF); - delay(300); - dsp_rect(x, y + C_HEIGHT, C_WIDTH, 1, 0); - delay(300); - } -} - void dsp_cursoron(void) { font = malloc(32 * 256); flash_read((char *)font, 0, 32 * 256); - task_start(task_cursor, 512); } -void dsp_putchar(int c) +void dsp_putchar(int c, unsigned int xpos, unsigned int ypos) { LOCK; - if (c == '\n') { + /*if (c == '\n') { curx = 0; if (++cury == S_HEIGHT) { UNLOCK; @@ -78,10 +56,10 @@ void dsp_putchar(int c) dsp_rect(curxo + curx * C_WIDTH, curyo + cury * C_HEIGHT, C_WIDTH, C_HEIGHT, 0); return; - } + }*/ - unsigned int x = curxo + curx * C_WIDTH; - unsigned int y = curyo + cury * C_HEIGHT; + unsigned int x = xpos * C_WIDTH; + unsigned int y = ypos * C_HEIGHT; dsp_set_addr(x, y, x + C_WIDTH - 1, y + C_HEIGHT - 1); uint32_t base = c * 32; @@ -94,7 +72,7 @@ void dsp_putchar(int c) } } - if (++curx == S_WIDTH) { + /*if (++curx == S_WIDTH) { curx = 0; if (++cury == S_HEIGHT) { UNLOCK; @@ -102,37 +80,14 @@ void dsp_putchar(int c) LOCK; cury = 0; } - } + }*/ UNLOCK; } -void dsp_puts(const char *s) -{ - unsigned int i = 0; - while (s[i]) - dsp_putchar(s[i++]); -} - -void dsp_cpos(int x, int y) -{ - curx = x; - cury = y; -} - -void dsp_spos(int x, int y) -{ - if ((int)curx + x >= 0) - curx += x; - if ((int)cury + y >= 0) - cury += y; -} - -void dsp_coff(int x, int y) -{ - curxo = x; - curyo = y; -} +// +// Drawing functions +// void dsp_rect(int x, int y, int w, int h, uint16_t color) { diff --git a/src/display_text.c b/src/display_text.c new file mode 100644 index 0000000..8a41fa5 --- /dev/null +++ b/src/display_text.c @@ -0,0 +1,168 @@ + +#include +#include +#include +#include +#include + +#define WIDTH 40 +#define HEIGHT 18 + +#define TTY_COUNT 2 + +typedef struct { + char *buf; + uint8_t x; + uint8_t y; +} tty_t; + +static tty_t text_tty[TTY_COUNT]; +static tty_t *text_current; +static uint8_t text_cursor; + +void task_cursor(void) +{ + while (1) { + delay(300); + if (text_cursor == 0) + continue; + + int x = text_current->x * C_WIDTH; + int y = text_current->y * C_HEIGHT; + dsp_rect(x, y + C_HEIGHT - 1, C_WIDTH, 1, 0xFFFF); + delay(300); + dsp_rect(x, y + C_HEIGHT - 1, C_WIDTH, 1, 0); + } +} + +void text_init(void) +{ + for (int i = 0; i < TTY_COUNT; i++) { + text_tty[i].buf = calloc(WIDTH * HEIGHT, sizeof(char)); + text_tty[i].x = 0; + text_tty[i].y = 0; + } + + text_current = &text_tty[0]; + + text_cursor = 1; + task_start(task_cursor, 512); +} + +void text_redraw(void) +{ + for (unsigned int i = 0; i < WIDTH; i++) { + //unsigned int zc = 0; + for (unsigned int j = 0; j < HEIGHT; j++) { + int c = text_current->buf[i + j * WIDTH]; + /*if (c == '\0') { + if (++zc == 3) + break; + } else if (zc > 0) { + zc = 0; + }*/ + + dsp_putchar(c, i, j); + } + } +} + +void text_switch(unsigned int i) +{ + if (i >= TTY_COUNT) + return; + + text_current = &text_tty[i]; + text_redraw(); +} + +void text_clear(void) +{ + for (unsigned int i = 0; i < WIDTH; i++) { + for (unsigned int j = 0; j < HEIGHT; j++) { + text_current->buf[i + j * WIDTH] = 0; + dsp_putchar(' ', i, j); + } + } + text_current->x = 0; + text_current->y = 0; +} + +void text_putchar(int c) +{ + uint8_t x = text_current->x; + uint8_t y = text_current->y; + + switch (c) { + case '\n': + y++; + // fall_through + case '\r': + x = 0; + break; + case '\t': + for (unsigned int i = 0; i < 4; i++) + dsp_putchar(' ', x++, y); + break; + case '\b': + x--; + dsp_putchar(' ', x, y); + break; + default: + dsp_putchar(c, x, y); + text_current->buf[x + y * WIDTH] = c; + x++; + break; + } + + if (x >= WIDTH) { + x = 0; + y++; + } + + if (y >= HEIGHT) { + // clear + for (int i = 1; i < HEIGHT; i++) { + memcpy(text_current->buf + (i - 1) * WIDTH, + text_current->buf + i * WIDTH, WIDTH); + } + x = 0; + y = HEIGHT - 1; + for (int i = 0; i < WIDTH; i++) + text_current->buf[i + y * WIDTH] = 0; + + text_redraw(); + } + + text_current->x = x; + text_current->y = y; +} + +void text_puts(const char *s) +{ + unsigned int i = 0; + while (s[i]) + text_putchar(s[i++]); +} + +void text_setpos(uint8_t x, uint8_t y) +{ + if (x >= WIDTH) + x = WIDTH - 1; + if (y >= HEIGHT) + y = HEIGHT - 1; + text_current->x = x; + text_current->y = y; +} + +void text_relpos(int8_t x, int8_t y) +{ + if ((int)(text_current->x + x) < 0) + text_current->x = 0; + else + text_current->x += x; + if ((int)(text_current->y + y) < 0) + text_current->y = 0; + else + text_current->y += y; +} diff --git a/src/fat32.c b/src/fat32.c index 1154998..3c64f52 100644 --- a/src/fat32.c +++ b/src/fat32.c @@ -15,6 +15,8 @@ static uint32_t RootDirCluster; static uint32_t ClustersLBA; static uint32_t FATStartLBA; +static uint8_t *RootDir = 0; + int fat_find(void) { uint8_t *block = malloc(512); @@ -65,9 +67,12 @@ int fat_namecmp(const char *fatname, const char *name) file_t *fat_findfile(const char *name) { - uint8_t *block = malloc(512 * SectorsPerCluster); - sd_read(block, fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + if (RootDir == 0) { + RootDir = sd_read(malloc(512 * SectorsPerCluster), + fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + } + uint8_t *block = RootDir; for (unsigned int i = 0; block[i * 32] != 0; i++) { if (block[i * 32] == 0xE5 || (block[i * 32 + 11] & 0x0F) == 0x0F) continue; @@ -79,34 +84,34 @@ file_t *fat_findfile(const char *name) file_t *file = malloc(sizeof(file_t)); file->size = size; file->start = start; - free(block); return file; } } - free(block); return 0; } char *fat_getname(uint32_t index) { - uint8_t *block = malloc(512 * SectorsPerCluster); - sd_read(block, fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + if (RootDir == 0) { + RootDir = sd_read(malloc(512 * SectorsPerCluster), + fat_cluster2lba(RootDirCluster), 512 * SectorsPerCluster); + } uint32_t idx = 0; + uint8_t *block = RootDir; for (unsigned int i = 0; block[i * 32] != 0; i++) { if (block[i * 32] == 0xE5 || (block[i * 32 + 11] & 0x0F) == 0x0F) continue; if (idx == index) { - char *name = strncpy(malloc(11), (char *)(block + i * 32), 11); - free(block); + char *name = strncpy(malloc(12), (char *)(block + i * 32), 11); + name[11] = '\0'; return name; } idx++; } - free(block); return 0; } diff --git a/src/main.c b/src/main.c index 4380eae..b60f626 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -90,9 +91,11 @@ void wakeup(void) void kmain(void) { dsp_init(); + dsp_cursoron(); + text_init(); + sd_init(); fat_find(); - dsp_cursoron(); keypad_start(); task_start(task_interpreter, 4096); @@ -117,8 +120,8 @@ instance *load_program(const char *name) // load file file_t *file = fat_findfile(name); if (file == 0) { - dsp_puts("can't find "); - dsp_puts(name); + text_puts("can't find "); + text_puts(name); goto fail; } @@ -184,6 +187,7 @@ void task_status(void) void task_interpreter(void) { + dsp_rect(0, 0, 480, 300, 0); instance *it = load_program("init"); // run the script diff --git a/src/script.c b/src/script.c index 5ba0c08..65dd5a4 100644 --- a/src/script.c +++ b/src/script.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ int script_menu(instance *it); int script_filemenu(instance *it); int script_program(instance *it); int script_free(instance *it); +int script_clear(instance *it); int math_sin(instance *it); int math_cos(instance *it); @@ -74,6 +76,7 @@ void script_loadlib(instance *it) inew_cfunc(it, "line", script_line); inew_cfunc(it, "rect", script_rect); inew_cfunc(it, "color", script_color); + inew_cfunc(it, "clear", script_clear); inew_cfunc(it, "rand", script_rand); inew_cfunc(it, "delay", script_delay); @@ -118,11 +121,15 @@ int script_menu(instance *it) int nargs = igetarg_integer(it, 0); float *resps = (float *)calloc(nargs, sizeof(float)); strncpy(listbuf, " : \0", 4); + + text_switch(1); + text_clear(); + for (int i = 0; i < nargs; i++) { listbuf[0] = i + '0'; - dsp_puts(listbuf); - dsp_puts((char *)igetarg(it, 1 + i * 2)->value.p); - dsp_puts("\n"); + text_puts(listbuf); + text_puts((char *)igetarg(it, 1 + i * 2)->value.p); + text_puts("\n"); resps[i] = igetarg(it, 2 + i * 2)->value.f; } @@ -133,6 +140,7 @@ int script_menu(instance *it) variable *v = make_varf(0, isdigit(c) ? c - '0' : -1.0f); ipush(it, (uint32_t)v); + text_switch(0); free(resps); return 0; } @@ -144,13 +152,13 @@ int script_filemenu(instance *it) char listbuf[4]; char *fname; strncpy(listbuf, " : \0", 4); - dsp_puts("Choose a file: \n"); + text_puts("Choose a file: \n"); for (unsigned int i = 0; (fname = /*initrd*/fat_getname(i)) != 0; i++) { listbuf[0] = i + '0'; - dsp_puts(listbuf); - dsp_puts(fname); + text_puts(listbuf); + text_puts(fname); free(fname); - dsp_puts("\n"); + text_puts("\n"); } int c; @@ -170,9 +178,9 @@ int script_puts(instance *it) char buf[33]; //snprintf(buf, 33, "%d", (int)v->value.f); // TODO ftostr(buf, v->value.f); - dsp_puts(buf); + text_puts(buf); } else if (v->type == STRING) { - dsp_puts((const char *)v->value.p); + text_puts((const char *)v->value.p); } return 0; } @@ -184,7 +192,7 @@ int script_putchar(instance *it) buf[0] = (int)v->value.f; buf[1] = '\0'; - dsp_puts(buf); + text_puts(buf); return 0; } @@ -219,13 +227,13 @@ int script_gets(instance *it) break; } else if (c[0] == K_LEFT) { if (index > 0) { - dsp_spos(-1, 0); + text_relpos(-1, 0); index--; } continue; } else if (c[0] == K_RIGHT) { if (index < furthest) { - dsp_spos(1, 0); + text_relpos(1, 0); index++; } continue; @@ -247,17 +255,17 @@ int script_gets(instance *it) if (c[0] == '\b' || c[0] == 127) { index--; if (index > -1) { - dsp_puts("\b"); + text_puts("\b"); index--; } } else if (keypad_insert != 0) { - dsp_spos(-index, 0); + text_relpos(-index, 0); s[furthest + 1] = '\0'; - dsp_puts(s); - dsp_spos(-(furthest - index), 0); + text_puts(s); + text_relpos(-(furthest - index), 0); furthest++; } else if (c[0] != '\n'/*'\r'*/) { - dsp_puts(c); + text_puts(c); } if (++index > furthest) @@ -299,14 +307,13 @@ int script_line(instance *it) int script_ppos(instance *it) { - dsp_coff(0, 0); - dsp_cpos(igetarg_integer(it, 0), igetarg_integer(it, 1)); + text_setpos(igetarg_integer(it, 0), igetarg_integer(it, 1)); return 0; } int script_rpos(instance *it) { - dsp_spos(igetarg_integer(it, 0), igetarg_integer(it, 1)); + text_relpos(igetarg_integer(it, 0), igetarg_integer(it, 1)); return 0; } @@ -351,10 +358,7 @@ int script_program(instance *it) int initrdOffset = (int)igetarg(it, 0)->value.f; char *name = fat_getname(initrdOffset); - dsp_rect(0, 0, 480, 300, 0); - dsp_cpos(0, 0); - dsp_coff(0, 0); - + text_clear(); instance *it2 = load_program(name); free(name); @@ -372,3 +376,10 @@ int script_free(instance *it) ipush(it, (uint32_t)make_varf(0, 98303 - heap_used)); return 0; } + +int script_clear(instance *it) +{ + (void)it; + text_clear(); + return 0; +}