From b13f1cdc8db94968e14f2f3158982fc09eb7c2bc Mon Sep 17 00:00:00 2001 From: adithya32 <163162210+KumarADITHYA123@users.noreply.github.com> Date: Sat, 29 Nov 2025 15:53:04 +0530 Subject: [PATCH 1/3] feat: add clock divider component - Create ClockDivider module for dividing clock frequencies by a configurable factor - Support divide factors: 2, 4, 8, 16, and custom values - Register component in module system for simulator availability - Add Clock Divider to Sequential Elements menu in UI - Component displays division factor (N) on canvas for visual clarity - Uses internal counter-based logic for clock division - Output frequency = Input frequency / divideFactor - Simplifies timing visualization for educational projects --- src/simulator/src/metadata.ts | 4 + src/simulator/src/moduleSetup.js | 2 + src/simulator/src/modules/ClockDivider.js | 112 ++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 src/simulator/src/modules/ClockDivider.js diff --git a/src/simulator/src/metadata.ts b/src/simulator/src/metadata.ts index 5d99084ca..c8391a1d9 100644 --- a/src/simulator/src/metadata.ts +++ b/src/simulator/src/metadata.ts @@ -38,6 +38,7 @@ export const circuitElementList = [ "TTY", "Keyboard", "Clock", + "ClockDivider", "DigitalLed", "Stepper", "VariableLed", @@ -85,6 +86,7 @@ export const inputList = [ "ConstantVal", "Input", "Clock", + "ClockDivider", "Button", "Counter" ] @@ -101,6 +103,7 @@ export const subCircuitInputList = [ "Power", "ConstantVal", "Clock", + "ClockDivider", "Button", "Counter" ] @@ -158,6 +161,7 @@ export const elementHierarchy: Record = { { name: "TTY", label: "TTY" }, { name: "Keyboard", label: "Keyboard" }, { name: "Clock", label: "Clock" }, + { name: "ClockDivider", label: "Clock Divider" }, { name: "Rom", label: "ROM" }, { name: "RAM", label: "RAM" }, { name: "verilogRAM", label: "Verilog RAM" }, diff --git a/src/simulator/src/moduleSetup.js b/src/simulator/src/moduleSetup.js index fb75f6a8e..07daa6a16 100644 --- a/src/simulator/src/moduleSetup.js +++ b/src/simulator/src/moduleSetup.js @@ -7,6 +7,7 @@ import ImageAnnotation from './modules/ImageAnnotation' import BitSelector from './modules/BitSelector' import Buffer from './modules/Buffer' import Button from './modules/Button' +import ClockDivider from './modules/ClockDivider' import ConstantVal from './modules/ConstantVal' import ControlledInverter from './modules/ControlledInverter' import Counter from './modules/Counter' @@ -123,6 +124,7 @@ export default function setupModules() { TTY, Keyboard, Clock, + ClockDivider, Rom, EEPROM, RAM, diff --git a/src/simulator/src/modules/ClockDivider.js b/src/simulator/src/modules/ClockDivider.js new file mode 100644 index 000000000..cb3f003be --- /dev/null +++ b/src/simulator/src/modules/ClockDivider.js @@ -0,0 +1,112 @@ +import CircuitElement from '../circuitElement' +import Node, { findNode } from '../node' +import { simulationArea } from '../simulationArea' +import { correctWidth, rect2, fillText } from '../canvasApi' +import { colors } from '../themer/themer' + +/** + * @class + * ClockDivider + * @extends CircuitElement + * @param {number} x - x coordinate of element. + * @param {number} y - y coordinate of element. + * @param {Scope=} scope - Circuit on which element is drawn + * @param {number=} divideFactor - The factor to divide the clock by (default 2) + * @category modules + */ +export default class ClockDivider extends CircuitElement { + constructor(x, y, scope = globalScope, divideFactor = 2) { + super(x, y, scope, 'RIGHT', 1) + this.divideFactor = divideFactor || 2 + this.counter = 0 + this.prevClockState = undefined + this.setDimensions(15, 15) + this.rectangleObject = true + + this.clock = new Node(-15, 0, 0, this, 1, 'Clock') + this.output = new Node(15, 0, 1, this, 1, 'Out') + this.mutableProperties = { + divideFactor: { + name: 'Divide Factor', + type: 'number', + max: '100', + min: '1', + func: 'setDivideFactor', + }, + } + } + + setDivideFactor(value) { + value = parseInt(value) + if (!isNaN(value) && value > 0) { + this.divideFactor = value + this.counter = 0 // Reset counter when factor changes + } + } + + /** + * @memberof ClockDivider + * fn to create save Json Data of object + * @return {JSON} + */ + customSave() { + const data = { + constructorParamaters: [this.divideFactor], + nodes: { + clock: findNode(this.clock), + output: findNode(this.output), + }, + } + return data + } + + /** + * @memberof ClockDivider + * resolve output values based on inputData + */ + resolve() { + if (this.clock.value !== this.prevClockState && this.clock.value === 1) { + this.counter++ + } + this.prevClockState = this.clock.value + + if (this.counter >= this.divideFactor) { + this.counter = 0 + } + + const outputValue = (this.counter % this.divideFactor) < (this.divideFactor / 2) ? 1 : 0 + + if (this.output.value !== outputValue) { + this.output.value = outputValue + simulationArea.simulationQueue.add(this.output) + } + } + + /** + * @memberof ClockDivider + * function to draw element + */ + customDraw() { + var ctx = simulationArea.context + var xx = this.x + var yy = this.y + + ctx.strokeStyle = colors['stroke'] + ctx.fillStyle = colors['fill'] + ctx.lineWidth = correctWidth(3) + + ctx.beginPath() + rect2(ctx, -15, -15, 30, 30, xx, yy, this.direction) + ctx.fill() + ctx.stroke() + + ctx.font = '14px Raleway' + ctx.fillStyle = colors['input_text'] + ctx.textAlign = 'center' + fillText(ctx, '÷' + this.divideFactor, xx, yy + 5) + } +} + +ClockDivider.prototype.tooltipText = 'Clock Divider: Divides the input clock frequency' +ClockDivider.prototype.helplink = 'https://docs.circuitverse.org/' // Placeholder as per instructions to not add extras +ClockDivider.prototype.objectType = 'ClockDivider' From 713ef21ed1d1f95c633559eb47e19758f25208f6 Mon Sep 17 00:00:00 2001 From: adithya32 <163162210+KumarADITHYA123@users.noreply.github.com> Date: Sat, 29 Nov 2025 16:22:00 +0530 Subject: [PATCH 2/3] fix: clamp divideFactor to min 2 (addresses review feedback) --- src/simulator/src/modules/ClockDivider.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/simulator/src/modules/ClockDivider.js b/src/simulator/src/modules/ClockDivider.js index cb3f003be..5e6b4761b 100644 --- a/src/simulator/src/modules/ClockDivider.js +++ b/src/simulator/src/modules/ClockDivider.js @@ -30,16 +30,21 @@ export default class ClockDivider extends CircuitElement { name: 'Divide Factor', type: 'number', max: '100', - min: '1', + min: '2', func: 'setDivideFactor', }, } } setDivideFactor(value) { - value = parseInt(value) - if (!isNaN(value) && value > 0) { - this.divideFactor = value + let factor = parseInt(value, 10) + if (isNaN(factor)) return + + // Clamp to UI-advertised range + factor = Math.max(2, Math.min(100, factor)) + + if (factor !== this.divideFactor) { + this.divideFactor = factor this.counter = 0 // Reset counter when factor changes } } From ceee37eda29e6a64bad047ddf60307ae76081393 Mon Sep 17 00:00:00 2001 From: adithya32 <163162210+KumarADITHYA123@users.noreply.github.com> Date: Sat, 29 Nov 2025 16:49:42 +0530 Subject: [PATCH 3/3] fix: typo in constructor parameters and font size tweak --- src/simulator/src/modules/ClockDivider.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simulator/src/modules/ClockDivider.js b/src/simulator/src/modules/ClockDivider.js index 5e6b4761b..2f354866c 100644 --- a/src/simulator/src/modules/ClockDivider.js +++ b/src/simulator/src/modules/ClockDivider.js @@ -56,7 +56,7 @@ export default class ClockDivider extends CircuitElement { */ customSave() { const data = { - constructorParamaters: [this.divideFactor], + constructorParameters: [this.divideFactor], nodes: { clock: findNode(this.clock), output: findNode(this.output), @@ -108,7 +108,7 @@ export default class ClockDivider extends CircuitElement { ctx.font = '14px Raleway' ctx.fillStyle = colors['input_text'] ctx.textAlign = 'center' - fillText(ctx, '÷' + this.divideFactor, xx, yy + 5) + fillText(ctx, '÷' + this.divideFactor, xx, yy + 5, 14) } }