uart: support RX
This commit is contained in:
parent
28190b0c3e
commit
fd00b7854b
|
@ -7,5 +7,6 @@
|
|||
1. 拨动右边的8个拨码开关, 可控制对应LED的亮灭
|
||||
1. 按下按钮可将8~12号中对应的LED亮灭效果取反
|
||||
1. 8个数码管流水显示数字0-7
|
||||
1. 窗口右侧为VGA输出, 将会展示一张图片
|
||||
1. 窗口左下角为VGA输出, 将会展示一张图片
|
||||
1. 窗口右侧中部为UART RX输入, 鼠标选中后可输入字符串, 按回车后字符串将通过UART RX端输入, 通过回环连接从UART TX端输出, 显示在右上方终端
|
||||
1. 敲击键盘, 终端将会输出按键的扫描码
|
||||
|
|
|
@ -22,3 +22,6 @@ seg7 (SEG7A, SEG7B, SEG7C, SEG7D, SEG7E, SEG7F, SEG7G, DEC7P)
|
|||
|
||||
ps2_clk PS2_CLK
|
||||
ps2_data PS2_DAT
|
||||
|
||||
uart_tx UART_TX
|
||||
uart_rx UART_RX
|
||||
|
|
|
@ -5,6 +5,8 @@ module top(
|
|||
input [7:0] sw,
|
||||
input ps2_clk,
|
||||
input ps2_data,
|
||||
input uart_rx,
|
||||
output uart_tx,
|
||||
output [15:0] ledr,
|
||||
output VGA_CLK,
|
||||
output VGA_HSYNC,
|
||||
|
@ -77,6 +79,11 @@ vmem my_vmem(
|
|||
.vga_data(vga_data)
|
||||
);
|
||||
|
||||
uart my_uart(
|
||||
.tx(uart_tx),
|
||||
.rx(uart_rx)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module vmem(
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
module uart (
|
||||
output tx,
|
||||
input rx
|
||||
);
|
||||
assign tx = rx;
|
||||
endmodule
|
|
@ -8,10 +8,11 @@
|
|||
class UART : public Component{
|
||||
private:
|
||||
Term *tx_term, *rx_term;
|
||||
int state;
|
||||
int tx_state, rx_state;
|
||||
uint16_t divisor;
|
||||
uint8_t data;
|
||||
uint8_t tx_data, rx_data;
|
||||
std::string rx_input;
|
||||
std::string rx_sending_str;
|
||||
static constexpr const char *rx_input_prompt = "UART TX (Press Enter to issue): ";
|
||||
bool tx_update_gui, rx_update_gui;
|
||||
uint8_t *p_tx;
|
||||
|
@ -22,7 +23,8 @@ public:
|
|||
|
||||
virtual void update_gui();
|
||||
virtual void update_state();
|
||||
void tx_check();
|
||||
void tx_receive();
|
||||
void rx_send();
|
||||
void rx_getchar(uint8_t);
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,10 @@ void nvboard_update() {
|
|||
|
||||
extern UART* uart;
|
||||
extern int16_t uart_divisor_cnt;
|
||||
if (unlikely((-- uart_divisor_cnt) < 0)) uart->tx_check();
|
||||
if (unlikely((-- uart_divisor_cnt) < 0)) {
|
||||
uart->tx_receive();
|
||||
uart->rx_send();
|
||||
}
|
||||
|
||||
static uint64_t last = 0;
|
||||
static int cpf = 1; // count per frame
|
||||
|
|
44
src/uart.cpp
44
src/uart.cpp
|
@ -10,7 +10,7 @@ int16_t uart_divisor_cnt = 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),
|
||||
state(0), divisor(16), tx_update_gui(false) {
|
||||
tx_state(0), rx_state(0), divisor(16), tx_update_gui(false) {
|
||||
tx_term = new Term(rend, x, y, w, h);
|
||||
rx_term = new Term(rend, x, y + h, w, 20);
|
||||
uart_divisor_cnt = divisor - 1;
|
||||
|
@ -20,7 +20,9 @@ UART::UART(SDL_Renderer *rend, int cnt, int init_val, int ct, int x, int y, int
|
|||
|
||||
rx_term->feed_str(rx_input_prompt);
|
||||
rx_input = "";
|
||||
rx_sending_str = "";
|
||||
rx_update_gui = true;
|
||||
pin_poke(UART_RX, 1);
|
||||
}
|
||||
|
||||
UART::~UART() {
|
||||
|
@ -30,30 +32,48 @@ UART::~UART() {
|
|||
void UART::update_gui() { // everything is done in update_state()
|
||||
}
|
||||
|
||||
void UART::tx_check() {
|
||||
void UART::tx_receive() {
|
||||
uart_divisor_cnt = divisor - 1;
|
||||
|
||||
uint8_t tx = *p_tx;
|
||||
if (state == 0) { // idle
|
||||
if (tx_state == 0) { // idle
|
||||
if (!tx) { // start bit
|
||||
data = 0;
|
||||
state ++;
|
||||
tx_data = 0;
|
||||
tx_state ++;
|
||||
}
|
||||
} else if (state >= 1 && state <= 8) { // data
|
||||
data = (tx << 7) | (data >> 1); // data bit
|
||||
state ++;
|
||||
} else if (state == 9) {
|
||||
} else if (tx_state >= 1 && tx_state <= 8) { // data
|
||||
tx_data = (tx << 7) | (tx_data >> 1); // data bit
|
||||
tx_state ++;
|
||||
} else if (tx_state == 9) {
|
||||
if (tx) { // stop bit
|
||||
state = 0;
|
||||
tx_term->feed_ch(data);
|
||||
tx_state = 0;
|
||||
tx_term->feed_ch(tx_data);
|
||||
tx_update_gui = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UART::rx_send() {
|
||||
// the uart_divisor_cnt is maintained in tx_receive()
|
||||
if (rx_state == 0) { // idle
|
||||
rx_data = rx_sending_str[0];
|
||||
if (rx_data == '\0') return;
|
||||
rx_sending_str.erase(0, 1);
|
||||
pin_poke(UART_RX, 0); // start bit
|
||||
rx_state ++;
|
||||
} else if (rx_state >= 1 && rx_state <= 8) { // data
|
||||
pin_poke(UART_RX, rx_data & 1); // data bit
|
||||
rx_data >>= 1;
|
||||
rx_state ++;
|
||||
} else if (rx_state == 9) {
|
||||
pin_poke(UART_RX, 1); // stop bit
|
||||
rx_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UART::rx_getchar(uint8_t ch) {
|
||||
if (ch == '\n') {
|
||||
printf("Get RX input = %s\n", rx_input.c_str());
|
||||
rx_sending_str += rx_input;
|
||||
rx_term->clear();
|
||||
rx_term->feed_str(rx_input_prompt);
|
||||
rx_input = "";
|
||||
|
|
Loading…
Reference in New Issue