Files
StoneRed.LogicSimulator/StoneRed.LogicSimulator/Simulation/LogicGates/DivideByNCounter.cs
T

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);
}
}
}