uart: support TX

This commit is contained in:
Zihao Yu 2024-01-04 02:50:08 +08:00
parent f4d22b5b16
commit 61f89b2aa7
5 changed files with 43 additions and 11 deletions

View File

@ -147,3 +147,6 @@ output VGA_B7
input PS2_CLK input PS2_CLK
input PS2_DAT input PS2_DAT
output UART_TX
input UART_RX

View File

@ -7,9 +7,14 @@
class UART : public Component{ class UART : public Component{
private: private:
Term *term; Term *term;
int state;
uint16_t divisor;
uint16_t divisor_cnt;
uint8_t data;
public: public:
UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int w, int h); UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int w, int h);
~UART(); ~UART();
void set_divisor(uint16_t d);
virtual void update_gui(); virtual void update_gui();
virtual void update_state(); virtual void update_state();

View File

@ -1,6 +1,7 @@
#include <nvboard.h> #include <nvboard.h>
#include <keyboard.h> #include <keyboard.h>
#include <vga.h> #include <vga.h>
#include <uart.h>
#include <sys/time.h> #include <sys/time.h>
#include <stdarg.h> #include <stdarg.h>
@ -36,6 +37,10 @@ void nvboard_update() {
extern bool is_kb_idle; extern bool is_kb_idle;
if (!is_kb_idle) kb->update_state(); if (!is_kb_idle) kb->update_state();
extern UART* uart;
extern bool is_uart_idle;
if (!(is_uart_idle && pin_peek(UART_TX))) uart->update_state();
static uint64_t last = 0; static uint64_t last = 0;
static uint32_t cpf = 0; // count per frame static uint32_t cpf = 0; // count per frame
static uint32_t cnt = 0; static uint32_t cnt = 0;

View File

@ -9,7 +9,6 @@ Term::Term(SDL_Renderer *r, int x, int y, int w, int h):
w_in_char = region.w / 10; w_in_char = region.w / 10;
h_in_char = region.h / 16; h_in_char = region.h / 16;
uint8_t *l = new_line(); uint8_t *l = new_line();
memset(l, 'a', w_in_char);
cursor_texture = new_texture(r, 10, 16, 0x10, 0x10, 0x10); cursor_texture = new_texture(r, 10, 16, 0x10, 0x10, 0x10);
} }

View File

@ -2,9 +2,11 @@
#include <uart.h> #include <uart.h>
UART* uart = NULL; UART* uart = NULL;
bool is_uart_idle = true;
UART::UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int w, int h): 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) { Component(rend, cnt, init_val, ct),
state(0), divisor(16), divisor_cnt(1) {
term = new Term(rend, x, y, w, h); term = new Term(rend, x, y, w, h);
} }
@ -17,15 +19,33 @@ void UART::update_gui() {
} }
void UART::update_state() { void UART::update_state() {
static int i = 0; if (divisor_cnt < divisor) {
i ++; divisor_cnt ++;
if (i < 10) return; return;
i = 0; }
static uint8_t ch = ' '; divisor_cnt = 1;
ch += 1;
if (ch == 128) ch = ' '; uint8_t tx = pin_peek(UART_TX);
term->feed_ch(ch); if (state == 0) { // idle
update_gui(); if (!tx) { // start bit
data = 0;
is_uart_idle = false;
state ++;
}
} else if (state >= 1 && state <= 8) { // data
data = (tx << 7) | (data >> 1); // data bit
state ++;
} else if (state == 9) {
if (tx) {
term->feed_ch(data); update_gui();
state = 0;
is_uart_idle = true;
} // stop bit
}
}
void UART::set_divisor(uint16_t d) {
divisor = d;
} }
void init_uart(SDL_Renderer *renderer) { void init_uart(SDL_Renderer *renderer) {