/* * Copyright (C) 2017 The Contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * A copy of the GNU General Public License can be found in the file * "gpl.txt" in the top directory of this repository. */ #include #define ver(...) _ver(kbd_verbose, 0, __VA_ARGS__) #define ver2(...) _ver(kbd_verbose, 1, __VA_ARGS__) #define ver3(...) _ver(kbd_verbose, 2, __VA_ARGS__) int32_t kbd_verbose = 0; #define BUF_SZ 16 static int32_t buf_hd = 0; static int32_t buf_tl = 0; static uint8_t buf[BUF_SZ]; static uint8_t reg = 0; static bool irq = false; static void xmit(void) { ver2("kbd xmit %d %d", buf_tl, buf_hd); if (buf_tl >= buf_hd) { return; } reg = buf[buf_tl % BUF_SZ]; irq = true; ver2("kbd xmit 0x%02x", reg); ++buf_tl; if (buf_tl >= BUF_SZ) { buf_hd -= BUF_SZ; buf_tl -= BUF_SZ; ver2("kbd adj %d %d", buf_tl, buf_hd); } } static void out(uint8_t c) { ver2("kbd out %d %d 0x%02x", buf_tl, buf_hd, c); if (SDL_LockMutex(cpu_mutex) < 0) { fail("SDL_LockMutex() failed: %s", SDL_GetError()); } if (buf_hd >= buf_tl + BUF_SZ) { err("keyboard port losing data"); } else { buf[buf_hd % BUF_SZ] = c; ++buf_hd; if (!irq) { xmit(); } } if (SDL_UnlockMutex(cpu_mutex) < 0) { fail("SDL_UnlockMutex() failed: %s", SDL_GetError()); } } static void but_on(int32_t sig) { out((uint8_t)(0x80 | sig)); out(0x01); } static void but_off(int32_t sig) { out((uint8_t)(0x80 | sig)); out(0x00); } #if defined NOT_YET static void key_touch(int32_t sig, int32_t val) { out((uint8_t)(0x80 | sig)); out(0x01); out((uint8_t)val); } static void key_off(int32_t sig) { out((uint8_t)(0x80 | sig)); out(0x00); } static void pot_128(int32_t sig, int32_t val) { out((uint8_t)(0x80 | sig)); out((uint8_t)val); } static void pot_256(int32_t sig, int32_t val) { out((uint8_t)(0x80 | sig)); out((uint8_t)((val >> 7) & 0x01)); out((uint8_t)(val & 0x7f)); } #endif void kbd_key(SDL_KeyboardEvent *ev) { (void)ev; } void kbd_text(SDL_TextInputEvent *ev) { for (int32_t i = 0; ev->text[i] != 0; ++i) { if (ev->text[i] >= '0' && ev->text[i] <= '9') { int32_t sig = 60 + ev->text[i] - '0'; but_on(sig); but_off(sig); continue; } switch (ev->text[i]) { case 'x': but_on(70); but_off(70); break; case 'e': but_on(71); but_off(71); break; case 'm': but_on(72); but_off(72); break; } } } void kbd_init(void) { ver("kbd init"); } void kbd_quit(void) { ver("kbd quit"); } bool kbd_exec(void) { ver3("kbd exec"); return irq; } uint32_t kbd_read(uint32_t off, int32_t sz) { ver2("kbd rd %u:%d", off, sz * 8); if (sz != 1 || off > 0) { fail("invalid kbd rd %u:%d", off, sz * 8); } irq = false; uint32_t res = reg; xmit(); return res; } void kbd_write(uint32_t off, int32_t sz, uint32_t val) { ver2("kbd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); fail("invalid kbd wr %u:%d", off, sz * 8); }