diff options
Diffstat (limited to 'tb/jtag_uart.cpp')
| -rw-r--r-- | tb/jtag_uart.cpp | 110 |
1 files changed, 102 insertions, 8 deletions
diff --git a/tb/jtag_uart.cpp b/tb/jtag_uart.cpp index 78d438e..3bef42e 100644 --- a/tb/jtag_uart.cpp +++ b/tb/jtag_uart.cpp @@ -1,3 +1,7 @@ +#include <cstdint> + +#include <ncursesw/ncurses.h> + #include "avalon.hpp" #include "jtag_uart.hpp" @@ -7,22 +11,87 @@ namespace taller::avalon : slave(base, 8, 4) {} + jtag_uart::~jtag_uart() noexcept + { + release(); + } + + void jtag_uart::tick() noexcept + { + if(!took_over || rx_avail == sizeof rx) + { + return; + } + + if(countdown > 0) + { + --countdown; + return; + } + + countdown = 10'000; + + int input = getch(); + if(input != ERR) + { + unsigned index = rx_next + rx_avail; + if(index >= sizeof rx) + { + index -= sizeof rx; + } + + rx[index] = input; + ++rx_avail; + } + + ctrl_ac = 1; + } + bool jtag_uart::read(std::uint32_t addr, std::uint32_t &data) noexcept { + bool valid_read; + bool ctrl_ri; + bool ctrl_wi; + bool ctrl_rrdy; + + std::uint8_t read; + switch(addr) { case 0: - data = 0; //TODO + read = rx[rx_next]; + valid_read = rx_avail > 0; + + if(valid_read) + { + --rx_avail; + rx_next = rx_next + 1 < sizeof rx ? rx_next + 1 : 0; + } + + data + = rx_avail << 16 + | valid_read << 15 + | (read & 0xff); + break; case 1: - data = - static_cast<std::uint32_t>(ctrl_re) << 0 - | static_cast<std::uint32_t>(ctrl_we) << 1 - //TODO: varios bits - | static_cast<std::uint32_t>(ctrl_ac) << 10 - //TODO: disponibilidad de tx fifo - | static_cast<std::uint32_t>(255) << 10; + ctrl_ri = ctrl_re && rx_avail > 0; + + // Siempre se puede escribir + ctrl_wi = ctrl_we; + + // Este bit no existe pero U-Boot lo espera por alguna razón + ctrl_rrdy = rx_avail > 0; + + data + = ctrl_re << 0 + | ctrl_we << 1 + | ctrl_ri << 8 + | ctrl_wi << 9 + | ctrl_ac << 10 + | ctrl_rrdy << 12 + | 63 << 16; break; } @@ -36,6 +105,8 @@ namespace taller::avalon { case 0: putchar(data & 0xff); + fflush(stdout); + ctrl_ac = 1; break; @@ -52,4 +123,27 @@ namespace taller::avalon return true; } + + void jtag_uart::takeover() noexcept + { + if(took_over) + { + return; + } + + assert(::initscr() != nullptr); + assert(::noecho() != ERR); + assert(::nodelay(stdscr, TRUE) != ERR); + assert(::cbreak() != ERR); + + took_over = true; + } + + void jtag_uart::release() noexcept + { + if(took_over) + { + ::endwin(); + } + } } |
