diff --git a/src/main/java/org/redstonechips/basiccircuits/BasicCircuits.java b/src/main/java/org/redstonechips/basiccircuits/BasicCircuits.java index a6c210c..eb699d4 100755 --- a/src/main/java/org/redstonechips/basiccircuits/BasicCircuits.java +++ b/src/main/java/org/redstonechips/basiccircuits/BasicCircuits.java @@ -11,8 +11,8 @@ public class BasicCircuits extends CircuitLibrary { @Override public Class[] getCircuitClasses() { - return new Class[] { adder.class, and.class, clock.class, counter.class, demultiplexer.class, divider.class, flipflop.class, - multiplexer.class, multiplier.class, or.class, pisoregister.class, print.class, random.class, receiver.class, + return new Class[] { adder.class, and.class, clock.class, counter.class, combocounter.class, demultiplexer.class, divider.class, + flipflop.class, multiplexer.class, multiplier.class, or.class, pisoregister.class, print.class, random.class, receiver.class, shiftregister.class, transmitter.class, xor.class, decoder.class, encoder.class, pixel.class, pulse.class, not.class, synth.class, srnor.class, terminal.class, router.class, ringcounter.class, iptransmitter.class, ipreceiver.class, comparator.class, delay.class, repeater.class, nand.class, nor.class, xnor.class, segdriver.class, dregister.class, diff --git a/src/main/java/org/redstonechips/basiccircuits/combocounter.java b/src/main/java/org/redstonechips/basiccircuits/combocounter.java new file mode 100644 index 0000000..3018a4d --- /dev/null +++ b/src/main/java/org/redstonechips/basiccircuits/combocounter.java @@ -0,0 +1,92 @@ +package org.redstonechips.basiccircuits; + +import java.util.HashMap; +import java.util.Map; +import org.redstonechips.circuit.Circuit; + +/** + * Combination counter that can both increment and decrement + */ +public class combocounter extends Circuit { + private int incPin = 0; + private int decPin = 1; + private int resetPin = 2; + + int min; + int max; + int count; + + @Override + public void input(boolean state, int inIdx) { + if (state) { + if (inIdx == incPin) { + if (count >= max) { + count = min; + } + else { + count = count + 1; + } + + if (chip.hasListeners()) debug("Counting " + count + "."); + this.writeInt(count, 0, outputlen); + } + else if (inIdx == decPin) { + if (count <= min) { + count = max; + } + else { + count = count - 1; + } + + if (chip.hasListeners()) debug("Counting " + count + "."); + this.writeInt(count, 0, outputlen); + } + else if (inIdx == resetPin) { + count = 0; + + if (chip.hasListeners()) debug("Resetting counter to " + count + "."); + this.writeInt(count, 0, outputlen); + } + + } + } + + @Override + public Circuit init(String[] args) { + if (inputlen == 0) { + return error("Expecting at least 1 input."); + } + + if (args.length==0) { + min = 0; + max = (int)Math.pow(2, outputlen) - 1; + } + else { + return error("Illegal number of arguments (max 0)."); + } + + count = min; + return this; + } + + @Override + public boolean isStateless() { + return false; + } + + @Override + public void setInternalState(Map state) { + String loadedCount = state.get("count"); + if (loadedCount != null) { + count = Integer.decode(loadedCount); + writeInt(count, 0, outputlen); + } + } + + @Override + public Map getInternalState() { + Map state = new HashMap(); + state.put("count", Integer.toString(count)); + return state; + } +} diff --git a/src/main/java/org/redstonechips/basiccircuits/display.java b/src/main/java/org/redstonechips/basiccircuits/display.java index 488dec3..2dd1e79 100755 --- a/src/main/java/org/redstonechips/basiccircuits/display.java +++ b/src/main/java/org/redstonechips/basiccircuits/display.java @@ -14,6 +14,7 @@ import org.redstonechips.memory.RamListener; import org.redstonechips.util.BooleanArrays; import org.redstonechips.util.BooleanSubset; +import org.redstonechips.util.Optional; import org.redstonechips.wireless.Receiver; /** @@ -101,7 +102,8 @@ public void dataChanged(Ram ram, long address, boolean[] data) { private void refreshDisplayFromRam() { long offset = ramPage * ramPageLength; for (long i=offset; i=2) { - if (args.length==2) { - try { - trigger = EdgeTriggering.valueOf(args[1]); - } catch (IllegalArgumentException ie) { - return error("Bad trigger argument: " + args[1]); - } + try { + trigger = EdgeTriggering.valueOf(args[1]); + } catch (IllegalArgumentException ie) { + return error("Bad trigger argument: " + args[1]); + } + } + + if (args.length>=3) { + try { + repeatedTriggerMode = RepeatedTriggerMode.valueOf(args[2]); + } catch (IllegalArgumentException e) { + return error("Bad repeated trigger mode argument: " + args[2]); } } + + if (repeatedTriggerMode==RepeatedTriggerMode.extend && inputlen!=outputlen) { + return error("Extend mode is incompatible with sequence mode"); + } if (interval!=0) { intervalInTicks = Math.round(interval/50); + pulseOffIds = new Integer[outputlen]; pulseOffs = new PulseOff[outputlen]; for (int i=0; i < outputlen; i++) { - pulseOffs[i] = new PulseOff(i); + pulseOffs[i] = new PulseOff(i, pulseOffIds); } } return this; } - + + private void trigger(final int idx) { + int checkRepeatIdx = 0; + + if (repeatedTriggerMode==RepeatedTriggerMode.legacy) { + pulse(idx); + } + else { + if (inputlen==outputlen) { + checkRepeatIdx = idx; + } + if (repeatedTriggerMode==RepeatedTriggerMode.ignore) { + if (pulseOffIds[checkRepeatIdx]==null) { + pulse(idx); + } + } + else if (repeatedTriggerMode==RepeatedTriggerMode.extend) { + if (pulseOffIds[checkRepeatIdx]!=null) { + rc.getServer().getScheduler().cancelTask(pulseOffIds[checkRepeatIdx]); + pulseOffIds[checkRepeatIdx] = null; + } + pulse(idx); + } + } + } + private void pulse(final int idx) { + if (inputlen==outputlen) + pulseSingle(idx); + else pulseSequence(); + } + + private void pulseSingle(final int idx) { write(true, idx); if (interval==0) { write(false, idx); } else { - rc.getServer().getScheduler().scheduleSyncDelayedTask(rc, pulseOffs[idx], intervalInTicks); + pulseOffIds[idx] = rc.getServer().getScheduler().scheduleSyncDelayedTask(rc, pulseOffs[idx], intervalInTicks); } } @@ -90,18 +130,25 @@ private void pulseSequence() { } } else { write(true, 0); - rc.getServer().getScheduler().scheduleSyncDelayedTask(rc, pulseOffs[0], intervalInTicks); + pulseOffIds[0] = rc.getServer().getScheduler().scheduleSyncDelayedTask(rc, pulseOffs[0], intervalInTicks); } } class PulseOff implements Runnable { int index; + Integer[] pulseOffIds; - public PulseOff(int index) { this.index = index; } + public PulseOff(int index, Integer[] pulseOffIds) { + this.index = index; + this.pulseOffIds = pulseOffIds; + } @Override public void run() { write(false, index); + if (inputlen==outputlen || index==0) { + pulseOffIds[index] = null; + } if (inputlen!=outputlen && pulseOffs.length>index+1) { write(true, index+1); rc.getServer().getScheduler().scheduleSyncDelayedTask(rc, pulseOffs[index+1], intervalInTicks); diff --git a/src/main/java/org/redstonechips/basiccircuits/sram.java b/src/main/java/org/redstonechips/basiccircuits/sram.java index 44ce54e..6c520da 100755 --- a/src/main/java/org/redstonechips/basiccircuits/sram.java +++ b/src/main/java/org/redstonechips/basiccircuits/sram.java @@ -2,6 +2,7 @@ package org.redstonechips.basiccircuits; import java.io.IOException; +import java.util.Arrays; import java.util.logging.Level; import org.redstonechips.paging.LineSource; import org.redstonechips.parsing.Range; @@ -16,6 +17,7 @@ import org.redstonechips.memory.RamListener; import org.redstonechips.paging.Pager; import org.redstonechips.util.BooleanArrays; +import org.redstonechips.util.Optional; /** * @@ -155,7 +157,8 @@ public void save() { private void readMemory() { long address = getInputAddress(); - boolean[] data = memory.read(address); + boolean[] data = memory.readDefaultZero(address, wordLength); + if (chip.hasListeners()) debug("Reading " + BooleanArrays.toPrettyString(data, wordLength) + " from address " + address); writeBits(data, 0, wordLength); } @@ -301,9 +304,16 @@ public MemoryLineSource(int offset, int length) { public String getLine(int idx) { String value; String address = zeroPad(idx+offset, (int)Math.pow(2, addressLength)-1); - boolean[] data = memory.read(idx+offset); - if (wordLength>32) value = Long.toHexString(BooleanArrays.toSignedInt(data, 0, wordLength)); - else value = BooleanArrays.toPrettyString(data, wordLength); + Optional dataOpt = memory.read(idx+offset); + boolean[] data = memory.readDefaultZero(idx+offset, wordLength); + + if (wordLength > 32) { + value = Long.toHexString(BooleanArrays.toSignedInt(data, 0, wordLength)); + } + else { + value = BooleanArrays.toPrettyString(data, wordLength); + } + return ChatColor.YELLOW.toString() + address + ": " + ChatColor.WHITE + value + "\n"; }