mirror of
https://github.com/Stone-Red-Code/StoneRed.LogicSimulator.git
synced 2026-09-04 00:56:23 +02:00
127 lines
3.3 KiB
C#
127 lines
3.3 KiB
C#
using MonoGame.Extended.Input;
|
|
|
|
using StoneRed.LogicSimulator.Api;
|
|
using StoneRed.LogicSimulator.Api.Attributes;
|
|
using StoneRed.LogicSimulator.Api.Interfaces;
|
|
|
|
using System;
|
|
|
|
namespace StoneRed.LogicSimulator.Simulation.LogicGates;
|
|
|
|
[LogicGateName("DivideByNCounter")]
|
|
[LogicGateDescription("A clock is a circuit that oscillates between a high and a low state.")]
|
|
internal class DivideByNCounter : LogicGate, IInteractable
|
|
{
|
|
private ICircuitSimulator? circuitSimulator;
|
|
private int gateId;
|
|
private int count = 0;
|
|
private int tickRate = 0;
|
|
private bool currentState = false;
|
|
private bool inputInitialized = false;
|
|
private bool lastInputState = false;
|
|
|
|
public override int OutputCount { get; set; } = 1;
|
|
|
|
public override int InputCount { get; set; } = 1;
|
|
|
|
public string Info
|
|
{
|
|
get
|
|
{
|
|
if (tickRate <= 0)
|
|
{
|
|
return "Disabled";
|
|
}
|
|
|
|
return tickRate + "\n" + ((count > tickRate) ? count - tickRate : count);
|
|
}
|
|
}
|
|
|
|
public void OnInteraction(MouseStateExtended mouseState, MouseStateExtended previousMouseState, KeyboardStateExtended keyboardStateExtended)
|
|
{
|
|
if (mouseState.DeltaScrollWheelValue == 0 || !keyboardStateExtended.IsShiftDown())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (mouseState.DeltaScrollWheelValue < 0 && tickRate < int.MaxValue - 10)
|
|
{
|
|
tickRate += keyboardStateExtended.IsControlDown() ? 10 : 1;
|
|
}
|
|
else if (tickRate >= 1)
|
|
{
|
|
tickRate -= keyboardStateExtended.IsControlDown() ? 10 : 1;
|
|
}
|
|
|
|
tickRate = Math.Clamp(tickRate, 0, int.MaxValue);
|
|
|
|
if (tickRate <= 0)
|
|
{
|
|
count = 0;
|
|
currentState = false;
|
|
circuitSimulator?.SetSource(gateId, false);
|
|
}
|
|
}
|
|
|
|
protected internal override void Register(ICircuitSimulator circuitSimulator)
|
|
{
|
|
this.circuitSimulator = circuitSimulator;
|
|
SimulatorGateId = circuitSimulator.AddGate(GateKind.Source);
|
|
gateId = SimulatorGateId;
|
|
count = 0;
|
|
currentState = false;
|
|
inputInitialized = false;
|
|
lastInputState = false;
|
|
circuitSimulator.SetSource(gateId, false);
|
|
_ = circuitSimulator.WatchGate(SimulatorGateId, (_, newInputMask) => OnInputChanged((newInputMask & 1) != 0));
|
|
}
|
|
|
|
private void OnInputChanged(bool inputState)
|
|
{
|
|
if (circuitSimulator == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!inputInitialized)
|
|
{
|
|
inputInitialized = true;
|
|
lastInputState = inputState;
|
|
return;
|
|
}
|
|
|
|
if (lastInputState == inputState)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lastInputState = inputState;
|
|
|
|
if (tickRate <= 0)
|
|
{
|
|
if (count != 0 || currentState)
|
|
{
|
|
count = 0;
|
|
currentState = false;
|
|
circuitSimulator.SetSource(gateId, false);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
count++;
|
|
|
|
if (count >= tickRate * 2)
|
|
{
|
|
count = 0;
|
|
}
|
|
|
|
bool newState = count > tickRate;
|
|
if (newState != currentState)
|
|
{
|
|
currentState = newState;
|
|
circuitSimulator.SetSource(gateId, newState);
|
|
}
|
|
}
|
|
}
|