From ccc032b379844f69aaf036e1787da0e8a0e35c20 Mon Sep 17 00:00:00 2001 From: n loewen Date: Tue, 29 Aug 2023 09:49:21 -0400 Subject: [PATCH] Move display functions to `io.js`, and re-implement keypad in `io.js` --- src/cardiograph.js | 28 +++++++++++++--------------- src/display.js | 22 ---------------------- src/io.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 37 deletions(-) delete mode 100644 src/display.js create mode 100644 src/io.js diff --git a/src/cardiograph.js b/src/cardiograph.js index c227129..68ddf59 100644 --- a/src/cardiograph.js +++ b/src/cardiograph.js @@ -1,14 +1,13 @@ -const CFG = require('./machine.config'); -const CPU = require('./cpu.lib.js'); - const { num2hex, bool2bit } = require('./logging.js'); -const display = require('./display.js'); - // TODO TEMPORARY - replace with reading STDIN: +const CFG = require('./machine.config.js'); +const CPU = require('./cpu.js'); +const io = require('./io.js'); + + +// TODO TEMPORARY - replace with reading STDIN: const assembler = require('./assembler.js'); const fs = require('fs'); -const { log } = require('console'); - const filename = process.argv[2]; const inputFile_str = fs.readFileSync(filename, 'utf8'); @@ -16,14 +15,15 @@ const { log } = require('console'); let cpu = new CPU(CFG.INITIAL_IP_ADDRESS, CFG.DEFAULT_CYCLE_LIMIT); -cpu.loadMemory(assemblerOutput.machineCode); // TODO -cpu.loadSourceInfo(assemblerOutput.debugInfo); // TODO +cpu.loadMemory(assemblerOutput.machineCode); +cpu.loadSourceInfo(assemblerOutput.debugInfo); cpu.onCycleEnd(tick); cpu.onCycleEnd(logDisplay); cpu.onCycleEnd(logCPUState); cpu.start(); +io.getKeypadInput(cpu); cpu.step(); async function tick() { @@ -37,7 +37,7 @@ async function tick() { } function logDisplay() { - display.show(cpu.memory, true); + io.showDisplay(cpu.memory, true); // TODO more compled printing } function logCPUState() { @@ -52,9 +52,7 @@ function logCPUState() { console.log(`Machine: $${num2hex(cpu.instruction.opcode)} $${num2hex(cpu.instruction.operand)}`); console.log(); console.log(`IP: $${num2hex(cpu.IP)} Acc: $${num2hex(cpu.acc)} ONZC ${bool2bit(cpu.flags.O)}${bool2bit(cpu.flags.N)}${bool2bit(cpu.flags.Z)}${bool2bit(cpu.flags.C)}`); - // TODO: - // console.log(`KEY: $${num2hex(cpu.state.memory[KEYPAD_ADDR])}  ${cpu.state.running ? "state.running" : "halted" }`); - console.log(); + console.log(`KEY: ${io.readKeyMem(cpu.memory)} ${cpu.running ? "running" : "halted" }`); console.log(); console.groupEnd(); }; @@ -62,12 +60,12 @@ function logCPUState() { /* (async function() { - let input = await getInput(); + let input = await readPipedStdin(); console.log(input); })() */ -async function getInput() { +async function readPipedStdin() { // https://wellingguzman.com/notes/node-pipe-input return new Promise(function (resolve, reject) { const stdin = process.stdin; diff --git a/src/display.js b/src/display.js deleted file mode 100644 index efa4c34..0000000 --- a/src/display.js +++ /dev/null @@ -1,22 +0,0 @@ -const { POINTER_TO_DISPLAY } = require('./machine.config'); -const { num2hex } = require('./logging.js'); - -/** - * Print the contents of display memory - * by default, each pixel is shown as a hex number - * @param {Uint8Array} mem - CPU memory - * @param {Boolean} pretty - Display pixels using black and white emoji circles - **/ -const printDisplay = (mem, pretty=false) => { - const disp = mem[POINTER_TO_DISPLAY]; - const num2pic = (n) => n > 0 ? '⚫' : '⚪'; - let fmt = (n) => num2hex(n); - if (pretty) fmt = (n) => num2pic(n); - for (let i = disp; i < disp + 25; i += 5) { - console.log(`${fmt(mem[i])} ${fmt(mem[i+1])} ${fmt(mem[i+2])} ${fmt(mem[i+3])} ${fmt(mem[i+4])}`); - } -} - -module.exports = { - "show": printDisplay, -} \ No newline at end of file diff --git a/src/io.js b/src/io.js new file mode 100644 index 0000000..364bd12 --- /dev/null +++ b/src/io.js @@ -0,0 +1,45 @@ +const readline = require('readline'); + +const CFG = require('./machine.config.js'); +const { num2hex } = require('./logging.js'); + +function readKeyMem(mem) { + return mem[CFG.KEYPAD_ADDR]; +} + +function getKeypadInput(cpu) { + readline.emitKeypressEvents(process.stdin); + if (process.stdin.setRawMode != null) { + process.stdin.setRawMode(true); + } + process.stdin.on('keypress', (str, key) => { + // TODO: is it possible to turn this off again? + if (key.sequence === '\x03') process.exit(); + let name = key.name.toUpperCase(); + if (name in CFG.KEY_MAP) { + cpu.memory[CFG.KEYPAD_ADDR] = CFG.KEY_MAP[name]; + } + }); +} + +/** + * Print the contents of display memory + * by default, each pixel is shown as a hex number + * @param {Uint8Array} mem - CPU memory + * @param {Boolean} pretty - Display pixels using black and white emoji circles + **/ +function showDisplay(mem, pretty=false) { + const disp = mem[CFG.POINTER_TO_DISPLAY]; + const num2pic = (n) => n > 0 ? '⚫' : '⚪'; + let fmt = (n) => num2hex(n); + if (pretty) fmt = (n) => num2pic(n); + for (let i = disp; i < disp + 25; i += 5) { + console.log(`${fmt(mem[i])} ${fmt(mem[i+1])} ${fmt(mem[i+2])} ${fmt(mem[i+3])} ${fmt(mem[i+4])}`); + } +} + +module.exports = { + "showDisplay": showDisplay, + "getKeypadInput": getKeypadInput, + "readKeyMem": readKeyMem, +} \ No newline at end of file