// Clock generation component for the LogicSimulator used on the 8-bit-computer // Copyright (C) 2022 Sascha Nitsch // 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. // You should have received a copy of the GNU General Public License // along with this program. If not, see . // eslint-disable-next-line @typescript-eslint/no-unused-vars function EightBitClockInit() { interface EightBitClockText { auto: string; manual: string; } interface EightBitClockParam extends BaseComponentParam { speed?: string; mode?: string; auto?: string; manual?: string; } class EightBitClock extends LogicBase { private clockState: boolean; private speed: number; private input: string; private runAuto: boolean; private texts: EightBitClockText; private manual: NodeListOf | undefined; private speedInput: HTMLInputElement | null = null; // eslint-disable-next-line @typescript-eslint/no-explicit-any private timer: any = undefined; private auto: NodeListOf | undefined; private CLK = false; constructor(simulator: Simulator, id: string, param: EightBitClockParam) { super(simulator, id, param); this.pins.set('CLK', new TriState(this, 30, -20)); this.pins.set('invCLK', new TriState(this, 30, 20)); this.clockState = false; if (param.speed) { this.speed = 0; this.input = param.speed; } else { this.speed = 1; this.input = 'undefined'; } this.runAuto = param.mode ? param.mode === 'auto' : false; this.texts = { auto: param.auto ? param.auto : 'auto', manual: param.manual ? param.manual : 'manual', }; this.auto = undefined; this.manual = undefined; } tick(): void { this.clockState = !this.clockState; if (this.manual) { this.manual[0].textContent = this.clockState ? '1' : '0'; } this.simulator.tick(); } setup(canvas: SVGElement) { super.doSetup('eightbitclock', canvas); if (this.speed === 0) { this.speedInput = document.getElementById(this.input); if (this.speedInput) { this.speedInput.addEventListener('change', this.changeSpeed.bind(this)); this.speed = parseFloat(this.speedInput.value); if (this.runAuto) { this.timer = setInterval(this.tick.bind(this), 500 / this.speed); } } } else { this.timer = setInterval(this.tick.bind(this), 500 / this.speed); } if (this.element) { const gAuto = this.element.querySelectorAll('g.auto')[0]; this.auto = gAuto.querySelectorAll('text.inner'); gAuto.querySelectorAll('.label')[0].innerHTML = this.texts.auto; gAuto.addEventListener('mousedown', this.toggleAuto.bind(this)); const gManual = this.element.querySelectorAll('g.manual')[0]; this.manual = gManual.querySelectorAll('text.inner'); gManual.querySelectorAll('.label')[0].innerHTML = this.texts.manual; gManual.addEventListener('mousedown', this.toggleManual.bind(this)); } } update() { const oldstate = this.CLK; this.CLK = this.clockState; this.getPin('CLK').setBool(this.clockState); this.getPin('invCLK').setBool(!this.clockState); return oldstate !== this.clockState; } changeSpeed() { if (this.speedInput) { this.speed = parseFloat(this.speedInput.value); } if (this.runAuto) { clearInterval(this.timer); this.timer = setInterval(this.tick.bind(this), 500 / this.speed); } } close() { clearInterval(this.timer); } toggleAuto(e: Event) { e.preventDefault(); if (this.runAuto) { clearInterval(this.timer); } else { this.timer = setInterval(this.tick.bind(this), 500 / this.speed); } this.runAuto = !this.runAuto; if (this.auto) { this.auto[0].textContent = this.runAuto ? '1' : '0'; } } toggleManual(e: Event) { e.preventDefault(); this.tick(); } } window.EightBitClock = EightBitClock; } // eslint-disable-next-line @typescript-eslint/no-unused-vars function EightBitClockDepends() { return 'LogicBase'; }