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_DAT
output UART_TX
input UART_RX

View File

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

View File

@ -1,6 +1,7 @@
#include <nvboard.h>
#include <keyboard.h>
#include <vga.h>
#include <uart.h>
#include <sys/time.h>
#include <stdarg.h>
@ -36,6 +37,10 @@ void nvboard_update() {
extern bool is_kb_idle;
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 uint32_t cpf = 0; // count per frame
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;
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);
}

View File

@ -2,9 +2,11 @@
#include <uart.h>
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):
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);
}
@ -17,15 +19,33 @@ void UART::update_gui() {
}
void UART::update_state() {
static int i = 0;
i ++;
if (i < 10) return;
i = 0;
static uint8_t ch = ' ';
ch += 1;
if (ch == 128) ch = ' ';
term->feed_ch(ch);
update_gui();
if (divisor_cnt < divisor) {
divisor_cnt ++;
return;
}
divisor_cnt = 1;
uint8_t tx = pin_peek(UART_TX);
if (state == 0) { // idle
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) {