From a92aa9f5db3a41e600f8b29e95ae1c7caa2f71a8 Mon Sep 17 00:00:00 2001 From: Scott Squires Date: Tue, 29 Dec 2015 14:35:08 -0600 Subject: [PATCH 1/5] add repeated trigger mode setting to pulse circuit The pulse circuit had (most likely) undesired behavior when the Circuit was triggered while a pulse was active. The subsequent triggers would unconditionally schedule tasks to turn off the signal after the pulse length. So if another pulse started after the first pulse ended, but there were additional triggers during the initial pulse, then the second pulse would turn off early. This commit adds a "repeated trigger" parameter to the pulse circuit. The 3rd parameter is optional and defaults to "legacy" for the original behavior. A value of "ignore" causes the circuit to ignore any triggers while the pulse is active. A value of "extend" causes the circuit to cancel the original task that would turn off the pulse and schedule a new one (for the original pulse length). --- .../redstonechips/basiccircuits/pulse.java | 83 +++++++++++++++---- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/redstonechips/basiccircuits/pulse.java b/src/main/java/org/redstonechips/basiccircuits/pulse.java index 14faf86..68ec843 100755 --- a/src/main/java/org/redstonechips/basiccircuits/pulse.java +++ b/src/main/java/org/redstonechips/basiccircuits/pulse.java @@ -10,23 +10,22 @@ public class pulse extends Circuit { public enum EdgeTriggering { positive, negative, doubleEdge }; + public enum RepeatedTriggerMode { legacy, ignore, extend }; private EdgeTriggering trigger = EdgeTriggering.positive; + private RepeatedTriggerMode repeatedTriggerMode = RepeatedTriggerMode.legacy; private long interval; private PulseOff[] pulseOffs; + private Integer[] pulseOffIds; private long intervalInTicks; @Override public void input(boolean state, final int inIdx) { if (state && (trigger==EdgeTriggering.positive || trigger==EdgeTriggering.doubleEdge)) { - if (inputlen==outputlen) - pulse(inIdx); - else pulseSequence(); + trigger(inIdx); } else if (!state && (trigger == EdgeTriggering.negative || trigger == EdgeTriggering.doubleEdge)) { - if (inputlen==outputlen) - pulse(inIdx); - else pulseSequence(); + trigger(inIdx); } } @@ -38,7 +37,6 @@ public Circuit init(String[] args) { if (inputlen==0) return error("Expecting at least one input and one output."); - if (args.length==0) interval = 1000; // 1 sec default @@ -51,33 +49,75 @@ public Circuit init(String[] args) { } if (args.length>=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); From 1930b2157656f3de2a0d02df03f0863d3c6a7819 Mon Sep 17 00:00:00 2001 From: Scott Squires Date: Sun, 20 Mar 2016 13:44:54 -0500 Subject: [PATCH 2/5] update encoder outputs when inputs are turned off as well as turned on On error, output zero. (Any number of pins set other than 1.) --- .../redstonechips/basiccircuits/encoder.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/redstonechips/basiccircuits/encoder.java b/src/main/java/org/redstonechips/basiccircuits/encoder.java index 9aacde7..ea26104 100755 --- a/src/main/java/org/redstonechips/basiccircuits/encoder.java +++ b/src/main/java/org/redstonechips/basiccircuits/encoder.java @@ -10,9 +10,20 @@ public class encoder extends Circuit { @Override public void input(boolean state, int inIdx) { - if (state) { - writeInt(inIdx, 0, outputlen); - } else { + int totalEnabledBits = 0; + int mostSignificantBit = -1; + + for (int i = 0; i < inputs.length; i++) { + if (inputs[i]) { + totalEnabledBits++; + mostSignificantBit = i; + } + } + + if (totalEnabledBits == 1) { + writeInt(mostSignificantBit, 0, outputlen); + } + else { this.clearOutputs(); } } From 455c1de0822ef562e782d5dd22e7fbfd37a6f794 Mon Sep 17 00:00:00 2001 From: Scott Squires Date: Thu, 26 May 2016 23:38:49 -0500 Subject: [PATCH 3/5] update code that uses the Ram.read() method to handle uninitialized addresses Fixes bug that prevents readonly sram chips from being initialized. Probably others as well. --- .../redstonechips/basiccircuits/display.java | 4 +++- .../redstonechips/basiccircuits/dregister.java | 2 +- .../org/redstonechips/basiccircuits/sram.java | 18 ++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) 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; i32) 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"; } From a068999837d4e50c24a8ef15f616ab792a3af629 Mon Sep 17 00:00:00 2001 From: Scott Squires Date: Sat, 11 Jun 2016 18:00:32 -0500 Subject: [PATCH 4/5] fix IndexOutOfBoundsException in pixel circuit PixelReceiver assumed that if there were no input pins then transmission would always be 5 bits in length. Changed to use the length of the transmission, up to a maximum of 5 bits. --- src/main/java/org/redstonechips/basiccircuits/pixel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/redstonechips/basiccircuits/pixel.java b/src/main/java/org/redstonechips/basiccircuits/pixel.java index f33c278..5238b63 100755 --- a/src/main/java/org/redstonechips/basiccircuits/pixel.java +++ b/src/main/java/org/redstonechips/basiccircuits/pixel.java @@ -181,7 +181,11 @@ public void receive(BooleanSubset bits) { // if we have 0 or 1 inputs there's no clock to adjust. just use the incoming bits. boolean[] valbits; if (inputlen<=1) { - valbits = bits.copy(0, (inputlen==0?5:inputlen)); + int copylen = 5; + if (bits.length() < copylen) { + copylen = bits.length(); + } + valbits = bits.copy(0, copylen); } else { valbits = new boolean[bits.length()+1]; for (int i=0; i Date: Mon, 4 Jul 2016 15:47:45 -0500 Subject: [PATCH 5/5] add combocounter circuit --- .../basiccircuits/BasicCircuits.java | 4 +- .../basiccircuits/combocounter.java | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/redstonechips/basiccircuits/combocounter.java 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; + } +}