add basic terminal
This commit is contained in:
parent
7d5900e5ea
commit
f4d22b5b16
|
@ -0,0 +1,26 @@
|
|||
#ifndef _NVBOARD_TERM_H
|
||||
#define _NVBOARD_TERM_H
|
||||
|
||||
class Term {
|
||||
private:
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Rect region;
|
||||
int w_in_char, h_in_char;
|
||||
std::vector<uint8_t *> lines;
|
||||
int cursor_x, cursor_y;
|
||||
SDL_Texture *cursor_texture;
|
||||
int screen_y;
|
||||
|
||||
void clear_screen();
|
||||
uint8_t *new_line();
|
||||
void draw_cursor();
|
||||
|
||||
public:
|
||||
Term(SDL_Renderer *r, int x, int y, int w, int h);
|
||||
~Term();
|
||||
void feed_ch(uint8_t ch);
|
||||
void update_gui();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -2,14 +2,13 @@
|
|||
#define _NVBOARD_UART_H
|
||||
|
||||
#include <component.h>
|
||||
#include <string>
|
||||
#include <term.h>
|
||||
|
||||
class UART : public Component{
|
||||
private:
|
||||
int region_w, region_h;
|
||||
std::string str;
|
||||
Term *term;
|
||||
public:
|
||||
UART(SDL_Renderer *rend, int cnt, int init_val, int ct);
|
||||
UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int w, int h);
|
||||
~UART();
|
||||
|
||||
virtual void update_gui();
|
||||
|
|
42
src/font.cpp
42
src/font.cpp
|
@ -1,29 +1,41 @@
|
|||
#include <nvboard.h>
|
||||
#include <SDL_ttf.h>
|
||||
|
||||
static TTF_Font *font = NULL;
|
||||
static SDL_Texture* font[128] = { NULL };
|
||||
|
||||
void init_font() {
|
||||
void init_font(SDL_Renderer *renderer) {
|
||||
int ret = TTF_Init();
|
||||
assert(ret != -1);
|
||||
std::string nvboard_home = getenv("NVBOARD_HOME");
|
||||
font = TTF_OpenFont((nvboard_home + "/resources/font/" + "FreeMono.ttf").c_str(), 16);
|
||||
assert(font != NULL);
|
||||
|
||||
TTF_Font *f = TTF_OpenFont((nvboard_home + "/resources/font/" + "FreeMono.ttf").c_str(), 16);
|
||||
assert(f != NULL);
|
||||
TTF_SetFontHinting(f, TTF_HINTING_MONO);
|
||||
TTF_SetFontStyle(f, TTF_STYLE_BOLD);
|
||||
|
||||
SDL_Color c = {.r = 0x00, .g = 0x00, .b = 0x00 };
|
||||
for (int i = 1; i < 128; i ++) {
|
||||
SDL_Surface *s = TTF_RenderGlyph_Solid(f, i, c);
|
||||
if (s == NULL) {
|
||||
printf("error = %s\n", SDL_GetError());
|
||||
}
|
||||
assert(s != NULL);
|
||||
assert(s->w == 10);
|
||||
assert(s->h == 16);
|
||||
SDL_Texture *t = SDL_CreateTextureFromSurface(renderer, s);
|
||||
assert(t != NULL);
|
||||
font[i] = t;
|
||||
SDL_FreeSurface(s);
|
||||
}
|
||||
|
||||
TTF_CloseFont(f);
|
||||
}
|
||||
|
||||
SDL_Texture* render_str(SDL_Renderer *renderer, std::string str, int wrap_len_in_pixel, int *w, int *h) {
|
||||
SDL_Color c = {.r = 0x00, .g = 0x00, .b = 0x00 };
|
||||
SDL_Surface *s = TTF_RenderText_Solid_Wrapped(font, str.c_str(), c, wrap_len_in_pixel);
|
||||
assert(s != NULL);
|
||||
SDL_Texture *t = SDL_CreateTextureFromSurface(renderer, s);
|
||||
assert(t != NULL);
|
||||
*w = s->w; *h = s->h;
|
||||
SDL_FreeSurface(s);
|
||||
return t;
|
||||
SDL_Texture* get_font_texture(uint8_t ch) {
|
||||
assert(ch < 128);
|
||||
return font[ch == 0 ? ' ' : ch];
|
||||
}
|
||||
|
||||
void close_font() {
|
||||
TTF_CloseFont(font);
|
||||
font = NULL;
|
||||
TTF_Quit();
|
||||
}
|
||||
|
|
|
@ -79,9 +79,8 @@ void nvboard_init(int vga_clk_cycle) {
|
|||
);
|
||||
SDL_SetRenderDrawColor(main_renderer, 0xff, 0xff, 0xff, 0);
|
||||
|
||||
void init_font();
|
||||
init_font();
|
||||
|
||||
void init_font(SDL_Renderer *renderer);
|
||||
init_font(main_renderer);
|
||||
init_render(main_renderer);
|
||||
init_components(main_renderer);
|
||||
init_gui(main_renderer);
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
#include <nvboard.h>
|
||||
#include <term.h>
|
||||
|
||||
SDL_Texture* get_font_texture(uint8_t ch);
|
||||
|
||||
Term::Term(SDL_Renderer *r, int x, int y, int w, int h):
|
||||
renderer(r), cursor_x(0), cursor_y(0), screen_y(0) {
|
||||
region = { .x = x, .y = y, .w = w, .h = h };
|
||||
w_in_char = region.w / 10;
|
||||
h_in_char = region.h / 16;
|
||||
uint8_t *l = new_line();
|
||||
memset(l, 'a', w_in_char);
|
||||
cursor_texture = new_texture(r, 10, 16, 0x10, 0x10, 0x10);
|
||||
}
|
||||
|
||||
Term::~Term() {
|
||||
SDL_DestroyTexture(cursor_texture);
|
||||
}
|
||||
|
||||
void Term::clear_screen() {
|
||||
SDL_RenderFillRect(renderer, ®ion);
|
||||
}
|
||||
|
||||
uint8_t* Term::new_line() {
|
||||
uint8_t *l = new uint8_t[w_in_char];
|
||||
memset(l, ' ', w_in_char);
|
||||
lines.push_back(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
void Term::feed_ch(uint8_t ch) {
|
||||
assert(ch < 128);
|
||||
int y = cursor_y;
|
||||
assert(y < lines.size());
|
||||
uint8_t *l = lines[y];
|
||||
l[cursor_x] = ch;
|
||||
cursor_x ++;
|
||||
if (cursor_x == w_in_char) {
|
||||
cursor_x = 0;
|
||||
cursor_y ++;
|
||||
if (cursor_y >= lines.size()) new_line();
|
||||
if (cursor_y == screen_y + h_in_char) screen_y ++; // scroll one line
|
||||
}
|
||||
}
|
||||
|
||||
void Term::draw_cursor() {
|
||||
if (cursor_y >= screen_y && cursor_y < screen_y + h_in_char) {
|
||||
int y = cursor_y - screen_y;
|
||||
int x = cursor_x;
|
||||
SDL_Rect rect = region;
|
||||
rect.w = 10, rect.h = 16;
|
||||
rect.y += 16 * y;
|
||||
rect.x += 10 * x;
|
||||
SDL_RenderCopy(renderer, cursor_texture, NULL, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
void Term::update_gui() {
|
||||
clear_screen();
|
||||
|
||||
SDL_Rect rect = region;
|
||||
int x_start = rect.x;
|
||||
rect.w = 10, rect.h = 16;
|
||||
for (int y = 0; y < h_in_char; y ++) {
|
||||
if (screen_y + y >= lines.size()) break;
|
||||
uint8_t *l = lines[screen_y + y];
|
||||
for (int x = 0; x < w_in_char; x ++) {
|
||||
uint8_t ch = l[x];
|
||||
SDL_Texture *t = get_font_texture(ch);
|
||||
SDL_RenderCopy(renderer, t, NULL, &rect);
|
||||
rect.x += 10;
|
||||
}
|
||||
rect.x = x_start;
|
||||
rect.y += 16;
|
||||
}
|
||||
draw_cursor();
|
||||
set_redraw();
|
||||
}
|
32
src/uart.cpp
32
src/uart.cpp
|
@ -3,14 +3,9 @@
|
|||
|
||||
UART* uart = NULL;
|
||||
|
||||
SDL_Texture* render_str(SDL_Renderer *renderer, std::string str, int wrap_len_in_pixel, int *w, int *h);
|
||||
|
||||
UART::UART(SDL_Renderer *rend, int cnt, int init_val, int ct):
|
||||
Component(rend, cnt, init_val, ct),
|
||||
region_w(WINDOW_WIDTH / 2), region_h(WINDOW_HEIGHT / 2), str(" ") {
|
||||
SDL_Texture *temp_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING, region_w, region_h);
|
||||
set_texture(temp_texture, 0);
|
||||
UART::UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int w, int h):
|
||||
Component(rend, cnt, init_val, ct) {
|
||||
term = new Term(rend, x, y, w, h);
|
||||
}
|
||||
|
||||
UART::~UART() {
|
||||
|
@ -18,15 +13,7 @@ UART::~UART() {
|
|||
}
|
||||
|
||||
void UART::update_gui() {
|
||||
SDL_Renderer *r = get_renderer();
|
||||
SDL_Rect rect = *get_rect(0);
|
||||
SDL_RenderFillRect(r, &rect);
|
||||
int w = 0, h = 0;
|
||||
SDL_Texture *t = render_str(r, str, region_w, &w, &h);
|
||||
rect.w = w; rect.h = h;
|
||||
SDL_RenderCopy(r, t, NULL, &rect);
|
||||
SDL_DestroyTexture(t);
|
||||
set_redraw();
|
||||
term->update_gui();
|
||||
}
|
||||
|
||||
void UART::update_state() {
|
||||
|
@ -34,15 +21,18 @@ void UART::update_state() {
|
|||
i ++;
|
||||
if (i < 10) return;
|
||||
i = 0;
|
||||
char last = str[str.length() - 1];
|
||||
str += last + 1;
|
||||
static uint8_t ch = ' ';
|
||||
ch += 1;
|
||||
if (ch == 128) ch = ' ';
|
||||
term->feed_ch(ch);
|
||||
update_gui();
|
||||
}
|
||||
|
||||
void init_uart(SDL_Renderer *renderer) {
|
||||
uart = new UART(renderer, 1, 0, UART_TYPE);
|
||||
int x = WINDOW_WIDTH / 2, y = 0, w = WINDOW_WIDTH / 2, h = WINDOW_HEIGHT / 2;
|
||||
uart = new UART(renderer, 1, 0, UART_TYPE, x, y, w, h);
|
||||
SDL_Rect *rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){WINDOW_WIDTH / 2, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2};
|
||||
*rect_ptr = (SDL_Rect){x, y, w, h};
|
||||
uart->set_rect(rect_ptr, 0);
|
||||
uart->add_pin(UART_TX);
|
||||
uart->add_pin(UART_RX);
|
||||
|
|
Loading…
Reference in New Issue