;(function(w, d) { var screenBuffer = "", inputBuffer = "", screenDom, inputRes = "", floader, vm /* screen rendering routine */ function renderScreen() { screenDom.textContent = screenBuffer + inputBuffer + "\u258f" screenDom.scrollTop = screenDom.scrollHeight } /* external program loading routine */ function loadProgFileHandler(e) { if(e.target.files.length > 0) { var fobj = e.target.files[0], rdr = new FileReader() rdr.onload = function() { var progsrc = rdr.result if(progsrc.length > 0) { var instrs = progsrc.split(/\s+/), i, l = instrs.length, instr, lno, cmd, x, y, z, icount = 0 for(i=0;i ") } } if(fobj) rdr.readAsText(fobj) } } /* main input routine: * digits 0 to 9, 10 is space, * 11 is minus/backspace, 12 is enter, 13 is decimal point, * 14 is program load action */ function doInput(number) { if(number >= 0 && number < 10) /* normal digit */ inputBuffer += ("" + number) else if(number == 10) /* space */ inputBuffer += " " else if(number == 11) { /* backspace or minus */ if(inputBuffer.length == 0) inputBuffer += "-" else inputBuffer = inputBuffer.slice(0, inputBuffer.length - 1) } else if(number == 12) { /* enter */ screenBuffer += inputBuffer + "\n" inputRes = inputBuffer inputBuffer = "" } else if(number == 13) /* decimal point */ inputBuffer += "." else if(number == 14) floader.click() /* trigger program loader */ renderScreen() } function setupInput() { /* setup physical keys */ w.addEventListener("keydown", function(e) { switch(e.key) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": e.preventDefault() doInput(parseInt(e.key)) break case "+": case "/": case " ": case "Call": case "ArrowDown": e.preventDefault() doInput(10) break case "Backspace": case "Back": case "ArrowLeft": case "Delete": case "-": e.preventDefault() e.stopPropagation() doInput(11) break case "#": case "Enter": e.preventDefault() doInput(12) break case "*": case ",": case ".": e.preventDefault() doInput(13) break case "l": case "L": case "ArrowUp": case "SoftLeft": e.preventDefault() doInput(14) break } }, false) /* setup virtual keys */ w.addEventListener("click", function(e) { switch(e.target.id) { case "b0": case "b1": case "b2": case "b3": case "b4": case "b5": case "b6": case "b7": case "b8": case "b9": e.preventDefault() doInput(parseInt(e.target.id.slice(1))) break case "bspc": e.preventDefault() doInput(10) break case "bbksp": e.preventDefault() doInput(11) break case "benter": e.preventDefault() doInput(12) break case "bpoint": e.preventDefault() doInput(13) break case "bprogload": e.preventDefault() doInput(14) break } }, false) } function lineOut(s) { /* line output routine */ screenBuffer += s renderScreen() } function charOut(c) { /* character output routine */ screenBuffer += String.fromCharCode(+c) renderScreen() } function lineIn(cb) { inputRes = "" var inv = setInterval(function resWait() { if(inputRes != "") { clearInterval(inv) cb(inputRes) inputRes = "" } }, 100) } function main() { /* UI entry point */ screenDom = d.getElementById("screenfield") floader = d.getElementById("programloadfield") floader.addEventListener("change", loadProgFileHandler, false) setupInput() prompt = "> " vm = createmu808(lineOut, charOut, lineIn) lineOut("mu808 v1 by Luxferre\nPROGMEM: 16383 steps\nDATAMEM: 16384 floats\n") ;(function repl() { lineOut(prompt) lineIn(function(entryString) { var eparts = entryString.split(/[^\-0-9]+/).slice(0, 5), lno = parseInt(eparts[0] || 0), cmd = parseInt(eparts[1] || 0), x = parseInt(eparts[2] || 0), y = parseInt(eparts[3] || 0), z = parseInt(eparts[4] || 0) vm.ilenter(lno, cmd, x, y, z, repl) }) })() } w.addEventListener("DOMContentLoaded", main, false) })(window, document)