diff --git a/include/lupi.h b/include/lupi.h index 5fe4066..7f89ac4 100644 --- a/include/lupi.h +++ b/include/lupi.h @@ -4,12 +4,35 @@ #ifndef LUPI_H #define LUPI_H +//#define LOGGING +#ifdef LOGGING +void logn(const char *message); +void logi(int message); +void logm(const char *message); +#else + #define logn(m) + #define logi(m) + #define logm(m) +#endif + //TODO: move to utils #define pushstuple(state, name, value) lua_pushstring((state), (name)); lua_pushstring((state), (value)); lua_settable((state), -3) #define pushctuple(state, name, value) lua_pushstring((state), (name)); lua_pushcfunction((state), (value)); lua_settable((state), -3) +lua_State* getL(); + void run_init(); void luanative_start(lua_State *L); void setup_modules(lua_State *L); void termutils_start(lua_State *L); +void epoll_prepare(); +int epoll_pull(int timeout); + +struct lupi_event_handler { + int (*handler)(int, void*); //FD, data, return number of pushed events + //TODO: doc? + int fd; + void* data; +}; + #endif diff --git a/src/c/epoll.c b/src/c/epoll.c new file mode 100644 index 0000000..34c63db --- /dev/null +++ b/src/c/epoll.c @@ -0,0 +1,70 @@ +#include "lupi.h" +#include +#include +#include +#include +#include +#include + +static int epollfd; + +static int handleStdin(int fd, void* data) { + char buf; + int r = read(fd, &buf, 1); //TODO: Wide chars? + if(r > 0) { + if(buf == 10) buf = 13; + lua_State* L = getL(); + + lua_getglobal(L, "pushEvent"); + lua_pushstring(L, "key_down"); + lua_pushstring(L, "TODO:SetThisUuid"); + lua_pushnumber(L, buf); + lua_pushnumber(L, -1); + lua_pushstring(L, "user"); + lua_call(L, 5, 0); + + lua_getglobal(L, "pushEvent"); + lua_pushstring(L, "key_up"); + lua_pushstring(L, "TODO:SetThisUuid"); + lua_pushnumber(L, buf); + lua_pushnumber(L, -1); + lua_pushstring(L, "user"); + lua_call(L, 5, 0); + + return 2; + } + return 0; +} + +void epoll_prepare() { + if ((epollfd = epoll_create1(0)) < 0) { + perror("epoll_create"); + exit(EXIT_FAILURE); + } + + struct lupi_event_handler* stdin_handler = malloc(sizeof(struct lupi_event_handler)); + stdin_handler->data = NULL; + stdin_handler->handler = handleStdin; + stdin_handler->fd = STDIN_FILENO; + + struct epoll_event stdinEvent; + stdinEvent.events = EPOLLIN | EPOLLPRI; + stdinEvent.data.ptr = stdin_handler; + + if ((epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &stdinEvent) < 0)) { + perror("epoll_ctl"); + exit(EXIT_FAILURE); + } +} + +int epoll_pull(int timeout) { + struct epoll_event evBuffer; + int pushed = 0; + + int eres = epoll_wait(epollfd, &evBuffer, 1, timeout); + if(eres > 0) { + struct lupi_event_handler* handler = (struct lupi_event_handler*)evBuffer.data.ptr; + pushed = handler->handler(handler->fd, handler->data); + } + return pushed; +} diff --git a/src/c/lnative.c b/src/c/lnative.c index 98a8ef2..8f72a5b 100644 --- a/src/c/lnative.c +++ b/src/c/lnative.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -17,9 +18,9 @@ #include #include - +//Enable in lupi.h #ifdef LOGGING -void logn (const char *message) { +void logn(const char *message) { FILE *file; file = fopen("lupi.log", "a"); @@ -33,7 +34,7 @@ void logn (const char *message) { } } -void logi (int message) { +void logi(int message) { FILE *file; file = fopen("lupi.log", "a"); @@ -48,7 +49,7 @@ void logi (int message) { } } -void logm (const char *message) { +void logm(const char *message) { FILE *file; file = fopen("lupi.log", "a"); @@ -273,6 +274,11 @@ static int l_fs_size (lua_State *L) { static int l_fs_read (lua_State *L) { unsigned int fd = lua_tonumber(L, 1); unsigned int count = lua_tonumber(L, 2); + size_t cur = lseek(fd, 0, SEEK_CUR); + size_t end = lseek(fd, 0, SEEK_END); + lseek(fd, cur, SEEK_SET); + if(count > end - cur) + count = end - cur; void* buf = malloc(count); size_t res = read(fd, buf, count); logm("read("); @@ -282,6 +288,7 @@ static int l_fs_read (lua_State *L) { logm(" of "); logi(count); logn(""); + if(res > 0) { lua_pushlstring(L, buf, res); free(buf); @@ -339,6 +346,10 @@ static int l_freeMemory (lua_State *L) { return 1; } +static int l_pull (lua_State *L) { + lua_pushnumber(L, epoll_pull(lua_tonumber(L, 1))); + return 1; +} void luanative_start(lua_State *L) { lua_createtable (L, 0, 1); @@ -365,6 +376,7 @@ void luanative_start(lua_State *L) { pushctuple(L, "uptime", l_uptime); pushctuple(L, "totalMemory", l_totalMemory); pushctuple(L, "freeMemory", l_freeMemory); + pushctuple(L, "pull", l_pull); lua_setglobal(L, "native"); } \ No newline at end of file diff --git a/src/c/run.c b/src/c/run.c index 0282967..78491b8 100644 --- a/src/c/run.c +++ b/src/c/run.c @@ -14,14 +14,20 @@ #include #include +static lua_State* L = NULL; + +lua_State* getL() { + return L; +} + void run_init() { - lua_State *L; L = luaL_newstate(); luaL_openlibs (L); setup_modules (L); luanative_start (L); termutils_start (L); + epoll_prepare(); //int status = luaL_loadstring(L, lua_init); int status = luaL_loadbuffer(L, lua_init, strlen(lua_init), "=INIT"); diff --git a/src/c/termutils.c b/src/c/termutils.c index 73c36d5..e29c4a2 100644 --- a/src/c/termutils.c +++ b/src/c/termutils.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,14 @@ static int l_get_term_sz (lua_State *L) { void termutils_start(lua_State *L) { signal(SIGWINCH, handle_winch); + struct termios old, new; + if (tcgetattr (STDOUT_FILENO, &old) != 0) + return; + new = old; + new.c_lflag &= ~ECHO; + if (tcsetattr (STDOUT_FILENO, TCSAFLUSH, &new) != 0) + return; + lua_createtable (L, 0, 1); pushctuple(L, "getSize", l_get_term_sz); diff --git a/src/lua/core/computer.lua b/src/lua/core/computer.lua index 531cf3e..e05d195 100644 --- a/src/lua/core/computer.lua +++ b/src/lua/core/computer.lua @@ -13,18 +13,120 @@ function api.address() end local signalQueue = {} +computer.signalTransformers = setmetatable({}, {__index = function(t, k) + return function(...) + return ... + end +end}) -function api.pushSignal(...) - signalQueue[#signalQueue + 1] = {...} +----- +--TODO: Move this out +local keymap = { + [48] = 0x2, + [49] = 0x3, + [50] = 0x4, + [51] = 0x5, + [52] = 0x6, + [53] = 0x7, + [54] = 0x8, + [55] = 0x9, + [56] = 0xA, + [57] = 0xB, + + [0x40 + 0x01] = 0x1E, + [0x40 + 0x02] = 0x30, + [0x40 + 0x04] = 0x2E, + [0x40 + 0x05] = 0x20, + [0x40 + 0x06] = 0x12, + [0x40 + 0x07] = 0x21, + [0x40 + 0x08] = 0x22, + [0x40 + 0x09] = 0x23, + [0x40 + 0x0A] = 0x17, + [0x40 + 0x0B] = 0x24, + [0x40 + 0x0C] = 0x25, + [0x40 + 0x0D] = 0x26, + [0x40 + 0x0E] = 0x32, + [0x40 + 0x0F] = 0x31, + [0x40 + 0x11] = 0x18, + [0x40 + 0x12] = 0x19, + [0x40 + 0x13] = 0x10, + [0x40 + 0x14] = 0x13, + [0x40 + 0x15] = 0x1F, + [0x40 + 0x16] = 0x14, + [0x40 + 0x17] = 0x16, + [0x40 + 0x18] = 0x2F, + [0x40 + 0x19] = 0x11, + [0x40 + 0x1A] = 0x2D, + [0x40 + 0x1B] = 0x15, + [0x40 + 0x1C] = 0x2C, + + [0x60 + 0x01] = 0x1E, + [0x60 + 0x02] = 0x30, + [0x60 + 0x04] = 0x2E, + [0x60 + 0x05] = 0x20, + [0x60 + 0x06] = 0x12, + [0x60 + 0x07] = 0x21, + [0x60 + 0x08] = 0x22, + [0x60 + 0x09] = 0x23, + [0x60 + 0x0A] = 0x17, + [0x60 + 0x0B] = 0x24, + [0x60 + 0x0C] = 0x25, + [0x60 + 0x0D] = 0x26, + [0x60 + 0x0E] = 0x32, + [0x60 + 0x0F] = 0x31, + [0x60 + 0x11] = 0x18, + [0x60 + 0x12] = 0x19, + [0x60 + 0x13] = 0x10, + [0x60 + 0x14] = 0x13, + [0x60 + 0x15] = 0x1F, + [0x60 + 0x16] = 0x14, + [0x60 + 0x17] = 0x16, + [0x60 + 0x18] = 0x2F, + [0x60 + 0x19] = 0x11, + [0x60 + 0x1A] = 0x2D, + [0x60 + 0x1B] = 0x15, + [0x60 + 0x1C] = 0x2C, + + [13] = 28, + +} + +function computer.signalTransformers.key_down(s, a, ascii, key, user) + if key ~= -1 then + return s, a, ascii, key, user + end + return s, a, ascii, keymap[ascii] or key, user +end + +function computer.signalTransformers.key_up(s, a, ascii, key, user) + if key ~= -1 then + return s, a, ascii, key, user + end + return s, a, ascii, keymap[ascii] or key, user +end + +----- + +function api.pushSignal(s, ...) + io.stderr:write("pushSignal "..s.."\n") + signalQueue[#signalQueue + 1] = {computer.signalTransformers[s](s, ...)} end function api.pullSignal(timeout) - if signalQueue[1] then return table.remove(signalQueue, 1) end - if type(timeout) == "number" then - native.sleep(timeout * 1000000); + if signalQueue[1] then return table.unpack(table.remove(signalQueue, 1)) end + local timeoutuptime = math.huge + + if not timeout then + timeout = -1 + else + timeout = timeout * 1000 + timeoutuptime = native.uptime() + timeout end - if signalQueue[1] then return table.remove(signalQueue, 1) end - --print(debug.traceback()) + local nevts = 0 + repeat + nevts = native.pull(timeout) + until nevts > 0 or native.uptime() > timeoutuptime + if signalQueue[1] then return table.unpack(table.remove(signalQueue, 1)) end end function api.uptime() diff --git a/src/lua/core/filesystem.lua b/src/lua/core/filesystem.lua index 12e52cc..4443bf7 100644 --- a/src/lua/core/filesystem.lua +++ b/src/lua/core/filesystem.lua @@ -137,7 +137,7 @@ function filesystem.register(basePath) end function fs.close(handle) checkArg(1, handle, "number") - return native.fs_close() + return native.fs_close(handle) end function fs.size(path) checkArg(1, path, "string") diff --git a/src/lua/core/init.lua b/src/lua/core/init.lua index 0585b91..9d0a234 100644 --- a/src/lua/core/init.lua +++ b/src/lua/core/init.lua @@ -64,6 +64,7 @@ function main() --Setup core modules modules.component.prepare() modules.computer.prepare() + _G.pushEvent = modules.computer.api.pushSignal modules.eeprom.register() modules.filesystem.register("root") diff --git a/src/lua/core/sandbox.lua b/src/lua/core/sandbox.lua index 4fe4375..209ae06 100644 --- a/src/lua/core/sandbox.lua +++ b/src/lua/core/sandbox.lua @@ -164,11 +164,11 @@ sandbox = { char = utf8.char, charWidth = function(c) checkArg(1, c, "string") - return modules.utf8.utf8charbytes(c) + return modules.utf8.charbytes(c) end, isWide = function(c) checkArg(1, c, "string") - return modules.utf8.utf8charbytes(c) > 1 + return modules.utf8.charbytes(c) > 1 end, len = utf8.len, lower = modules.utf8.lower, diff --git a/src/lua/core/textgpu.lua b/src/lua/core/textgpu.lua index 9ab13ee..84dcecc 100644 --- a/src/lua/core/textgpu.lua +++ b/src/lua/core/textgpu.lua @@ -51,9 +51,11 @@ function textgpu.start() if isPaletteIndex then return --TODO: Maybe? end + local old = foreground background = tostring(math.floor(modules.color.nearest(color, mapping))) io.write("\x1b[4" .. background .. "m") io.flush() + return mapping[old] end function gpu.setForeground(color, isPaletteIndex) checkArg(1, color, "number") @@ -61,9 +63,11 @@ function textgpu.start() if isPaletteIndex then return --TODO: Maybe? end + local old = foreground foreground = tostring(math.floor(modules.color.nearest(color, mapping))) io.write("\x1b[3" .. foreground .. "m") io.flush() + return mapping[old] end function gpu.getBackground() return mapping[background], false @@ -92,6 +96,14 @@ function textgpu.start() function gpu.getResolution() return termutils.getSize() end + function gpu.getViewport() + return termutils.getSize() + end + function gpu.setViewport(w, h) + checkArg(1, w, "number") + checkArg(2, h, "number") + return false, "Viewport not supported for this gpu" + end function gpu.setResolution(w, h) checkArg(1, w, "number") checkArg(2, h, "number")