summaryrefslogtreecommitdiff
path: root/tb/jtag_uart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tb/jtag_uart.cpp')
-rw-r--r--tb/jtag_uart.cpp110
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();
+ }
+ }
}