8-bit-computer/eightbitclock.ts

143 lines
4.7 KiB
TypeScript

// 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 <https://www.gnu.org/licenses/>.
// 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<Element> | undefined;
private speedInput: HTMLInputElement | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private timer: any = undefined;
private auto: NodeListOf<Element> | 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 = <HTMLInputElement | null>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';
}